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