Magellan Linux

Annotation of /trunk/mkinitrd-magellan/busybox/util-linux/fdisk_sun.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 532 - (hide annotations) (download)
Sat Sep 1 22:45:15 2007 UTC (16 years, 9 months ago) by niro
File MIME type: text/plain
File size: 20684 byte(s)
-import if magellan mkinitrd; it is a fork of redhats mkinitrd-5.0.8 with all magellan patches and features; deprecates magellan-src/mkinitrd

1 niro 532 #if ENABLE_FEATURE_SUN_LABEL
2    
3     #define SUN_LABEL_MAGIC 0xDABE
4     #define SUN_LABEL_MAGIC_SWAPPED 0xBEDA
5     #define SUN_SSWAP16(x) (sun_other_endian ? fdisk_swap16(x) : (uint16_t)(x))
6     #define SUN_SSWAP32(x) (sun_other_endian ? fdisk_swap32(x) : (uint32_t)(x))
7    
8     /* Copied from linux/major.h */
9     #define FLOPPY_MAJOR 2
10    
11     #define SCSI_IOCTL_GET_IDLUN 0x5382
12    
13     /*
14     * fdisksunlabel.c
15     *
16     * I think this is mostly, or entirely, due to
17     * Jakub Jelinek (jj@sunsite.mff.cuni.cz), July 1996
18     *
19     * Merged with fdisk for other architectures, aeb, June 1998.
20     *
21     * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
22     * Internationalization
23     */
24    
25    
26     static int sun_other_endian;
27     static int scsi_disk;
28     static int floppy;
29    
30     #ifndef IDE0_MAJOR
31     #define IDE0_MAJOR 3
32     #endif
33     #ifndef IDE1_MAJOR
34     #define IDE1_MAJOR 22
35     #endif
36    
37     static void
38     guess_device_type(void)
39     {
40     struct stat bootstat;
41    
42     if (fstat(fd, &bootstat) < 0) {
43     scsi_disk = 0;
44     floppy = 0;
45     } else if (S_ISBLK(bootstat.st_mode)
46     && (major(bootstat.st_rdev) == IDE0_MAJOR ||
47     major(bootstat.st_rdev) == IDE1_MAJOR)) {
48     scsi_disk = 0;
49     floppy = 0;
50     } else if (S_ISBLK(bootstat.st_mode)
51     && major(bootstat.st_rdev) == FLOPPY_MAJOR) {
52     scsi_disk = 0;
53     floppy = 1;
54     } else {
55     scsi_disk = 1;
56     floppy = 0;
57     }
58     }
59    
60     static const struct systypes sun_sys_types[] = {
61     { "\x00" "Empty" }, /* 0 */
62     { "\x01" "Boot" }, /* 1 */
63     { "\x02" "SunOS root" }, /* 2 */
64     { "\x03" "SunOS swap" }, /* SUNOS_SWAP */
65     { "\x04" "SunOS usr" }, /* 4 */
66     { "\x05" "Whole disk" }, /* SUN_WHOLE_DISK */
67     { "\x06" "SunOS stand" }, /* 6 */
68     { "\x07" "SunOS var" }, /* 7 */
69     { "\x08" "SunOS home" }, /* 8 */
70     { "\x82" "Linux swap" }, /* LINUX_SWAP */
71     { "\x83" "Linux native" }, /* LINUX_NATIVE */
72     { "\x8e" "Linux LVM" }, /* 0x8e */
73     /* New (2.2.x) raid partition with autodetect using persistent superblock */
74     { "\xfd" "Linux raid autodetect" }, /* 0xfd */
75     { NULL }
76     };
77    
78    
79     static void
80     set_sun_partition(int i, uint start, uint stop, int sysid)
81     {
82     sunlabel->infos[i].id = sysid;
83     sunlabel->partitions[i].start_cylinder =
84     SUN_SSWAP32(start / (heads * sectors));
85     sunlabel->partitions[i].num_sectors =
86     SUN_SSWAP32(stop - start);
87     set_changed(i);
88     }
89    
90     static int
91     check_sun_label(void)
92     {
93     unsigned short *ush;
94     int csum;
95    
96     if (sunlabel->magic != SUN_LABEL_MAGIC
97     && sunlabel->magic != SUN_LABEL_MAGIC_SWAPPED) {
98     current_label_type = label_dos;
99     sun_other_endian = 0;
100     return 0;
101     }
102     sun_other_endian = (sunlabel->magic == SUN_LABEL_MAGIC_SWAPPED);
103     ush = ((unsigned short *) (sunlabel + 1)) - 1;
104     for (csum = 0; ush >= (unsigned short *)sunlabel;) csum ^= *ush--;
105     if (csum) {
106     fprintf(stderr,_("Detected sun disklabel with wrong checksum.\n"
107     "Probably you'll have to set all the values,\n"
108     "e.g. heads, sectors, cylinders and partitions\n"
109     "or force a fresh label (s command in main menu)\n"));
110     } else {
111     heads = SUN_SSWAP16(sunlabel->ntrks);
112     cylinders = SUN_SSWAP16(sunlabel->ncyl);
113     sectors = SUN_SSWAP16(sunlabel->nsect);
114     }
115     update_units();
116     current_label_type = label_sun;
117     partitions = 8;
118     return 1;
119     }
120    
121     static const struct sun_predefined_drives {
122     const char *vendor;
123     const char *model;
124     unsigned short sparecyl;
125     unsigned short ncyl;
126     unsigned short nacyl;
127     unsigned short pcylcount;
128     unsigned short ntrks;
129     unsigned short nsect;
130     unsigned short rspeed;
131     } sun_drives[] = {
132     { "Quantum","ProDrive 80S",1,832,2,834,6,34,3662},
133     { "Quantum","ProDrive 105S",1,974,2,1019,6,35,3662},
134     { "CDC","Wren IV 94171-344",3,1545,2,1549,9,46,3600},
135     { "IBM","DPES-31080",0,4901,2,4903,4,108,5400},
136     { "IBM","DORS-32160",0,1015,2,1017,67,62,5400},
137     { "IBM","DNES-318350",0,11199,2,11474,10,320,7200},
138     { "SEAGATE","ST34371",0,3880,2,3882,16,135,7228},
139     { "","SUN0104",1,974,2,1019,6,35,3662},
140     { "","SUN0207",4,1254,2,1272,9,36,3600},
141     { "","SUN0327",3,1545,2,1549,9,46,3600},
142     { "","SUN0340",0,1538,2,1544,6,72,4200},
143     { "","SUN0424",2,1151,2,2500,9,80,4400},
144     { "","SUN0535",0,1866,2,2500,7,80,5400},
145     { "","SUN0669",5,1614,2,1632,15,54,3600},
146     { "","SUN1.0G",5,1703,2,1931,15,80,3597},
147     { "","SUN1.05",0,2036,2,2038,14,72,5400},
148     { "","SUN1.3G",6,1965,2,3500,17,80,5400},
149     { "","SUN2.1G",0,2733,2,3500,19,80,5400},
150     { "IOMEGA","Jaz",0,1019,2,1021,64,32,5394},
151     };
152    
153     static const struct sun_predefined_drives *
154     sun_autoconfigure_scsi(void)
155     {
156     const struct sun_predefined_drives *p = NULL;
157    
158     #ifdef SCSI_IOCTL_GET_IDLUN
159     unsigned int id[2];
160     char buffer[2048];
161     char buffer2[2048];
162     FILE *pfd;
163     char *vendor;
164     char *model;
165     char *q;
166     int i;
167    
168     if (ioctl(fd, SCSI_IOCTL_GET_IDLUN, &id))
169     return NULL;
170    
171     sprintf(buffer,
172     "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n",
173     /* This is very wrong (works only if you have one HBA),
174     but I haven't found a way how to get hostno
175     from the current kernel */
176     0,
177     (id[0]>>16) & 0xff,
178     id[0] & 0xff,
179     (id[0]>>8) & 0xff
180     );
181     pfd = fopen("/proc/scsi/scsi", "r");
182     if (!pfd) {
183     return NULL;
184     }
185     while (fgets(buffer2, 2048, pfd)) {
186     if (strcmp(buffer, buffer2))
187     continue;
188     if (!fgets(buffer2, 2048, pfd))
189     break;
190     q = strstr(buffer2, "Vendor: ");
191     if (!q)
192     break;
193     q += 8;
194     vendor = q;
195     q = strstr(q, " ");
196     *q++ = '\0'; /* truncate vendor name */
197     q = strstr(q, "Model: ");
198     if (!q)
199     break;
200     *q = '\0';
201     q += 7;
202     model = q;
203     q = strstr(q, " Rev: ");
204     if (!q)
205     break;
206     *q = '\0';
207     for (i = 0; i < SIZE(sun_drives); i++) {
208     if (*sun_drives[i].vendor && strcasecmp(sun_drives[i].vendor, vendor))
209     continue;
210     if (!strstr(model, sun_drives[i].model))
211     continue;
212     printf(_("Autoconfigure found a %s%s%s\n"),
213     sun_drives[i].vendor,
214     (*sun_drives[i].vendor) ? " " : "",
215     sun_drives[i].model);
216     p = sun_drives + i;
217     break;
218     }
219     break;
220     }
221     fclose(pfd);
222     #endif
223     return p;
224     }
225    
226     static void
227     create_sunlabel(void)
228     {
229     struct hd_geometry geometry;
230     unsigned int ndiv;
231     int i;
232     unsigned char c;
233     const struct sun_predefined_drives *p = NULL;
234    
235     fprintf(stderr,
236     _("Building a new sun disklabel. Changes will remain in memory only,\n"
237     "until you decide to write them. After that, of course, the previous\n"
238     "content won't be recoverable.\n\n"));
239     sun_other_endian = BB_LITTLE_ENDIAN;
240     memset(MBRbuffer, 0, sizeof(MBRbuffer));
241     sunlabel->magic = SUN_SSWAP16(SUN_LABEL_MAGIC);
242     if (!floppy) {
243     puts(_("Drive type\n"
244     " ? auto configure\n"
245     " 0 custom (with hardware detected defaults)"));
246     for (i = 0; i < SIZE(sun_drives); i++) {
247     printf(" %c %s%s%s\n",
248     i + 'a', sun_drives[i].vendor,
249     (*sun_drives[i].vendor) ? " " : "",
250     sun_drives[i].model);
251     }
252     while (1) {
253     c = read_nonempty(_("Select type (? for auto, 0 for custom): "));
254     if (c >= 'a' && c < 'a' + SIZE(sun_drives)) {
255     p = sun_drives + c - 'a';
256     break;
257     } else if (c >= 'A' && c < 'A' + SIZE(sun_drives)) {
258     p = sun_drives + c - 'A';
259     break;
260     } else if (c == '0') {
261     break;
262     } else if (c == '?' && scsi_disk) {
263     p = sun_autoconfigure_scsi();
264     if (!p)
265     printf(_("Autoconfigure failed.\n"));
266     else
267     break;
268     }
269     }
270     }
271     if (!p || floppy) {
272     if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
273     heads = geometry.heads;
274     sectors = geometry.sectors;
275     cylinders = geometry.cylinders;
276     } else {
277     heads = 0;
278     sectors = 0;
279     cylinders = 0;
280     }
281     if (floppy) {
282     sunlabel->nacyl = 0;
283     sunlabel->pcylcount = SUN_SSWAP16(cylinders);
284     sunlabel->rspeed = SUN_SSWAP16(300);
285     sunlabel->ilfact = SUN_SSWAP16(1);
286     sunlabel->sparecyl = 0;
287     } else {
288     heads = read_int(1,heads,1024,0,_("Heads"));
289     sectors = read_int(1,sectors,1024,0,_("Sectors/track"));
290     if (cylinders)
291     cylinders = read_int(1,cylinders-2,65535,0,_("Cylinders"));
292     else
293     cylinders = read_int(1,0,65535,0,_("Cylinders"));
294     sunlabel->nacyl = SUN_SSWAP16(read_int(0,2,65535,0, _("Alternate cylinders")));
295     sunlabel->pcylcount = SUN_SSWAP16(read_int(0,cylinders+SUN_SSWAP16(sunlabel->nacyl), 65535,0, _("Physical cylinders")));
296     sunlabel->rspeed = SUN_SSWAP16(read_int(1,5400,100000,0, _("Rotation speed (rpm)")));
297     sunlabel->ilfact = SUN_SSWAP16(read_int(1,1,32,0, _("Interleave factor")));
298     sunlabel->sparecyl = SUN_SSWAP16(read_int(0,0,sectors,0, _("Extra sectors per cylinder")));
299     }
300     } else {
301     sunlabel->sparecyl = SUN_SSWAP16(p->sparecyl);
302     sunlabel->ncyl = SUN_SSWAP16(p->ncyl);
303     sunlabel->nacyl = SUN_SSWAP16(p->nacyl);
304     sunlabel->pcylcount = SUN_SSWAP16(p->pcylcount);
305     sunlabel->ntrks = SUN_SSWAP16(p->ntrks);
306     sunlabel->nsect = SUN_SSWAP16(p->nsect);
307     sunlabel->rspeed = SUN_SSWAP16(p->rspeed);
308     sunlabel->ilfact = SUN_SSWAP16(1);
309     cylinders = p->ncyl;
310     heads = p->ntrks;
311     sectors = p->nsect;
312     puts(_("You may change all the disk params from the x menu"));
313     }
314    
315     snprintf((char *)(sunlabel->info), sizeof(sunlabel->info),
316     "%s%s%s cyl %d alt %d hd %d sec %d",
317     p ? p->vendor : "", (p && *p->vendor) ? " " : "",
318     p ? p->model : (floppy ? _("3,5\" floppy") : _("Linux custom")),
319     cylinders, SUN_SSWAP16(sunlabel->nacyl), heads, sectors);
320    
321     sunlabel->ntrks = SUN_SSWAP16(heads);
322     sunlabel->nsect = SUN_SSWAP16(sectors);
323     sunlabel->ncyl = SUN_SSWAP16(cylinders);
324     if (floppy)
325     set_sun_partition(0, 0, cylinders * heads * sectors, LINUX_NATIVE);
326     else {
327     if (cylinders * heads * sectors >= 150 * 2048) {
328     ndiv = cylinders - (50 * 2048 / (heads * sectors)); /* 50M swap */
329     } else
330     ndiv = cylinders * 2 / 3;
331     set_sun_partition(0, 0, ndiv * heads * sectors, LINUX_NATIVE);
332     set_sun_partition(1, ndiv * heads * sectors, cylinders * heads * sectors, LINUX_SWAP);
333     sunlabel->infos[1].flags |= 0x01; /* Not mountable */
334     }
335     set_sun_partition(2, 0, cylinders * heads * sectors, SUN_WHOLE_DISK);
336     {
337     unsigned short *ush = (unsigned short *)sunlabel;
338     unsigned short csum = 0;
339     while (ush < (unsigned short *)(&sunlabel->csum))
340     csum ^= *ush++;
341     sunlabel->csum = csum;
342     }
343    
344     set_all_unchanged();
345     set_changed(0);
346     get_boot(create_empty_sun);
347     }
348    
349     static void
350     toggle_sunflags(int i, unsigned char mask)
351     {
352     if (sunlabel->infos[i].flags & mask)
353     sunlabel->infos[i].flags &= ~mask;
354     else
355     sunlabel->infos[i].flags |= mask;
356     set_changed(i);
357     }
358    
359     static void
360     fetch_sun(uint *starts, uint *lens, uint *start, uint *stop)
361     {
362     int i, continuous = 1;
363    
364     *start = 0;
365     *stop = cylinders * heads * sectors;
366     for (i = 0; i < partitions; i++) {
367     if (sunlabel->partitions[i].num_sectors
368     && sunlabel->infos[i].id
369     && sunlabel->infos[i].id != SUN_WHOLE_DISK) {
370     starts[i] = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
371     lens[i] = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
372     if (continuous) {
373     if (starts[i] == *start)
374     *start += lens[i];
375     else if (starts[i] + lens[i] >= *stop)
376     *stop = starts[i];
377     else
378     continuous = 0;
379     /* There will be probably more gaps
380     than one, so lets check afterwards */
381     }
382     } else {
383     starts[i] = 0;
384     lens[i] = 0;
385     }
386     }
387     }
388    
389     static uint *verify_sun_starts;
390    
391     static int
392     verify_sun_cmp(int *a, int *b)
393     {
394     if (*a == -1) return 1;
395     if (*b == -1) return -1;
396     if (verify_sun_starts[*a] > verify_sun_starts[*b]) return 1;
397     return -1;
398     }
399    
400     static void
401     verify_sun(void)
402     {
403     uint starts[8], lens[8], start, stop;
404     int i,j,k,starto,endo;
405     int array[8];
406    
407     verify_sun_starts = starts;
408     fetch_sun(starts,lens,&start,&stop);
409     for (k = 0; k < 7; k++) {
410     for (i = 0; i < 8; i++) {
411     if (k && (lens[i] % (heads * sectors))) {
412     printf(_("Partition %d doesn't end on cylinder boundary\n"), i+1);
413     }
414     if (lens[i]) {
415     for (j = 0; j < i; j++)
416     if (lens[j]) {
417     if (starts[j] == starts[i]+lens[i]) {
418     starts[j] = starts[i]; lens[j] += lens[i];
419     lens[i] = 0;
420     } else if (starts[i] == starts[j]+lens[j]){
421     lens[j] += lens[i];
422     lens[i] = 0;
423     } else if (!k) {
424     if (starts[i] < starts[j]+lens[j]
425     && starts[j] < starts[i]+lens[i]) {
426     starto = starts[i];
427     if (starts[j] > starto)
428     starto = starts[j];
429     endo = starts[i]+lens[i];
430     if (starts[j]+lens[j] < endo)
431     endo = starts[j]+lens[j];
432     printf(_("Partition %d overlaps with others in "
433     "sectors %d-%d\n"), i+1, starto, endo);
434     }
435     }
436     }
437     }
438     }
439     }
440     for (i = 0; i < 8; i++) {
441     if (lens[i])
442     array[i] = i;
443     else
444     array[i] = -1;
445     }
446     qsort(array,SIZE(array),sizeof(array[0]),
447     (int (*)(const void *,const void *)) verify_sun_cmp);
448     if (array[0] == -1) {
449     printf(_("No partitions defined\n"));
450     return;
451     }
452     stop = cylinders * heads * sectors;
453     if (starts[array[0]])
454     printf(_("Unused gap - sectors 0-%d\n"),starts[array[0]]);
455     for (i = 0; i < 7 && array[i+1] != -1; i++) {
456     printf(_("Unused gap - sectors %d-%d\n"),starts[array[i]]+lens[array[i]],starts[array[i+1]]);
457     }
458     start = starts[array[i]] + lens[array[i]];
459     if (start < stop)
460     printf(_("Unused gap - sectors %d-%d\n"),start,stop);
461     }
462    
463     static void
464     add_sun_partition(int n, int sys)
465     {
466     uint start, stop, stop2;
467     uint starts[8], lens[8];
468     int whole_disk = 0;
469    
470     char mesg[256];
471     int i, first, last;
472    
473     if (sunlabel->partitions[n].num_sectors && sunlabel->infos[n].id) {
474     printf(_("Partition %d is already defined. Delete "
475     "it before re-adding it.\n"), n + 1);
476     return;
477     }
478    
479     fetch_sun(starts,lens,&start,&stop);
480     if (stop <= start) {
481     if (n == 2)
482     whole_disk = 1;
483     else {
484     printf(_("Other partitions already cover the whole disk.\nDelete "
485     "some/shrink them before retry.\n"));
486     return;
487     }
488     }
489     snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
490     while (1) {
491     if (whole_disk)
492     first = read_int(0, 0, 0, 0, mesg);
493     else
494     first = read_int(scround(start), scround(stop)+1,
495     scround(stop), 0, mesg);
496     if (display_in_cyl_units)
497     first *= units_per_sector;
498     else
499     /* Starting sector has to be properly aligned */
500     first = (first + heads * sectors - 1) / (heads * sectors);
501     if (n == 2 && first != 0)
502     printf("\
503     It is highly recommended that the third partition covers the whole disk\n\
504     and is of type `Whole disk'\n");
505     /* ewt asks to add: "don't start a partition at cyl 0"
506     However, edmundo@rano.demon.co.uk writes:
507     "In addition to having a Sun partition table, to be able to
508     boot from the disc, the first partition, /dev/sdX1, must
509     start at cylinder 0. This means that /dev/sdX1 contains
510     the partition table and the boot block, as these are the
511     first two sectors of the disc. Therefore you must be
512     careful what you use /dev/sdX1 for. In particular, you must
513     not use a partition starting at cylinder 0 for Linux swap,
514     as that would overwrite the partition table and the boot
515     block. You may, however, use such a partition for a UFS
516     or EXT2 file system, as these file systems leave the first
517     1024 bytes undisturbed. */
518     /* On the other hand, one should not use partitions
519     starting at block 0 in an md, or the label will
520     be trashed. */
521     for (i = 0; i < partitions; i++)
522     if (lens[i] && starts[i] <= first && starts[i] + lens[i] > first)
523     break;
524     if (i < partitions && !whole_disk) {
525     if (n == 2 && !first) {
526     whole_disk = 1;
527     break;
528     }
529     printf(_("Sector %d is already allocated\n"), first);
530     } else
531     break;
532     }
533     stop = cylinders * heads * sectors;
534     stop2 = stop;
535     for (i = 0; i < partitions; i++) {
536     if (starts[i] > first && starts[i] < stop)
537     stop = starts[i];
538     }
539     snprintf(mesg, sizeof(mesg),
540     _("Last %s or +size or +sizeM or +sizeK"),
541     str_units(SINGULAR));
542     if (whole_disk)
543     last = read_int(scround(stop2), scround(stop2), scround(stop2),
544     0, mesg);
545     else if (n == 2 && !first)
546     last = read_int(scround(first), scround(stop2), scround(stop2),
547     scround(first), mesg);
548     else
549     last = read_int(scround(first), scround(stop), scround(stop),
550     scround(first), mesg);
551     if (display_in_cyl_units)
552     last *= units_per_sector;
553     if (n == 2 && !first) {
554     if (last >= stop2) {
555     whole_disk = 1;
556     last = stop2;
557     } else if (last > stop) {
558     printf(_("You haven't covered the whole disk with "
559     "the 3rd partition, but your value\n"
560     "%d %s covers some other partition. "
561     "Your entry has been changed\n"
562     "to %d %s\n"),
563     scround(last), str_units(SINGULAR),
564     scround(stop), str_units(SINGULAR));
565     last = stop;
566     }
567     } else if (!whole_disk && last > stop)
568     last = stop;
569    
570     if (whole_disk)
571     sys = SUN_WHOLE_DISK;
572     set_sun_partition(n, first, last, sys);
573     }
574    
575     static void
576     sun_delete_partition(int i)
577     {
578     unsigned int nsec;
579    
580     if (i == 2
581     && sunlabel->infos[i].id == SUN_WHOLE_DISK
582     && !sunlabel->partitions[i].start_cylinder
583     && (nsec = SUN_SSWAP32(sunlabel->partitions[i].num_sectors)) == heads * sectors * cylinders)
584     printf(_("If you want to maintain SunOS/Solaris compatibility, "
585     "consider leaving this\n"
586     "partition as Whole disk (5), starting at 0, with %u "
587     "sectors\n"), nsec);
588     sunlabel->infos[i].id = 0;
589     sunlabel->partitions[i].num_sectors = 0;
590     }
591    
592     static void
593     sun_change_sysid(int i, int sys)
594     {
595     if (sys == LINUX_SWAP && !sunlabel->partitions[i].start_cylinder) {
596     read_maybe_empty(
597     _("It is highly recommended that the partition at offset 0\n"
598     "is UFS, EXT2FS filesystem or SunOS swap. Putting Linux swap\n"
599     "there may destroy your partition table and bootblock.\n"
600     "Type YES if you're very sure you would like that partition\n"
601     "tagged with 82 (Linux swap): "));
602     if (strcmp (line_ptr, _("YES\n")))
603     return;
604     }
605     switch (sys) {
606     case SUNOS_SWAP:
607     case LINUX_SWAP:
608     /* swaps are not mountable by default */
609     sunlabel->infos[i].flags |= 0x01;
610     break;
611     default:
612     /* assume other types are mountable;
613     user can change it anyway */
614     sunlabel->infos[i].flags &= ~0x01;
615     break;
616     }
617     sunlabel->infos[i].id = sys;
618     }
619    
620     static void
621     sun_list_table(int xtra)
622     {
623     int i, w;
624    
625     w = strlen(disk_device);
626     if (xtra)
627     printf(
628     _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d rpm\n"
629     "%d cylinders, %d alternate cylinders, %d physical cylinders\n"
630     "%d extra sects/cyl, interleave %d:1\n"
631     "%s\n"
632     "Units = %s of %d * 512 bytes\n\n"),
633     disk_device, heads, sectors, SUN_SSWAP16(sunlabel->rspeed),
634     cylinders, SUN_SSWAP16(sunlabel->nacyl),
635     SUN_SSWAP16(sunlabel->pcylcount),
636     SUN_SSWAP16(sunlabel->sparecyl),
637     SUN_SSWAP16(sunlabel->ilfact),
638     (char *)sunlabel,
639     str_units(PLURAL), units_per_sector);
640     else
641     printf(
642     _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d cylinders\n"
643     "Units = %s of %d * 512 bytes\n\n"),
644     disk_device, heads, sectors, cylinders,
645     str_units(PLURAL), units_per_sector);
646    
647     printf(_("%*s Flag Start End Blocks Id System\n"),
648     w + 1, _("Device"));
649     for (i = 0 ; i < partitions; i++) {
650     if (sunlabel->partitions[i].num_sectors) {
651     uint32_t start = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
652     uint32_t len = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
653     printf("%s %c%c %9ld %9ld %9ld%c %2x %s\n",
654     partname(disk_device, i+1, w), /* device */
655     (sunlabel->infos[i].flags & 0x01) ? 'u' : ' ', /* flags */
656     (sunlabel->infos[i].flags & 0x10) ? 'r' : ' ',
657     (long) scround(start), /* start */
658     (long) scround(start+len), /* end */
659     (long) len / 2, len & 1 ? '+' : ' ', /* odd flag on end */
660     sunlabel->infos[i].id, /* type id */
661     partition_type(sunlabel->infos[i].id)); /* type name */
662     }
663     }
664     }
665    
666     #if ENABLE_FEATURE_FDISK_ADVANCED
667    
668     static void
669     sun_set_alt_cyl(void)
670     {
671     sunlabel->nacyl =
672     SUN_SSWAP16(read_int(0,SUN_SSWAP16(sunlabel->nacyl), 65535, 0,
673     _("Number of alternate cylinders")));
674     }
675    
676     static void
677     sun_set_ncyl(int cyl)
678     {
679     sunlabel->ncyl = SUN_SSWAP16(cyl);
680     }
681    
682     static void
683     sun_set_xcyl(void)
684     {
685     sunlabel->sparecyl =
686     SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->sparecyl), sectors, 0,
687     _("Extra sectors per cylinder")));
688     }
689    
690     static void
691     sun_set_ilfact(void)
692     {
693     sunlabel->ilfact =
694     SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->ilfact), 32, 0,
695     _("Interleave factor")));
696     }
697    
698     static void
699     sun_set_rspeed(void)
700     {
701     sunlabel->rspeed =
702     SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->rspeed), 100000, 0,
703     _("Rotation speed (rpm)")));
704     }
705    
706     static void
707     sun_set_pcylcount(void)
708     {
709     sunlabel->pcylcount =
710     SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->pcylcount), 65535, 0,
711     _("Number of physical cylinders")));
712     }
713     #endif /* FEATURE_FDISK_ADVANCED */
714    
715     static void
716     sun_write_table(void)
717     {
718     unsigned short *ush = (unsigned short *)sunlabel;
719     unsigned short csum = 0;
720    
721     while (ush < (unsigned short *)(&sunlabel->csum))
722     csum ^= *ush++;
723     sunlabel->csum = csum;
724     if (lseek(fd, 0, SEEK_SET) < 0)
725     fdisk_fatal(unable_to_seek);
726     if (write(fd, sunlabel, SECTOR_SIZE) != SECTOR_SIZE)
727     fdisk_fatal(unable_to_write);
728     }
729     #endif /* SUN_LABEL */