]> err.no Git - util-linux/commitdiff
fdisk: many significant improvements and fixes to Sun label handling
authorDavid Miller <davem@davemloft.net>
Fri, 29 Jun 2007 22:50:21 +0000 (15:50 -0700)
committerKarel Zak <kzak@redhat.com>
Mon, 2 Jul 2007 12:41:36 +0000 (14:41 +0200)
1) Properly describe the exact layout and fields of the sun disk
   label.  Several fields were incorrectly mentioned and others
   wrongly sized.

2) Properly set the version, sane, and num_partitions fields.

   Because we weren't doing this, programs such as Solaris's format
   and the Solaris kernel itself refused to recognize our disk labels
   as valid.

3) Move SSWAP*() macros into fdisksunlabel.c as there is no reason
   for them to be exposed to the rest of fdisk.

4) Kill the sun_predefined_drives array hack and assosciated code.

   Instead size the disk and figure out the geometry properly just
   like the SGI and MSDOS partition handling do, by means of the
   HD_GETGEO ioctl() and disksize().

5) If the disk label read is found to not have the proper values
   set in version, sane, or num_partitions, fix them, recompute the
   label checksum, dirty the disk label, and let the user know what
   we did and that the fixed values will be written out if they 'w'.

   This gives users an easy way to fix up disk labels created by
   disk labelling programs which had this bug.

6) Create a sun_sys_getid() function so that fdisk.c does not need
   to reference the sun disk label details directly, just like the
   SGI code does.

Signed-off-by: David S. Miller <davem@davemloft.net>
fdisk/fdisk.c
fdisk/fdisksunlabel.c
fdisk/fdisksunlabel.h

index c4ab6d569cbc28800de5c0840f3991aa12d644f3..292b7a85ed81520e6eb3a1078ad21f9413707837 100644 (file)
@@ -470,7 +470,7 @@ xmenu(void) {
 static int
 get_sysid(int i) {
        return (
-               sun_label ? sunlabel->infos[i].id :
+               sun_label ? sun_get_sysid(i) :
                sgi_label ? sgi_get_sysid(i) :
                ptes[i].part_table->sys_ind);
 }
@@ -1178,7 +1178,7 @@ get_partition(int warn, int max) {
                if ((!sun_label && !sgi_label && !pe->part_table->sys_ind)
                    || (sun_label &&
                        (!sunlabel->partitions[i].num_sectors ||
-                        !sunlabel->infos[i].id))
+                        !sunlabel->part_tags[i].tag))
                    || (sgi_label && (!sgi_get_num_sectors(i)))
                   )
                        fprintf(stderr,
@@ -1400,7 +1400,7 @@ change_sysid(void) {
                }
 
                 if (sys < 256) {
-                       if (sun_label && i == 2 && sys != WHOLE_DISK)
+                       if (sun_label && i == 2 && sys != SUN_TAG_BACKUP)
                                printf(_("Consider leaving partition 3 "
                                       "as Whole disk (5),\n"
                                       "as SunOS/Solaris expects it and "
@@ -2614,7 +2614,7 @@ main(int argc, char **argv) {
                                toggle_active(get_partition(1, partitions));
                        else if (sun_label)
                                toggle_sunflags(get_partition(1, partitions),
-                                               0x01);
+                                               SUN_FLAG_UNMNT);
                        else if (sgi_label)
                                sgi_set_bootpartition(
                                        get_partition(1, partitions));
@@ -2638,7 +2638,7 @@ main(int argc, char **argv) {
                                toggle_dos_compatibility_flag();
                        else if (sun_label)
                                toggle_sunflags(get_partition(1, partitions),
-                                               0x10);
+                                               SUN_FLAG_RONLY);
                        else if (sgi_label)
                                sgi_set_swappartition(
                                                get_partition(1, partitions));
index a1994e288307cebba8967ef0d4958f8bca2c7f56..f67aa261a543902cc9abbce926918d5038cec8eb 100644 (file)
@@ -36,25 +36,23 @@ static int     other_endian = 0;
 static int     scsi_disk = 0;
 static int     floppy = 0;
 
-#define LINUX_SWAP      0x82
-#define LINUX_NATIVE    0x83
-
 struct systypes sun_sys_types[] = {
-       {0, N_("Empty")},
-       {1, N_("Boot")},
-       {2, N_("SunOS root")},
-       {SUNOS_SWAP, N_("SunOS swap")},
-       {4, N_("SunOS usr")},
-       {WHOLE_DISK, N_("Whole disk")},
-       {6, N_("SunOS stand")},
-       {7, N_("SunOS var")},
-       {8, N_("SunOS home")},
-       {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 */
+       {SUN_TAG_UNASSIGNED, N_("Unassigned")},
+       {SUN_TAG_BOOT, N_("Boot")},
+       {SUN_TAG_ROOT, N_("SunOS root")},
+       {SUN_TAG_SWAP, N_("SunOS swap")},
+       {SUN_TAG_USR, N_("SunOS usr")},
+       {SUN_TAG_BACKUP, N_("Whole disk")},
+       {SUN_TAG_STAND, N_("SunOS stand")},
+       {SUN_TAG_VAR, N_("SunOS var")},
+       {SUN_TAG_HOME, N_("SunOS home")},
+       {SUN_TAG_ALTSCTR, N_("SunOS alt sectors")},
+       {SUN_TAG_CACHE, N_("SunOS cachefs")},
+       {SUN_TAG_RESERVED, N_("SunOS reserved")},
+       {SUN_TAG_LINUX_SWAP, N_("Linux swap")},
+       {SUN_TAG_LINUX_NATIVE, N_("Linux native")},
+       {SUN_TAG_LINUX_LVM, N_("Linux LVM")},
+       {SUN_TAG_LINUX_RAID, N_("Linux raid autodetect")},
        { 0, NULL }
 };
 
@@ -65,10 +63,10 @@ static inline __u32 __swap32(__u32 x) {
         return (((__u32)(x) & 0xFF) << 24) | (((__u32)(x) & 0xFF00) << 8) | (((__u32)(x) & 0xFF0000) >> 8) | (((__u32)(x) & 0xFF000000) >> 24);
 }
 
-int
-get_num_sectors(struct sun_partition p) {
-       return SSWAP32(p.num_sectors);
-}
+#define SSWAP16(x) (other_endian ? __swap16(x) \
+                                : (__u16)(x))
+#define SSWAP32(x) (other_endian ? __swap32(x) \
+                                : (__u32)(x))
 
 #ifndef IDE0_MAJOR
 #define IDE0_MAJOR 3
@@ -76,7 +74,8 @@ get_num_sectors(struct sun_partition p) {
 #ifndef IDE1_MAJOR
 #define IDE1_MAJOR 22
 #endif
-void guess_device_type(int fd) {
+void guess_device_type(int fd)
+{
        struct stat bootstat;
 
        if (fstat (fd, &bootstat) < 0) {
@@ -97,9 +96,10 @@ void guess_device_type(int fd) {
        }
 }
 
-static void
-set_sun_partition(int i, unsigned int start, unsigned int stop, int sysid) {
-       sunlabel->infos[i].id = sysid;
+static void set_sun_partition(int i, __u32 start, __u32 stop, __u16 sysid)
+{
+       sunlabel->part_tags[i].tag = SSWAP16(sysid);
+       sunlabel->part_tags[i].flag = SSWAP16(0);
        sunlabel->partitions[i].start_cylinder =
                SSWAP32(start / (heads * sectors));
        sunlabel->partitions[i].num_sectors =
@@ -107,15 +107,15 @@ set_sun_partition(int i, unsigned int start, unsigned int stop, int sysid) {
        set_changed(i);
 }
 
-void
-sun_nolabel(void) {
+void sun_nolabel(void)
+{
        sun_label = 0;
        sunlabel->magic = 0;
        partitions = 4;
 }
 
-int
-check_sun_label(void) {
+int check_sun_label(void)
+{
        unsigned short *ush;
        int csum;
 
@@ -126,133 +126,67 @@ check_sun_label(void) {
                return 0;
        }
        other_endian = (sunlabel->magic == SUN_LABEL_MAGIC_SWAPPED);
+
        ush = ((unsigned short *) (sunlabel + 1)) - 1;
-       for (csum = 0; ush >= (unsigned short *)sunlabel;) csum ^= *ush--;
+       for (csum = 0; ush >= (unsigned short *)sunlabel;)
+               csum ^= *ush--;
+
        if (csum) {
                fprintf(stderr,_("Detected sun disklabel with wrong checksum.\n"
                                "Probably you'll have to set all the values,\n"
                                "e.g. heads, sectors, cylinders and partitions\n"
                                "or force a fresh label (s command in main menu)\n"));
        } else {
-               heads = SSWAP16(sunlabel->ntrks);
+               int need_fixing = 0;
+
+               heads = SSWAP16(sunlabel->nhead);
                cylinders = SSWAP16(sunlabel->ncyl);
                sectors = SSWAP16(sunlabel->nsect);
+
+               if (sunlabel->version != SSWAP32(SUN_LABEL_VERSION)) {
+                       fprintf(stderr,_("Detected sun disklabel with wrong version [0x%08x].\n"),
+                               sunlabel->version);
+                       need_fixing = 1;
+               }
+               if (sunlabel->sanity != SSWAP32(SUN_LABEL_SANE)) {
+                       fprintf(stderr,_("Detected sun disklabel with wrong sanity [0x%08x].\n"),
+                               sunlabel->sanity);
+                       need_fixing = 1;
+               }
+               if (sunlabel->num_partitions != SSWAP16(SUN_NUM_PARTITIONS)) {
+                       fprintf(stderr,_("Detected sun disklabel with wrong num_partitions [%u].\n"),
+                               sunlabel->num_partitions);
+                       need_fixing = 1;
+               }
+               if (need_fixing) {
+                       fprintf(stderr, _("Warning: Wrong values need to be "
+                                         "fixed up and will be corrected "
+                                         "by w(rite)\n"));
+                       sunlabel->version = SSWAP32(SUN_LABEL_VERSION);
+                       sunlabel->sanity = SSWAP32(SUN_LABEL_SANE);
+                       sunlabel->num_partitions = SSWAP16(SUN_NUM_PARTITIONS);
+
+                       ush = (unsigned short *)sunlabel;
+                       csum = 0;
+                       while(ush < (unsigned short *)(&sunlabel->cksum))
+                               csum ^= *ush++;
+                       sunlabel->cksum = csum;
+
+                       set_changed(0);
+               }
        }
        update_units();
        sun_label = 1;
-       partitions = 8;
+       partitions = SUN_NUM_PARTITIONS;
        return 1;
 }
 
-struct sun_predefined_drives {
-       char *vendor;
-       char *model;
-       unsigned short sparecyl;
-       unsigned short ncyl;
-       unsigned short nacyl;
-       unsigned short pcylcount;
-       unsigned short ntrks;
-       unsigned short nsect;
-       unsigned short rspeed;
-} sun_drives[] = {
-{"Quantum","ProDrive 80S",1,832,2,834,6,34,3662},
-{"Quantum","ProDrive 105S",1,974,2,1019,6,35,3662},
-{"CDC","Wren IV 94171-344",3,1545,2,1549,9,46,3600},
-{"IBM","DPES-31080",0,4901,2,4903,4,108,5400},
-{"IBM","DORS-32160",0,1015,2,1017,67,62,5400},
-{"IBM","DNES-318350",0,11199,2,11474,10,320,7200},
-{"SEAGATE","ST34371",0,3880,2,3882,16,135,7228},
-{"","SUN0104",1,974,2,1019,6,35,3662},
-{"","SUN0207",4,1254,2,1272,9,36,3600},
-{"","SUN0327",3,1545,2,1549,9,46,3600},
-{"","SUN0340",0,1538,2,1544,6,72,4200},
-{"","SUN0424",2,1151,2,2500,9,80,4400},
-{"","SUN0535",0,1866,2,2500,7,80,5400},
-{"","SUN0669",5,1614,2,1632,15,54,3600},
-{"","SUN1.0G",5,1703,2,1931,15,80,3597},
-{"","SUN1.05",0,2036,2,2038,14,72,5400},
-{"","SUN1.3G",6,1965,2,3500,17,80,5400},
-{"","SUN2.1G",0,2733,2,3500,19,80,5400},
-{"IOMEGA","Jaz",0,1019,2,1021,64,32,5394},
-};
-
-static struct sun_predefined_drives *
-sun_autoconfigure_scsi(void) {
-    struct sun_predefined_drives *p = NULL;
-
-#ifdef SCSI_IOCTL_GET_IDLUN
-    unsigned int id[2];
-    char buffer[2048];
-    char buffer2[2048];
-    FILE *pfd;
-    char *vendor;
-    char *model;
-    char *q;
-    int i;
-
-    if (!ioctl(fd, SCSI_IOCTL_GET_IDLUN, &id)) {
-        sprintf(buffer,
-            "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n",
-#if 0                    
-            ((id[0]>>24)&0xff)-/*PROC_SCSI_SCSI+PROC_SCSI_FILE*/33,
-#else
-            /* This is very wrong (works only if you have one HBA),
-               but I haven't found a way how to get hostno
-               from the current kernel */
-            0,
-#endif                        
-            (id[0]>>16)&0xff,
-            id[0]&0xff,
-            (id[0]>>8)&0xff);
-        pfd = fopen("/proc/scsi/scsi","r");
-        if (pfd) {
-            while (fgets(buffer2,2048,pfd)) {
-               if (!strcmp(buffer, buffer2)) {
-                    if (fgets(buffer2,2048,pfd)) {
-                        q = strstr(buffer2,"Vendor: ");
-                        if (q) {
-                            q += 8;
-                            vendor = q;
-                           q = strstr(q," ");
-                           *q++ = 0;   /* truncate vendor name */
-                            q = strstr(q,"Model: ");
-                            if (q) {
-                                *q = 0;
-                                q += 7;
-                                model = q;
-                                q = strstr(q," Rev: ");
-                                if (q) {
-                                    *q = 0;
-                                    for (i = 0; i < SIZE(sun_drives); i++) {
-                                        if (*sun_drives[i].vendor && strcasecmp(sun_drives[i].vendor, vendor))
-                                            continue;
-                                        if (!strstr(model, sun_drives[i].model))
-                                            continue;
-                                        printf(_("Autoconfigure found a %s%s%s\n"),sun_drives[i].vendor,(*sun_drives[i].vendor) ? " " : "",sun_drives[i].model);
-                                        p = sun_drives + i;
-                                        break;
-                                    }
-                                }
-                            }
-                        }
-                    }
-                    break;
-                }
-            }
-            fclose(pfd);
-        }
-    }
-#endif
-    return p;
-}
-
 void create_sunlabel(void)
 {
        struct hd_geometry geometry;
+       unsigned long long llsectors, llcyls;
        unsigned int ndiv;
-       int i;
-       unsigned char c;
-       struct sun_predefined_drives *p = NULL;
+       int res, sec_fac;
 
        fprintf(stderr,
        _("Building a new sun disklabel. Changes will remain in memory only,\n"
@@ -265,116 +199,70 @@ void create_sunlabel(void)
 #endif
        memset(MBRbuffer, 0, sizeof(MBRbuffer));
        sunlabel->magic = SSWAP16(SUN_LABEL_MAGIC);
-       if (!floppy) {
-           puts(_("Drive type\n"
-                "   ?   auto configure\n"
-                "   0   custom (with hardware detected defaults)"));
-           for (i = 0; i < SIZE(sun_drives); i++) {
-               printf("   %c   %s%s%s\n",
-                      i + 'a', sun_drives[i].vendor,
-                      (*sun_drives[i].vendor) ? " " : "",
-                      sun_drives[i].model);
-           }
-           for (;;) {
-               c = read_char(_("Select type (? for auto, 0 for custom): "));
-               if (c >= 'a' && c < 'a' + SIZE(sun_drives)) {
-                   p = sun_drives + c - 'a';
-                   break;
-               } else if (c >= 'A' && c < 'A' + SIZE(sun_drives)) {
-                   p = sun_drives + c - 'A';
-                   break;
-               } else if (c == '0') {
-                   break;
-               } else if (c == '?' && scsi_disk) {
-                   p = sun_autoconfigure_scsi();
-                   if (!p)
-                       printf(_("Autoconfigure failed.\n"));
-                   else
-                       break;
-               }
-           }
-       }
-       if (!p || floppy) {
-           if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
+       sunlabel->sanity = SSWAP32(SUN_LABEL_SANE);
+       sunlabel->version = SSWAP32(SUN_LABEL_VERSION);
+       sunlabel->num_partitions = SSWAP16(SUN_NUM_PARTITIONS);
+
+       res = disksize(fd, &llsectors);
+       sec_fac = sector_size / 512;
+
+       if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
                heads = geometry.heads;
                sectors = geometry.sectors;
-               cylinders = geometry.cylinders;
-           } else {
-               heads = 0;
-               sectors = 0;
-               cylinders = 0;
-           }
-           if (floppy) {
-               sunlabel->nacyl = 0;
-               sunlabel->pcylcount = SSWAP16(cylinders);
-               sunlabel->rspeed = SSWAP16(300);
-               sunlabel->ilfact = SSWAP16(1);
-               sunlabel->sparecyl = 0;
-           } else {
-               heads = read_int(1,heads,1024,0,_("Heads"));
-               sectors = read_int(1,sectors,1024,0,_("Sectors/track"));
-               if (cylinders)
-                   cylinders = read_int(1,cylinders-2,65535,0,_("Cylinders"));
-               else
-                   cylinders = read_int(1,0,65535,0,_("Cylinders"));
-               sunlabel->nacyl =
-                       SSWAP16(read_int(0,2,65535,0,
-                                        _("Alternate cylinders")));
-               sunlabel->pcylcount =
-                       SSWAP16(read_int(0,cylinders+SSWAP16(sunlabel->nacyl),
-                                        65535,0,_("Physical cylinders")));
-               sunlabel->rspeed =
-                       SSWAP16(read_int(1,5400,100000,0,
-                                        _("Rotation speed (rpm)")));
-               sunlabel->ilfact =
-                       SSWAP16(read_int(1,1,32,0,_("Interleave factor")));
-               sunlabel->sparecyl =
-                       SSWAP16(read_int(0,0,sectors,0,
-                                        _("Extra sectors per cylinder")));
-           }
+               if (res == 0) {
+                       llcyls = llsectors / (heads * sectors * sec_fac);
+                       cylinders = llcyls;
+                       if (cylinders != llcyls)
+                               cylinders = ~0;
+               } else {
+                       cylinders = geometry.cylinders;
+                       fprintf(stderr,
+                               _("Warning:  BLKGETSIZE ioctl failed on %s.  "
+                                 "Using geometry cylinder value of %d.\n"
+                                 "This value may be truncated for devices"
+                                 " > 33.8 GB.\n"), disk_device, cylinders);
+               }
        } else {
-           sunlabel->sparecyl = SSWAP16(p->sparecyl);
-           sunlabel->ncyl = SSWAP16(p->ncyl);
-           sunlabel->nacyl = SSWAP16(p->nacyl);
-           sunlabel->pcylcount = SSWAP16(p->pcylcount);
-           sunlabel->ntrks = SSWAP16(p->ntrks);
-           sunlabel->nsect = SSWAP16(p->nsect);
-           sunlabel->rspeed = SSWAP16(p->rspeed);
-           sunlabel->ilfact = SSWAP16(1);
-           cylinders = p->ncyl;
-           heads = p->ntrks;
-           sectors = p->nsect;
-           puts(_("You may change all the disk params from the x menu"));
+               heads = read_int(1,1,1024,0,_("Heads"));
+               sectors = read_int(1,1,1024,0,_("Sectors/track"));
+               cylinders = read_int(1,1,65535,0,_("Cylinders"));
        }
 
-       snprintf(sunlabel->info, sizeof(sunlabel->info),
-                "%s%s%s cyl %d alt %d hd %d sec %llu",
-                p ? p->vendor : "", (p && *p->vendor) ? " " : "",
-                p ? p->model
-                  : (floppy ? _("3,5\" floppy") : _("Linux custom")),
-               cylinders, SSWAP16(sunlabel->nacyl), heads, sectors);
+       sunlabel->acyl   = SSWAP16(2);
+       sunlabel->pcyl   = SSWAP16(cylinders);
+       sunlabel->ncyl   = SSWAP16(cylinders - 2);
+       sunlabel->rpm    = SSWAP16(5400);
+       sunlabel->intrlv = SSWAP16(1);
+       sunlabel->apc    = SSWAP16(0);
 
-       sunlabel->ntrks = SSWAP16(heads);
+       sunlabel->nhead = SSWAP16(heads);
        sunlabel->nsect = SSWAP16(sectors);
        sunlabel->ncyl = SSWAP16(cylinders);
-       if (floppy)
-           set_sun_partition(0, 0, cylinders * heads * sectors, LINUX_NATIVE);
-       else {
-           if (cylinders * heads * sectors >= 150 * 2048) {
+
+       snprintf(sunlabel->label_id, sizeof(sunlabel->label_id),
+                "Linux cyl %d alt %d hd %d sec %llu",
+                cylinders, SSWAP16(sunlabel->acyl), heads, sectors);
+
+       if (cylinders * heads * sectors >= 150 * 2048) {
                ndiv = cylinders - (50 * 2048 / (heads * sectors)); /* 50M swap */
-           } else
+       } else
                ndiv = cylinders * 2 / 3;
-           set_sun_partition(0, 0, ndiv * heads * sectors, LINUX_NATIVE);
-           set_sun_partition(1, ndiv * heads * sectors, cylinders * heads * sectors, LINUX_SWAP);
-           sunlabel->infos[1].flags |= 0x01; /* Not mountable */
-       }
-       set_sun_partition(2, 0, cylinders * heads * sectors, WHOLE_DISK);
+
+       set_sun_partition(0, 0, ndiv * heads * sectors,
+                         SUN_TAG_LINUX_NATIVE);
+       set_sun_partition(1, ndiv * heads * sectors,
+                         cylinders * heads * sectors,
+                         SUN_TAG_LINUX_SWAP);
+       sunlabel->part_tags[1].flag |= SSWAP16(SUN_FLAG_UNMNT);
+
+       set_sun_partition(2, 0, cylinders * heads * sectors, SUN_TAG_BACKUP);
+
        {
                unsigned short *ush = (unsigned short *)sunlabel;
                unsigned short csum = 0;
-               while(ush < (unsigned short *)(&sunlabel->csum))
+               while(ush < (unsigned short *)(&sunlabel->cksum))
                        csum ^= *ush++;
-               sunlabel->csum = csum;
+               sunlabel->cksum = csum;
        }
 
        set_all_unchanged();
@@ -382,24 +270,32 @@ void create_sunlabel(void)
        set_changed(0);
 }
 
-void
-toggle_sunflags(int i, unsigned char mask) {
-       if (sunlabel->infos[i].flags & mask)
-               sunlabel->infos[i].flags &= ~mask;
-       else sunlabel->infos[i].flags |= mask;
+void toggle_sunflags(int i, __u16 mask)
+{
+       struct sun_tag_flag *p = &sunlabel->part_tags[i];
+
+       p->flag ^= SSWAP16(mask);
+
        set_changed(i);
 }
 
-static void
-fetch_sun(unsigned int *starts, unsigned int *lens, unsigned int *start, unsigned int *stop) {
+static void fetch_sun(__u32 *starts, __u32 *lens, __u32 *start, __u32 *stop)
+{
        int i, continuous = 1;
-       *start = 0; *stop = cylinders * heads * sectors;
+
+       *start = 0;
+       *stop = cylinders * heads * sectors;
+
        for (i = 0; i < partitions; i++) {
-               if (sunlabel->partitions[i].num_sectors
-                   && sunlabel->infos[i].id
-                   && sunlabel->infos[i].id != WHOLE_DISK) {
-                       starts[i] = SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
-                       lens[i] = SSWAP32(sunlabel->partitions[i].num_sectors);
+               struct sun_partition *part = &sunlabel->partitions[i];
+               struct sun_tag_flag *tag = &sunlabel->part_tags[i];
+
+               if (part->num_sectors &&
+                   tag->tag != SSWAP16(SUN_TAG_UNASSIGNED) &&
+                   tag->tag != SSWAP16(SUN_TAG_BACKUP)) {
+                       starts[i] = (SSWAP32(part->start_cylinder) *
+                                    heads * sectors);
+                       lens[i] = SSWAP32(part->num_sectors);
                        if (continuous) {
                                if (starts[i] == *start)
                                        *start += lens[i];
@@ -419,24 +315,29 @@ fetch_sun(unsigned int *starts, unsigned int *lens, unsigned int *start, unsigne
 
 static unsigned int *verify_sun_starts;
 
-static int
-verify_sun_cmp(int *a, int *b) {
-    if (*a == -1) return 1;
-    if (*b == -1) return -1;
-    if (verify_sun_starts[*a] > verify_sun_starts[*b]) return 1;
+static int verify_sun_cmp(int *a, int *b)
+{
+    if (*a == -1)
+           return 1;
+    if (*b == -1)
+           return -1;
+    if (verify_sun_starts[*a] > verify_sun_starts[*b])
+           return 1;
     return -1;
 }
 
-void
-verify_sun(void) {
-    unsigned int starts[8], lens[8], start, stop;
+void verify_sun(void)
+{
+    __u32 starts[SUN_NUM_PARTITIONS], lens[SUN_NUM_PARTITIONS], start, stop;
     int i,j,k,starto,endo;
-    int array[8];
+    int array[SUN_NUM_PARTITIONS];
 
     verify_sun_starts = starts;
-    fetch_sun(starts,lens,&start,&stop);
+
+    fetch_sun(starts, lens, &start, &stop);
+
     for (k = 0; k < 7; k++) {
-       for (i = 0; i < 8; i++) {
+       for (i = 0; i < SUN_NUM_PARTITIONS; i++) {
            if (k && (lens[i] % (heads * sectors))) {
                printf(_("Partition %d doesn't end on cylinder boundary\n"), i+1);
            }
@@ -466,7 +367,7 @@ verify_sun(void) {
            }
        }
     }
-    for (i = 0; i < 8; i++) {
+    for (i = 0; i < SUN_NUM_PARTITIONS; i++) {
         if (lens[i])
             array[i] = i;
         else
@@ -480,31 +381,35 @@ verify_sun(void) {
     }
     stop = cylinders * heads * sectors;
     if (starts[array[0]])
-        printf(_("Unused gap - sectors 0-%d\n"),starts[array[0]]);
+        printf(_("Unused gap - sectors 0-%d\n"), starts[array[0]]);
     for (i = 0; i < 7 && array[i+1] != -1; i++) {
-        printf(_("Unused gap - sectors %d-%d\n"),starts[array[i]]+lens[array[i]],starts[array[i+1]]);
+        printf(_("Unused gap - sectors %d-%d\n"),
+              (starts[array[i]] + lens[array[i]]),
+              starts[array[i+1]]);
     }
-    start = starts[array[i]]+lens[array[i]];
+    start = (starts[array[i]] + lens[array[i]]);
     if (start < stop)
-        printf(_("Unused gap - sectors %d-%d\n"),start,stop);
+        printf(_("Unused gap - sectors %d-%d\n"), start, stop);
 }
 
-void
-add_sun_partition(int n, int sys) {
-       unsigned int start, stop, stop2;
-       unsigned int starts[8], lens[8];
+void add_sun_partition(int n, int sys)
+{
+       __u32 starts[SUN_NUM_PARTITIONS], lens[SUN_NUM_PARTITIONS];
+       struct sun_partition *part = &sunlabel->partitions[n];
+       struct sun_tag_flag *tag = &sunlabel->part_tags[n];
+       __u32 start, stop, stop2;
        int whole_disk = 0;
                
        char mesg[256];
        int i, first, last;
 
-       if (sunlabel->partitions[n].num_sectors && sunlabel->infos[n].id) {
+       if (part->num_sectors && tag->tag != SSWAP16(SUN_TAG_UNASSIGNED)) {
                printf(_("Partition %d is already defined.  Delete "
                        "it before re-adding it.\n"), n + 1);
                return;
        }
        
-       fetch_sun(starts,lens,&start,&stop);
+       fetch_sun(starts, lens, &start, &stop);
        if (stop <= start) {
                if (n == 2)
                        whole_disk = 1;
@@ -600,29 +505,37 @@ and is of type `Whole disk'\n");
        } else if (!whole_disk && last > stop)
                last = stop;
 
-       if (whole_disk) sys = WHOLE_DISK;
+       if (whole_disk)
+               sys = SUN_TAG_BACKUP;
+
        set_sun_partition(n, first, last, sys);
 }
 
-void
-sun_delete_partition(int i) {
+void sun_delete_partition(int i)
+{
+       struct sun_partition *part = &sunlabel->partitions[i];
+       struct sun_tag_flag *tag = &sunlabel->part_tags[i];
        unsigned int nsec;
 
-       if (i == 2 && sunlabel->infos[i].id == WHOLE_DISK && 
-           !sunlabel->partitions[i].start_cylinder && 
-           (nsec = SSWAP32(sunlabel->partitions[i].num_sectors))
+       if (i == 2 &&
+           tag->tag == SSWAP16(SUN_TAG_BACKUP) &&
+           !part->start_cylinder &&
+           (nsec = SSWAP32(part->num_sectors))
              == heads * sectors * cylinders)
                printf(_("If you want to maintain SunOS/Solaris compatibility, "
                       "consider leaving this\n"
                       "partition as Whole disk (5), starting at 0, with %u "
                       "sectors\n"), nsec);
-       sunlabel->infos[i].id = 0;
-       sunlabel->partitions[i].num_sectors = 0;
+       tag->tag = SSWAP16(SUN_TAG_UNASSIGNED);
+       part->num_sectors = 0;
 }
 
-void
-sun_change_sysid(int i, int sys) {
-       if (sys == LINUX_SWAP && !sunlabel->partitions[i].start_cylinder) {
+void sun_change_sysid(int i, __u16 sys)
+{
+       struct sun_partition *part = &sunlabel->partitions[i];
+       struct sun_tag_flag *tag = &sunlabel->part_tags[i];
+
+       if (sys == SUN_TAG_LINUX_SWAP && !part->start_cylinder) {
            read_chars(
              _("It is highly recommended that the partition at offset 0\n"
              "is UFS, EXT2FS filesystem or SunOS swap. Putting Linux swap\n"
@@ -633,22 +546,22 @@ sun_change_sysid(int i, int sys) {
                    return;
        }
        switch (sys) {
-       case SUNOS_SWAP:
-       case LINUX_SWAP:
+       case SUN_TAG_SWAP:
+       case SUN_TAG_LINUX_SWAP:
                /* swaps are not mountable by default */
-               sunlabel->infos[i].flags |= 0x01;
+               tag->flag |= SSWAP16(SUN_FLAG_UNMNT);
                break;
        default:
                /* assume other types are mountable;
                   user can change it anyway */
-               sunlabel->infos[i].flags &= ~0x01;
+               tag->flag &= ~SSWAP16(SUN_FLAG_UNMNT);
                break;
        }
-       sunlabel->infos[i].id = sys;
+       tag->tag = SSWAP16(sys);
 }
 
-void
-sun_list_table(int xtra) {
+void sun_list_table(int xtra)
+{
        int i, w;
        char *type;
 
@@ -658,14 +571,16 @@ sun_list_table(int xtra) {
                _("\nDisk %s (Sun disk label): %d heads, %llu sectors, %d rpm\n"
                "%d cylinders, %d alternate cylinders, %d physical cylinders\n"
                "%d extra sects/cyl, interleave %d:1\n"
-               "%s\n"
+               "Label ID: %s\n"
+               "Volume ID: %s\n"
                "Units = %s of %d * 512 bytes\n\n"),
-                      disk_device, heads, sectors, SSWAP16(sunlabel->rspeed),
-                      cylinders, SSWAP16(sunlabel->nacyl),
-                      SSWAP16(sunlabel->pcylcount),
-                      SSWAP16(sunlabel->sparecyl),
-                      SSWAP16(sunlabel->ilfact),
-                      (char *)sunlabel,
+                      disk_device, heads, sectors, SSWAP16(sunlabel->rpm),
+                      cylinders, SSWAP16(sunlabel->acyl),
+                      SSWAP16(sunlabel->pcyl),
+                      SSWAP16(sunlabel->apc),
+                      SSWAP16(sunlabel->intrlv),
+                      sunlabel->label_id,
+                      sunlabel->volume_id,
                       str_units(PLURAL), units_per_sector);
        else
                printf(
@@ -677,74 +592,82 @@ sun_list_table(int xtra) {
        printf(_("%*s Flag    Start       End    Blocks   Id  System\n"),
               w + 1, _("Device"));
        for (i = 0 ; i < partitions; i++) {
-               if (sunlabel->partitions[i].num_sectors) {
-                       __u32 start = SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
-                       __u32 len = SSWAP32(sunlabel->partitions[i].num_sectors);
+               struct sun_partition *part = &sunlabel->partitions[i];
+               struct sun_tag_flag *tag = &sunlabel->part_tags[i];
+
+               if (part->num_sectors) {
+                       __u32 start = SSWAP32(part->start_cylinder) * heads * sectors;
+                       __u32 len = SSWAP32(part->num_sectors);
                        printf(
                            "%s %c%c %9ld %9ld %9ld%c  %2x  %s\n",
 /* device */             partname(disk_device, i+1, w),
-/* flags */              (sunlabel->infos[i].flags & 0x01) ? 'u' : ' ',
-                         (sunlabel->infos[i].flags & 0x10) ? 'r' : ' ',
+/* flags */              (tag->flag & SSWAP16(SUN_FLAG_UNMNT)) ? 'u' : ' ',
+                         (tag->flag & SSWAP16(SUN_FLAG_RONLY)) ? 'r' : ' ',
 /* start */              (long) scround(start),
 /* end */                (long) scround(start+len),
 /* odd flag on end */    (long) len / 2, len & 1 ? '+' : ' ',
-/* type id */            sunlabel->infos[i].id,
-/* type name */                  (type = partition_type(sunlabel->infos[i].id))
+/* type id */            SSWAP16(tag->tag),
+/* type name */                  (type = partition_type(SSWAP16(tag->tag)))
                                ? type : _("Unknown"));
                }
        }
 }
 
-void
-sun_set_alt_cyl(void) {
-       sunlabel->nacyl =
-               SSWAP16(read_int(0,SSWAP16(sunlabel->nacyl), 65535, 0,
+void sun_set_alt_cyl(void)
+{
+       sunlabel->acyl =
+               SSWAP16(read_int(0,SSWAP16(sunlabel->acyl), 65535, 0,
                                 _("Number of alternate cylinders")));
 }
 
-void
-sun_set_ncyl(int cyl) {
+void sun_set_ncyl(int cyl)
+{
        sunlabel->ncyl = SSWAP16(cyl);
 }
 
-void
-sun_set_xcyl(void) {
-       sunlabel->sparecyl =
-               SSWAP16(read_int(0, SSWAP16(sunlabel->sparecyl), sectors, 0,
+void sun_set_xcyl(void)
+{
+       sunlabel->apc =
+               SSWAP16(read_int(0, SSWAP16(sunlabel->apc), sectors, 0,
                                 _("Extra sectors per cylinder")));
 }
 
-void
-sun_set_ilfact(void) {
-       sunlabel->ilfact =
-               SSWAP16(read_int(1, SSWAP16(sunlabel->ilfact), 32, 0,
+void sun_set_ilfact(void)
+{
+       sunlabel->intrlv =
+               SSWAP16(read_int(1, SSWAP16(sunlabel->intrlv), 32, 0,
                                 _("Interleave factor")));
 }
 
-void
-sun_set_rspeed(void) {
-       sunlabel->rspeed =
-               SSWAP16(read_int(1, SSWAP16(sunlabel->rspeed), 100000, 0,
+void sun_set_rspeed(void)
+{
+       sunlabel->rpm =
+               SSWAP16(read_int(1, SSWAP16(sunlabel->rpm), 100000, 0,
                                 _("Rotation speed (rpm)")));
 }
 
-void
-sun_set_pcylcount(void) {
-       sunlabel->pcylcount =
-               SSWAP16(read_int(0, SSWAP16(sunlabel->pcylcount), 65535, 0,
+void sun_set_pcylcount(void)
+{
+       sunlabel->pcyl =
+               SSWAP16(read_int(0, SSWAP16(sunlabel->pcyl), 65535, 0,
                                 _("Number of physical cylinders")));
 }
 
-void
-sun_write_table(void) {
+void sun_write_table(void)
+{
        unsigned short *ush = (unsigned short *)sunlabel;
        unsigned short csum = 0;
 
-       while(ush < (unsigned short *)(&sunlabel->csum))
+       while(ush < (unsigned short *)(&sunlabel->cksum))
                csum ^= *ush++;
-       sunlabel->csum = csum;
+       sunlabel->cksum = csum;
        if (lseek(fd, 0, SEEK_SET) < 0)
                fatal(unable_to_seek);
        if (write(fd, sunlabel, SECTOR_SIZE) != SECTOR_SIZE)
                fatal(unable_to_write);
 }
+
+int sun_get_sysid(int i)
+{
+       return SSWAP16(sunlabel->part_tags[i].tag);
+}
index e322e66e9a3a11defa1ccda6702908d47b232f70..c8e069804a38097bf27a41a6aee27553fd50e900 100644 (file)
@@ -3,53 +3,86 @@
 
 #include <linux/types.h>   /* for __u16, __u32 */
 
-typedef struct {
-       unsigned char info[128];   /* Informative text string */
-       unsigned char spare0[14];
-       struct sun_info {
-               unsigned char spare1;
-               unsigned char id;
-               unsigned char spare2;
-               unsigned char flags;
-       } infos[8];
-       unsigned char spare1[246]; /* Boot information etc. */
-       unsigned short rspeed;     /* Disk rotational speed */
-       unsigned short pcylcount;  /* Physical cylinder count */
-       unsigned short sparecyl;   /* extra sects per cylinder */
-       unsigned char spare2[4];   /* More magic... */
-       unsigned short ilfact;     /* Interleave factor */
-       unsigned short ncyl;       /* Data cylinder count */
-       unsigned short nacyl;      /* Alt. cylinder count */
-       unsigned short ntrks;      /* Tracks per cylinder */
-       unsigned short nsect;      /* Sectors per track */
-       unsigned char spare3[4];   /* Even more magic... */
-       struct sun_partition {
-               __u32 start_cylinder;
-               __u32 num_sectors;
-       } partitions[8];
-       unsigned short magic;      /* Magic number */
-       unsigned short csum;       /* Label xor'd checksum */
-} sun_partition;
+struct sun_partition {
+       __u32   start_cylinder;
+       __u32   num_sectors;
+};
 
-#define SUN_LABEL_MAGIC          0xDABE
-#define SUN_LABEL_MAGIC_SWAPPED  0xBEDA
-#define sunlabel ((sun_partition *)MBRbuffer)
-#define SSWAP16(x) (other_endian ? __swap16(x) \
-                                : (__u16)(x))
-#define SSWAP32(x) (other_endian ? __swap32(x) \
-                                : (__u32)(x))
-/* fdisksunlabel.c */
-#define SUNOS_SWAP 3
-#define WHOLE_DISK 5
+struct sun_tag_flag {
+       __u16   tag;
+#define SUN_TAG_UNASSIGNED     0x00    /* Unassigned partition */
+#define SUN_TAG_BOOT           0x01    /* Boot partition       */
+#define SUN_TAG_ROOT           0x02    /* Root filesystem      */
+#define SUN_TAG_SWAP           0x03    /* Swap partition       */
+#define SUN_TAG_USR            0x04    /* /usr filesystem      */
+#define SUN_TAG_BACKUP         0x05    /* Full-disk slice      */
+#define SUN_TAG_STAND          0x06    /* Stand partition      */
+#define SUN_TAG_VAR            0x07    /* /var filesystem      */
+#define SUN_TAG_HOME           0x08    /* /home filesystem     */
+#define SUN_TAG_ALTSCTR                0x09    /* Alt sector partition */
+#define SUN_TAG_CACHE          0x0a    /* Cachefs partition    */
+#define SUN_TAG_RESERVED       0x0b    /* SMI reserved data    */
+#define SUN_TAG_LINUX_SWAP     0x82    /* Linux SWAP           */
+#define SUN_TAG_LINUX_NATIVE   0x83    /* Linux filesystem     */
+#define SUN_TAG_LINUX_LVM      0x8e    /* Linux LVM            */
+#define SUN_TAG_LINUX_RAID     0xfd    /* LInux RAID           */
+
+       __u16   flag;
+#define SUN_FLAG_UNMNT         0x01    /* Unmountable partition*/
+#define SUN_FLAG_RONLY         0x10    /* Read only            */
+};
+
+#define SUN_LABEL_SIZE         512
+
+#define SUN_LABEL_ID_SIZE      128
+#define SUN_VOLUME_ID_SIZE     8
 
+#define SUN_LABEL_VERSION      0x00000001
+#define SUN_LABEL_SANE         0x600ddeee
+#define SUN_NUM_PARTITIONS     8
+
+struct sun_disk_label {
+       char                    label_id[SUN_LABEL_ID_SIZE];
+       __u32                   version;
+       char                    volume_id[SUN_VOLUME_ID_SIZE];
+       __u16                   num_partitions;
+       struct sun_tag_flag     part_tags[SUN_NUM_PARTITIONS];
+       __u32                   bootinfo[3];
+       __u32                   sanity;
+       __u32                   resv[10];
+       __u32                   part_timestamps[SUN_NUM_PARTITIONS];
+       __u32                   write_reinstruct;
+       __u32                   read_reinstruct;
+       __u8                    pad[148];
+       __u16                   rpm;
+       __u16                   pcyl;
+       __u16                   apc;
+       __u16                   resv1;
+       __u16                   resv2;
+       __u16                   intrlv;
+       __u16                   ncyl;
+       __u16                   acyl;
+       __u16                   nhead;
+       __u16                   nsect;
+       __u16                   resv3;
+       __u16                   resv4;
+       struct sun_partition    partitions[SUN_NUM_PARTITIONS];
+       __u16                   magic;
+       __u16                   cksum;
+};
+
+#define SUN_LABEL_MAGIC                0xDABE
+#define SUN_LABEL_MAGIC_SWAPPED        0xBEDA
+#define sunlabel ((struct sun_disk_label *)MBRbuffer)
+
+/* fdisksunlabel.c */
 extern struct systypes sun_sys_types[];
-extern int get_num_sectors(struct sun_partition p);
 extern void guess_device_type(int fd);
 extern int check_sun_label(void);
 extern void sun_nolabel(void);
 extern void create_sunlabel(void);
 extern void sun_delete_partition(int i);
-extern void sun_change_sysid(int i, int sys);
+extern void sun_change_sysid(int i, __u16 sys);
 extern void sun_list_table(int xtra);
 extern void verify_sun(void);
 extern void add_sun_partition(int n, int sys);
@@ -60,6 +93,7 @@ extern void sun_set_xcyl(void);
 extern void sun_set_ilfact(void);
 extern void sun_set_rspeed(void);
 extern void sun_set_pcylcount(void);
-extern void toggle_sunflags(int i, unsigned char mask);
+extern void toggle_sunflags(int i, __u16 mask);
+extern int sun_get_sysid(int i);
 
 #endif /* FDISK_SUN_LABEL_H */