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