diff options
author | Karel Zak | 2006-12-07 00:25:43 +0100 |
---|---|---|
committer | Karel Zak | 2006-12-07 00:25:43 +0100 |
commit | 22853e4a82c6ef7b336527529acb94b14a0b0fd8 (patch) | |
tree | ee28e4598c8c449d7e811711d8ce8eb17caecfb6 /fdisk/fdisk.c | |
parent | Imported from util-linux-2.10f tarball. (diff) | |
download | kernel-qcow2-util-linux-22853e4a82c6ef7b336527529acb94b14a0b0fd8.tar.gz kernel-qcow2-util-linux-22853e4a82c6ef7b336527529acb94b14a0b0fd8.tar.xz kernel-qcow2-util-linux-22853e4a82c6ef7b336527529acb94b14a0b0fd8.zip |
Imported from util-linux-2.10m tarball.
Diffstat (limited to 'fdisk/fdisk.c')
-rw-r--r-- | fdisk/fdisk.c | 1074 |
1 files changed, 661 insertions, 413 deletions
diff --git a/fdisk/fdisk.c b/fdisk/fdisk.c index 56caa9a17..45110ccd6 100644 --- a/fdisk/fdisk.c +++ b/fdisk/fdisk.c @@ -7,81 +7,27 @@ * published by the Free Software Foundation: either version 1 or * (at your option) any later version. * - * Before Linux version 0.95c, this program requires a kernel patch. - * - * Modified, Tue Feb 2 18:46:49 1993, faith@cs.unc.edu to better support SCSI. - * Modified, Sat Feb 27 18:11:27 1993, faith@cs.unc.edu: added extfs support. - * Modified, Sat Mar 6 10:14:12 1993, faith@cs.unc.edu: added more comments. - * Modified, Sat Mar 6 12:25:45 1993, faith@cs.unc.edu: - * Added patches from Michael Bischoff (i1041905@ws.rz.tu-bs.de - * or mbi@mo.math.nat.tu-bs.de) to fix the following problems: - * 1) Incorrect mapping of head/sector/cylinder to absolute sector - * 2) Odd sector count causes one sector to be lost - * Modified, Sat Mar 6 12:25:52 1993, faith@cs.unc.edu: improved verification. - * Modified, Sat Apr 17 15:00:00 1993, LeBlanc@mcc.ac.uk: add -s, fix -l. - * Modified, Sat Apr 24 10:00:00 1993, LeBlanc@mcc.ac.uk: fix overlap bug. - * Modified, Wed May 5 21:30:00 1993, LeBlanc@mcc.ac.uk: errors to stderr. - * Modified, Mon Mar 21 20:00:00 1994, LeBlanc@mcc.ac.uk: - * more stderr for messages, avoid division by 0, and - * give reboot message only if ioctl(fd, BLKRRPART) fails. - * Modified, Mon Apr 25 01:01:05 1994, martin@cs.unc.edu: - * 1) Added support for DOS, OS/2, ... compatibility. We should be able - * use this fdisk to partition our drives for other operating systems. - * 2) Added a print the raw data in the partition table command. - * Modified, Wed Jun 22 21:05:30 1994, faith@cs.unc.edu: - * Added/changed a few partition type names to conform to cfdisk. - * (suggested by Sujal, smpatel@wam.umd.edu) - * Modified 3/5/95 leisner@sdsp.mc.xerox.com -- on -l only open - * devices RDONLY (instead of RDWR). This allows you to - * have the disks as rw-r----- with group disk (and if you - * want is safe to setguid fdisk to disk). - * Modified Sat Mar 11 10:02 1995 with more partition types, faith@cs.unc.edu - * Modified, Thu May 4 01:11:45 1995, esr@snark.thyrsus.com: - * It's user-interface cleanup time. - * Actual error messages for out-of-bounds values (what a concept!). - * Enable read-only access to partition table for learners. - * Smart defaults for most numeric prompts. - * Fixed a bug preventing a partition from crossing cylinder 8064, aeb, 950801. - * Read partition table twice to avoid kernel bug - * (from Daniel Quinlan <quinlan@yggdrasil.com>), Tue Sep 26 10:25:28 1995 - * Modified, Sat Jul 1 23:43:16 MET DST 1995, fasten@cs.bonn.edu: - * editor for NetBSD/i386 (and Linux/Alpha?) disklabels. - * Tue Sep 26 17:07:54 1995: More patches from aeb. Fix segfaults, all >4GB. - * Don't destroy random data if extd partition starts past 4GB, aeb, 950818. - * Don't segfault on bad partition created by previous fdisk. - * Fixed for using variable blocksizes (needed by magnet-optical drive-patch) - * (from orschaer@cip.informatik.uni-erlangen.de) - * Modified, Fri Jul 14 11:13:35 MET DST 1996, jj@sunsite.mff.cuni.cz: - * editor for Sun disklabels. - * Modified, Wed Jul 3 10:14:17 MET DST 1996, jj@sunsite.mff.cuni.cz: - * support for Sun floppies - * Modified, Thu Jul 24 16:42:33 MET DST 1997, fasten@shw.com: - * LINUX_EXTENDED support - * Added Windows 95 partition types, aeb. - * Fixed a bug described by johnf@whitsunday.net.au, aeb, 980408. - * [There are lots of other bugs - nobody should use this program] - * [cfdisk on the other hand is nice and correct] - * Try to avoid reading a CD-ROM. - * Do not print Begin column -- it confuses too many people -- aeb, 980610. - * Modified, Sat Oct 3 14:40:17 MET DST 1998, ANeuper@GUUG.de - * Support SGI's partitioning -- an, 980930. - * Do the verify using LBA, not CHS, limits -- aeb, 981206. - * Corrected single-cylinder partition creating a little, now that - * ankry@mif.pg.gda.pl pointed out a bug; there are more bugs -- aeb, 990214. + * For detailed old history, see older versions. + * Contributions before 2000 by faith@cs.unc.edu, Michael Bischoff, + * LeBlanc@mcc.ac.uk, martin@cs.unc.edu, leisner@sdsp.mc.xerox.com, + * esr@snark.thyrsus.com, aeb@cwi.nl, quinlan@yggdrasil.com, + * fasten@cs.bonn.edu, orschaer@cip.informatik.uni-erlangen.de, + * jj@sunsite.mff.cuni.cz, fasten@shw.com, ANeuper@GUUG.de, + * kgw@suse.de. * - * Sat Mar 20 09:31:05 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br> - * Internationalization + * Modified, Sun Feb 20 2000, kalium@gmx.de + * Added fix operation allowing to reorder primary/extended partition + * entries within the partition table. Some programs or OSes have + * problems using a partition table with entries not ordered + * according to their positions on disk. + * Munged this patch to also make it work for logical partitions. + * aeb, 2000-02-20. * - * Corrected deleting last logical partition -- aeb, 990430. - * Removed all assumptions on file names -- aeb, 990709 - * [modprobe gave ugly error messages, and the number of devices to probe - * increased all the time: hda, sda, eda, rd/c0d0, ida/c0d0, ... - * Also partition naming was very ugly.] + * Wed Mar 1 14:34:53 EST 2000 David Huggins-Daines <dhuggins@linuxcare.com> + * Better support for OSF/1 disklabels on Alpha. * - * Corrected a bug where creating an extended hda3, say, then a logical hda5 - * that does not start at the beginning of hda3, then a logical hda6 that does - * start at the beginning of hda3 would wipe out the partition table describing - * hda5. [Patch by Klaus G. Wagner" <kgw@suse.de>] -- aeb, 990711 + * 2000-04-06, Michal Jaegermann (michal@ellpspace.math.ualberta.ca) + * fixed and added some alpha stuff. */ @@ -94,14 +40,11 @@ #include <setjmp.h> #include <errno.h> #include <getopt.h> -#include "nls.h" - #include <sys/stat.h> -#include <sys/ioctl.h> #include <linux/hdreg.h> /* for HDIO_GETGEO */ -#include <linux/fs.h> /* for BLKRRPART, BLKGETSIZE */ +#include "nls.h" #include "common.h" #include "fdisk.h" @@ -122,7 +65,7 @@ #define LINE_LENGTH 80 -#define offset(b, n) ((struct partition *)((b) + 0x1be + \ +#define pt_offset(b, n) ((struct partition *)((b) + 0x1be + \ (n) * sizeof(struct partition))) #define sector(s) ((s) & 0x3f) #define cylinder(s, c) ((c) | (((s) & 0xc0) << 2)) @@ -139,7 +82,7 @@ } /* A valid partition table sector ends in 0x55 0xaa */ -unsigned int +static unsigned int part_table_flag(char *b) { return ((uint) b[510]) + (((uint) b[511]) << 8); } @@ -149,7 +92,7 @@ valid_part_table_flag(unsigned char *b) { return (b[510] == 0x55 && b[511] == 0xaa); } -void +static void write_part_table_flag(char *b) { b[510] = 0x55; b[511] = 0xaa; @@ -157,7 +100,7 @@ write_part_table_flag(char *b) { /* start_sect and nr_sects are stored little endian on all machines */ /* moreover, they are not aligned correctly */ -void +static void store4_little_endian(unsigned char *cp, unsigned int val) { cp[0] = (val & 0xff); cp[1] = ((val >> 8) & 0xff); @@ -165,13 +108,13 @@ store4_little_endian(unsigned char *cp, unsigned int val) { cp[3] = ((val >> 24) & 0xff); } -unsigned int +static unsigned int read4_little_endian(unsigned char *cp) { return (uint)(cp[0]) + ((uint)(cp[1]) << 8) + ((uint)(cp[2]) << 16) + ((uint)(cp[3]) << 24); } -void +static void set_start_sect(struct partition *p, unsigned int start_sect) { store4_little_endian(p->start4, start_sect); } @@ -181,7 +124,7 @@ get_start_sect(struct partition *p) { return read4_little_endian(p->start4); } -void +static void set_nr_sects(struct partition *p, unsigned int nr_sects) { store4_little_endian(p->size4, nr_sects); } @@ -194,13 +137,31 @@ get_nr_sects(struct partition *p) { /* normally O_RDWR, -l option gives O_RDONLY */ static int type_open = O_RDWR; +/* + * Raw disk label. For DOS-type partition tables the MBR, + * with descriptions of the primary partitions. + */ +char MBRbuffer[MAX_SECTOR_SIZE]; + +/* + * per partition table entry data + * + * The four primary partitions have the same sectorbuffer (MBRbuffer) + * and have NULL ext_pointer. + * Each logical partition table entry has two pointers, one for the + * partition and one link to the next one. + */ +struct pte { + struct partition *part_table; /* points into sectorbuffer */ + struct partition *ext_pointer; /* points into sectorbuffer */ + char changed; /* boolean */ + uint offset; /* disk sector number */ + char *sectorbuffer; /* disk sector contents */ +} ptes[MAXIMUM_PARTS]; + char *disk_device, /* must be specified */ *line_ptr, /* interactive input */ - line_buffer[LINE_LENGTH], - changed[MAXIMUM_PARTS], /* marks changed buffers */ - buffer[MAX_SECTOR_SIZE], /* first four partitions */ - *buffers[MAXIMUM_PARTS] /* pointers to buffers */ - = {buffer, buffer, buffer, buffer}; + line_buffer[LINE_LENGTH]; int fd, /* the disk */ ext_index, /* the prime extended partition */ @@ -209,6 +170,8 @@ int fd, /* the disk */ dos_compatible_flag = ~0, partitions = 4; /* maximum partition + 1 */ +uint user_cylinders, user_heads, user_sectors; + uint heads, sectors, cylinders, @@ -216,23 +179,16 @@ uint heads, sector_offset = 1, units_per_sector = 1, display_in_cyl_units = 1, - extended_offset = 0, /* offset of link pointers */ - offsets[MAXIMUM_PARTS] = {0, 0, 0, 0}; + extended_offset = 0; /* offset of link pointers */ +#define dos_label (!sun_label && !sgi_label && !aix_label && !osf_label) int sun_label = 0; /* looking at sun disklabel */ int sgi_label = 0; /* looking at sgi disklabel */ int aix_label = 0; /* looking at aix disklabel */ - -struct partition *part_table[MAXIMUM_PARTS] /* partitions */ - = {offset(buffer, 0), offset(buffer, 1), - offset(buffer, 2), offset(buffer, 3)}, - *ext_pointers[MAXIMUM_PARTS] /* link pointers */ - = {NULL, NULL, NULL, NULL}; - +int osf_label = 0; /* looking at osf disklabel */ jmp_buf listingbuf; -void fatal(enum failure why) -{ +void fatal(enum failure why) { char error[LINE_LENGTH], *message = error; @@ -289,8 +245,66 @@ void fatal(enum failure why) exit(1); } -void menu(void) -{ +static void +seek_sector(int fd, uint secno) { + ext2_loff_t offset = (ext2_loff_t) secno * sector_size; + if (ext2_llseek(fd, offset, SEEK_SET) == (ext2_loff_t) -1) + fatal(unable_to_seek); +} + +static void +read_sector(int fd, uint secno, char *buf) { + seek_sector(fd, secno); + if (read(fd, buf, sector_size) != sector_size) + fatal(unable_to_read); +} + +static void +write_sector(int fd, uint secno, char *buf) { + seek_sector(fd, secno); + if (write(fd, buf, sector_size) != sector_size) + fatal(unable_to_write); +} + +/* Allocate a buffer and read a partition table sector */ +static void +read_pte(int fd, int pno, uint offset) { + struct pte *pe = &ptes[pno]; + + pe->offset = offset; + pe->sectorbuffer = (char *) malloc(sector_size); + if (!pe->sectorbuffer) + fatal(out_of_memory); + read_sector(fd, offset, pe->sectorbuffer); + pe->changed = 0; + pe->part_table = pe->ext_pointer = NULL; +} + +static unsigned int +get_partition_start(struct pte *pe) { + return pe->offset + get_start_sect(pe->part_table); +} + +struct partition * +get_part_table(int i) { + return ptes[i].part_table; +} + +void +set_all_unchanged(void) { + int i; + + for (i = 0; i < MAXIMUM_PARTS; i++) + ptes[i].changed = 0; +} + +void +set_changed(int i) { + ptes[i].changed = 1; +} + +static void +menu(void) { if (sun_label) { puts(_("Command action")); puts(_(" a toggle a read only flag")); /* sun */ @@ -356,11 +370,11 @@ void menu(void) } } -void xmenu(void) -{ +static void +xmenu(void) { if (sun_label) { puts(_("Command action")); - puts(_(" a change number of alternate cylinders")); /*sun*/ + puts(_(" a change number of alternate cylinders")); /*sun*/ puts(_(" c change number of cylinders")); puts(_(" d print the raw data in the partition table")); puts(_(" e change number of extra sectors per cylinder"));/*sun*/ @@ -376,12 +390,45 @@ void xmenu(void) puts(_(" w write table to disk and exit")); puts(_(" y change number of physical cylinders")); /*sun*/ } + else if(sgi_label) { + puts(_("Command action")); + puts(_(" b move beginning of data in a partition")); /* !sun */ + puts(_(" c change number of cylinders")); + puts(_(" d print the raw data in the partition table")); + puts(_(" e list extended partitions")); /* !sun */ + puts(_(" g create an IRIX partition table")); /* sgi */ + puts(_(" h change number of heads")); + puts(_(" m print this menu")); + puts(_(" p print the partition table")); + puts(_(" q quit without saving changes")); + puts(_(" r return to main menu")); + puts(_(" s change number of sectors/track")); + puts(_(" v verify the partition table")); + puts(_(" w write table to disk and exit")); + } + else if(aix_label) { + puts(_("Command action")); + puts(_(" b move beginning of data in a partition")); /* !sun */ + puts(_(" c change number of cylinders")); + puts(_(" d print the raw data in the partition table")); + puts(_(" e list extended partitions")); /* !sun */ + puts(_(" g create an IRIX partition table")); /* sgi */ + puts(_(" h change number of heads")); + puts(_(" m print this menu")); + puts(_(" p print the partition table")); + puts(_(" q quit without saving changes")); + puts(_(" r return to main menu")); + puts(_(" s change number of sectors/track")); + puts(_(" v verify the partition table")); + puts(_(" w write table to disk and exit")); + } else { puts(_("Command action")); puts(_(" b move beginning of data in a partition")); /* !sun */ puts(_(" c change number of cylinders")); puts(_(" d print the raw data in the partition table")); puts(_(" e list extended partitions")); /* !sun */ + puts(_(" f fix partition order")); /* !sun, !aix, !sgi */ puts(_(" g create an IRIX partition table")); /* sgi */ puts(_(" h change number of heads")); puts(_(" m print this menu")); @@ -391,17 +438,17 @@ void xmenu(void) puts(_(" s change number of sectors/track")); puts(_(" v verify the partition table")); puts(_(" w write table to disk and exit")); - } + } } -int +static int get_sysid(int i) { return ( sun_label ? sunlabel->infos[i].id : - sgi_label ? sgi_get_sysid(i) : part_table[i]->sys_ind); + sgi_label ? sgi_get_sysid(i) : ptes[i].part_table->sys_ind); } -struct systypes * +static struct systypes * get_sys_types(void) { return ( sun_label ? sun_sys_types : @@ -444,8 +491,10 @@ void list_types(struct systypes *sys) putchar('\n'); } -void clear_partition(struct partition *p) -{ +static void +clear_partition(struct partition *p) { + if (!p) + return; p->boot_ind = 0; p->head = 0; p->sector = 0; @@ -458,9 +507,9 @@ void clear_partition(struct partition *p) set_nr_sects(p,0); } -void set_partition(int i, struct partition *p, uint start, uint stop, - int sysid, uint offset) -{ +static void +set_partition(int i, struct partition *p, uint start, uint stop, + int sysid, uint offset) { p->boot_ind = 0; p->sys_ind = sysid; set_start_sect(p, start - offset); @@ -471,11 +520,11 @@ void set_partition(int i, struct partition *p, uint start, uint stop, if (dos_compatible_flag && (stop/(sectors*heads) > 1023)) stop = heads*sectors*1024 - 1; set_hsc(p->end_head, p->end_sector, p->end_cyl, stop); - changed[i] = 1; + ptes[i].changed = 1; } -int test_c(char **m, char *mesg) -{ +static int +test_c(char **m, char *mesg) { int val = 0; if (!*m) fprintf(stderr, _("You must set")); @@ -487,8 +536,8 @@ int test_c(char **m, char *mesg) return val; } -int warn_geometry(void) -{ +static int +warn_geometry(void) { char *m = NULL; int prev = 0; if (!heads) @@ -515,85 +564,95 @@ void update_units(void) units_per_sector = 1; /* in sectors */ } -void warn_cylinders(void) -{ - if (!sun_label && !sgi_label && cylinders > 1024 && !nowarn) +static void +warn_cylinders(void) { + if (dos_label && cylinders > 1024 && !nowarn) fprintf(stderr, "\n\ The number of cylinders for this disk is set to %d.\n\ There is nothing wrong with that, but this is larger than 1024,\n\ and could in certain setups cause problems with:\n\ -1) software that runs at boot time (e.g., LILO)\n\ +1) software that runs at boot time (e.g., old versions of LILO)\n\ 2) booting and partitioning software from other OSs\n\ (e.g., DOS FDISK, OS/2 FDISK)\n", cylinders); } -void read_extended(struct partition *p) -{ +static void +read_extended(int ext) { int i; - struct partition *q; + struct pte *pex; + struct partition *p, *q; + + ext_index = ext; + pex = &ptes[ext]; + pex->ext_pointer = pex->part_table; - ext_pointers[ext_index] = part_table[ext_index]; + p = pex->part_table; if (!get_start_sect(p)) fprintf(stderr, _("Bad offset in primary extended partition\n")); else while (IS_EXTENDED (p->sys_ind)) { + struct pte *pe = &ptes[partitions]; + if (partitions >= MAXIMUM_PARTS) { /* This is not a Linux restriction, but this program uses arrays of size MAXIMUM_PARTS. Do not try to `improve' this test. */ + struct pte *pre = &ptes[partitions-1]; + fprintf(stderr, _("Warning: deleting partitions after %d\n"), partitions); - clear_partition(ext_pointers[partitions - 1]); - changed[partitions - 1] = 1; + clear_partition(pre->ext_pointer); + pre->changed = 1; return; } - offsets[partitions] = extended_offset + get_start_sect(p); + + read_pte(fd, partitions, extended_offset + get_start_sect(p)); + if (!extended_offset) extended_offset = get_start_sect(p); - if (ext2_llseek(fd, (ext2_loff_t)offsets[partitions] - * sector_size, SEEK_SET) < 0) - fatal(unable_to_seek); - if (!(buffers[partitions] = (char *) malloc(sector_size))) - fatal(out_of_memory); - if (sector_size != read(fd, buffers[partitions], sector_size)) - fatal(unable_to_read); - part_table[partitions] = ext_pointers[partitions] = NULL; - q = p = offset(buffers[partitions], 0); + + q = p = pt_offset(pe->sectorbuffer, 0); for (i = 0; i < 4; i++, p++) { if (IS_EXTENDED (p->sys_ind)) { - if (ext_pointers[partitions]) - fprintf(stderr, _("Warning: extra link " - "pointer in partition table " - "%d\n"), partitions + 1); + if (pe->ext_pointer) + fprintf(stderr, _("Warning: extra link" + " pointer in partition table " + "%d\n"), partitions + 1); else - ext_pointers[partitions] = p; + pe->ext_pointer = p; } else if (p->sys_ind) { - if (part_table[partitions]) + if (pe->part_table) fprintf(stderr, _("Warning: ignoring extra data " - "in partition table %d\n"), + "in partition table %d\n"), partitions + 1); else - part_table[partitions] = p; + pe->part_table = p; } } - if (!part_table[partitions]) { - if (q != ext_pointers[partitions]) - part_table[partitions] = q; - else part_table[partitions] = q + 1; + + /* very strange code here... */ + if (!pe->part_table) { + if (q != pe->ext_pointer) + pe->part_table = q; + else + pe->part_table = q + 1; } - if (!ext_pointers[partitions]) { - if (q != part_table[partitions]) - ext_pointers[partitions] = q; - else ext_pointers[partitions] = q + 1; + if (!pe->ext_pointer) { + if (q != pe->part_table) + pe->ext_pointer = q; + else + pe->ext_pointer = q + 1; } - p = ext_pointers[partitions++]; + + p = pe->ext_pointer; + partitions++; } } -void create_doslabel(void) -{ +static void +create_doslabel(void) { int i; fprintf(stderr, @@ -604,38 +663,17 @@ void create_doslabel(void) sun_nolabel(); /* otherwise always recognised as sun */ sgi_nolabel(); /* otherwise always recognised as sgi */ - write_part_table_flag(buffer); + write_part_table_flag(MBRbuffer); for (i = 0; i < 4; i++) - clear_partition(part_table[i]); - for (i = 1; i < MAXIMUM_PARTS; i++) - changed[i] = 0; - changed[0] = 1; + if (ptes[i].part_table) + clear_partition(ptes[i].part_table); + set_all_unchanged(); + set_changed(0); get_boot(create_empty); } -/* - * Read MBR. Returns: - * -1: no 0xaa55 flag present (possibly entire disk BSD) - * 0: found or created label - */ -int get_boot(enum action what) -{ - int i, sec_fac; - struct hd_geometry geometry; - - partitions = 4; - sec_fac = sector_size / 512; - - if (what == create_empty) - goto got_table; /* skip reading disk */ - - if ((fd = open(disk_device, type_open)) < 0) { - if ((fd = open(disk_device, O_RDONLY)) < 0) - fatal(unable_to_open); - else - printf(_("You will not be able to write the partition table.\n")); - } - +static void +get_sectorsize(int fd) { #if defined(BLKSSZGET) && defined(HAVE_blkpg_h) /* For a short while BLKSSZGET gave a wrong sector size */ { int arg; @@ -645,36 +683,95 @@ int get_boot(enum action what) printf(_("Note: sector size is %d (not %d)\n"), sector_size, DEFAULT_SECTOR_SIZE); } +#else + sector_size = DEFAULT_SECTOR_SIZE; #endif +} - guess_device_type(fd); +/* + * Ask kernel about geometry. Invent something reasonable + * in case the kernel has no opinion. + */ +void +get_geometry(int fd, struct geom *g) { + int sec_fac; + long longsectors; + struct hd_geometry geometry; + int res1, res2; - if (sector_size != read(fd, buffer, sector_size)) - fatal(unable_to_read); + get_sectorsize(fd); + sec_fac = sector_size / 512; + guess_device_type(fd); + + res1 = ioctl(fd, BLKGETSIZE, &longsectors); #ifdef HDIO_REQ - if (!ioctl(fd, HDIO_REQ, &geometry)) { + res2 = ioctl(fd, HDIO_REQ, &geometry); #else - if (!ioctl(fd, HDIO_GETGEO, &geometry)) { + res2 = ioctl(fd, HDIO_GETGEO, &geometry); #endif + + /* never use geometry.cylinders - it is truncated */ + heads = cylinders = sectors = 0; + sector_offset = 1; + if (res2 == 0) { heads = geometry.heads; sectors = geometry.sectors; - cylinders = geometry.cylinders; - cylinders /= sec_fac; /* do not round up */ - if (dos_compatible_flag) + if (heads * sectors == 0) + res2 = -1; + else if (dos_compatible_flag) sector_offset = sectors; - } else { - long longsectors; - if (!ioctl(fd, BLKGETSIZE, &longsectors)) { - heads = 1; - cylinders = 1; - sectors = longsectors / sec_fac; - } else { - heads = cylinders = sectors = 0; - } } + if (res1 == 0 && res2 == 0) { /* normal case */ + cylinders = longsectors / (heads * sectors); + cylinders /= sec_fac; /* do not round up */ + } else if (res1 == 0) { /* size but no geometry */ + heads = cylinders = 1; + sectors = longsectors / sec_fac; + } + + if (!sectors) + sectors = user_sectors; + if (!heads) + heads = user_heads; + if (!cylinders) + cylinders = user_cylinders; + + if (g) { + g->heads = heads; + g->sectors = sectors; + g->cylinders = cylinders; + } +} + +/* + * Read MBR. Returns: + * -1: no 0xaa55 flag present (possibly entire disk BSD) + * 0: found or created label + */ +int +get_boot(enum action what) { + int i; + + partitions = 4; + + if (what == create_empty) + goto got_table; /* skip reading disk */ + + if ((fd = open(disk_device, type_open)) < 0) { + if ((fd = open(disk_device, O_RDONLY)) < 0) + fatal(unable_to_open); + else + printf(_("You will not be able to write the partition table.\n")); + } + + get_geometry(fd, NULL); + update_units(); + if (sector_size != read(fd, MBRbuffer, sector_size)) + fatal(unable_to_read); + got_table: if (check_sun_label()) @@ -686,12 +783,15 @@ got_table: if (check_aix_label()) return 0; - if (!valid_part_table_flag(buffer)) { + if (check_osf_label()) + return 0; + + if (!valid_part_table_flag(MBRbuffer)) { switch(what) { case fdisk: fprintf(stderr, _("Device contains neither a valid DOS partition" - " table, nor Sun or SGI disklabel\n")); + " table, nor Sun, SGI or OSF disklabel\n")); #ifdef __sparc__ create_sunlabel(); #else @@ -713,21 +813,39 @@ got_table: warn_cylinders(); warn_geometry(); - for (i = 0; i < 4; i++) - if(IS_EXTENDED (part_table[i]->sys_ind)) { + for (i = 0; i < 4; i++) { + struct pte *pe = &ptes[i]; + + pe->part_table = pt_offset(MBRbuffer, i); + pe->ext_pointer = NULL; + pe->changed = 0; + pe->offset = 0; + pe->sectorbuffer = MBRbuffer; + } + + for (i = 0; i < 4; i++) { + struct pte *pe = &ptes[i]; + + if (IS_EXTENDED (pe->part_table->sys_ind)) { if (partitions != 4) fprintf(stderr, _("Ignoring extra extended " "partition %d\n"), i + 1); - else read_extended(part_table[ext_index = i]); + else + read_extended(i); } - for (i = 3; i < partitions; i++) - if (!valid_part_table_flag(buffers[i])) { + } + + for (i = 3; i < partitions; i++) { + struct pte *pe = &ptes[i]; + + if (!valid_part_table_flag(pe->sectorbuffer)) { fprintf(stderr, _("Warning: invalid flag 0x%04x of partition " "table %d will be corrected by w(rite)\n"), - part_table_flag(buffers[i]), i + 1); - changed[i] = 1; + part_table_flag(pe->sectorbuffer), i + 1); + pe->changed = 1; } + } return 0; } @@ -874,7 +992,7 @@ read_int(uint low, uint dflt, uint high, uint base, char *mesg) } } if (use_default) - printf(_("Using default value %d\n"), i = dflt); + printf(_("Using default value %d\n"), i = dflt); if (i >= low && i <= high) break; else @@ -883,12 +1001,16 @@ read_int(uint low, uint dflt, uint high, uint base, char *mesg) return i; } -int get_partition(int warn, int max) -{ - int i = read_int(1, 0, max, 0, _("Partition number")) - 1; +int +get_partition(int warn, int max) { + struct pte *pe; + int i; + + i = read_int(1, 0, max, 0, _("Partition number")) - 1; + pe = &ptes[i]; if (warn && ( - (!sun_label && !sgi_label && !part_table[i]->sys_ind) + (!sun_label && !sgi_label && !pe->part_table->sys_ind) || (sun_label && (!sunlabel->partitions[i].num_sectors || !sunlabel->infos[i].id)) @@ -897,8 +1019,8 @@ int get_partition(int warn, int max) return i; } -char *const str_units(int n) /* n==1: use singular */ -{ +char * const +str_units(int n) { /* n==1: use singular */ if (n == 1) return display_in_cyl_units ? _("cylinder") : _("sector"); else @@ -913,22 +1035,21 @@ void change_units(void) str_units(PLURAL)); } -void toggle_active(int i) -{ - struct partition *p = part_table[i]; +static void +toggle_active(int i) { + struct pte *pe = &ptes[i]; + struct partition *p = pe->part_table; if (IS_EXTENDED (p->sys_ind) && !p->boot_ind) fprintf(stderr, _("WARNING: Partition %d is an extended partition\n"), i + 1); - if (p->boot_ind) - p->boot_ind = 0; - else p->boot_ind = ACTIVE_FLAG; - changed[i] = 1; + p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG); + pe->changed = 1; } -void toggle_dos(void) -{ +static void +toggle_dos_compatibility_flag(void) { dos_compatible_flag = ~dos_compatible_flag; if (dos_compatible_flag) { sector_offset = sectors; @@ -940,9 +1061,11 @@ void toggle_dos(void) } } -void delete_partition(int i) -{ - struct partition *p = part_table[i], *q = ext_pointers[i]; +static void +delete_partition(int i) { + struct pte *pe = &ptes[i]; + struct partition *p = pe->part_table; + struct partition *q = pe->ext_pointer; /* Note that for the fifth partition (i == 4) we don't actually * decrement partitions. @@ -950,7 +1073,7 @@ void delete_partition(int i) if (warn_geometry()) return; - changed[i] = 1; + pe->changed = 1; if (sun_label) { sun_delete_partition(i); @@ -962,21 +1085,21 @@ void delete_partition(int i) } if (i < 4) { if (IS_EXTENDED (p->sys_ind) && i == ext_index) { - while (partitions > 4) - free(buffers[--partitions]); - ext_pointers[ext_index] = NULL; + partitions = 4; + ptes[ext_index].ext_pointer = NULL; extended_offset = 0; } clear_partition(p); } else if (!q->sys_ind && i > 4) { - free(buffers[--partitions]); - clear_partition(ext_pointers[--i]); - changed[i] = 1; + --partitions; + --i; + clear_partition(ptes[i].ext_pointer); + ptes[i].changed = 1; } else if (i > 3) { if (i > 4) { - p = ext_pointers[i - 1]; + p = ptes[i-1].ext_pointer; p->boot_ind = 0; p->head = q->head; p->sector = q->sector; @@ -987,37 +1110,33 @@ void delete_partition(int i) p->end_cyl = q->end_cyl; set_start_sect(p, get_start_sect(q)); set_nr_sects(p, get_nr_sects(q)); - changed[i - 1] = 1; + ptes[i-1].changed = 1; } else { - if(part_table[5]) /* prevent SEGFAULT */ - set_start_sect(part_table[5], - get_start_sect(part_table[5]) + - offsets[5] - extended_offset); - offsets[5] = extended_offset; - changed[5] = 1; + struct pte *pe = &ptes[5]; + + if(pe->part_table) /* prevent SEGFAULT */ + set_start_sect(pe->part_table, + get_partition_start(pe) - + extended_offset); + pe->offset = extended_offset; + pe->changed = 1; } if (partitions > 5) { partitions--; - free(buffers[i]); while (i < partitions) { - changed[i] = changed[i + 1]; - buffers[i] = buffers[i + 1]; - offsets[i] = offsets[i + 1]; - part_table[i] = part_table[i + 1]; - ext_pointers[i] = ext_pointers[i + 1]; + ptes[i] = ptes[i+1]; i++; } - } - else - clear_partition(part_table[i]); + } else + clear_partition(ptes[i].part_table); } } -void change_sysid(void) -{ +static void +change_sysid(void) { char *temp; int i = get_partition(0, partitions), sys, origsys; - struct partition *p = part_table[i]; + struct partition *p = ptes[i].part_table; origsys = sys = get_sysid(i); @@ -1064,12 +1183,12 @@ void change_sysid(void) if (sgi_label) { sgi_change_sysid(i, sys); } else - part_table[i]->sys_ind = sys; + p->sys_ind = sys; printf (_("Changed system type of partition %d " "to %x (%s)\n"), i + 1, sys, (temp = partition_type(sys)) ? temp : _("Unknown")); - changed[i] = 1; + ptes[i].changed = 1; break; } } @@ -1080,8 +1199,7 @@ void change_sysid(void) * Jan. 1990 (version 1.2.1 by Gordon W. Ross Aug. 1990; Modified by S. * Lubkin Oct. 1991). */ -static void long2chs(ulong ls, uint *c, uint *h, uint *s) -{ +static void long2chs(ulong ls, uint *c, uint *h, uint *s) { int spc = heads * sectors; *c = ls / spc; @@ -1090,8 +1208,7 @@ static void long2chs(ulong ls, uint *c, uint *h, uint *s) *s = ls % sectors + 1; /* sectors count from 1 */ } -static void check_consistency(struct partition *p, int partition) -{ +static void check_consistency(struct partition *p, int partition) { uint pbc, pbh, pbs; /* physical beginning c, h, s */ uint pec, peh, pes; /* physical ending c, h, s */ uint lbc, lbh, lbs; /* logical beginning c, h, s */ @@ -1152,18 +1269,91 @@ static void check_consistency(struct partition *p, int partition) } } -void list_disk_geometry(void) -{ +static void +list_disk_geometry(void) { printf(_("\nDisk %s: %d heads, %d sectors, %d cylinders\nUnits = " "%s of %d * %d bytes\n\n"), disk_device, heads, sectors, cylinders, str_units(PLURAL), units_per_sector, sector_size); } -void list_table(int xtra) -{ +/* + * Check whether partition entries are ordered by their starting positions. + * Return 0 if OK. Return i if partition i should have been earlier. + * Two separate checks: primary and logical partitions. + */ +static int +wrong_p_order(int *prev) { + struct pte *pe; + struct partition *p; + uint last_p_start_pos = 0, p_start_pos; + int i, last_i = 0; + + for (i = 0 ; i < partitions; i++) { + if (i == 4) { + last_i = 4; + last_p_start_pos = 0; + } + pe = &ptes[i]; + if ((p = pe->part_table)->sys_ind) { + p_start_pos = get_partition_start(pe); + + if (last_p_start_pos > p_start_pos) { + if (prev) + *prev = last_i; + return i; + } + + last_p_start_pos = p_start_pos; + last_i = i; + } + } + return 0; +} + +static void +fix_partition_table_order(void) { + struct pte *pei, *pek, ptebuf; + int i,k; + + if(!wrong_p_order(NULL)) { + printf(_("Nothing to do. Ordering is correct already.\n\n")); + return; + } + + while ((i = wrong_p_order(&k)) != 0) { + /* partition i should have come earlier, move it */ + pei = &ptes[i]; + pek = &ptes[k]; + + if (i < 4) { + /* We have to move data in the MBR */ + struct partition *pi, *pk, *pe, pbuf; + + pe = pei->ext_pointer; + pei->ext_pointer = pek->ext_pointer; + pek->ext_pointer = pe; + + pi = pei->part_table; + pk = pek->part_table; + + memmove(&pbuf, pi, sizeof(struct partition)); + memmove(pi, pk, sizeof(struct partition)); + memmove(pk, &pbuf, sizeof(struct partition)); + } else { + /* Only change is change in numbering */ + ptebuf = *pei; + *pei = *pek; + *pek = ptebuf; + } + pei->changed = pek->changed = 1; + + } +} + +static void +list_table(int xtra) { struct partition *p; char *type; - int digit_last = 0; int i, w; if (sun_label) { @@ -1176,26 +1366,30 @@ void list_table(int xtra) return; } - w = strlen(disk_device); + list_disk_geometry(); + + if (osf_label) { + xbsd_print_disklabel(xtra); + return; + } + /* Heuristic: we list partition 3 of /dev/foo as /dev/foo3, but if the device name ends in a digit, say /dev/foo1, then the partition is called /dev/foo1p3. */ - if (isdigit(disk_device[w-1])) - digit_last = 1; - - list_disk_geometry(); - + w = strlen(disk_device); + if (w && isdigit(disk_device[w-1])) + w++; if (w < 5) w = 5; - /* FIXME! let's see how this shows up with other languagues - acme@conectiva.com.br */ - printf(_("%*s Boot Start End Blocks Id System\n"), - (digit_last ? w + 2 : w + 1), _("Device")); + w+1, _("Device")); for (i = 0 ; i < partitions; i++) { - if ((p = part_table[i])->sys_ind) { + struct pte *pe = &ptes[i]; + + p = pe->part_table; + if (p->sys_ind) { unsigned int psects = get_nr_sects(p); unsigned int pblocks = psects; unsigned int podd = 0; @@ -1207,12 +1401,12 @@ void list_table(int xtra) if (sector_size > 1024) pblocks *= (sector_size / 1024); printf( - "%*s%s%-2d %c %9ld %9ld %9ld%c %2x %s\n", -/* device */ w, disk_device, (digit_last ? "p" : ""), i+1, + "%s %c %9ld %9ld %9ld%c %2x %s\n", + partname(disk_device, i+1, w+2), /* boot flag */ !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG ? '*' : '?', -/* start */ (long) cround(get_start_sect(p) + offsets[i]), -/* end */ (long) cround(get_start_sect(p) + offsets[i] + psects +/* start */ (long) cround(get_partition_start(pe)), +/* end */ (long) cround(get_partition_start(pe) + psects - (psects ? 1 : 0)), /* odd flag on end */ (long) pblocks, podd ? '+' : ' ', /* type id */ p->sys_ind, @@ -1221,22 +1415,28 @@ void list_table(int xtra) check_consistency(p, i); } } + + /* Is partition table in disk order? It need not be, but... */ + /* partition table entries are not checked for correct order if this + is a sgi, sun or aix labeled disk... */ + if (dos_label && wrong_p_order(NULL)) { + printf(_("\nPartition table entries are not in disk order\n")); + } } -void x_list_table(int extend) -{ - struct partition *p, **q; +static void +x_list_table(int extend) { + struct pte *pe; + struct partition *p; int i; - if (extend) - q = ext_pointers; - else - q = part_table; printf(_("\nDisk %s: %d heads, %d sectors, %d cylinders\n\n"), disk_device, heads, sectors, cylinders); printf(_("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n")); - for (i = 0 ; i < partitions; i++) - if ((p = q[i]) != NULL) { + for (i = 0 ; i < partitions; i++) { + pe = &ptes[i]; + p = (extend ? pe->ext_pointer : pe->part_table); + if (p != NULL) { printf("%2d %02x%4d%4d%5d%4d%4d%5d%9d%9d %02x\n", i + 1, p->boot_ind, p->head, sector(p->sector), @@ -1247,26 +1447,29 @@ void x_list_table(int extend) if (p->sys_ind) check_consistency(p, i); } + } } -void fill_bounds(uint *first, uint *last) -{ +static void +fill_bounds(uint *first, uint *last) { int i; - struct partition *p = part_table[0]; + struct pte *pe = &ptes[0]; + struct partition *p; - for (i = 0; i < partitions; p = part_table[++i]) { + for (i = 0; i < partitions; pe++,i++) { + p = pe->part_table; if (!p->sys_ind || IS_EXTENDED (p->sys_ind)) { first[i] = 0xffffffff; last[i] = 0; } else { - first[i] = get_start_sect(p) + offsets[i]; + first[i] = get_partition_start(pe); last[i] = first[i] + get_nr_sects(p) - 1; } } } -void check(int n, uint h, uint s, uint c, uint start) -{ +static void +check(int n, uint h, uint s, uint c, uint start) { uint total, real_s, real_c; real_s = sector(s) - 1; @@ -1290,9 +1493,8 @@ void check(int n, uint h, uint s, uint c, uint start) "total %d\n"), n, start, total); } - -void verify(void) -{ +static void +verify(void) { int i, j; uint total = 1; uint first[partitions], last[partitions]; @@ -1312,10 +1514,13 @@ void verify(void) } fill_bounds(first, last); - for (i = 0; i < partitions; p = part_table[++i]) + for (i = 0; i < partitions; i++) { + struct pte *pe = &ptes[i]; + + p = pe->part_table; if (p->sys_ind && !IS_EXTENDED (p->sys_ind)) { check_consistency(p, i); - if (get_start_sect(p) + offsets[i] < first[i]) + if (get_partition_start(pe) < first[i]) printf(_("Warning: bad start-of-data in " "partition %d\n"), i + 1); check(i + 1, p->end_head, p->end_sector, p->end_cyl, @@ -1332,14 +1537,16 @@ void verify(void) last[i] : last[j]; } } + } if (extended_offset) { - uint e_last = get_start_sect(part_table[ext_index]) + - get_nr_sects(part_table[ext_index]) - 1; + struct pte *pex = &ptes[ext_index]; + uint e_last = get_start_sect(pex->part_table) + + get_nr_sects(pex->part_table) - 1; - for (p = part_table[i = 4]; i < partitions; - p = part_table[++i]) { + for (i = 4; i < partitions; i++) { total++; + p = ptes[i].part_table; if (!p->sys_ind) { if (i != 4 || i + 1 < partitions) printf(_("Warning: partition %d " @@ -1359,15 +1566,16 @@ void verify(void) printf(_("%d unallocated sectors\n"), total); } -void add_partition(int n, int sys) -{ +static void +add_partition(int n, int sys) { char mesg[256]; /* 48 does not suffice in Japanese */ int i, read = 0; - struct partition *p = part_table[n], *q = part_table[ext_index]; + struct partition *p = ptes[n].part_table; + struct partition *q = ptes[ext_index].part_table; uint start, stop = 0, limit, temp, first[partitions], last[partitions]; - if (p->sys_ind) { + if (p && p->sys_ind) { printf(_("Partition %d is already defined. Delete " "it before re-adding it.\n"), n + 1); return; @@ -1395,7 +1603,7 @@ void add_partition(int n, int sys) for (i = 0; i < partitions; i++) { int lastplusoff; - if (start == offsets[i]) + if (start == ptes[i].offset) start += sector_offset; lastplusoff = last[i] + ((n<4) ? 0 : sector_offset); if (start >= first[i] && start <= lastplusoff) @@ -1421,26 +1629,28 @@ void add_partition(int n, int sys) } } while (start != temp || !read); if (n > 4) { /* NOT for fifth partition */ - offsets[n] = start - sector_offset; - if (offsets[n] == extended_offset) { /* must be corrected */ - offsets[n]++; + struct pte *pe = &ptes[n]; + + pe->offset = start - sector_offset; + if (pe->offset == extended_offset) { /* must be corrected */ + pe->offset++; if (sector_offset == 1) start++; } } for (i = 0; i < partitions; i++) { - if (start < offsets[i] && limit >= offsets[i]) - limit = offsets[i] - 1; + struct pte *pe = &ptes[i]; + + if (start < pe->offset && limit >= pe->offset) + limit = pe->offset - 1; if (start < first[i] && limit >= first[i]) limit = first[i] - 1; } if (start > limit) { printf(_("No free sectors available\n")); - if (n > 4) { - free(buffers[n]); + if (n > 4) partitions--; - } return; } if (cround(start) == cround(limit)) { @@ -1457,22 +1667,25 @@ void add_partition(int n, int sys) } } - set_partition(n, p, start, stop, sys, offsets[n]); + set_partition(n, p, start, stop, sys, ptes[n].offset); if (IS_EXTENDED (sys)) { + struct pte *pe4 = &ptes[4]; + struct pte *pen = &ptes[n]; + ext_index = n; - offsets[4] = extended_offset = start; - ext_pointers[n] = p; - if (!(buffers[4] = calloc(1, sector_size))) + pen->ext_pointer = p; + pe4->offset = extended_offset = start; + if (!(pe4->sectorbuffer = calloc(1, sector_size))) fatal(out_of_memory); - part_table[4] = offset(buffers[4], 0); - ext_pointers[4] = part_table[4] + 1; - changed[4] = 1; + pe4->part_table = pt_offset(pe4->sectorbuffer, 0); + pe4->ext_pointer = pe4->part_table + 1; + pe4->changed = 1; partitions = 5; } else { if (n > 4) - set_partition(n - 1, ext_pointers[n - 1], - offsets[n], stop, EXTENDED, + set_partition(n - 1, ptes[n-1].ext_pointer, + ptes[n].offset, stop, EXTENDED, extended_offset); #if 0 if ((limit = get_nr_sects(p)) & 1) @@ -1482,21 +1695,24 @@ void add_partition(int n, int sys) } } -void add_logical(void) -{ - if (partitions > 5 || part_table[4]->sys_ind) { - if (!(buffers[partitions] = calloc(1, sector_size))) +static void +add_logical(void) { + if (partitions > 5 || ptes[4].part_table->sys_ind) { + struct pte *pe = &ptes[partitions]; + + if (!(pe->sectorbuffer = calloc(1, sector_size))) fatal(out_of_memory); - part_table[partitions] = offset(buffers[partitions], 0); - ext_pointers[partitions] = part_table[partitions] + 1; - offsets[partitions] = 0; + pe->part_table = pt_offset(pe->sectorbuffer, 0); + pe->ext_pointer = pe->part_table + 1; + pe->offset = 0; + pe->changed = 1; partitions++; } add_partition(partitions - 1, LINUX_NATIVE); } -void new_partition(void) -{ +static void +new_partition(void) { int i, free_primary = 0; if (warn_geometry()) @@ -1518,7 +1734,7 @@ void new_partition(void) } for (i = 0; i < 4; i++) - free_primary += !part_table[i]->sys_ind; + free_primary += !ptes[i].part_table->sys_ind; if (!free_primary) { if (extended_offset) add_logical(); @@ -1552,30 +1768,33 @@ void new_partition(void) } } -void write_table(void) -{ +static void +write_table(void) { int i; - changed[3] = changed[0] || changed[1] || changed[2] || changed[3]; - if (!sun_label && !sgi_label) { - for (i = 3; i < partitions; i++) { - if (changed[i]) { - write_part_table_flag(buffers[i]); - if (ext2_llseek(fd, (ext2_loff_t)offsets[i] - * sector_size, SEEK_SET) < 0) - fatal(unable_to_seek); - if (write(fd, buffers[i], sector_size) != sector_size) - fatal(unable_to_write); + if (dos_label) { + for (i=0; i<3; i++) + if(ptes[i].changed) + ptes[3].changed = 1; + for (i = 3; i < partitions; i++) { + struct pte *pe = &ptes[i]; + + if (pe->changed) { + write_part_table_flag(pe->sectorbuffer); + write_sector(fd, pe->offset, pe->sectorbuffer); + } } - } } else if (sgi_label) { - /* no test on change? the printf below might be mistaken */ - sgi_write_table(); + /* no test on change? the printf below might be mistaken */ + sgi_write_table(); } else if (sun_label) { - if (changed[3] || changed[4] || changed[5] || - changed[6] || changed[7]) { - sun_write_table(); - } + int needw = 0; + + for (i=0; i<8; i++) + if(ptes[i].changed) + needw = 1; + if (needw) + sun_write_table(); } printf(_("The partition table has been altered!\n\n")); @@ -1624,15 +1843,15 @@ reread_partition_table(int leave) { } #define MAX_PER_LINE 16 -void print_buffer(char buffer[]) -{ +static void +print_buffer(char pbuffer[]) { int i, l; for (i = 0, l = 0; i < sector_size; i++, l++) { if (l == 0) printf("0x%03X:", i); - printf(" %02X", (unsigned char) buffer[i]); + printf(" %02X", (unsigned char) pbuffer[i]); if (l == MAX_PER_LINE - 1) { printf("\n"); l = -1; @@ -1643,20 +1862,21 @@ void print_buffer(char buffer[]) printf("\n"); } -void print_raw(void) -{ +static void +print_raw(void) { int i; printf(_("Device: %s\n"), disk_device); if (sun_label || sgi_label) - print_buffer(buffer); + print_buffer(MBRbuffer); else for (i = 3; i < partitions; i++) - print_buffer(buffers[i]); + print_buffer(ptes[i].sectorbuffer); } -void move_begin(int i) -{ - struct partition *p = part_table[i]; +static void +move_begin(int i) { + struct pte *pe = &ptes[i]; + struct partition *p = pe->part_table; uint new, first; if (warn_geometry()) @@ -1665,38 +1885,42 @@ void move_begin(int i) printf(_("Partition %d has no data area\n"), i + 1); return; } - first = get_start_sect(p) + offsets[i]; - new = read_int(first, first, - get_start_sect(p) + get_nr_sects(p) + offsets[i] - 1, - first, _("New beginning of data")) - offsets[i]; + first = get_partition_start(pe); + new = read_int(first, first, first + get_nr_sects(p) - 1, first, + _("New beginning of data")) - pe->offset; if (new != get_nr_sects(p)) { first = get_nr_sects(p) + get_start_sect(p) - new; set_nr_sects(p, first); set_start_sect(p, new); - changed[i] = 1; + pe->changed = 1; } } -void xselect(void) -{ +static void +xselect(void) { + char c; + while(1) { putchar('\n'); - switch (tolower(read_char(_("Expert command (m for help): ")))) { + c = tolower(read_char(_("Expert command (m for help): "))); + switch (c) { case 'a': if (sun_label) sun_set_alt_cyl(); break; case 'b': - if (!sun_label && !sgi_label) + if (dos_label) move_begin(get_partition(0, partitions)); break; case 'c': - cylinders = read_int(1, cylinders, 131071, - 0, _("Number of cylinders")); + user_cylinders = cylinders = + read_int(1, cylinders, 131071, 0, + _("Number of cylinders")); if (sun_label) sun_set_ncyl(cylinders); - warn_cylinders(); + if (dos_label) + warn_cylinders(); break; case 'd': print_raw(); @@ -1706,14 +1930,18 @@ void xselect(void) sgi_set_xcyl(); else if (sun_label) sun_set_xcyl(); - else + else if (dos_label) x_list_table(1); break; + case 'f': + if(dos_label) + fix_partition_table_order(); + break; case 'g': create_sgilabel(); break; case 'h': - heads = read_int(1, heads, 256, 0, + user_heads = heads = read_int(1, heads, 256, 0, _("Number of heads")); update_units(); break; @@ -1738,7 +1966,7 @@ void xselect(void) case 'r': return; case 's': - sectors = read_int(1, sectors, 63, 0, + user_sectors = sectors = read_int(1, sectors, 63, 0, _("Number of sectors")); if (dos_compatible_flag) { sector_offset = sectors; @@ -1764,7 +1992,7 @@ void xselect(void) } } -int +static int is_ide_cdrom(char *device) { /* No device was given explicitly, and we are trying some likely things. But opening /dev/hdc may produce errors like @@ -1792,8 +2020,8 @@ is_ide_cdrom(char *device) { return 0; } -void try(char *device, int user_specified) -{ +static void +try(char *device, int user_specified) { disk_device = device; if (!setjmp(listingbuf)) { if (!user_specified) @@ -1827,8 +2055,8 @@ void try(char *device, int user_specified) /* for fdisk -l: try all things in /proc/partitions that look like a partition name (do not end in a digit) */ -void -tryprocpt() { +static void +tryprocpt(void) { FILE *procpt; char line[100], ptname[100], devname[120], *s; int ma, mi, sz; @@ -1851,16 +2079,14 @@ tryprocpt() { } } -int -dir_exists(char *dirname) { - struct stat statbuf; +static void +dummy(int *kk) {} - return (stat(dirname, &statbuf) == 0 && S_ISDIR(statbuf.st_mode)); +static void +unknown_command(int c) { + printf(_("%c: unknown command\n"), c); } -void -dummy(int *kk) {} - int main(int argc, char **argv) { int j, c; @@ -1878,7 +2104,7 @@ main(int argc, char **argv) { * fdisk -s [partition] ... * fdisk [-b sectorsize] [-u] device */ - while ((c = getopt(argc, argv, "b:lsuv")) != EOF) { + while ((c = getopt(argc, argv, "b:lsuvV")) != EOF) { switch (c) { case 'b': /* ugly: this sector size is really per device, @@ -1899,6 +2125,7 @@ main(int argc, char **argv) { case 'u': display_in_cyl_units = 0; break; + case 'V': case 'v': printf("fdisk v" UTIL_LINUX_VERSION "\n"); exit(0); @@ -1968,19 +2195,34 @@ main(int argc, char **argv) { get_boot(fdisk); +#ifdef __alpha__ + /* On alpha, if we detect a disklabel, go directly to + disklabel mode (typically you'll be switching from DOS + partition tables to disklabels, not the other way around) + - dhuggins@linuxcare.com */ + if (osf_label) { + printf(_("Detected an OSF/1 disklabel on %s, entering disklabel mode.\n" + "To return to DOS partition table mode, use the 'r' command.\n"), + disk_device); + bselect(); + } +#endif + while (1) { putchar('\n'); - switch (tolower(read_char(_("Command (m for help): ")))) { + c = tolower(read_char(_("Command (m for help): "))); + switch (c) { case 'a': - if (sun_label) + if (dos_label) + toggle_active(get_partition(1, partitions)); + else if (sun_label) toggle_sunflags(get_partition(1, partitions), 0x01); + else if (sgi_label) + sgi_set_bootpartition( + get_partition(1, partitions)); else - if (sgi_label) - sgi_set_bootpartition( - get_partition(1, partitions)); - else - toggle_active(get_partition(1, partitions)); + unknown_command(c); break; case 'b': if (sgi_label) { @@ -1995,15 +2237,16 @@ main(int argc, char **argv) { bselect(); break; case 'c': - if (sun_label) + if (dos_label) + toggle_dos_compatibility_flag(); + else if (sun_label) toggle_sunflags(get_partition(1, partitions), 0x10); - else - if (sgi_label) - sgi_set_swappartition( + else if (sgi_label) + sgi_set_swappartition( get_partition(1, partitions)); - else - toggle_dos(); + else + unknown_command(c); break; case 'd': delete_partition( @@ -2013,10 +2256,13 @@ main(int argc, char **argv) { if (sgi_label) create_sgiinfo(); else - menu(); + unknown_command(c); case 'l': list_types(get_sys_types()); break; + case 'm': + menu(); + break; case 'n': new_partition(); break; @@ -2046,14 +2292,16 @@ main(int argc, char **argv) { write_table(); /* does not return */ break; case 'x': - if( sgi_label ) { + if(sgi_label) { fprintf(stderr, _("\n\tSorry, no experts menu for SGI " "partition tables available.\n\n")); } else xselect(); break; - default: menu(); + default: + unknown_command(c); + menu(); } } return 0; |