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