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