From 364cda4857f7dd5e2b4e2eb7583a2eaa279ef4ed Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Thu, 7 Dec 2006 00:25:48 +0100 Subject: Imported from util-linux-2.11f tarball. --- fdisk/cfdisk.c | 19 ++++++- fdisk/fdisk.c | 145 ++++++++++++++++++++++++++++++++++--------------- fdisk/fdiskbsdlabel.c | 13 +++-- fdisk/fdiskbsdlabel.h | 4 +- fdisk/fdisksgilabel.c | 33 +++++------ fdisk/fdisksunlabel.c | 19 +++++++ fdisk/i386_sys_types.c | 4 +- fdisk/sfdisk.c | 75 +++++++++++++++++-------- 8 files changed, 215 insertions(+), 97 deletions(-) (limited to 'fdisk') diff --git a/fdisk/cfdisk.c b/fdisk/cfdisk.c index 8b5643e62..d9ef3f630 100644 --- a/fdisk/cfdisk.c +++ b/fdisk/cfdisk.c @@ -1431,8 +1431,23 @@ get_partition_table_geometry(partition_table *bufp) { int bad = FALSE; if (bufp->p.magicflag[0] != PART_TABLE_FLAG0 || - bufp->p.magicflag[1] != PART_TABLE_FLAG1) - fatal(_("Bad signature on partition table"), 3); + bufp->p.magicflag[1] != PART_TABLE_FLAG1) { + /* Matthew Wilcox: slightly friendlier version of + fatal(_("Bad signature on partition table"), 3); + */ + int cont; + mvaddstr(WARNING_START, 0, + _("No partition table or unknown signature on partition table")); + mvaddstr(WARNING_START+1, 0, + _("Do you wish to start with a zero table [y/N] ?")); + putchar(BELL); + refresh(); + cont = getch(); + if ((cont != 'y') && (cont != 'Y')) + die_x(3); + zero_table = TRUE; + return; + } hh = ss = 0; for (i=0; i<4; i++) { diff --git a/fdisk/fdisk.c b/fdisk/fdisk.c index a439f3273..0c57ed22e 100644 --- a/fdisk/fdisk.c +++ b/fdisk/fdisk.c @@ -517,8 +517,17 @@ clear_partition(struct partition *p) { } static void -set_partition(int i, struct partition *p, uint start, uint stop, - int sysid, uint offset) { +set_partition(int i, int doext, uint start, uint stop, int sysid) { + struct partition *p; + uint offset; + + if (doext) { + p = ptes[i].ext_pointer; + offset = extended_offset; + } else { + p = ptes[i].part_table; + offset = ptes[i].offset; + } p->boot_ind = 0; p->sys_ind = sysid; set_start_sect(p, start - offset); @@ -1157,14 +1166,7 @@ delete_partition(int i) { if (i > 4) { /* delete this link in the chain */ p = ptes[i-1].ext_pointer; - p->boot_ind = 0; - p->head = q->head; - p->sector = q->sector; - p->cyl = q->cyl; - p->sys_ind = EXTENDED; - p->end_head = q->end_head; - p->end_sector = q->end_sector; - p->end_cyl = q->end_cyl; + *p = *q; set_start_sect(p, get_start_sect(q)); set_nr_sects(p, get_nr_sects(q)); ptes[i-1].changed = 1; @@ -1370,9 +1372,72 @@ wrong_p_order(int *prev) { return 0; } +/* + * Fix the chain of logicals. + * extended_offset is unchanged, the set of sectors used is unchanged + * The chain is sorted so that sectors increase, and so that + * starting sectors increase. + * + * After this it may still be that cfdisk doesnt like the table. + * (This is because cfdisk considers expanded parts, from link to + * end of partition, and these may still overlap.) + * Now + * sfdisk /dev/hda > ohda; sfdisk /dev/hda < ohda + * may help. + */ +static void +fix_chain_of_logicals(void) { + int j, oj, ojj, sj, sjj; + struct partition *pj,*pjj,tmp; + + /* Stage 1: sort sectors but leave sector of part 4 */ + /* (Its sector is the global extended_offset.) */ + stage1: + for(j = 5; j < partitions-1; j++) { + oj = ptes[j].offset; + ojj = ptes[j+1].offset; + if (oj > ojj) { + ptes[j].offset = ojj; + ptes[j+1].offset = oj; + pj = ptes[j].part_table; + set_start_sect(pj, get_start_sect(pj)+oj-ojj); + pjj = ptes[j+1].part_table; + set_start_sect(pjj, get_start_sect(pjj)+ojj-oj); + set_start_sect(ptes[j-1].ext_pointer, + ojj-extended_offset); + set_start_sect(ptes[j].ext_pointer, + oj-extended_offset); + goto stage1; + } + } + + /* Stage 2: sort starting sectors */ + stage2: + for(j = 4; j < partitions-1; j++) { + pj = ptes[j].part_table; + pjj = ptes[j+1].part_table; + sj = get_start_sect(pj); + sjj = get_start_sect(pjj); + oj = ptes[j].offset; + ojj = ptes[j+1].offset; + if (oj+sj > ojj+sjj) { + tmp = *pj; + *pj = *pjj; + *pjj = tmp; + set_start_sect(pj, ojj+sjj-oj); + set_start_sect(pjj, oj+sj-ojj); + goto stage2; + } + } + + /* Probably something was changed */ + for(j = 4; j < partitions; j++) + ptes[j].changed = 1; +} + static void fix_partition_table_order(void) { - struct pte *pei, *pek, ptebuf; + struct pte *pei, *pek; int i,k; if(!wrong_p_order(NULL)) { @@ -1380,34 +1445,32 @@ fix_partition_table_order(void) { return; } - while ((i = wrong_p_order(&k)) != 0) { + while ((i = wrong_p_order(&k)) != 0 && i < 4) { /* partition i should have come earlier, move it */ + /* We have to move data in the MBR */ + struct partition *pi, *pk, *pe, pbuf; 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; - pe = pei->ext_pointer; - pei->ext_pointer = pek->ext_pointer; - pek->ext_pointer = pe; + pi = pei->part_table; + pk = pek->part_table; - 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)); - 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; - } + + if (i) + fix_chain_of_logicals(); + + printf("Done.\n"); + } static void @@ -1637,7 +1700,7 @@ add_partition(int n, int sys) { if (p && p->sys_ind) { printf(_("Partition %d is already defined. Delete " - "it before re-adding it.\n"), n + 1); + "it before re-adding it.\n"), n + 1); return; } fill_bounds(first, last); @@ -1693,9 +1756,9 @@ add_partition(int n, int sys) { pe->offset = start - sector_offset; if (pe->offset == extended_offset) { /* must be corrected */ - pe->offset++; - if (sector_offset == 1) - start++; + pe->offset++; + if (sector_offset == 1) + start++; } } @@ -1728,7 +1791,9 @@ add_partition(int n, int sys) { } } - set_partition(n, p, start, stop, sys, ptes[n].offset); + set_partition(n, 0, start, stop, sys); + if (n > 4) + set_partition(n - 1, 1, ptes[n].offset, stop, EXTENDED); if (IS_EXTENDED (sys)) { struct pte *pe4 = &ptes[4]; @@ -1743,16 +1808,6 @@ add_partition(int n, int sys) { pe4->ext_pointer = pe4->part_table + 1; pe4->changed = 1; partitions = 5; - } else { - if (n > 4) - 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) - printf(_("Warning: partition %d has an odd " - "number of sectors.\n"), n + 1); -#endif } } diff --git a/fdisk/fdiskbsdlabel.c b/fdisk/fdiskbsdlabel.c index 80efc36e6..0522d3651 100644 --- a/fdisk/fdiskbsdlabel.c +++ b/fdisk/fdiskbsdlabel.c @@ -104,6 +104,7 @@ static struct xbsd_disklabel xbsd_dlabel; int check_osf_label(void) { + osf_label = 0; if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0) return 0; osf_label = 1; @@ -265,10 +266,10 @@ xbsd_new_part (void) if (!xbsd_check_new_partition (&i)) return; -#if !defined (__alpha__) && !defined (__powerpc__) +#if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__) begin = get_start_sect(xbsd_part); end = begin + get_nr_sects(xbsd_part) - 1; -#elif defined (__alpha__) || defined (__powerpc__) +#else begin = 0; end = xbsd_dlabel.d_secperunit - 1; #endif @@ -419,7 +420,7 @@ xbsd_create_disklabel (void) { c = read_char (_("Do you want to create a disklabel? (y/n) ")); if (tolower(c) == 'y') { if (xbsd_initlabel ( -#if defined (__alpha__) || defined (__powerpc__) +#if defined (__alpha__) || defined (__powerpc__) || defined (__hppa__) NULL, &xbsd_dlabel, 0 #else xbsd_part, &xbsd_dlabel, xbsd_part_index @@ -548,7 +549,7 @@ xbsd_write_bootstrap (void) bcopy (&dl, d, sizeof (struct xbsd_disklabel)); -#if defined (__powerpc__) +#if defined (__powerpc__) || defined (__hppa__) sector = 0; #elif defined (__alpha__) sector = 0; @@ -748,9 +749,9 @@ xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d) { int sector; -#if !defined (__alpha__) && !defined (__powerpc__) +#if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__) sector = get_start_sect(p) + BSD_LABELSECTOR; -#elif defined (__alpha__) || defined (__powerpc__) +#else sector = BSD_LABELSECTOR; #endif diff --git a/fdisk/fdiskbsdlabel.h b/fdisk/fdiskbsdlabel.h index e46e02614..c2e4bb989 100644 --- a/fdisk/fdiskbsdlabel.h +++ b/fdisk/fdiskbsdlabel.h @@ -43,10 +43,10 @@ #define BSD_LINUX_BOOTDIR "/usr/ucb/mdec" -#if defined (i386) || defined (__sparc__) || defined (__arm__) || defined (__mips__) +#if defined (i386) || defined (__sparc__) || defined (__arm__) || defined (__mips__) || defined (__s390__) || defined (__sh__) #define BSD_LABELSECTOR 1 #define BSD_LABELOFFSET 0 -#elif defined (__alpha__) || defined (__powerpc__) || defined (__ia64__) +#elif defined (__alpha__) || defined (__powerpc__) || defined (__ia64__) || defined (__hppa__) #define BSD_LABELSECTOR 0 #define BSD_LABELOFFSET 64 #else diff --git a/fdisk/fdisksgilabel.c b/fdisk/fdisksgilabel.c index 09296905d..88afcd86a 100644 --- a/fdisk/fdisksgilabel.c +++ b/fdisk/fdisksgilabel.c @@ -193,12 +193,12 @@ check_sgi_label() { void sgi_list_table( int xtra ) { int i, w; + int kpi = 0; /* kernel partition ID */ char *type; w = strlen( disk_device ); - if( xtra ) - { + if( xtra ) { printf(_("\nDisk %s (SGI disk label): %d heads, %d sectors\n" "%d cylinders, %d physical cylinders\n" "%d extra sects/cyl, interleave %d:1\n" @@ -210,8 +210,7 @@ sgi_list_table( int xtra ) { SSWAP16(sgiparam.ilfact), (char *)sgilabel, str_units(PLURAL), units_per_sector); - } else - { + } else { printf( _("\nDisk %s (SGI disk label): " "%d heads, %d sectors, %d cylinders\n" "Units = %s of %d * 512 bytes\n\n"), @@ -219,17 +218,17 @@ sgi_list_table( int xtra ) { str_units(PLURAL), units_per_sector ); } printf(_("----- partitions -----\n" - "%*s Info Start End Sectors Id System\n"), + "Pt# %*s Info Start End Sectors Id System\n"), w + 1, _("Device")); - for (i = 0 ; i < partitions; i++) - { - if( sgi_get_num_sectors(i) || debug ) - { + for (i = 0 ; i < partitions; i++) { + if( sgi_get_num_sectors(i) || debug ) { __u32 start = sgi_get_start_sector(i); __u32 len = sgi_get_num_sectors(i); + kpi++; /* only count nonempty partitions */ printf( - "%*s%-2d %4s %9ld %9ld %9ld %2x %s\n", -/* device */ w, disk_device, i + 1, + "%2d: %s %4s %9ld %9ld %9ld %2x %s\n", +/* fdisk part number */ i+1, +/* device */ partname(disk_device, kpi, w+2), /* flags */ (sgi_get_swappartition() == i) ? "swap" : /* flags */ (sgi_get_bootpartition() == i) ? "boot" : " ", /* start */ (long) scround(start), @@ -240,8 +239,8 @@ sgi_list_table( int xtra ) { ? type : _("Unknown")); } } - printf(_("----- bootinfo -----\nBootfile: %s\n" - "----- directory entries -----\n"), + printf(_("----- Bootinfo -----\nBootfile: %s\n" + "----- Directory Entries -----\n"), sgilabel->boot_file ); for (i = 0 ; i < volumes; i++) { @@ -735,11 +734,9 @@ create_sgilabel(void) _("Building a new SGI disklabel. Changes will remain in memory only,\n" "until you decide to write them. After that, of course, the previous\n" "content will be unrecoverably lost.\n\n")); -#if BYTE_ORDER == LITTLE_ENDIAN - other_endian = 1; -#else - other_endian = 0; -#endif + + other_endian = (BYTE_ORDER == LITTLE_ENDIAN); + #ifdef HDIO_REQ if (!ioctl(fd, HDIO_REQ, &geometry)) #else diff --git a/fdisk/fdisksunlabel.c b/fdisk/fdisksunlabel.c index 2a36852a5..ff54ed5b5 100644 --- a/fdisk/fdisksunlabel.c +++ b/fdisk/fdisksunlabel.c @@ -52,6 +52,9 @@ struct systypes sun_sys_types[] = { {LINUX_SWAP, N_("Linux swap")}, {LINUX_NATIVE, N_("Linux native")}, {0x8e, N_("Linux LVM")}, + {0xfd, N_("Linux raid autodetect")},/* New (2.2.x) raid partition + with autodetect using + persistent superblock */ { 0, NULL } }; @@ -531,6 +534,22 @@ add_sun_partition(int n, int sys) { printf ("\ It is highly recommended that the third partition covers the whole disk\n\ and is of type `Whole disk'\n"); + /* ewt asks to add: "don't start a partition at cyl 0" + However, edmundo@rano.demon.co.uk writes: + "In addition to having a Sun partition table, to be able to + boot from the disc, the first partition, /dev/sdX1, must + start at cylinder 0. This means that /dev/sdX1 contains + the partition table and the boot block, as these are the + first two sectors of the disc. Therefore you must be + careful what you use /dev/sdX1 for. In particular, you must + not use a partition starting at cylinder 0 for Linux swap, + as that would overwrite the partition table and the boot + block. You may, however, use such a partition for a UFS + or EXT2 file system, as these file systems leave the first + 1024 bytes undisturbed. */ + /* On the other hand, one should not use partitions + starting at block 0 in an md, or the label will + be trashed. */ for (i = 0; i < partitions; i++) if (lens[i] && starts[i] <= first && starts[i] + lens[i] > first) diff --git a/fdisk/i386_sys_types.c b/fdisk/i386_sys_types.c index ce01b189a..87639c6ba 100644 --- a/fdisk/i386_sys_types.c +++ b/fdisk/i386_sys_types.c @@ -24,7 +24,7 @@ struct systypes i386_sys_types[] = { {0x14, N_("Hidden FAT16 <32M")}, {0x16, N_("Hidden FAT16")}, {0x17, N_("Hidden HPFS/NTFS")}, - {0x18, N_("AST Windows swapfile")}, + {0x18, N_("AST SmartSleep")}, {0x1b, N_("Hidden Win95 FAT32")}, {0x1c, N_("Hidden Win95 FAT32 (LBA)")}, {0x1e, N_("Hidden Win95 FAT16 (LBA)")}, @@ -69,6 +69,7 @@ struct systypes i386_sys_types[] = { {0xa7, N_("NeXTSTEP")}, {0xb7, N_("BSDI fs")}, {0xb8, N_("BSDI swap")}, + {0xbb, N_("Boot Wizard hidden")}, {0xc1, N_("DRDOS/sec (FAT-12)")}, {0xc4, N_("DRDOS/sec (FAT-16 < 32M)")}, {0xc6, N_("DRDOS/sec (FAT-16)")}, @@ -77,6 +78,7 @@ struct systypes i386_sys_types[] = { {0xdb, N_("CP/M / CTOS / ...")},/* CP/M or Concurrent CP/M or Concurrent DOS or CTOS */ {0xde, N_("Dell Utility")}, /* Dell PowerEdge Server utilities */ + {0xdf, N_("BootIt")}, /* BootIt EMBRM */ {0xe1, N_("DOS access")}, /* DOS access or SpeedStor 12-bit FAT extended partition */ {0xe3, N_("DOS R/O")}, /* DOS R/O or SpeedStor */ diff --git a/fdisk/sfdisk.c b/fdisk/sfdisk.c index e60259849..db1b7f4dd 100644 --- a/fdisk/sfdisk.c +++ b/fdisk/sfdisk.c @@ -220,12 +220,12 @@ get_sector(char *dev, int fd, unsigned long sno) { static int msdos_signature (struct sector *s) { - if (*(unsigned short *) (s->data + 0x1fe) != 0xaa55) { - error(_("ERROR: sector %lu does not have an msdos signature\n"), - s->sectornumber); - return 0; - } - return 1; + unsigned char *data = s->data; + if (data[510] == 0x55 && data[511] == 0xaa) + return 1; + error(_("ERROR: sector %lu does not have an msdos signature\n"), + s->sectornumber); + return 0; } static int @@ -1146,9 +1146,10 @@ partitions_ok(struct disk_desc *z) { for (q = partitions; q < partitions+partno; q++) if (is_extended(q->p.sys_type)) if (p->start <= q->start && p->start + p->size > q->start) { - warn(_("Warning: partition %s contains part of "), PNO(p)); - warn(_("the partition table (sector %lu),\n"), q->start); - warn(_("and will destroy it when filled\n")); + warn(_("Warning: partition %s contains part of " + "the partition table (sector %lu),\n" + "and will destroy it when filled\n"), + PNO(p), q->start); return 0; } @@ -1161,7 +1162,8 @@ partitions_ok(struct disk_desc *z) { return 0; } if (p->size && p->start + p->size > ds) { - warn(_("Warning: partition %s extends past end of disk\n"), PNO(p)); + warn(_("Warning: partition %s extends past end of disk\n"), + PNO(p)); return 0; } } @@ -1175,8 +1177,8 @@ partitions_ok(struct disk_desc *z) { if (p->p.sys_type == EXTENDED_PARTITION) ect++; if (ect > 1 && !Linux) { - warn(_("Among the primary partitions, at most one can be extended\n")); - warn(_(" (although this is not a problem under Linux)\n")); + warn(_("Among the primary partitions, at most one can be extended\n" + " (although this is not a problem under Linux)\n")); return 0; } } @@ -1284,13 +1286,15 @@ extended_partition(char *dev, int fd, struct part_desc *ep, struct disk_desc *z) /* This is BAD */ if (DOS_extended) { here = start -= (start % B.cylindersize); - printf(_("Warning: shifted start of the extd partition from %ld to %ld\n"), + printf(_("Warning: shifted start of the extd partition " + "from %ld to %ld\n" + "(For listing purposes only. " + "Do not change its contents.)\n"), ep->start, start); - printf(_("(For listing purposes only. Do not change its contents.)\n")); } else { printf(_("Warning: extended partition does not start at a " - "cylinder boundary.\n")); - printf(_("DOS and Linux will interpret the contents differently.\n")); + "cylinder boundary.\n" + "DOS and Linux will interpret the contents differently.\n")); } } @@ -1542,7 +1546,8 @@ write_partitions(char *dev, int fd, struct disk_desc *z) { if (!s) return 0; s->to_be_written = 1; copy_from_part(&(p->p), s->data + p->offset); - *(unsigned short *)(&(s->data[0x1fe])) = 0xaa55; + s->data[510] = 0x55; + s->data[511] = 0xaa; } if (save_sector_file) { if (!save_sectors(dev, fd)) { @@ -1701,13 +1706,23 @@ read_stdin(unsigned char **fields, unsigned char *line, int fieldssize, int line } /* read a number, use default if absent */ +/* a sign gives an offset from the default */ static int get_ul(char *u, unsigned long *up, unsigned long def, int base) { char *nu; + int sign = 0; + unsigned long val; + if (*u == '+') { + sign = 1; + u++; + } else if (*u == '-') { + sign = -1; + u++; + } if (*u) { errno = 0; - *up = strtoul(u, &nu, base); + val = strtoul(u, &nu, base); if (errno == ERANGE) { printf(_("number too big\n")); return -1; @@ -1716,6 +1731,11 @@ get_ul(char *u, unsigned long *up, unsigned long def, int base) { printf(_("trailing junk after number\n")); return -1; } + if (sign == 1) + val = def + val; + else if (sign == -1) + val = def - val; + *up = val; } else *up = def; return 0; @@ -2277,18 +2297,27 @@ static const struct option long_opts[] = { { NULL, 0, NULL, 0 } }; -/* default devices to list */ +/* default devices to list - will be removed */ static struct devd { char *pref, *letters; } defdevs[] = { { "hd", "abcdefgh" }, { "sd", "abcde" }, { "xd", "ab" }, - { "ed", "abcd" } + { "ed", "abcd" }, + /* Compaq's SMART Array Controllers */ + { "cciss/c0d", "01234567" }, + { "cciss/c1d", "01234567" }, + /* Compaq's SMART2 Intelligent Disk Array Controllers */ + { "ida/c0d", "01234567" }, + { "ida/c1d", "01234567" }, + /* Mylex DAC960/AcceleRAID/eXtremeRAID PCI RAID Controllers */ + { "rd/c0d", "01234567" }, + { "rd/c1d", "01234567" } }; static int -is_ide_cdrom(char *device) { +is_ide_cdrom_or_tape(char *device) { /* No device was given explicitly, and we are trying some likely things. But opening /dev/hdc may produce errors like "hdc: tray open or drive not ready" @@ -2302,7 +2331,7 @@ is_ide_cdrom(char *device) { sprintf(buf, "/proc/ide/%s/media", device+5); procf = fopen(buf, "r"); if (procf != NULL && fgets(buf, sizeof(buf), procf)) - return !strncmp(buf, "cdrom", 5); + return !strncmp(buf, "cdrom", 5) || !strncmp(buf, "tape", 4); /* Now when this proc file does not exist, skip the device when it is read-only. */ @@ -2456,7 +2485,7 @@ main(int argc, char **argv) { lp = dp->letters; while(*lp) { sprintf(device, "/dev/%s%c", dp->pref, *lp++); - if (!strcmp(dp->pref, "hd") && is_ide_cdrom(device)) + if (!strcmp(dp->pref, "hd") && is_ide_cdrom_or_tape(device)) continue; if (opt_out_geom) do_geom(device, 1); -- cgit v1.2.3-55-g7522