]> git.ipfire.org Git - thirdparty/util-linux.git/blob - fdisk/fdisk.c
fdisk: doesn't handle large (4KiB) sectors properly
[thirdparty/util-linux.git] / fdisk / fdisk.c
1 /* fdisk.c -- Partition table manipulator for Linux.
2 *
3 * Copyright (C) 1992 A. V. Le Blanc (LeBlanc@mcc.ac.uk)
4 *
5 * This program is free software. You can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation: either version 1 or
8 * (at your option) any later version.
9 */
10
11 #include <unistd.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <fcntl.h>
16 #include <ctype.h>
17 #include <setjmp.h>
18 #include <errno.h>
19 #include <getopt.h>
20 #include <sys/stat.h>
21 #include <sys/time.h>
22 #include <time.h>
23 #include <limits.h>
24
25 #include "nls.h"
26 #include "blkdev.h"
27 #include "common.h"
28 #include "fdisk.h"
29
30 #include "fdisksunlabel.h"
31 #include "fdisksgilabel.h"
32 #include "fdiskaixlabel.h"
33 #include "fdiskmaclabel.h"
34
35 #ifdef HAVE_LINUX_COMPILER_H
36 #include <linux/compiler.h>
37 #endif
38 #ifdef HAVE_LINUX_BLKPG_H
39 #include <linux/blkpg.h>
40 #endif
41
42 #include "gpt.h"
43
44 static void delete_partition(int i);
45
46 #define hex_val(c) ({ \
47 char _c = (c); \
48 isdigit(_c) ? _c - '0' : \
49 tolower(_c) + 10 - 'a'; \
50 })
51
52
53 #define LINE_LENGTH 800
54 #define pt_offset(b, n) ((struct partition *)((b) + 0x1be + \
55 (n) * sizeof(struct partition)))
56 #define sector(s) ((s) & 0x3f)
57 #define cylinder(s, c) ((c) | (((s) & 0xc0) << 2))
58
59 #define hsc2sector(h,s,c) (sector(s) - 1 + sectors * \
60 ((h) + heads * cylinder(s,c)))
61 #define set_hsc(h,s,c,sector) { \
62 s = sector % sectors + 1; \
63 sector /= sectors; \
64 h = sector % heads; \
65 sector /= heads; \
66 c = sector & 0xff; \
67 s |= (sector >> 2) & 0xc0; \
68 }
69
70 /* A valid partition table sector ends in 0x55 0xaa */
71 static unsigned int
72 part_table_flag(unsigned char *b) {
73 return ((unsigned int) b[510]) + (((unsigned int) b[511]) << 8);
74 }
75
76 int
77 valid_part_table_flag(unsigned char *b) {
78 return (b[510] == 0x55 && b[511] == 0xaa);
79 }
80
81 static void
82 write_part_table_flag(unsigned char *b) {
83 b[510] = 0x55;
84 b[511] = 0xaa;
85 }
86
87 /* start_sect and nr_sects are stored little endian on all machines */
88 /* moreover, they are not aligned correctly */
89 static void
90 store4_little_endian(unsigned char *cp, unsigned int val) {
91 cp[0] = (val & 0xff);
92 cp[1] = ((val >> 8) & 0xff);
93 cp[2] = ((val >> 16) & 0xff);
94 cp[3] = ((val >> 24) & 0xff);
95 }
96
97 static unsigned int
98 read4_little_endian(const unsigned char *cp) {
99 return (unsigned int)(cp[0]) + ((unsigned int)(cp[1]) << 8)
100 + ((unsigned int)(cp[2]) << 16)
101 + ((unsigned int)(cp[3]) << 24);
102 }
103
104 static void
105 set_start_sect(struct partition *p, unsigned int start_sect) {
106 store4_little_endian(p->start4, start_sect);
107 }
108
109 unsigned long long
110 get_start_sect(struct partition *p) {
111 return read4_little_endian(p->start4);
112 }
113
114 static void
115 set_nr_sects(struct partition *p, unsigned long long nr_sects) {
116 store4_little_endian(p->size4, nr_sects);
117 }
118
119 unsigned long long
120 get_nr_sects(struct partition *p) {
121 return read4_little_endian(p->size4);
122 }
123
124 static ssize_t
125 xread(int fd, void *buf, size_t count) {
126 char *p = buf;
127 ssize_t out = 0;
128 ssize_t rv;
129
130 while (count) {
131 rv = read(fd, p, count);
132 if (rv == -1) {
133 if (errno == EINTR || errno == EAGAIN)
134 continue;
135 return out ? out : -1; /* Error */
136 } else if (rv == 0) {
137 return out; /* EOF */
138 }
139
140 p += rv;
141 out += rv;
142 count -= rv;
143 }
144
145 return out;
146 }
147
148 static unsigned int
149 get_random_id(void) {
150 int fd;
151 unsigned int v;
152 ssize_t rv = -1;
153 struct timeval tv;
154
155 fd = open("/dev/urandom", O_RDONLY);
156 if (fd >= 0) {
157 rv = xread(fd, &v, sizeof v);
158 close(fd);
159 }
160
161 if (rv == sizeof v)
162 return v;
163
164 /* Fallback: sucks, but better than nothing */
165 gettimeofday(&tv, NULL);
166 return (unsigned int)(tv.tv_sec + (tv.tv_usec << 12) + getpid());
167 }
168
169 /* normally O_RDWR, -l option gives O_RDONLY */
170 static int type_open = O_RDWR;
171
172 /*
173 * Raw disk label. For DOS-type partition tables the MBR,
174 * with descriptions of the primary partitions.
175 */
176 unsigned char MBRbuffer[MAX_SECTOR_SIZE];
177
178 /*
179 * per partition table entry data
180 *
181 * The four primary partitions have the same sectorbuffer (MBRbuffer)
182 * and have NULL ext_pointer.
183 * Each logical partition table entry has two pointers, one for the
184 * partition and one link to the next one.
185 */
186 struct pte {
187 struct partition *part_table; /* points into sectorbuffer */
188 struct partition *ext_pointer; /* points into sectorbuffer */
189 char changed; /* boolean */
190 unsigned long long offset; /* disk sector number */
191 unsigned char *sectorbuffer; /* disk sector contents */
192 } ptes[MAXIMUM_PARTS];
193
194 char *disk_device, /* must be specified */
195 *line_ptr, /* interactive input */
196 line_buffer[LINE_LENGTH];
197
198 int fd, /* the disk */
199 ext_index, /* the prime extended partition */
200 listing = 0, /* no aborts for fdisk -l */
201 nowarn = 0, /* no warnings for fdisk -l/-s */
202 dos_compatible_flag = ~0,
203 dos_changed = 0,
204 partitions = 4; /* maximum partition + 1 */
205
206 unsigned int user_cylinders, user_heads, user_sectors;
207 unsigned int pt_heads, pt_sectors;
208 unsigned int kern_heads, kern_sectors;
209
210 unsigned long long sector_offset = 1, extended_offset = 0, sectors;
211
212 unsigned int heads,
213 cylinders,
214 sector_size = DEFAULT_SECTOR_SIZE,
215 sector_factor = 1,
216 user_set_sector_size = 0,
217 units_per_sector = 1,
218 display_in_cyl_units = 1;
219
220 unsigned long long total_number_of_sectors;
221
222 #define dos_label (!sun_label && !sgi_label && !aix_label && !mac_label && !osf_label)
223 int sun_label = 0; /* looking at sun disklabel */
224 int sgi_label = 0; /* looking at sgi disklabel */
225 int aix_label = 0; /* looking at aix disklabel */
226 int osf_label = 0; /* looking at OSF/1 disklabel */
227 int mac_label = 0; /* looking at mac disklabel */
228 int possibly_osf_label = 0;
229
230 jmp_buf listingbuf;
231
232 void fatal(enum failure why) {
233 char error[LINE_LENGTH],
234 *message = error;
235
236 if (listing) {
237 close(fd);
238 longjmp(listingbuf, 1);
239 }
240
241 switch (why) {
242 case usage: message = _(
243 "Usage: fdisk [-b SSZ] [-u] DISK Change partition table\n"
244 " fdisk -l [-b SSZ] [-u] DISK List partition table(s)\n"
245 " fdisk -s PARTITION Give partition size(s) in blocks\n"
246 " fdisk -v Give fdisk version\n"
247 "Here DISK is something like /dev/hdb or /dev/sda\n"
248 "and PARTITION is something like /dev/hda7\n"
249 "-u: give Start and End in sector (instead of cylinder) units\n"
250 "-b 2048: (for certain MO disks) use 2048-byte sectors\n");
251 break;
252 case usage2:
253 /* msg in cases where fdisk used to probe */
254 message = _(
255 "Usage: fdisk [-l] [-b SSZ] [-u] device\n"
256 "E.g.: fdisk /dev/hda (for the first IDE disk)\n"
257 " or: fdisk /dev/sdc (for the third SCSI disk)\n"
258 " or: fdisk /dev/eda (for the first PS/2 ESDI drive)\n"
259 " or: fdisk /dev/rd/c0d0 or: fdisk /dev/ida/c0d0 (for RAID devices)\n"
260 " ...\n");
261 break;
262 case unable_to_open:
263 snprintf(error, sizeof(error),
264 _("Unable to open %s\n"), disk_device);
265 break;
266 case unable_to_read:
267 snprintf(error, sizeof(error),
268 _("Unable to read %s\n"), disk_device);
269 break;
270 case unable_to_seek:
271 snprintf(error, sizeof(error),
272 _("Unable to seek on %s\n"),disk_device);
273 break;
274 case unable_to_write:
275 snprintf(error, sizeof(error),
276 _("Unable to write %s\n"), disk_device);
277 break;
278 case ioctl_error:
279 snprintf(error, sizeof(error),
280 _("BLKGETSIZE ioctl failed on %s\n"),
281 disk_device);
282 break;
283 case out_of_memory:
284 message = _("Unable to allocate any more memory\n");
285 break;
286 default:
287 message = _("Fatal error\n");
288 }
289
290 fputc('\n', stderr);
291 fputs(message, stderr);
292 exit(1);
293 }
294
295 static void
296 seek_sector(int fd, unsigned long long secno) {
297 off_t offset = (off_t) secno * sector_size;
298 if (lseek(fd, offset, SEEK_SET) == (off_t) -1)
299 fatal(unable_to_seek);
300 }
301
302 static void
303 read_sector(int fd, unsigned long long secno, unsigned char *buf) {
304 seek_sector(fd, secno);
305 if (read(fd, buf, sector_size) != sector_size)
306 fatal(unable_to_read);
307 }
308
309 static void
310 write_sector(int fd, unsigned long long secno, unsigned char *buf) {
311 seek_sector(fd, secno);
312 if (write(fd, buf, sector_size) != sector_size)
313 fatal(unable_to_write);
314 }
315
316 /* Allocate a buffer and read a partition table sector */
317 static void
318 read_pte(int fd, int pno, unsigned long long offset) {
319 struct pte *pe = &ptes[pno];
320
321 pe->offset = offset;
322 pe->sectorbuffer = malloc(sector_size);
323 if (!pe->sectorbuffer)
324 fatal(out_of_memory);
325 read_sector(fd, offset, pe->sectorbuffer);
326 pe->changed = 0;
327 pe->part_table = pe->ext_pointer = NULL;
328 }
329
330 static unsigned long long
331 get_partition_start(struct pte *pe) {
332 return pe->offset + get_start_sect(pe->part_table);
333 }
334
335 struct partition *
336 get_part_table(int i) {
337 return ptes[i].part_table;
338 }
339
340 void
341 set_all_unchanged(void) {
342 int i;
343
344 for (i = 0; i < MAXIMUM_PARTS; i++)
345 ptes[i].changed = 0;
346 }
347
348 void
349 set_changed(int i) {
350 ptes[i].changed = 1;
351 }
352
353 static int
354 is_garbage_table(void) {
355 int i;
356
357 for (i = 0; i < 4; i++) {
358 struct pte *pe = &ptes[i];
359 struct partition *p = pe->part_table;
360
361 if (p->boot_ind != 0 && p->boot_ind != 0x80)
362 return 1;
363 }
364 return 0;
365 }
366
367 /*
368 * Avoid warning about DOS partitions when no DOS partition was changed.
369 * Here a heuristic "is probably dos partition".
370 * We might also do the opposite and warn in all cases except
371 * for "is probably nondos partition".
372 */
373 static int
374 is_dos_partition(int t) {
375 return (t == 1 || t == 4 || t == 6 ||
376 t == 0x0b || t == 0x0c || t == 0x0e ||
377 t == 0x11 || t == 0x12 || t == 0x14 || t == 0x16 ||
378 t == 0x1b || t == 0x1c || t == 0x1e || t == 0x24 ||
379 t == 0xc1 || t == 0xc4 || t == 0xc6);
380 }
381
382 static void
383 menu(void) {
384 if (sun_label) {
385 puts(_("Command action"));
386 puts(_(" a toggle a read only flag")); /* sun */
387 puts(_(" b edit bsd disklabel"));
388 puts(_(" c toggle the mountable flag")); /* sun */
389 puts(_(" d delete a partition"));
390 puts(_(" l list known partition types"));
391 puts(_(" m print this menu"));
392 puts(_(" n add a new partition"));
393 puts(_(" o create a new empty DOS partition table"));
394 puts(_(" p print the partition table"));
395 puts(_(" q quit without saving changes"));
396 puts(_(" s create a new empty Sun disklabel")); /* sun */
397 puts(_(" t change a partition's system id"));
398 puts(_(" u change display/entry units"));
399 puts(_(" v verify the partition table"));
400 puts(_(" w write table to disk and exit"));
401 puts(_(" x extra functionality (experts only)"));
402 }
403 else if (sgi_label) {
404 puts(_("Command action"));
405 puts(_(" a select bootable partition")); /* sgi flavour */
406 puts(_(" b edit bootfile entry")); /* sgi */
407 puts(_(" c select sgi swap partition")); /* sgi flavour */
408 puts(_(" d delete a partition"));
409 puts(_(" l list known partition types"));
410 puts(_(" m print this menu"));
411 puts(_(" n add a new partition"));
412 puts(_(" o create a new empty DOS partition table"));
413 puts(_(" p print the partition table"));
414 puts(_(" q quit without saving changes"));
415 puts(_(" s create a new empty Sun disklabel")); /* sun */
416 puts(_(" t change a partition's system id"));
417 puts(_(" u change display/entry units"));
418 puts(_(" v verify the partition table"));
419 puts(_(" w write table to disk and exit"));
420 }
421 else if (aix_label || mac_label) {
422 puts(_("Command action"));
423 puts(_(" m print this menu"));
424 puts(_(" o create a new empty DOS partition table"));
425 puts(_(" q quit without saving changes"));
426 puts(_(" s create a new empty Sun disklabel")); /* sun */
427 }
428 else {
429 puts(_("Command action"));
430 puts(_(" a toggle a bootable flag"));
431 puts(_(" b edit bsd disklabel"));
432 puts(_(" c toggle the dos compatibility flag"));
433 puts(_(" d delete a partition"));
434 puts(_(" l list known partition types"));
435 puts(_(" m print this menu"));
436 puts(_(" n add a new partition"));
437 puts(_(" o create a new empty DOS partition table"));
438 puts(_(" p print the partition table"));
439 puts(_(" q quit without saving changes"));
440 puts(_(" s create a new empty Sun disklabel")); /* sun */
441 puts(_(" t change a partition's system id"));
442 puts(_(" u change display/entry units"));
443 puts(_(" v verify the partition table"));
444 puts(_(" w write table to disk and exit"));
445 puts(_(" x extra functionality (experts only)"));
446 }
447 }
448
449 static void
450 xmenu(void) {
451 if (sun_label) {
452 puts(_("Command action"));
453 puts(_(" a change number of alternate cylinders")); /*sun*/
454 puts(_(" c change number of cylinders"));
455 puts(_(" d print the raw data in the partition table"));
456 puts(_(" e change number of extra sectors per cylinder"));/*sun*/
457 puts(_(" h change number of heads"));
458 puts(_(" i change interleave factor")); /*sun*/
459 puts(_(" o change rotation speed (rpm)")); /*sun*/
460 puts(_(" m print this menu"));
461 puts(_(" p print the partition table"));
462 puts(_(" q quit without saving changes"));
463 puts(_(" r return to main menu"));
464 puts(_(" s change number of sectors/track"));
465 puts(_(" v verify the partition table"));
466 puts(_(" w write table to disk and exit"));
467 puts(_(" y change number of physical cylinders")); /*sun*/
468 }
469 else if (sgi_label) {
470 puts(_("Command action"));
471 puts(_(" b move beginning of data in a partition")); /* !sun */
472 puts(_(" c change number of cylinders"));
473 puts(_(" d print the raw data in the partition table"));
474 puts(_(" e list extended partitions")); /* !sun */
475 puts(_(" g create an IRIX (SGI) partition table"));/* sgi */
476 puts(_(" h change number of heads"));
477 puts(_(" m print this menu"));
478 puts(_(" p print the partition table"));
479 puts(_(" q quit without saving changes"));
480 puts(_(" r return to main menu"));
481 puts(_(" s change number of sectors/track"));
482 puts(_(" v verify the partition table"));
483 puts(_(" w write table to disk and exit"));
484 }
485 else if (aix_label || mac_label) {
486 puts(_("Command action"));
487 puts(_(" b move beginning of data in a partition")); /* !sun */
488 puts(_(" c change number of cylinders"));
489 puts(_(" d print the raw data in the partition table"));
490 puts(_(" e list extended partitions")); /* !sun */
491 puts(_(" g create an IRIX (SGI) partition table"));/* sgi */
492 puts(_(" h change number of heads"));
493 puts(_(" m print this menu"));
494 puts(_(" p print the partition table"));
495 puts(_(" q quit without saving changes"));
496 puts(_(" r return to main menu"));
497 puts(_(" s change number of sectors/track"));
498 puts(_(" v verify the partition table"));
499 puts(_(" w write table to disk and exit"));
500 }
501 else {
502 puts(_("Command action"));
503 puts(_(" b move beginning of data in a partition")); /* !sun */
504 puts(_(" c change number of cylinders"));
505 puts(_(" d print the raw data in the partition table"));
506 puts(_(" e list extended partitions")); /* !sun */
507 puts(_(" f fix partition order")); /* !sun, !aix, !sgi */
508 puts(_(" g create an IRIX (SGI) partition table"));/* sgi */
509 puts(_(" h change number of heads"));
510 puts(_(" i change the disk identifier")); /* dos only */
511 puts(_(" m print this menu"));
512 puts(_(" p print the partition table"));
513 puts(_(" q quit without saving changes"));
514 puts(_(" r return to main menu"));
515 puts(_(" s change number of sectors/track"));
516 puts(_(" v verify the partition table"));
517 puts(_(" w write table to disk and exit"));
518 }
519 }
520
521 static int
522 get_sysid(int i) {
523 return (
524 sun_label ? sun_get_sysid(i) :
525 sgi_label ? sgi_get_sysid(i) :
526 ptes[i].part_table->sys_ind);
527 }
528
529 static struct systypes *
530 get_sys_types(void) {
531 return (
532 sun_label ? sun_sys_types :
533 sgi_label ? sgi_sys_types :
534 i386_sys_types);
535 }
536
537 char *partition_type(unsigned char type)
538 {
539 int i;
540 struct systypes *types = get_sys_types();
541
542 for (i=0; types[i].name; i++)
543 if (types[i].type == type)
544 return _(types[i].name);
545
546 return NULL;
547 }
548
549 void list_types(struct systypes *sys)
550 {
551 unsigned int last[4], done = 0, next = 0, size;
552 int i;
553
554 for (i = 0; sys[i].name; i++);
555 size = i;
556
557 for (i = 3; i >= 0; i--)
558 last[3 - i] = done += (size + i - done) / (i + 1);
559 i = done = 0;
560
561 do {
562 printf("%c%2x %-15.15s", i ? ' ' : '\n',
563 sys[next].type, _(sys[next].name));
564 next = last[i++] + done;
565 if (i > 3 || next >= last[i]) {
566 i = 0;
567 next = ++done;
568 }
569 } while (done < last[0]);
570 putchar('\n');
571 }
572
573 static int
574 is_cleared_partition(struct partition *p) {
575 return !(!p || p->boot_ind || p->head || p->sector || p->cyl ||
576 p->sys_ind || p->end_head || p->end_sector || p->end_cyl ||
577 get_start_sect(p) || get_nr_sects(p));
578 }
579
580 static void
581 clear_partition(struct partition *p) {
582 if (!p)
583 return;
584 p->boot_ind = 0;
585 p->head = 0;
586 p->sector = 0;
587 p->cyl = 0;
588 p->sys_ind = 0;
589 p->end_head = 0;
590 p->end_sector = 0;
591 p->end_cyl = 0;
592 set_start_sect(p,0);
593 set_nr_sects(p,0);
594 }
595
596 static void
597 set_partition(int i, int doext, unsigned long long start,
598 unsigned long long stop, int sysid) {
599 struct partition *p;
600 unsigned long long offset;
601
602 if (doext) {
603 p = ptes[i].ext_pointer;
604 offset = extended_offset;
605 } else {
606 p = ptes[i].part_table;
607 offset = ptes[i].offset;
608 }
609 p->boot_ind = 0;
610 p->sys_ind = sysid;
611 set_start_sect(p, start - offset);
612 set_nr_sects(p, stop - start + 1);
613 if (dos_compatible_flag && (start/(sectors*heads) > 1023))
614 start = heads*sectors*1024 - 1;
615 set_hsc(p->head, p->sector, p->cyl, start);
616 if (dos_compatible_flag && (stop/(sectors*heads) > 1023))
617 stop = heads*sectors*1024 - 1;
618 set_hsc(p->end_head, p->end_sector, p->end_cyl, stop);
619 ptes[i].changed = 1;
620 }
621
622 static int
623 test_c(char **m, char *mesg) {
624 int val = 0;
625 if (!*m)
626 fprintf(stderr, _("You must set"));
627 else {
628 fprintf(stderr, " %s", *m);
629 val = 1;
630 }
631 *m = mesg;
632 return val;
633 }
634
635 static int
636 warn_geometry(void) {
637 char *m = NULL;
638 int prev = 0;
639
640 if (sgi_label) /* cannot set cylinders etc anyway */
641 return 0;
642 if (!heads)
643 prev = test_c(&m, _("heads"));
644 if (!sectors)
645 prev = test_c(&m, _("sectors"));
646 if (!cylinders)
647 prev = test_c(&m, _("cylinders"));
648 if (!m)
649 return 0;
650 fprintf(stderr,
651 _("%s%s.\nYou can do this from the extra functions menu.\n"),
652 prev ? _(" and ") : " ", m);
653 return 1;
654 }
655
656 void update_units(void)
657 {
658 int cyl_units = heads * sectors;
659
660 if (display_in_cyl_units && cyl_units)
661 units_per_sector = cyl_units;
662 else
663 units_per_sector = 1; /* in sectors */
664 }
665
666 static void
667 warn_cylinders(void) {
668 if (dos_label && cylinders > 1024 && !nowarn)
669 fprintf(stderr, _("\n"
670 "The number of cylinders for this disk is set to %d.\n"
671 "There is nothing wrong with that, but this is larger than 1024,\n"
672 "and could in certain setups cause problems with:\n"
673 "1) software that runs at boot time (e.g., old versions of LILO)\n"
674 "2) booting and partitioning software from other OSs\n"
675 " (e.g., DOS FDISK, OS/2 FDISK)\n"),
676 cylinders);
677
678 if (total_number_of_sectors > UINT_MAX) {
679 int giga = (total_number_of_sectors << 9) / 1000000000;
680 int hectogiga = (giga + 50) / 100;
681
682 fprintf(stderr, _("\n"
683 "WARNING: The size of this disk is %d.%d TB (%llu bytes).\n"
684 "DOS partition table format can not be used on drives for volumes\n"
685 "larger than 2.2 TB (2199023255040 bytes). Use parted(1) and GUID \n"
686 "partition table format (GPT).\n\n"),
687 hectogiga / 10, hectogiga % 10,
688 total_number_of_sectors << 9);
689 }
690 }
691
692 static void
693 read_extended(int ext) {
694 int i;
695 struct pte *pex;
696 struct partition *p, *q;
697
698 ext_index = ext;
699 pex = &ptes[ext];
700 pex->ext_pointer = pex->part_table;
701
702 p = pex->part_table;
703 if (!get_start_sect(p)) {
704 fprintf(stderr,
705 _("Bad offset in primary extended partition\n"));
706 return;
707 }
708
709 while (IS_EXTENDED (p->sys_ind)) {
710 struct pte *pe = &ptes[partitions];
711
712 if (partitions >= MAXIMUM_PARTS) {
713 /* This is not a Linux restriction, but
714 this program uses arrays of size MAXIMUM_PARTS.
715 Do not try to `improve' this test. */
716 struct pte *pre = &ptes[partitions-1];
717
718 fprintf(stderr,
719 _("Warning: omitting partitions after #%d.\n"
720 "They will be deleted "
721 "if you save this partition table.\n"),
722 partitions);
723 clear_partition(pre->ext_pointer);
724 pre->changed = 1;
725 return;
726 }
727
728 read_pte(fd, partitions, extended_offset + get_start_sect(p));
729
730 if (!extended_offset)
731 extended_offset = get_start_sect(p);
732
733 q = p = pt_offset(pe->sectorbuffer, 0);
734 for (i = 0; i < 4; i++, p++) if (get_nr_sects(p)) {
735 if (IS_EXTENDED (p->sys_ind)) {
736 if (pe->ext_pointer)
737 fprintf(stderr,
738 _("Warning: extra link "
739 "pointer in partition table"
740 " %d\n"), partitions + 1);
741 else
742 pe->ext_pointer = p;
743 } else if (p->sys_ind) {
744 if (pe->part_table)
745 fprintf(stderr,
746 _("Warning: ignoring extra "
747 "data in partition table"
748 " %d\n"), partitions + 1);
749 else
750 pe->part_table = p;
751 }
752 }
753
754 /* very strange code here... */
755 if (!pe->part_table) {
756 if (q != pe->ext_pointer)
757 pe->part_table = q;
758 else
759 pe->part_table = q + 1;
760 }
761 if (!pe->ext_pointer) {
762 if (q != pe->part_table)
763 pe->ext_pointer = q;
764 else
765 pe->ext_pointer = q + 1;
766 }
767
768 p = pe->ext_pointer;
769 partitions++;
770 }
771
772 /* remove empty links */
773 remove:
774 for (i = 4; i < partitions; i++) {
775 struct pte *pe = &ptes[i];
776
777 if (!get_nr_sects(pe->part_table) &&
778 (partitions > 5 || ptes[4].part_table->sys_ind)) {
779 printf(_("omitting empty partition (%d)\n"), i+1);
780 delete_partition(i);
781 goto remove; /* numbering changed */
782 }
783 }
784 }
785
786 static void
787 dos_write_mbr_id(unsigned char *b, unsigned int id) {
788 store4_little_endian(&b[440], id);
789 }
790
791 static unsigned int
792 dos_read_mbr_id(const unsigned char *b) {
793 return read4_little_endian(&b[440]);
794 }
795
796 static void
797 dos_print_mbr_id(void) {
798 printf(_("Disk identifier: 0x%08x\n"), dos_read_mbr_id(MBRbuffer));
799 }
800
801 static void
802 dos_set_mbr_id(void) {
803 unsigned long new_id;
804 char *ep;
805 char ps[64];
806
807 snprintf(ps, sizeof ps, _("New disk identifier (current 0x%08x): "),
808 dos_read_mbr_id(MBRbuffer));
809
810 if (read_chars(ps) == '\n')
811 return;
812
813 new_id = strtoul(line_ptr, &ep, 0);
814 if (*ep != '\n')
815 return;
816
817 dos_write_mbr_id(MBRbuffer, new_id);
818 dos_print_mbr_id();
819 }
820
821 static void
822 create_doslabel(void) {
823 unsigned int id = get_random_id();
824
825 fprintf(stderr,
826 _("Building a new DOS disklabel with disk identifier 0x%08x.\n"
827 "Changes will remain in memory only, until you decide to write them.\n"
828 "After that, of course, the previous content won't be recoverable.\n\n"),
829 id);
830 sun_nolabel(); /* otherwise always recognised as sun */
831 sgi_nolabel(); /* otherwise always recognised as sgi */
832 mac_label = aix_label = osf_label = possibly_osf_label = 0;
833 partitions = 4;
834
835 /* Zero out the MBR buffer */
836 extended_offset = 0;
837 set_all_unchanged();
838 set_changed(0);
839 get_boot(create_empty_dos);
840
841 /* Generate an MBR ID for this disk */
842 dos_write_mbr_id(MBRbuffer, id);
843
844 /* Mark it bootable (unfortunately required) */
845 write_part_table_flag(MBRbuffer);
846 }
847
848 static void
849 get_sectorsize(int fd) {
850 int arg;
851
852 if (user_set_sector_size)
853 return;
854
855 if (blkdev_get_sector_size(fd, &arg) == 0)
856 sector_size = arg;
857 if (sector_size != DEFAULT_SECTOR_SIZE)
858 printf(_("Note: sector size is %d (not %d)\n"),
859 sector_size, DEFAULT_SECTOR_SIZE);
860 }
861
862 static void
863 get_kernel_geometry(int fd) {
864 #ifdef HDIO_GETGEO
865 struct hd_geometry geometry;
866
867 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
868 kern_heads = geometry.heads;
869 kern_sectors = geometry.sectors;
870 /* never use geometry.cylinders - it is truncated */
871 }
872 #endif
873 }
874
875 static void
876 get_partition_table_geometry(void) {
877 unsigned char *bufp = MBRbuffer;
878 struct partition *p;
879 int i, h, s, hh, ss;
880 int first = 1;
881 int bad = 0;
882
883 if (!(valid_part_table_flag(bufp)))
884 return;
885
886 hh = ss = 0;
887 for (i=0; i<4; i++) {
888 p = pt_offset(bufp, i);
889 if (p->sys_ind != 0) {
890 h = p->end_head + 1;
891 s = (p->end_sector & 077);
892 if (first) {
893 hh = h;
894 ss = s;
895 first = 0;
896 } else if (hh != h || ss != s)
897 bad = 1;
898 }
899 }
900
901 if (!first && !bad) {
902 pt_heads = hh;
903 pt_sectors = ss;
904 }
905 }
906
907 void
908 get_geometry(int fd, struct geom *g) {
909 unsigned long long llsectors, llcyls;
910
911 get_sectorsize(fd);
912 sector_factor = sector_size / 512;
913 guess_device_type(fd);
914 heads = cylinders = sectors = 0;
915 kern_heads = kern_sectors = 0;
916 pt_heads = pt_sectors = 0;
917
918 get_kernel_geometry(fd);
919 get_partition_table_geometry();
920
921 heads = user_heads ? user_heads :
922 pt_heads ? pt_heads :
923 kern_heads ? kern_heads : 255;
924 sectors = user_sectors ? user_sectors :
925 pt_sectors ? pt_sectors :
926 kern_sectors ? kern_sectors : 63;
927
928 if (blkdev_get_sectors(fd, &llsectors) == -1)
929 llsectors = 0;
930
931 total_number_of_sectors = llsectors;
932
933 sector_offset = 1;
934 if (dos_compatible_flag)
935 sector_offset = sectors;
936
937 llcyls = total_number_of_sectors / (heads * sectors * sector_factor);
938 cylinders = llcyls;
939 if (cylinders != llcyls) /* truncated? */
940 cylinders = ~0;
941 if (!cylinders)
942 cylinders = user_cylinders;
943
944 if (g) {
945 g->heads = heads;
946 g->sectors = sectors;
947 g->cylinders = cylinders;
948 }
949 }
950
951 /*
952 * Read MBR. Returns:
953 * -1: no 0xaa55 flag present (possibly entire disk BSD)
954 * 0: found or created label
955 * 1: I/O error
956 */
957 int
958 get_boot(enum action what) {
959 int i;
960
961 partitions = 4;
962 ext_index = 0;
963 extended_offset = 0;
964
965 for (i = 0; i < 4; i++) {
966 struct pte *pe = &ptes[i];
967
968 pe->part_table = pt_offset(MBRbuffer, i);
969 pe->ext_pointer = NULL;
970 pe->offset = 0;
971 pe->sectorbuffer = MBRbuffer;
972 pe->changed = (what == create_empty_dos);
973 }
974
975 if (what == create_empty_sun && check_sun_label())
976 return 0;
977
978 memset(MBRbuffer, 0, 512);
979
980 if (what == create_empty_dos)
981 goto got_dos_table; /* skip reading disk */
982
983 if ((fd = open(disk_device, type_open)) < 0) {
984 if ((fd = open(disk_device, O_RDONLY)) < 0) {
985 if (what == try_only)
986 return 1;
987 fatal(unable_to_open);
988 } else
989 printf(_("You will not be able to write "
990 "the partition table.\n"));
991 }
992
993 if (512 != read(fd, MBRbuffer, 512)) {
994 if (what == try_only)
995 return 1;
996 fatal(unable_to_read);
997 }
998
999 get_geometry(fd, NULL);
1000
1001 update_units();
1002
1003 if (check_sun_label())
1004 return 0;
1005
1006 if (check_sgi_label())
1007 return 0;
1008
1009 if (check_aix_label())
1010 return 0;
1011
1012 if (check_mac_label())
1013 return 0;
1014
1015 if (check_osf_label()) {
1016 possibly_osf_label = 1;
1017 if (!valid_part_table_flag(MBRbuffer)) {
1018 osf_label = 1;
1019 return 0;
1020 }
1021 printf(_("This disk has both DOS and BSD magic.\n"
1022 "Give the 'b' command to go to BSD mode.\n"));
1023 }
1024
1025 got_dos_table:
1026
1027 if (!valid_part_table_flag(MBRbuffer)) {
1028 switch(what) {
1029 case fdisk:
1030 fprintf(stderr,
1031 _("Device contains neither a valid DOS "
1032 "partition table, nor Sun, SGI or OSF "
1033 "disklabel\n"));
1034 #ifdef __sparc__
1035 create_sunlabel();
1036 #else
1037 create_doslabel();
1038 #endif
1039 return 0;
1040 case require:
1041 return -1;
1042 case try_only:
1043 return -1;
1044 case create_empty_dos:
1045 case create_empty_sun:
1046 break;
1047 default:
1048 fprintf(stderr, _("Internal error\n"));
1049 exit(1);
1050 }
1051 }
1052
1053 warn_cylinders();
1054 warn_geometry();
1055
1056 for (i = 0; i < 4; i++) {
1057 struct pte *pe = &ptes[i];
1058
1059 if (IS_EXTENDED (pe->part_table->sys_ind)) {
1060 if (partitions != 4)
1061 fprintf(stderr, _("Ignoring extra extended "
1062 "partition %d\n"), i + 1);
1063 else
1064 read_extended(i);
1065 }
1066 }
1067
1068 for (i = 3; i < partitions; i++) {
1069 struct pte *pe = &ptes[i];
1070
1071 if (!valid_part_table_flag(pe->sectorbuffer)) {
1072 fprintf(stderr,
1073 _("Warning: invalid flag 0x%04x of partition "
1074 "table %d will be corrected by w(rite)\n"),
1075 part_table_flag(pe->sectorbuffer), i + 1);
1076 pe->changed = 1;
1077 }
1078 }
1079
1080 return 0;
1081 }
1082
1083 /* read line; return 0 or first char */
1084 int
1085 read_line(void)
1086 {
1087 static int got_eof = 0;
1088
1089 line_ptr = line_buffer;
1090 if (!fgets(line_buffer, LINE_LENGTH, stdin)) {
1091 if (feof(stdin))
1092 got_eof++; /* user typed ^D ? */
1093 if (got_eof >= 3) {
1094 fflush(stdout);
1095 fprintf(stderr, _("\ngot EOF thrice - exiting..\n"));
1096 exit(1);
1097 }
1098 return 0;
1099 }
1100 while (*line_ptr && !isgraph(*line_ptr))
1101 line_ptr++;
1102 return *line_ptr;
1103 }
1104
1105 char
1106 read_char(char *mesg)
1107 {
1108 do {
1109 fputs(mesg, stdout);
1110 fflush (stdout); /* requested by niles@scyld.com */
1111 } while (!read_line());
1112 return *line_ptr;
1113 }
1114
1115 char
1116 read_chars(char *mesg)
1117 {
1118 fputs(mesg, stdout);
1119 fflush (stdout); /* niles@scyld.com */
1120 if (!read_line()) {
1121 *line_ptr = '\n';
1122 line_ptr[1] = 0;
1123 }
1124 return *line_ptr;
1125 }
1126
1127 int
1128 read_hex(struct systypes *sys)
1129 {
1130 int hex;
1131
1132 while (1)
1133 {
1134 read_char(_("Hex code (type L to list codes): "));
1135 if (tolower(*line_ptr) == 'l')
1136 list_types(sys);
1137 else if (isxdigit (*line_ptr))
1138 {
1139 hex = 0;
1140 do
1141 hex = hex << 4 | hex_val(*line_ptr++);
1142 while (isxdigit(*line_ptr));
1143 return hex;
1144 }
1145 }
1146 }
1147
1148 /*
1149 * Print the message MESG, then read an integer in LOW..HIGH.
1150 * If the user hits Enter, DFLT is returned, provided that is in LOW..HIGH.
1151 * Answers like +10 are interpreted as offsets from BASE.
1152 *
1153 * There is no default if DFLT is not between LOW and HIGH.
1154 */
1155 unsigned int
1156 read_int(unsigned int low, unsigned int dflt, unsigned int high,
1157 unsigned int base, char *mesg)
1158 {
1159 unsigned int i;
1160 int default_ok = 1;
1161 static char *ms = NULL;
1162 static int mslen = 0;
1163
1164 if (!ms || strlen(mesg)+100 > mslen) {
1165 mslen = strlen(mesg)+200;
1166 if (!(ms = realloc(ms,mslen)))
1167 fatal(out_of_memory);
1168 }
1169
1170 if (dflt < low || dflt > high)
1171 default_ok = 0;
1172
1173 if (default_ok)
1174 snprintf(ms, mslen, _("%s (%u-%u, default %u): "),
1175 mesg, low, high, dflt);
1176 else
1177 snprintf(ms, mslen, "%s (%u-%u): ",
1178 mesg, low, high);
1179
1180 while (1) {
1181 int use_default = default_ok;
1182
1183 /* ask question and read answer */
1184 while (read_chars(ms) != '\n' && !isdigit(*line_ptr)
1185 && *line_ptr != '-' && *line_ptr != '+')
1186 continue;
1187
1188 if (*line_ptr == '+' || *line_ptr == '-') {
1189 int minus = (*line_ptr == '-');
1190 int absolute = 0;
1191 int suflen;
1192
1193 i = atoi(line_ptr+1);
1194
1195 while (isdigit(*++line_ptr))
1196 use_default = 0;
1197
1198 suflen = strlen(line_ptr) - 1;
1199
1200 while(isspace(*(line_ptr + suflen)))
1201 *(line_ptr + suflen--) = '\0';
1202
1203 if ((*line_ptr == 'C' || *line_ptr == 'c') &&
1204 *(line_ptr + 1) == '\0') {
1205 /*
1206 * Cylinders
1207 */
1208 if (!display_in_cyl_units)
1209 i *= heads * sectors;
1210 } else if (*line_ptr &&
1211 *(line_ptr + 1) == 'B' &&
1212 *(line_ptr + 2) == '\0') {
1213 /*
1214 * 10^N
1215 */
1216 if (*line_ptr == 'K')
1217 absolute = 1000;
1218 else if (*line_ptr == 'M')
1219 absolute = 1000000;
1220 else if (*line_ptr == 'G')
1221 absolute = 1000000000;
1222 else
1223 absolute = -1;
1224 } else if (*line_ptr &&
1225 *(line_ptr + 1) == '\0') {
1226 /*
1227 * 2^N
1228 */
1229 if (*line_ptr == 'K')
1230 absolute = 1 << 10;
1231 else if (*line_ptr == 'M')
1232 absolute = 1 << 20;
1233 else if (*line_ptr == 'G')
1234 absolute = 1 << 30;
1235 else
1236 absolute = -1;
1237 } else if (*line_ptr != '\0')
1238 absolute = -1;
1239
1240 if (absolute == -1) {
1241 printf(_("Unsupported suffix: '%s'.\n"), line_ptr);
1242 printf(_("Supported: 10^N: KB (KiloByte), MB (MegaByte), GB (GigaByte)\n"
1243 " 2^N: K (KibiByte), M (MebiByte), G (GibiByte)\n"));
1244 continue;
1245 }
1246
1247 if (absolute && i) {
1248 unsigned long long bytes;
1249 unsigned long unit;
1250
1251 bytes = (unsigned long long) i * absolute;
1252 unit = sector_size * units_per_sector;
1253 bytes += unit/2; /* round */
1254 bytes /= unit;
1255 i = bytes;
1256 }
1257 if (minus)
1258 i = -i;
1259 i += base;
1260 } else {
1261 i = atoi(line_ptr);
1262 while (isdigit(*line_ptr)) {
1263 line_ptr++;
1264 use_default = 0;
1265 }
1266 }
1267 if (use_default)
1268 printf(_("Using default value %u\n"), i = dflt);
1269 if (i >= low && i <= high)
1270 break;
1271 else
1272 printf(_("Value out of range.\n"));
1273 }
1274 return i;
1275 }
1276
1277 int
1278 get_partition(int warn, int max) {
1279 struct pte *pe;
1280 int i;
1281
1282 i = read_int(1, 0, max, 0, _("Partition number")) - 1;
1283 pe = &ptes[i];
1284
1285 if (warn) {
1286 if ((!sun_label && !sgi_label && !pe->part_table->sys_ind)
1287 || (sun_label &&
1288 (!sunlabel->partitions[i].num_sectors ||
1289 !sunlabel->part_tags[i].tag))
1290 || (sgi_label && (!sgi_get_num_sectors(i)))
1291 )
1292 fprintf(stderr,
1293 _("Warning: partition %d has empty type\n"),
1294 i+1);
1295 }
1296 return i;
1297 }
1298
1299 static int
1300 get_existing_partition(int warn, int max) {
1301 int pno = -1;
1302 int i;
1303
1304 for (i = 0; i < max; i++) {
1305 struct pte *pe = &ptes[i];
1306 struct partition *p = pe->part_table;
1307
1308 if (p && !is_cleared_partition(p)) {
1309 if (pno >= 0)
1310 goto not_unique;
1311 pno = i;
1312 }
1313 }
1314 if (pno >= 0) {
1315 printf(_("Selected partition %d\n"), pno+1);
1316 return pno;
1317 }
1318 printf(_("No partition is defined yet!\n"));
1319 return -1;
1320
1321 not_unique:
1322 return get_partition(warn, max);
1323 }
1324
1325 static int
1326 get_nonexisting_partition(int warn, int max) {
1327 int pno = -1;
1328 int i;
1329
1330 for (i = 0; i < max; i++) {
1331 struct pte *pe = &ptes[i];
1332 struct partition *p = pe->part_table;
1333
1334 if (p && is_cleared_partition(p)) {
1335 if (pno >= 0)
1336 goto not_unique;
1337 pno = i;
1338 }
1339 }
1340 if (pno >= 0) {
1341 printf(_("Selected partition %d\n"), pno+1);
1342 return pno;
1343 }
1344 printf(_("All primary partitions have been defined already!\n"));
1345 return -1;
1346
1347 not_unique:
1348 return get_partition(warn, max);
1349 }
1350
1351 const char *
1352 str_units(int n) { /* n==1: use singular */
1353 if (n == 1)
1354 return display_in_cyl_units ? _("cylinder") : _("sector");
1355 else
1356 return display_in_cyl_units ? _("cylinders") : _("sectors");
1357 }
1358
1359 void change_units(void)
1360 {
1361 display_in_cyl_units = !display_in_cyl_units;
1362 update_units();
1363 printf(_("Changing display/entry units to %s\n"),
1364 str_units(PLURAL));
1365 }
1366
1367 static void
1368 toggle_active(int i) {
1369 struct pte *pe = &ptes[i];
1370 struct partition *p = pe->part_table;
1371
1372 if (IS_EXTENDED (p->sys_ind) && !p->boot_ind)
1373 fprintf(stderr,
1374 _("WARNING: Partition %d is an extended partition\n"),
1375 i + 1);
1376 p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG);
1377 pe->changed = 1;
1378 }
1379
1380 static void
1381 toggle_dos_compatibility_flag(void) {
1382 dos_compatible_flag = ~dos_compatible_flag;
1383 if (dos_compatible_flag) {
1384 sector_offset = sectors;
1385 printf(_("DOS Compatibility flag is set\n"));
1386 }
1387 else {
1388 sector_offset = 1;
1389 printf(_("DOS Compatibility flag is not set\n"));
1390 }
1391 }
1392
1393 static void
1394 delete_partition(int i) {
1395 struct pte *pe = &ptes[i];
1396 struct partition *p = pe->part_table;
1397 struct partition *q = pe->ext_pointer;
1398
1399 /* Note that for the fifth partition (i == 4) we don't actually
1400 * decrement partitions.
1401 */
1402
1403 if (warn_geometry())
1404 return; /* C/H/S not set */
1405 pe->changed = 1;
1406
1407 if (sun_label) {
1408 sun_delete_partition(i);
1409 return;
1410 }
1411
1412 if (sgi_label) {
1413 sgi_delete_partition(i);
1414 return;
1415 }
1416
1417 if (i < 4) {
1418 if (IS_EXTENDED (p->sys_ind) && i == ext_index) {
1419 partitions = 4;
1420 ptes[ext_index].ext_pointer = NULL;
1421 extended_offset = 0;
1422 }
1423 clear_partition(p);
1424 return;
1425 }
1426
1427 if (!q->sys_ind && i > 4) {
1428 /* the last one in the chain - just delete */
1429 --partitions;
1430 --i;
1431 clear_partition(ptes[i].ext_pointer);
1432 ptes[i].changed = 1;
1433 } else {
1434 /* not the last one - further ones will be moved down */
1435 if (i > 4) {
1436 /* delete this link in the chain */
1437 p = ptes[i-1].ext_pointer;
1438 *p = *q;
1439 set_start_sect(p, get_start_sect(q));
1440 set_nr_sects(p, get_nr_sects(q));
1441 ptes[i-1].changed = 1;
1442 } else if (partitions > 5) { /* 5 will be moved to 4 */
1443 /* the first logical in a longer chain */
1444 struct pte *pe = &ptes[5];
1445
1446 if (pe->part_table) /* prevent SEGFAULT */
1447 set_start_sect(pe->part_table,
1448 get_partition_start(pe) -
1449 extended_offset);
1450 pe->offset = extended_offset;
1451 pe->changed = 1;
1452 }
1453
1454 if (partitions > 5) {
1455 partitions--;
1456 while (i < partitions) {
1457 ptes[i] = ptes[i+1];
1458 i++;
1459 }
1460 } else
1461 /* the only logical: clear only */
1462 clear_partition(ptes[i].part_table);
1463 }
1464 }
1465
1466 static void
1467 change_sysid(void) {
1468 char *temp;
1469 int i, sys, origsys;
1470 struct partition *p;
1471
1472 /* If sgi_label then don't use get_existing_partition,
1473 let the user select a partition, since get_existing_partition()
1474 only works for Linux like partition tables. */
1475 if (!sgi_label) {
1476 i = get_existing_partition(0, partitions);
1477 } else {
1478 i = get_partition(0, partitions);
1479 }
1480
1481 if (i == -1)
1482 return;
1483 p = ptes[i].part_table;
1484 origsys = sys = get_sysid(i);
1485
1486 /* if changing types T to 0 is allowed, then
1487 the reverse change must be allowed, too */
1488 if (!sys && !sgi_label && !sun_label && !get_nr_sects(p))
1489 printf(_("Partition %d does not exist yet!\n"), i + 1);
1490 else while (1) {
1491 sys = read_hex (get_sys_types());
1492
1493 if (!sys && !sgi_label && !sun_label) {
1494 printf(_("Type 0 means free space to many systems\n"
1495 "(but not to Linux). Having partitions of\n"
1496 "type 0 is probably unwise. You can delete\n"
1497 "a partition using the `d' command.\n"));
1498 /* break; */
1499 }
1500
1501 if (!sun_label && !sgi_label) {
1502 if (IS_EXTENDED (sys) != IS_EXTENDED (p->sys_ind)) {
1503 printf(_("You cannot change a partition into"
1504 " an extended one or vice versa\n"
1505 "Delete it first.\n"));
1506 break;
1507 }
1508 }
1509
1510 if (sys < 256) {
1511 if (sun_label && i == 2 && sys != SUN_TAG_BACKUP)
1512 printf(_("Consider leaving partition 3 "
1513 "as Whole disk (5),\n"
1514 "as SunOS/Solaris expects it and "
1515 "even Linux likes it.\n\n"));
1516 if (sgi_label && ((i == 10 && sys != ENTIRE_DISK)
1517 || (i == 8 && sys != 0)))
1518 printf(_("Consider leaving partition 9 "
1519 "as volume header (0),\nand "
1520 "partition 11 as entire volume (6), "
1521 "as IRIX expects it.\n\n"));
1522 if (sys == origsys)
1523 break;
1524 if (sun_label) {
1525 ptes[i].changed = sun_change_sysid(i, sys);
1526 } else
1527 if (sgi_label) {
1528 ptes[i].changed = sgi_change_sysid(i, sys);
1529 } else {
1530 p->sys_ind = sys;
1531 ptes[i].changed = 1;
1532 }
1533 temp = partition_type(sys) ? : _("Unknown");
1534 if (ptes[i].changed)
1535 printf (_("Changed system type of partition %d "
1536 "to %x (%s)\n"), i + 1, sys, temp);
1537 else
1538 printf (_("System type of partition %d is unchanged: "
1539 "%x (%s)\n"), i + 1, sys, temp);
1540 if (is_dos_partition(origsys) ||
1541 is_dos_partition(sys))
1542 dos_changed = 1;
1543 break;
1544 }
1545 }
1546 }
1547
1548 /* check_consistency() and long2chs() added Sat Mar 6 12:28:16 1993,
1549 * faith@cs.unc.edu, based on code fragments from pfdisk by Gordon W. Ross,
1550 * Jan. 1990 (version 1.2.1 by Gordon W. Ross Aug. 1990; Modified by S.
1551 * Lubkin Oct. 1991). */
1552
1553 static void
1554 long2chs(ulong ls, unsigned int *c, unsigned int *h, unsigned int *s) {
1555 int spc = heads * sectors;
1556
1557 *c = ls / spc;
1558 ls = ls % spc;
1559 *h = ls / sectors;
1560 *s = ls % sectors + 1; /* sectors count from 1 */
1561 }
1562
1563 static void check_consistency(struct partition *p, int partition) {
1564 unsigned int pbc, pbh, pbs; /* physical beginning c, h, s */
1565 unsigned int pec, peh, pes; /* physical ending c, h, s */
1566 unsigned int lbc, lbh, lbs; /* logical beginning c, h, s */
1567 unsigned int lec, leh, les; /* logical ending c, h, s */
1568
1569 if (!heads || !sectors || (partition >= 4))
1570 return; /* do not check extended partitions */
1571
1572 /* physical beginning c, h, s */
1573 pbc = (p->cyl & 0xff) | ((p->sector << 2) & 0x300);
1574 pbh = p->head;
1575 pbs = p->sector & 0x3f;
1576
1577 /* physical ending c, h, s */
1578 pec = (p->end_cyl & 0xff) | ((p->end_sector << 2) & 0x300);
1579 peh = p->end_head;
1580 pes = p->end_sector & 0x3f;
1581
1582 /* compute logical beginning (c, h, s) */
1583 long2chs(get_start_sect(p), &lbc, &lbh, &lbs);
1584
1585 /* compute logical ending (c, h, s) */
1586 long2chs(get_start_sect(p) + get_nr_sects(p) - 1, &lec, &leh, &les);
1587
1588 /* Same physical / logical beginning? */
1589 if (cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) {
1590 printf(_("Partition %d has different physical/logical "
1591 "beginnings (non-Linux?):\n"), partition + 1);
1592 printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs);
1593 printf(_("logical=(%d, %d, %d)\n"),lbc, lbh, lbs);
1594 }
1595
1596 /* Same physical / logical ending? */
1597 if (cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) {
1598 printf(_("Partition %d has different physical/logical "
1599 "endings:\n"), partition + 1);
1600 printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
1601 printf(_("logical=(%d, %d, %d)\n"),lec, leh, les);
1602 }
1603
1604 #if 0
1605 /* Beginning on cylinder boundary? */
1606 if (pbh != !pbc || pbs != 1) {
1607 printf(_("Partition %i does not start on cylinder "
1608 "boundary:\n"), partition + 1);
1609 printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs);
1610 printf(_("should be (%d, %d, 1)\n"), pbc, !pbc);
1611 }
1612 #endif
1613
1614 /* Ending on cylinder boundary? */
1615 if (peh != (heads - 1) || pes != sectors) {
1616 printf(_("Partition %i does not end on cylinder boundary.\n"),
1617 partition + 1);
1618 #if 0
1619 printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
1620 printf(_("should be (%d, %d, %d)\n"),
1621 pec, heads - 1, sectors);
1622 #endif
1623 }
1624 }
1625
1626 static void
1627 list_disk_geometry(void) {
1628 long long bytes = (total_number_of_sectors << 9);
1629 long megabytes = bytes/1000000;
1630
1631 if (megabytes < 10000)
1632 printf(_("\nDisk %s: %ld MB, %lld bytes\n"),
1633 disk_device, megabytes, bytes);
1634 else {
1635 long hectomega = (megabytes + 50) / 100;
1636 printf(_("\nDisk %s: %ld.%ld GB, %lld bytes\n"),
1637 disk_device, hectomega / 10, hectomega % 10, bytes);
1638 }
1639 printf(_("%d heads, %llu sectors/track, %d cylinders"),
1640 heads, sectors, cylinders);
1641 if (units_per_sector == 1)
1642 printf(_(", total %llu sectors"),
1643 total_number_of_sectors / sector_factor);
1644 printf("\n");
1645 printf(_("Units = %s of %d * %d = %d bytes\n"),
1646 str_units(PLURAL),
1647 units_per_sector, sector_size, units_per_sector * sector_size);
1648 if (dos_label)
1649 dos_print_mbr_id();
1650 printf("\n");
1651 }
1652
1653 /*
1654 * Check whether partition entries are ordered by their starting positions.
1655 * Return 0 if OK. Return i if partition i should have been earlier.
1656 * Two separate checks: primary and logical partitions.
1657 */
1658 static int
1659 wrong_p_order(int *prev) {
1660 struct pte *pe;
1661 struct partition *p;
1662 unsigned int last_p_start_pos = 0, p_start_pos;
1663 int i, last_i = 0;
1664
1665 for (i = 0 ; i < partitions; i++) {
1666 if (i == 4) {
1667 last_i = 4;
1668 last_p_start_pos = 0;
1669 }
1670 pe = &ptes[i];
1671 if ((p = pe->part_table)->sys_ind) {
1672 p_start_pos = get_partition_start(pe);
1673
1674 if (last_p_start_pos > p_start_pos) {
1675 if (prev)
1676 *prev = last_i;
1677 return i;
1678 }
1679
1680 last_p_start_pos = p_start_pos;
1681 last_i = i;
1682 }
1683 }
1684 return 0;
1685 }
1686
1687 /*
1688 * Fix the chain of logicals.
1689 * extended_offset is unchanged, the set of sectors used is unchanged
1690 * The chain is sorted so that sectors increase, and so that
1691 * starting sectors increase.
1692 *
1693 * After this it may still be that cfdisk doesnt like the table.
1694 * (This is because cfdisk considers expanded parts, from link to
1695 * end of partition, and these may still overlap.)
1696 * Now
1697 * sfdisk /dev/hda > ohda; sfdisk /dev/hda < ohda
1698 * may help.
1699 */
1700 static void
1701 fix_chain_of_logicals(void) {
1702 int j, oj, ojj, sj, sjj;
1703 struct partition *pj,*pjj,tmp;
1704
1705 /* Stage 1: sort sectors but leave sector of part 4 */
1706 /* (Its sector is the global extended_offset.) */
1707 stage1:
1708 for (j = 5; j < partitions-1; j++) {
1709 oj = ptes[j].offset;
1710 ojj = ptes[j+1].offset;
1711 if (oj > ojj) {
1712 ptes[j].offset = ojj;
1713 ptes[j+1].offset = oj;
1714 pj = ptes[j].part_table;
1715 set_start_sect(pj, get_start_sect(pj)+oj-ojj);
1716 pjj = ptes[j+1].part_table;
1717 set_start_sect(pjj, get_start_sect(pjj)+ojj-oj);
1718 set_start_sect(ptes[j-1].ext_pointer,
1719 ojj-extended_offset);
1720 set_start_sect(ptes[j].ext_pointer,
1721 oj-extended_offset);
1722 goto stage1;
1723 }
1724 }
1725
1726 /* Stage 2: sort starting sectors */
1727 stage2:
1728 for (j = 4; j < partitions-1; j++) {
1729 pj = ptes[j].part_table;
1730 pjj = ptes[j+1].part_table;
1731 sj = get_start_sect(pj);
1732 sjj = get_start_sect(pjj);
1733 oj = ptes[j].offset;
1734 ojj = ptes[j+1].offset;
1735 if (oj+sj > ojj+sjj) {
1736 tmp = *pj;
1737 *pj = *pjj;
1738 *pjj = tmp;
1739 set_start_sect(pj, ojj+sjj-oj);
1740 set_start_sect(pjj, oj+sj-ojj);
1741 goto stage2;
1742 }
1743 }
1744
1745 /* Probably something was changed */
1746 for (j = 4; j < partitions; j++)
1747 ptes[j].changed = 1;
1748 }
1749
1750 static void
1751 fix_partition_table_order(void) {
1752 struct pte *pei, *pek;
1753 int i,k;
1754
1755 if (!wrong_p_order(NULL)) {
1756 printf(_("Nothing to do. Ordering is correct already.\n\n"));
1757 return;
1758 }
1759
1760 while ((i = wrong_p_order(&k)) != 0 && i < 4) {
1761 /* partition i should have come earlier, move it */
1762 /* We have to move data in the MBR */
1763 struct partition *pi, *pk, *pe, pbuf;
1764 pei = &ptes[i];
1765 pek = &ptes[k];
1766
1767 pe = pei->ext_pointer;
1768 pei->ext_pointer = pek->ext_pointer;
1769 pek->ext_pointer = pe;
1770
1771 pi = pei->part_table;
1772 pk = pek->part_table;
1773
1774 memmove(&pbuf, pi, sizeof(struct partition));
1775 memmove(pi, pk, sizeof(struct partition));
1776 memmove(pk, &pbuf, sizeof(struct partition));
1777
1778 pei->changed = pek->changed = 1;
1779 }
1780
1781 if (i)
1782 fix_chain_of_logicals();
1783
1784 printf(_("Done.\n"));
1785
1786 }
1787
1788 static void
1789 list_table(int xtra) {
1790 struct partition *p;
1791 char *type;
1792 int i, w;
1793
1794 if (sun_label) {
1795 sun_list_table(xtra);
1796 return;
1797 }
1798
1799 if (sgi_label) {
1800 sgi_list_table(xtra);
1801 return;
1802 }
1803
1804 list_disk_geometry();
1805
1806 if (osf_label) {
1807 xbsd_print_disklabel(xtra);
1808 return;
1809 }
1810
1811 if (is_garbage_table()) {
1812 printf(_("This doesn't look like a partition table\n"
1813 "Probably you selected the wrong device.\n\n"));
1814 }
1815
1816 /* Heuristic: we list partition 3 of /dev/foo as /dev/foo3,
1817 but if the device name ends in a digit, say /dev/foo1,
1818 then the partition is called /dev/foo1p3. */
1819 w = strlen(disk_device);
1820 if (w && isdigit(disk_device[w-1]))
1821 w++;
1822 if (w < 5)
1823 w = 5;
1824
1825 printf(_("%*s Boot Start End Blocks Id System\n"),
1826 w+1, _("Device"));
1827
1828 for (i = 0; i < partitions; i++) {
1829 struct pte *pe = &ptes[i];
1830
1831 p = pe->part_table;
1832 if (p && !is_cleared_partition(p)) {
1833 unsigned int psects = get_nr_sects(p);
1834 unsigned int pblocks = psects;
1835 unsigned int podd = 0;
1836
1837 if (sector_size < 1024) {
1838 pblocks /= (1024 / sector_size);
1839 podd = psects % (1024 / sector_size);
1840 }
1841 if (sector_size > 1024)
1842 pblocks *= (sector_size / 1024);
1843 printf(
1844 "%s %c %11lu %11lu %11lu%c %2x %s\n",
1845 partname(disk_device, i+1, w+2),
1846 /* boot flag */ !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG
1847 ? '*' : '?',
1848 /* start */ (unsigned long) cround(get_partition_start(pe)),
1849 /* end */ (unsigned long) cround(get_partition_start(pe) + psects
1850 - (psects ? 1 : 0)),
1851 /* odd flag on end */ (unsigned long) pblocks, podd ? '+' : ' ',
1852 /* type id */ p->sys_ind,
1853 /* type name */ (type = partition_type(p->sys_ind)) ?
1854 type : _("Unknown"));
1855 check_consistency(p, i);
1856 }
1857 }
1858
1859 /* Is partition table in disk order? It need not be, but... */
1860 /* partition table entries are not checked for correct order if this
1861 is a sgi, sun or aix labeled disk... */
1862 if (dos_label && wrong_p_order(NULL)) {
1863 printf(_("\nPartition table entries are not in disk order\n"));
1864 }
1865 }
1866
1867 static void
1868 x_list_table(int extend) {
1869 struct pte *pe;
1870 struct partition *p;
1871 int i;
1872
1873 printf(_("\nDisk %s: %d heads, %llu sectors, %d cylinders\n\n"),
1874 disk_device, heads, sectors, cylinders);
1875 printf(_("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n"));
1876 for (i = 0 ; i < partitions; i++) {
1877 pe = &ptes[i];
1878 p = (extend ? pe->ext_pointer : pe->part_table);
1879 if (p != NULL) {
1880 printf("%2d %02x%4d%4d%5d%4d%4d%5d%11lu%11lu %02x\n",
1881 i + 1, p->boot_ind, p->head,
1882 sector(p->sector),
1883 cylinder(p->sector, p->cyl), p->end_head,
1884 sector(p->end_sector),
1885 cylinder(p->end_sector, p->end_cyl),
1886 (unsigned long) get_start_sect(p),
1887 (unsigned long) get_nr_sects(p), p->sys_ind);
1888 if (p->sys_ind)
1889 check_consistency(p, i);
1890 }
1891 }
1892 }
1893
1894 static void
1895 fill_bounds(unsigned long long *first, unsigned long long *last) {
1896 int i;
1897 struct pte *pe = &ptes[0];
1898 struct partition *p;
1899
1900 for (i = 0; i < partitions; pe++,i++) {
1901 p = pe->part_table;
1902 if (!p->sys_ind || IS_EXTENDED (p->sys_ind)) {
1903 first[i] = 0xffffffff;
1904 last[i] = 0;
1905 } else {
1906 first[i] = get_partition_start(pe);
1907 last[i] = first[i] + get_nr_sects(p) - 1;
1908 }
1909 }
1910 }
1911
1912 static void
1913 check(int n, unsigned int h, unsigned int s, unsigned int c,
1914 unsigned int start) {
1915 unsigned int total, real_s, real_c;
1916
1917 real_s = sector(s) - 1;
1918 real_c = cylinder(s, c);
1919 total = (real_c * sectors + real_s) * heads + h;
1920 if (!total)
1921 fprintf(stderr, _("Warning: partition %d contains sector 0\n"), n);
1922 if (h >= heads)
1923 fprintf(stderr,
1924 _("Partition %d: head %d greater than maximum %d\n"),
1925 n, h + 1, heads);
1926 if (real_s >= sectors)
1927 fprintf(stderr, _("Partition %d: sector %d greater than "
1928 "maximum %llu\n"), n, s, sectors);
1929 if (real_c >= cylinders)
1930 fprintf(stderr, _("Partitions %d: cylinder %d greater than "
1931 "maximum %d\n"), n, real_c + 1, cylinders);
1932 if (cylinders <= 1024 && start != total)
1933 fprintf(stderr,
1934 _("Partition %d: previous sectors %d disagrees with "
1935 "total %d\n"), n, start, total);
1936 }
1937
1938 static void
1939 verify(void) {
1940 int i, j;
1941 unsigned long total = 1;
1942 unsigned long long first[partitions], last[partitions];
1943 struct partition *p;
1944
1945 if (warn_geometry())
1946 return;
1947
1948 if (sun_label) {
1949 verify_sun();
1950 return;
1951 }
1952
1953 if (sgi_label) {
1954 verify_sgi(1);
1955 return;
1956 }
1957
1958 fill_bounds(first, last);
1959 for (i = 0; i < partitions; i++) {
1960 struct pte *pe = &ptes[i];
1961
1962 p = pe->part_table;
1963 if (p->sys_ind && !IS_EXTENDED (p->sys_ind)) {
1964 check_consistency(p, i);
1965 if (get_partition_start(pe) < first[i])
1966 printf(_("Warning: bad start-of-data in "
1967 "partition %d\n"), i + 1);
1968 check(i + 1, p->end_head, p->end_sector, p->end_cyl,
1969 last[i]);
1970 total += last[i] + 1 - first[i];
1971 for (j = 0; j < i; j++)
1972 if ((first[i] >= first[j] && first[i] <= last[j])
1973 || ((last[i] <= last[j] && last[i] >= first[j]))) {
1974 printf(_("Warning: partition %d overlaps "
1975 "partition %d.\n"), j + 1, i + 1);
1976 total += first[i] >= first[j] ?
1977 first[i] : first[j];
1978 total -= last[i] <= last[j] ?
1979 last[i] : last[j];
1980 }
1981 }
1982 }
1983
1984 if (extended_offset) {
1985 struct pte *pex = &ptes[ext_index];
1986 unsigned long long e_last = get_start_sect(pex->part_table) +
1987 get_nr_sects(pex->part_table) - 1;
1988
1989 for (i = 4; i < partitions; i++) {
1990 total++;
1991 p = ptes[i].part_table;
1992 if (!p->sys_ind) {
1993 if (i != 4 || i + 1 < partitions)
1994 printf(_("Warning: partition %d "
1995 "is empty\n"), i + 1);
1996 }
1997 else if (first[i] < extended_offset ||
1998 last[i] > e_last)
1999 printf(_("Logical partition %d not entirely in "
2000 "partition %d\n"), i + 1, ext_index + 1);
2001 }
2002 }
2003
2004 if (total > total_number_of_sectors)
2005 printf(_("Total allocated sectors %ld greater than the maximum"
2006 " %lld\n"), total, total_number_of_sectors);
2007 else if (total < total_number_of_sectors)
2008 printf(_("%lld unallocated sectors\n"),
2009 total_number_of_sectors - total);
2010 }
2011
2012 static void
2013 add_partition(int n, int sys) {
2014 char mesg[256]; /* 48 does not suffice in Japanese */
2015 int i, read = 0;
2016 struct partition *p = ptes[n].part_table;
2017 struct partition *q = ptes[ext_index].part_table;
2018 long long llimit;
2019 unsigned long long start, stop = 0, limit, temp,
2020 first[partitions], last[partitions];
2021
2022 if (p && p->sys_ind) {
2023 printf(_("Partition %d is already defined. Delete "
2024 "it before re-adding it.\n"), n + 1);
2025 return;
2026 }
2027 fill_bounds(first, last);
2028 if (n < 4) {
2029 start = sector_offset;
2030 if (display_in_cyl_units || !total_number_of_sectors)
2031 llimit = heads * sectors * cylinders - 1;
2032 else
2033 llimit = (total_number_of_sectors / sector_factor) - 1;
2034 limit = llimit;
2035 if (limit != llimit)
2036 limit = 0x7fffffff;
2037 if (extended_offset) {
2038 first[ext_index] = extended_offset;
2039 last[ext_index] = get_start_sect(q) +
2040 get_nr_sects(q) - 1;
2041 }
2042 } else {
2043 start = extended_offset + sector_offset;
2044 limit = get_start_sect(q) + get_nr_sects(q) - 1;
2045 }
2046 if (display_in_cyl_units)
2047 for (i = 0; i < partitions; i++)
2048 first[i] = (cround(first[i]) - 1) * units_per_sector;
2049
2050 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
2051 do {
2052 temp = start;
2053 for (i = 0; i < partitions; i++) {
2054 unsigned long long lastplusoff;
2055
2056 if (start == ptes[i].offset)
2057 start += sector_offset;
2058 lastplusoff = last[i] + ((n<4) ? 0 : sector_offset);
2059 if (start >= first[i] && start <= lastplusoff)
2060 start = lastplusoff + 1;
2061 }
2062 if (start > limit)
2063 break;
2064 if (start >= temp+units_per_sector && read) {
2065 printf(_("Sector %llu is already allocated\n"), temp);
2066 temp = start;
2067 read = 0;
2068 }
2069 if (!read && start == temp) {
2070 unsigned long long i = start;
2071
2072 start = read_int(cround(i), cround(i), cround(limit),
2073 0, mesg);
2074 if (display_in_cyl_units) {
2075 start = (start - 1) * units_per_sector;
2076 if (start < i) start = i;
2077 }
2078 read = 1;
2079 }
2080 } while (start != temp || !read);
2081 if (n > 4) { /* NOT for fifth partition */
2082 struct pte *pe = &ptes[n];
2083
2084 pe->offset = start - sector_offset;
2085 if (pe->offset == extended_offset) { /* must be corrected */
2086 pe->offset++;
2087 if (sector_offset == 1)
2088 start++;
2089 }
2090 }
2091
2092 for (i = 0; i < partitions; i++) {
2093 struct pte *pe = &ptes[i];
2094
2095 if (start < pe->offset && limit >= pe->offset)
2096 limit = pe->offset - 1;
2097 if (start < first[i] && limit >= first[i])
2098 limit = first[i] - 1;
2099 }
2100 if (start > limit) {
2101 printf(_("No free sectors available\n"));
2102 if (n > 4)
2103 partitions--;
2104 return;
2105 }
2106 if (cround(start) == cround(limit)) {
2107 stop = limit;
2108 } else {
2109 snprintf(mesg, sizeof(mesg),
2110 _("Last %1$s, +%2$s or +size{K,M,G}"),
2111 str_units(SINGULAR), str_units(PLURAL));
2112
2113 stop = read_int(cround(start), cround(limit), cround(limit),
2114 cround(start), mesg);
2115 if (display_in_cyl_units) {
2116 stop = stop * units_per_sector - 1;
2117 if (stop >limit)
2118 stop = limit;
2119 }
2120 }
2121
2122 set_partition(n, 0, start, stop, sys);
2123 if (n > 4)
2124 set_partition(n - 1, 1, ptes[n].offset, stop, EXTENDED);
2125
2126 if (IS_EXTENDED (sys)) {
2127 struct pte *pe4 = &ptes[4];
2128 struct pte *pen = &ptes[n];
2129
2130 ext_index = n;
2131 pen->ext_pointer = p;
2132 pe4->offset = extended_offset = start;
2133 if (!(pe4->sectorbuffer = calloc(1, sector_size)))
2134 fatal(out_of_memory);
2135 pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
2136 pe4->ext_pointer = pe4->part_table + 1;
2137 pe4->changed = 1;
2138 partitions = 5;
2139 }
2140 }
2141
2142 static void
2143 add_logical(void) {
2144 if (partitions > 5 || ptes[4].part_table->sys_ind) {
2145 struct pte *pe = &ptes[partitions];
2146
2147 if (!(pe->sectorbuffer = calloc(1, sector_size)))
2148 fatal(out_of_memory);
2149 pe->part_table = pt_offset(pe->sectorbuffer, 0);
2150 pe->ext_pointer = pe->part_table + 1;
2151 pe->offset = 0;
2152 pe->changed = 1;
2153 partitions++;
2154 }
2155 add_partition(partitions - 1, LINUX_NATIVE);
2156 }
2157
2158 static void
2159 new_partition(void) {
2160 int i, free_primary = 0;
2161
2162 if (warn_geometry())
2163 return;
2164
2165 if (sun_label) {
2166 add_sun_partition(get_partition(0, partitions), LINUX_NATIVE);
2167 return;
2168 }
2169
2170 if (sgi_label) {
2171 sgi_add_partition(get_partition(0, partitions), LINUX_NATIVE);
2172 return;
2173 }
2174
2175 if (aix_label) {
2176 printf(_("\tSorry - this fdisk cannot handle AIX disk labels."
2177 "\n\tIf you want to add DOS-type partitions, create"
2178 "\n\ta new empty DOS partition table first. (Use o.)"
2179 "\n\tWARNING: "
2180 "This will destroy the present disk contents.\n"));
2181 return;
2182 }
2183
2184 if (mac_label) {
2185 printf(_("\tSorry - this fdisk cannot handle Mac disk labels."
2186 "\n\tIf you want to add DOS-type partitions, create"
2187 "\n\ta new empty DOS partition table first. (Use o.)"
2188 "\n\tWARNING: "
2189 "This will destroy the present disk contents.\n"));
2190 return;
2191 }
2192
2193 for (i = 0; i < 4; i++)
2194 free_primary += !ptes[i].part_table->sys_ind;
2195
2196 if (!free_primary && partitions >= MAXIMUM_PARTS) {
2197 printf(_("The maximum number of partitions has been created\n"));
2198 return;
2199 }
2200
2201 if (!free_primary) {
2202 if (extended_offset)
2203 add_logical();
2204 else
2205 printf(_("You must delete some partition and add "
2206 "an extended partition first\n"));
2207 } else if (partitions >= MAXIMUM_PARTS) {
2208 printf(_("All logical partitions are in use\n"));
2209 printf(_("Adding a primary partition\n"));
2210 add_partition(get_partition(0, 4), LINUX_NATIVE);
2211 } else {
2212 char c, line[LINE_LENGTH];
2213 snprintf(line, sizeof(line),
2214 _("Command action\n %s\n p primary "
2215 "partition (1-4)\n"), extended_offset ?
2216 _("l logical (5 or over)") : _("e extended"));
2217 while (1) {
2218 if ((c = tolower(read_char(line))) == 'p') {
2219 int i = get_nonexisting_partition(0, 4);
2220 if (i >= 0)
2221 add_partition(i, LINUX_NATIVE);
2222 return;
2223 }
2224 else if (c == 'l' && extended_offset) {
2225 add_logical();
2226 return;
2227 }
2228 else if (c == 'e' && !extended_offset) {
2229 int i = get_nonexisting_partition(0, 4);
2230 if (i >= 0)
2231 add_partition(i, EXTENDED);
2232 return;
2233 }
2234 else
2235 printf(_("Invalid partition number "
2236 "for type `%c'\n"), c);
2237 }
2238 }
2239 }
2240
2241 static void
2242 write_table(void) {
2243 int i;
2244
2245 if (dos_label) {
2246 for (i=0; i<3; i++)
2247 if (ptes[i].changed)
2248 ptes[3].changed = 1;
2249 for (i = 3; i < partitions; i++) {
2250 struct pte *pe = &ptes[i];
2251
2252 if (pe->changed) {
2253 write_part_table_flag(pe->sectorbuffer);
2254 write_sector(fd, pe->offset, pe->sectorbuffer);
2255 }
2256 }
2257 }
2258 else if (sgi_label) {
2259 /* no test on change? the printf below might be mistaken */
2260 sgi_write_table();
2261 } else if (sun_label) {
2262 int needw = 0;
2263
2264 for (i=0; i<8; i++)
2265 if (ptes[i].changed)
2266 needw = 1;
2267 if (needw)
2268 sun_write_table();
2269 }
2270
2271 printf(_("The partition table has been altered!\n\n"));
2272 reread_partition_table(1);
2273 }
2274
2275 void
2276 reread_partition_table(int leave) {
2277 int i;
2278 struct stat statbuf;
2279
2280 i = fstat(fd, &statbuf);
2281 if (i == 0 && S_ISBLK(statbuf.st_mode)) {
2282 sync();
2283 sleep(2);
2284 #ifdef BLKRRPART
2285 printf(_("Calling ioctl() to re-read partition table.\n"));
2286 i = ioctl(fd, BLKRRPART);
2287 #else
2288 errno = ENOSYS;
2289 i = 1;
2290 #endif
2291 }
2292
2293 if (i) {
2294 printf(_("\nWARNING: Re-reading the partition table failed with error %d: %s.\n"
2295 "The kernel still uses the old table. The new table will be used at\n"
2296 "the next reboot or after you run partprobe(8) or kpartx(8)\n"),
2297 errno, strerror(errno));
2298 }
2299
2300 if (dos_changed)
2301 printf(
2302 _("\nWARNING: If you have created or modified any DOS 6.x\n"
2303 "partitions, please see the fdisk manual page for additional\n"
2304 "information.\n"));
2305
2306 if (leave) {
2307 if (fsync(fd) || close(fd)) {
2308 fprintf(stderr, _("\nError closing file\n"));
2309 exit(1);
2310 }
2311
2312 printf(_("Syncing disks.\n"));
2313 sync();
2314 sleep(4); /* for sync() */
2315 exit(!!i);
2316 }
2317 }
2318
2319 #define MAX_PER_LINE 16
2320 static void
2321 print_buffer(unsigned char pbuffer[]) {
2322 int i,
2323 l;
2324
2325 for (i = 0, l = 0; i < sector_size; i++, l++) {
2326 if (l == 0)
2327 printf("0x%03X:", i);
2328 printf(" %02X", pbuffer[i]);
2329 if (l == MAX_PER_LINE - 1) {
2330 printf("\n");
2331 l = -1;
2332 }
2333 }
2334 if (l > 0)
2335 printf("\n");
2336 printf("\n");
2337 }
2338
2339 static void
2340 print_raw(void) {
2341 int i;
2342
2343 printf(_("Device: %s\n"), disk_device);
2344 if (sun_label || sgi_label)
2345 print_buffer(MBRbuffer);
2346 else for (i = 3; i < partitions; i++)
2347 print_buffer(ptes[i].sectorbuffer);
2348 }
2349
2350 static void
2351 move_begin(int i) {
2352 struct pte *pe = &ptes[i];
2353 struct partition *p = pe->part_table;
2354 unsigned int new, first;
2355
2356 if (warn_geometry())
2357 return;
2358 if (!p->sys_ind || !get_nr_sects(p) || IS_EXTENDED (p->sys_ind)) {
2359 printf(_("Partition %d has no data area\n"), i + 1);
2360 return;
2361 }
2362 first = get_partition_start(pe);
2363 new = read_int(first, first, first + get_nr_sects(p) - 1, first,
2364 _("New beginning of data")) - pe->offset;
2365
2366 if (new != get_nr_sects(p)) {
2367 first = get_nr_sects(p) + get_start_sect(p) - new;
2368 set_nr_sects(p, first);
2369 set_start_sect(p, new);
2370 pe->changed = 1;
2371 }
2372 }
2373
2374 static void
2375 xselect(void) {
2376 char c;
2377
2378 while(1) {
2379 putchar('\n');
2380 c = tolower(read_char(_("Expert command (m for help): ")));
2381 switch (c) {
2382 case 'a':
2383 if (sun_label)
2384 sun_set_alt_cyl();
2385 break;
2386 case 'b':
2387 if (dos_label)
2388 move_begin(get_partition(0, partitions));
2389 break;
2390 case 'c':
2391 user_cylinders = cylinders =
2392 read_int(1, cylinders, 1048576, 0,
2393 _("Number of cylinders"));
2394 if (sun_label)
2395 sun_set_ncyl(cylinders);
2396 if (dos_label)
2397 warn_cylinders();
2398 break;
2399 case 'd':
2400 print_raw();
2401 break;
2402 case 'e':
2403 if (sgi_label)
2404 sgi_set_xcyl();
2405 else if (sun_label)
2406 sun_set_xcyl();
2407 else
2408 if (dos_label)
2409 x_list_table(1);
2410 break;
2411 case 'f':
2412 if (dos_label)
2413 fix_partition_table_order();
2414 break;
2415 case 'g':
2416 create_sgilabel();
2417 break;
2418 case 'h':
2419 user_heads = heads = read_int(1, heads, 256, 0,
2420 _("Number of heads"));
2421 update_units();
2422 break;
2423 case 'i':
2424 if (sun_label)
2425 sun_set_ilfact();
2426 if (dos_label)
2427 dos_set_mbr_id();
2428 break;
2429 case 'o':
2430 if (sun_label)
2431 sun_set_rspeed();
2432 break;
2433 case 'p':
2434 if (sun_label)
2435 list_table(1);
2436 else
2437 x_list_table(0);
2438 break;
2439 case 'q':
2440 close(fd);
2441 printf("\n");
2442 exit(0);
2443 case 'r':
2444 return;
2445 case 's':
2446 user_sectors = sectors = read_int(1, sectors, 63, 0,
2447 _("Number of sectors"));
2448 if (dos_compatible_flag) {
2449 sector_offset = sectors;
2450 fprintf(stderr, _("Warning: setting "
2451 "sector offset for DOS "
2452 "compatiblity\n"));
2453 }
2454 update_units();
2455 break;
2456 case 'v':
2457 verify();
2458 break;
2459 case 'w':
2460 write_table(); /* does not return */
2461 break;
2462 case 'y':
2463 if (sun_label)
2464 sun_set_pcylcount();
2465 break;
2466 default:
2467 xmenu();
2468 }
2469 }
2470 }
2471
2472 static int
2473 is_ide_cdrom_or_tape(char *device) {
2474 FILE *procf;
2475 char buf[100];
2476 struct stat statbuf;
2477 int is_ide = 0;
2478
2479 /* No device was given explicitly, and we are trying some
2480 likely things. But opening /dev/hdc may produce errors like
2481 "hdc: tray open or drive not ready"
2482 if it happens to be a CD-ROM drive. It even happens that
2483 the process hangs on the attempt to read a music CD.
2484 So try to be careful. This only works since 2.1.73. */
2485
2486 if (strncmp("/dev/hd", device, 7))
2487 return 0;
2488
2489 snprintf(buf, sizeof(buf), "/proc/ide/%s/media", device+5);
2490 procf = fopen(buf, "r");
2491 if (procf != NULL && fgets(buf, sizeof(buf), procf))
2492 is_ide = (!strncmp(buf, "cdrom", 5) ||
2493 !strncmp(buf, "tape", 4));
2494 else
2495 /* Now when this proc file does not exist, skip the
2496 device when it is read-only. */
2497 if (stat(device, &statbuf) == 0)
2498 is_ide = ((statbuf.st_mode & 0222) == 0);
2499
2500 if (procf)
2501 fclose(procf);
2502 return is_ide;
2503 }
2504
2505 static void
2506 gpt_warning(char *dev)
2507 {
2508 if (dev && gpt_probe_signature_devname(dev))
2509 fprintf(stderr, _("\nWARNING: GPT (GUID Partition Table) detected on '%s'! "
2510 "The util fdisk doesn't support GPT. Use GNU Parted.\n\n"), dev);
2511 }
2512
2513 static void
2514 try(char *device, int user_specified) {
2515 int gb;
2516
2517 disk_device = device;
2518 if (setjmp(listingbuf))
2519 return;
2520 if (!user_specified)
2521 if (is_ide_cdrom_or_tape(device))
2522 return;
2523 gpt_warning(device);
2524 if ((fd = open(disk_device, type_open)) >= 0) {
2525 gb = get_boot(try_only);
2526 if (gb > 0) { /* I/O error */
2527 } else if (gb < 0) { /* no DOS signature */
2528 list_disk_geometry();
2529 if (!aix_label && !mac_label && btrydev(device) < 0)
2530 fprintf(stderr,
2531 _("Disk %s doesn't contain a valid "
2532 "partition table\n"), device);
2533 } else {
2534 list_table(0);
2535 }
2536 close(fd);
2537 } else {
2538 /* Ignore other errors, since we try IDE
2539 and SCSI hard disks which may not be
2540 installed on the system. */
2541 if (errno == EACCES) {
2542 fprintf(stderr, _("Cannot open %s\n"), device);
2543 return;
2544 }
2545 }
2546 }
2547
2548 /*
2549 * for fdisk -l:
2550 * try all things in /proc/partitions that look like a full disk
2551 */
2552 static void
2553 tryprocpt(void) {
2554 FILE *procpt;
2555 char line[100], ptname[100], devname[120];
2556 int ma, mi;
2557 unsigned long long sz;
2558
2559 procpt = fopen(PROC_PARTITIONS, "r");
2560 if (procpt == NULL) {
2561 fprintf(stderr, _("cannot open %s\n"), PROC_PARTITIONS);
2562 return;
2563 }
2564
2565 while (fgets(line, sizeof(line), procpt)) {
2566 if (sscanf (line, " %d %d %llu %100[^\n ]",
2567 &ma, &mi, &sz, ptname) != 4)
2568 continue;
2569 snprintf(devname, sizeof(devname), "/dev/%s", ptname);
2570 if (is_probably_full_disk(devname))
2571 try(devname, 0);
2572 }
2573 fclose(procpt);
2574 }
2575
2576 static void
2577 dummy(int *kk) {}
2578
2579 static void
2580 unknown_command(int c) {
2581 printf(_("%c: unknown command\n"), c);
2582 }
2583
2584
2585
2586 int
2587 main(int argc, char **argv) {
2588 int j, c;
2589 int optl = 0, opts = 0;
2590
2591 setlocale(LC_ALL, "");
2592 bindtextdomain(PACKAGE, LOCALEDIR);
2593 textdomain(PACKAGE);
2594
2595 /*
2596 * Calls:
2597 * fdisk -v
2598 * fdisk -l [-b sectorsize] [-u] device ...
2599 * fdisk -s [partition] ...
2600 * fdisk [-b sectorsize] [-u] device
2601 *
2602 * Options -C, -H, -S set the geometry.
2603 *
2604 */
2605 while ((c = getopt(argc, argv, "b:C:H:lsS:uvV")) != -1) {
2606 switch (c) {
2607 case 'b':
2608 /* Ugly: this sector size is really per device,
2609 so cannot be combined with multiple disks,
2610 and te same goes for the C/H/S options.
2611 */
2612 sector_size = atoi(optarg);
2613 if (sector_size != 512 && sector_size != 1024 &&
2614 sector_size != 2048)
2615 fatal(usage);
2616 sector_offset = 2;
2617 user_set_sector_size = 1;
2618 break;
2619 case 'C':
2620 user_cylinders = atoi(optarg);
2621 break;
2622 case 'H':
2623 user_heads = atoi(optarg);
2624 if (user_heads <= 0 || user_heads >= 256)
2625 user_heads = 0;
2626 break;
2627 case 'S':
2628 user_sectors = atoi(optarg);
2629 if (user_sectors <= 0 || user_sectors >= 64)
2630 user_sectors = 0;
2631 break;
2632 case 'l':
2633 optl = 1;
2634 break;
2635 case 's':
2636 opts = 1;
2637 break;
2638 case 'u':
2639 display_in_cyl_units = 0;
2640 break;
2641 case 'V':
2642 case 'v':
2643 printf("fdisk (%s)\n", PACKAGE_STRING);
2644 exit(0);
2645 default:
2646 fatal(usage);
2647 }
2648 }
2649
2650 #if 0
2651 printf(_("This kernel finds the sector size itself - "
2652 "-b option ignored\n"));
2653 #else
2654 if (user_set_sector_size && argc-optind != 1)
2655 printf(_("Warning: the -b (set sector size) option should"
2656 " be used with one specified device\n"));
2657 #endif
2658
2659 if (optl) {
2660 nowarn = 1;
2661 type_open = O_RDONLY;
2662 if (argc > optind) {
2663 int k;
2664 /* avoid gcc warning:
2665 variable `k' might be clobbered by `longjmp' */
2666 dummy(&k);
2667 listing = 1;
2668 for (k = optind; k < argc; k++)
2669 try(argv[k], 1);
2670 } else {
2671 /* we no longer have default device names */
2672 /* but we can use /proc/partitions instead */
2673 tryprocpt();
2674 }
2675 exit(0);
2676 }
2677
2678 if (opts) {
2679 unsigned long long size;
2680
2681 nowarn = 1;
2682 type_open = O_RDONLY;
2683
2684 opts = argc - optind;
2685 if (opts <= 0)
2686 fatal(usage);
2687
2688 for (j = optind; j < argc; j++) {
2689 disk_device = argv[j];
2690 if ((fd = open(disk_device, type_open)) < 0)
2691 fatal(unable_to_open);
2692 if (blkdev_get_sectors(fd, &size) == -1)
2693 fatal(ioctl_error);
2694 close(fd);
2695 if (opts == 1)
2696 printf("%llu\n", size/2);
2697 else
2698 printf("%s: %llu\n", argv[j], size/2);
2699 }
2700 exit(0);
2701 }
2702
2703 if (argc-optind == 1)
2704 disk_device = argv[optind];
2705 else if (argc-optind != 0)
2706 fatal(usage);
2707 else
2708 fatal(usage2);
2709
2710 gpt_warning(disk_device);
2711 get_boot(fdisk);
2712
2713 if (osf_label) {
2714 /* OSF label, and no DOS label */
2715 printf(_("Detected an OSF/1 disklabel on %s, entering "
2716 "disklabel mode.\n"),
2717 disk_device);
2718 bselect();
2719 osf_label = 0;
2720 /* If we return we may want to make an empty DOS label? */
2721 }
2722
2723 while (1) {
2724 putchar('\n');
2725 c = tolower(read_char(_("Command (m for help): ")));
2726 switch (c) {
2727 case 'a':
2728 if (dos_label)
2729 toggle_active(get_partition(1, partitions));
2730 else if (sun_label)
2731 toggle_sunflags(get_partition(1, partitions),
2732 SUN_FLAG_UNMNT);
2733 else if (sgi_label)
2734 sgi_set_bootpartition(
2735 get_partition(1, partitions));
2736 else
2737 unknown_command(c);
2738 break;
2739 case 'b':
2740 if (sgi_label) {
2741 printf(_("\nThe current boot file is: %s\n"),
2742 sgi_get_bootfile());
2743 if (read_chars(_("Please enter the name of the "
2744 "new boot file: ")) == '\n')
2745 printf(_("Boot file unchanged\n"));
2746 else
2747 sgi_set_bootfile(line_ptr);
2748 } else
2749 bselect();
2750 break;
2751 case 'c':
2752 if (dos_label)
2753 toggle_dos_compatibility_flag();
2754 else if (sun_label)
2755 toggle_sunflags(get_partition(1, partitions),
2756 SUN_FLAG_RONLY);
2757 else if (sgi_label)
2758 sgi_set_swappartition(
2759 get_partition(1, partitions));
2760 else
2761 unknown_command(c);
2762 break;
2763 case 'd':
2764 /* If sgi_label then don't use get_existing_partition,
2765 let the user select a partition, since
2766 get_existing_partition() only works for Linux-like
2767 partition tables */
2768 if (!sgi_label) {
2769 j = get_existing_partition(1, partitions);
2770 } else {
2771 j = get_partition(1, partitions);
2772 }
2773 if (j >= 0)
2774 delete_partition(j);
2775 break;
2776 case 'i':
2777 if (sgi_label)
2778 create_sgiinfo();
2779 else
2780 unknown_command(c);
2781 case 'l':
2782 list_types(get_sys_types());
2783 break;
2784 case 'm':
2785 menu();
2786 break;
2787 case 'n':
2788 new_partition();
2789 break;
2790 case 'o':
2791 create_doslabel();
2792 break;
2793 case 'p':
2794 list_table(0);
2795 break;
2796 case 'q':
2797 close(fd);
2798 printf("\n");
2799 exit(0);
2800 case 's':
2801 create_sunlabel();
2802 break;
2803 case 't':
2804 change_sysid();
2805 break;
2806 case 'u':
2807 change_units();
2808 break;
2809 case 'v':
2810 verify();
2811 break;
2812 case 'w':
2813 write_table(); /* does not return */
2814 break;
2815 case 'x':
2816 if (sgi_label) {
2817 fprintf(stderr,
2818 _("\n\tSorry, no experts menu for SGI "
2819 "partition tables available.\n\n"));
2820 } else
2821 xselect();
2822 break;
2823 default:
2824 unknown_command(c);
2825 menu();
2826 }
2827 }
2828 return 0;
2829 }