]>
git.ipfire.org Git - thirdparty/util-linux.git/blob - fdisk/fdisk.c
1 /* fdisk.c -- Partition table manipulator for Linux.
3 * Copyright (C) 1992 A. V. Le Blanc (LeBlanc@mcc.ac.uk)
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.
30 #include "fdisksunlabel.h"
31 #include "fdisksgilabel.h"
32 #include "fdiskaixlabel.h"
33 #include "fdiskmaclabel.h"
35 #ifdef HAVE_LINUX_COMPILER_H
36 #include <linux/compiler.h>
38 #ifdef HAVE_LINUX_BLKPG_H
39 #include <linux/blkpg.h>
44 static void delete_partition(int i
);
46 #define hex_val(c) ({ \
48 isdigit(_c) ? _c - '0' : \
49 tolower(_c) + 10 - 'a'; \
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))
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; \
67 s |= (sector >> 2) & 0xc0; \
70 /* A valid partition table sector ends in 0x55 0xaa */
72 part_table_flag(unsigned char *b
) {
73 return ((unsigned int) b
[510]) + (((unsigned int) b
[511]) << 8);
77 valid_part_table_flag(unsigned char *b
) {
78 return (b
[510] == 0x55 && b
[511] == 0xaa);
82 write_part_table_flag(unsigned char *b
) {
87 /* start_sect and nr_sects are stored little endian on all machines */
88 /* moreover, they are not aligned correctly */
90 store4_little_endian(unsigned char *cp
, unsigned int val
) {
92 cp
[1] = ((val
>> 8) & 0xff);
93 cp
[2] = ((val
>> 16) & 0xff);
94 cp
[3] = ((val
>> 24) & 0xff);
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);
105 set_start_sect(struct partition
*p
, unsigned int start_sect
) {
106 store4_little_endian(p
->start4
, start_sect
);
110 get_start_sect(struct partition
*p
) {
111 return read4_little_endian(p
->start4
);
115 set_nr_sects(struct partition
*p
, unsigned long long nr_sects
) {
116 store4_little_endian(p
->size4
, nr_sects
);
120 get_nr_sects(struct partition
*p
) {
121 return read4_little_endian(p
->size4
);
125 xread(int fd
, void *buf
, size_t count
) {
131 rv
= read(fd
, p
, count
);
133 if (errno
== EINTR
|| errno
== EAGAIN
)
135 return out
? out
: -1; /* Error */
136 } else if (rv
== 0) {
137 return out
; /* EOF */
149 get_random_id(void) {
155 fd
= open("/dev/urandom", O_RDONLY
);
157 rv
= xread(fd
, &v
, sizeof v
);
164 /* Fallback: sucks, but better than nothing */
165 gettimeofday(&tv
, NULL
);
166 return (unsigned int)(tv
.tv_sec
+ (tv
.tv_usec
<< 12) + getpid());
169 /* normally O_RDWR, -l option gives O_RDONLY */
170 static int type_open
= O_RDWR
;
173 * Raw disk label. For DOS-type partition tables the MBR,
174 * with descriptions of the primary partitions.
176 unsigned char MBRbuffer
[MAX_SECTOR_SIZE
];
179 * per partition table entry data
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.
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
];
194 char *disk_device
, /* must be specified */
195 *line_ptr
, /* interactive input */
196 line_buffer
[LINE_LENGTH
];
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,
204 partitions
= 4; /* maximum partition + 1 */
206 unsigned int user_cylinders
, user_heads
, user_sectors
;
207 unsigned int pt_heads
, pt_sectors
;
208 unsigned int kern_heads
, kern_sectors
;
210 unsigned long long sector_offset
= 1, extended_offset
= 0, sectors
;
214 sector_size
= DEFAULT_SECTOR_SIZE
,
216 user_set_sector_size
= 0,
217 units_per_sector
= 1,
218 display_in_cyl_units
= 1;
220 unsigned long long total_number_of_sectors
; /* (!) 512-byte sectors */
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;
232 void fatal(enum failure why
) {
233 char error
[LINE_LENGTH
],
238 longjmp(listingbuf
, 1);
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");
253 /* msg in cases where fdisk used to probe */
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"
263 snprintf(error
, sizeof(error
),
264 _("Unable to open %s\n"), disk_device
);
267 snprintf(error
, sizeof(error
),
268 _("Unable to read %s\n"), disk_device
);
271 snprintf(error
, sizeof(error
),
272 _("Unable to seek on %s\n"),disk_device
);
274 case unable_to_write
:
275 snprintf(error
, sizeof(error
),
276 _("Unable to write %s\n"), disk_device
);
279 snprintf(error
, sizeof(error
),
280 _("BLKGETSIZE ioctl failed on %s\n"),
284 message
= _("Unable to allocate any more memory\n");
287 message
= _("Fatal error\n");
291 fputs(message
, stderr
);
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
);
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
);
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
);
316 /* Allocate a buffer and read a partition table sector */
318 read_pte(int fd
, int pno
, unsigned long long offset
) {
319 struct pte
*pe
= &ptes
[pno
];
322 pe
->sectorbuffer
= malloc(sector_size
);
323 if (!pe
->sectorbuffer
)
324 fatal(out_of_memory
);
325 read_sector(fd
, offset
, pe
->sectorbuffer
);
327 pe
->part_table
= pe
->ext_pointer
= NULL
;
330 static unsigned long long
331 get_partition_start(struct pte
*pe
) {
332 return pe
->offset
+ get_start_sect(pe
->part_table
);
336 get_part_table(int i
) {
337 return ptes
[i
].part_table
;
341 set_all_unchanged(void) {
344 for (i
= 0; i
< MAXIMUM_PARTS
; i
++)
354 is_garbage_table(void) {
357 for (i
= 0; i
< 4; i
++) {
358 struct pte
*pe
= &ptes
[i
];
359 struct partition
*p
= pe
->part_table
;
361 if (p
->boot_ind
!= 0 && p
->boot_ind
!= 0x80)
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".
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);
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)"));
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"));
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 */
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)"));
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*/
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"));
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"));
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"));
524 sun_label
? sun_get_sysid(i
) :
525 sgi_label
? sgi_get_sysid(i
) :
526 ptes
[i
].part_table
->sys_ind
);
529 static struct systypes
*
530 get_sys_types(void) {
532 sun_label
? sun_sys_types
:
533 sgi_label
? sgi_sys_types
:
537 char *partition_type(unsigned char type
)
540 struct systypes
*types
= get_sys_types();
542 for (i
=0; types
[i
].name
; i
++)
543 if (types
[i
].type
== type
)
544 return _(types
[i
].name
);
549 void list_types(struct systypes
*sys
)
551 unsigned int last
[4], done
= 0, next
= 0, size
;
554 for (i
= 0; sys
[i
].name
; i
++);
557 for (i
= 3; i
>= 0; i
--)
558 last
[3 - i
] = done
+= (size
+ i
- done
) / (i
+ 1);
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
]) {
569 } while (done
< last
[0]);
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
));
581 clear_partition(struct partition
*p
) {
597 set_partition(int i
, int doext
, unsigned long long start
,
598 unsigned long long stop
, int sysid
) {
600 unsigned long long offset
;
603 p
= ptes
[i
].ext_pointer
;
604 offset
= extended_offset
;
606 p
= ptes
[i
].part_table
;
607 offset
= ptes
[i
].offset
;
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
);
623 test_c(char **m
, char *mesg
) {
626 fprintf(stderr
, _("You must set"));
628 fprintf(stderr
, " %s", *m
);
636 warn_geometry(void) {
640 if (sgi_label
) /* cannot set cylinders etc anyway */
643 prev
= test_c(&m
, _("heads"));
645 prev
= test_c(&m
, _("sectors"));
647 prev
= test_c(&m
, _("cylinders"));
651 _("%s%s.\nYou can do this from the extra functions menu.\n"),
652 prev
? _(" and ") : " ", m
);
656 void update_units(void)
658 int cyl_units
= heads
* sectors
;
660 if (display_in_cyl_units
&& cyl_units
)
661 units_per_sector
= cyl_units
;
663 units_per_sector
= 1; /* in sectors */
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"),
678 if (total_number_of_sectors
> UINT_MAX
) {
679 int giga
= (total_number_of_sectors
<< 9) / 1000000000;
680 int hectogiga
= (giga
+ 50) / 100;
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 (%llu bytes) for %d-byte sectors. 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 (unsigned long long ) UINT_MAX
* sector_size
,
695 read_extended(int ext
) {
698 struct partition
*p
, *q
;
702 pex
->ext_pointer
= pex
->part_table
;
705 if (!get_start_sect(p
)) {
707 _("Bad offset in primary extended partition\n"));
711 while (IS_EXTENDED (p
->sys_ind
)) {
712 struct pte
*pe
= &ptes
[partitions
];
714 if (partitions
>= MAXIMUM_PARTS
) {
715 /* This is not a Linux restriction, but
716 this program uses arrays of size MAXIMUM_PARTS.
717 Do not try to `improve' this test. */
718 struct pte
*pre
= &ptes
[partitions
-1];
721 _("Warning: omitting partitions after #%d.\n"
722 "They will be deleted "
723 "if you save this partition table.\n"),
725 clear_partition(pre
->ext_pointer
);
730 read_pte(fd
, partitions
, extended_offset
+ get_start_sect(p
));
732 if (!extended_offset
)
733 extended_offset
= get_start_sect(p
);
735 q
= p
= pt_offset(pe
->sectorbuffer
, 0);
736 for (i
= 0; i
< 4; i
++, p
++) if (get_nr_sects(p
)) {
737 if (IS_EXTENDED (p
->sys_ind
)) {
740 _("Warning: extra link "
741 "pointer in partition table"
742 " %d\n"), partitions
+ 1);
745 } else if (p
->sys_ind
) {
748 _("Warning: ignoring extra "
749 "data in partition table"
750 " %d\n"), partitions
+ 1);
756 /* very strange code here... */
757 if (!pe
->part_table
) {
758 if (q
!= pe
->ext_pointer
)
761 pe
->part_table
= q
+ 1;
763 if (!pe
->ext_pointer
) {
764 if (q
!= pe
->part_table
)
767 pe
->ext_pointer
= q
+ 1;
774 /* remove empty links */
776 for (i
= 4; i
< partitions
; i
++) {
777 struct pte
*pe
= &ptes
[i
];
779 if (!get_nr_sects(pe
->part_table
) &&
780 (partitions
> 5 || ptes
[4].part_table
->sys_ind
)) {
781 printf(_("omitting empty partition (%d)\n"), i
+1);
783 goto remove
; /* numbering changed */
789 dos_write_mbr_id(unsigned char *b
, unsigned int id
) {
790 store4_little_endian(&b
[440], id
);
794 dos_read_mbr_id(const unsigned char *b
) {
795 return read4_little_endian(&b
[440]);
799 dos_print_mbr_id(void) {
800 printf(_("Disk identifier: 0x%08x\n"), dos_read_mbr_id(MBRbuffer
));
804 dos_set_mbr_id(void) {
805 unsigned long new_id
;
809 snprintf(ps
, sizeof ps
, _("New disk identifier (current 0x%08x): "),
810 dos_read_mbr_id(MBRbuffer
));
812 if (read_chars(ps
) == '\n')
815 new_id
= strtoul(line_ptr
, &ep
, 0);
819 dos_write_mbr_id(MBRbuffer
, new_id
);
824 create_doslabel(void) {
825 unsigned int id
= get_random_id();
828 _("Building a new DOS disklabel with disk identifier 0x%08x.\n"
829 "Changes will remain in memory only, until you decide to write them.\n"
830 "After that, of course, the previous content won't be recoverable.\n\n"),
832 sun_nolabel(); /* otherwise always recognised as sun */
833 sgi_nolabel(); /* otherwise always recognised as sgi */
834 mac_label
= aix_label
= osf_label
= possibly_osf_label
= 0;
837 /* Zero out the MBR buffer */
841 get_boot(create_empty_dos
);
843 /* Generate an MBR ID for this disk */
844 dos_write_mbr_id(MBRbuffer
, id
);
846 /* Mark it bootable (unfortunately required) */
847 write_part_table_flag(MBRbuffer
);
851 get_sectorsize(int fd
) {
854 if (user_set_sector_size
)
857 if (blkdev_get_sector_size(fd
, &arg
) == 0)
859 if (sector_size
!= DEFAULT_SECTOR_SIZE
)
860 printf(_("Note: sector size is %d (not %d)\n"),
861 sector_size
, DEFAULT_SECTOR_SIZE
);
865 get_kernel_geometry(int fd
) {
867 struct hd_geometry geometry
;
869 if (!ioctl(fd
, HDIO_GETGEO
, &geometry
)) {
870 kern_heads
= geometry
.heads
;
871 kern_sectors
= geometry
.sectors
;
872 /* never use geometry.cylinders - it is truncated */
878 get_partition_table_geometry(void) {
879 unsigned char *bufp
= MBRbuffer
;
885 if (!(valid_part_table_flag(bufp
)))
889 for (i
=0; i
<4; i
++) {
890 p
= pt_offset(bufp
, i
);
891 if (p
->sys_ind
!= 0) {
893 s
= (p
->end_sector
& 077);
898 } else if (hh
!= h
|| ss
!= s
)
903 if (!first
&& !bad
) {
910 get_geometry(int fd
, struct geom
*g
) {
911 unsigned long long llcyls
;
914 sector_factor
= sector_size
/ 512;
915 guess_device_type(fd
);
916 heads
= cylinders
= sectors
= 0;
917 kern_heads
= kern_sectors
= 0;
918 pt_heads
= pt_sectors
= 0;
920 get_kernel_geometry(fd
);
921 get_partition_table_geometry();
923 heads
= user_heads
? user_heads
:
924 pt_heads
? pt_heads
:
925 kern_heads
? kern_heads
: 255;
926 sectors
= user_sectors
? user_sectors
:
927 pt_sectors
? pt_sectors
:
928 kern_sectors
? kern_sectors
: 63;
930 if (blkdev_get_sectors(fd
, &total_number_of_sectors
) == -1)
931 total_number_of_sectors
= 0;
934 if (dos_compatible_flag
)
935 sector_offset
= sectors
;
937 llcyls
= total_number_of_sectors
/ (heads
* sectors
* sector_factor
);
939 if (cylinders
!= llcyls
) /* truncated? */
942 cylinders
= user_cylinders
;
946 g
->sectors
= sectors
;
947 g
->cylinders
= cylinders
;
953 * -1: no 0xaa55 flag present (possibly entire disk BSD)
954 * 0: found or created label
958 get_boot(enum action what
) {
965 for (i
= 0; i
< 4; i
++) {
966 struct pte
*pe
= &ptes
[i
];
968 pe
->part_table
= pt_offset(MBRbuffer
, i
);
969 pe
->ext_pointer
= NULL
;
971 pe
->sectorbuffer
= MBRbuffer
;
972 pe
->changed
= (what
== create_empty_dos
);
975 if (what
== create_empty_sun
&& check_sun_label())
978 memset(MBRbuffer
, 0, 512);
980 if (what
== create_empty_dos
)
981 goto got_dos_table
; /* skip reading disk */
983 if ((fd
= open(disk_device
, type_open
)) < 0) {
984 if ((fd
= open(disk_device
, O_RDONLY
)) < 0) {
985 if (what
== try_only
)
987 fatal(unable_to_open
);
989 printf(_("You will not be able to write "
990 "the partition table.\n"));
993 if (512 != read(fd
, MBRbuffer
, 512)) {
994 if (what
== try_only
)
996 fatal(unable_to_read
);
999 get_geometry(fd
, NULL
);
1003 if (check_sun_label())
1006 if (check_sgi_label())
1009 if (check_aix_label())
1012 if (check_mac_label())
1015 if (check_osf_label()) {
1016 possibly_osf_label
= 1;
1017 if (!valid_part_table_flag(MBRbuffer
)) {
1021 printf(_("This disk has both DOS and BSD magic.\n"
1022 "Give the 'b' command to go to BSD mode.\n"));
1027 if (!valid_part_table_flag(MBRbuffer
)) {
1031 _("Device contains neither a valid DOS "
1032 "partition table, nor Sun, SGI or OSF "
1044 case create_empty_dos
:
1045 case create_empty_sun
:
1048 fprintf(stderr
, _("Internal error\n"));
1056 for (i
= 0; i
< 4; i
++) {
1057 struct pte
*pe
= &ptes
[i
];
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);
1068 for (i
= 3; i
< partitions
; i
++) {
1069 struct pte
*pe
= &ptes
[i
];
1071 if (!valid_part_table_flag(pe
->sectorbuffer
)) {
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);
1083 /* read line; return 0 or first char */
1087 static int got_eof
= 0;
1089 line_ptr
= line_buffer
;
1090 if (!fgets(line_buffer
, LINE_LENGTH
, stdin
)) {
1092 got_eof
++; /* user typed ^D ? */
1095 fprintf(stderr
, _("\ngot EOF thrice - exiting..\n"));
1100 while (*line_ptr
&& !isgraph(*line_ptr
))
1106 read_char(char *mesg
)
1109 fputs(mesg
, stdout
);
1110 fflush (stdout
); /* requested by niles@scyld.com */
1111 } while (!read_line());
1116 read_chars(char *mesg
)
1118 fputs(mesg
, stdout
);
1119 fflush (stdout
); /* niles@scyld.com */
1128 read_hex(struct systypes
*sys
)
1134 read_char(_("Hex code (type L to list codes): "));
1135 if (tolower(*line_ptr
) == 'l')
1137 else if (isxdigit (*line_ptr
))
1141 hex
= hex
<< 4 | hex_val(*line_ptr
++);
1142 while (isxdigit(*line_ptr
));
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.
1153 * There is no default if DFLT is not between LOW and HIGH.
1156 read_int(unsigned int low
, unsigned int dflt
, unsigned int high
,
1157 unsigned int base
, char *mesg
)
1161 static char *ms
= NULL
;
1162 static int mslen
= 0;
1164 if (!ms
|| strlen(mesg
)+100 > mslen
) {
1165 mslen
= strlen(mesg
)+200;
1166 if (!(ms
= realloc(ms
,mslen
)))
1167 fatal(out_of_memory
);
1170 if (dflt
< low
|| dflt
> high
)
1174 snprintf(ms
, mslen
, _("%s (%u-%u, default %u): "),
1175 mesg
, low
, high
, dflt
);
1177 snprintf(ms
, mslen
, "%s (%u-%u): ",
1181 int use_default
= default_ok
;
1183 /* ask question and read answer */
1184 while (read_chars(ms
) != '\n' && !isdigit(*line_ptr
)
1185 && *line_ptr
!= '-' && *line_ptr
!= '+')
1188 if (*line_ptr
== '+' || *line_ptr
== '-') {
1189 int minus
= (*line_ptr
== '-');
1193 i
= atoi(line_ptr
+1);
1195 while (isdigit(*++line_ptr
))
1198 suflen
= strlen(line_ptr
) - 1;
1200 while(isspace(*(line_ptr
+ suflen
)))
1201 *(line_ptr
+ suflen
--) = '\0';
1203 if ((*line_ptr
== 'C' || *line_ptr
== 'c') &&
1204 *(line_ptr
+ 1) == '\0') {
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') {
1216 if (*line_ptr
== 'K')
1218 else if (*line_ptr
== 'M')
1220 else if (*line_ptr
== 'G')
1221 absolute
= 1000000000;
1224 } else if (*line_ptr
&&
1225 *(line_ptr
+ 1) == '\0') {
1229 if (*line_ptr
== 'K')
1231 else if (*line_ptr
== 'M')
1233 else if (*line_ptr
== 'G')
1237 } else if (*line_ptr
!= '\0')
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"));
1247 if (absolute
&& i
) {
1248 unsigned long long bytes
;
1251 bytes
= (unsigned long long) i
* absolute
;
1252 unit
= sector_size
* units_per_sector
;
1253 bytes
+= unit
/2; /* round */
1262 while (isdigit(*line_ptr
)) {
1268 printf(_("Using default value %u\n"), i
= dflt
);
1269 if (i
>= low
&& i
<= high
)
1272 printf(_("Value out of range.\n"));
1278 get_partition(int warn
, int max
) {
1282 i
= read_int(1, 0, max
, 0, _("Partition number")) - 1;
1286 if ((!sun_label
&& !sgi_label
&& !pe
->part_table
->sys_ind
)
1288 (!sunlabel
->partitions
[i
].num_sectors
||
1289 !sunlabel
->part_tags
[i
].tag
))
1290 || (sgi_label
&& (!sgi_get_num_sectors(i
)))
1293 _("Warning: partition %d has empty type\n"),
1300 get_existing_partition(int warn
, int max
) {
1304 for (i
= 0; i
< max
; i
++) {
1305 struct pte
*pe
= &ptes
[i
];
1306 struct partition
*p
= pe
->part_table
;
1308 if (p
&& !is_cleared_partition(p
)) {
1315 printf(_("Selected partition %d\n"), pno
+1);
1318 printf(_("No partition is defined yet!\n"));
1322 return get_partition(warn
, max
);
1326 get_nonexisting_partition(int warn
, int max
) {
1330 for (i
= 0; i
< max
; i
++) {
1331 struct pte
*pe
= &ptes
[i
];
1332 struct partition
*p
= pe
->part_table
;
1334 if (p
&& is_cleared_partition(p
)) {
1341 printf(_("Selected partition %d\n"), pno
+1);
1344 printf(_("All primary partitions have been defined already!\n"));
1348 return get_partition(warn
, max
);
1352 str_units(int n
) { /* n==1: use singular */
1354 return display_in_cyl_units
? _("cylinder") : _("sector");
1356 return display_in_cyl_units
? _("cylinders") : _("sectors");
1359 void change_units(void)
1361 display_in_cyl_units
= !display_in_cyl_units
;
1363 printf(_("Changing display/entry units to %s\n"),
1368 toggle_active(int i
) {
1369 struct pte
*pe
= &ptes
[i
];
1370 struct partition
*p
= pe
->part_table
;
1372 if (IS_EXTENDED (p
->sys_ind
) && !p
->boot_ind
)
1374 _("WARNING: Partition %d is an extended partition\n"),
1376 p
->boot_ind
= (p
->boot_ind
? 0 : ACTIVE_FLAG
);
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"));
1389 printf(_("DOS Compatibility flag is not set\n"));
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
;
1399 /* Note that for the fifth partition (i == 4) we don't actually
1400 * decrement partitions.
1403 if (warn_geometry())
1404 return; /* C/H/S not set */
1408 sun_delete_partition(i
);
1413 sgi_delete_partition(i
);
1418 if (IS_EXTENDED (p
->sys_ind
) && i
== ext_index
) {
1420 ptes
[ext_index
].ext_pointer
= NULL
;
1421 extended_offset
= 0;
1427 if (!q
->sys_ind
&& i
> 4) {
1428 /* the last one in the chain - just delete */
1431 clear_partition(ptes
[i
].ext_pointer
);
1432 ptes
[i
].changed
= 1;
1434 /* not the last one - further ones will be moved down */
1436 /* delete this link in the chain */
1437 p
= ptes
[i
-1].ext_pointer
;
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];
1446 if (pe
->part_table
) /* prevent SEGFAULT */
1447 set_start_sect(pe
->part_table
,
1448 get_partition_start(pe
) -
1450 pe
->offset
= extended_offset
;
1454 if (partitions
> 5) {
1456 while (i
< partitions
) {
1457 ptes
[i
] = ptes
[i
+1];
1461 /* the only logical: clear only */
1462 clear_partition(ptes
[i
].part_table
);
1467 change_sysid(void) {
1469 int i
, sys
, origsys
;
1470 struct partition
*p
;
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. */
1476 i
= get_existing_partition(0, partitions
);
1478 i
= get_partition(0, partitions
);
1483 p
= ptes
[i
].part_table
;
1484 origsys
= sys
= get_sysid(i
);
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);
1491 sys
= read_hex (get_sys_types());
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"));
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"));
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"));
1525 ptes
[i
].changed
= sun_change_sysid(i
, sys
);
1528 ptes
[i
].changed
= sgi_change_sysid(i
, sys
);
1531 ptes
[i
].changed
= 1;
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
);
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
))
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). */
1554 long2chs(ulong ls
, unsigned int *c
, unsigned int *h
, unsigned int *s
) {
1555 int spc
= heads
* sectors
;
1560 *s
= ls
% sectors
+ 1; /* sectors count from 1 */
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 */
1569 if (!heads
|| !sectors
|| (partition
>= 4))
1570 return; /* do not check extended partitions */
1572 /* physical beginning c, h, s */
1573 pbc
= (p
->cyl
& 0xff) | ((p
->sector
<< 2) & 0x300);
1575 pbs
= p
->sector
& 0x3f;
1577 /* physical ending c, h, s */
1578 pec
= (p
->end_cyl
& 0xff) | ((p
->end_sector
<< 2) & 0x300);
1580 pes
= p
->end_sector
& 0x3f;
1582 /* compute logical beginning (c, h, s) */
1583 long2chs(get_start_sect(p
), &lbc
, &lbh
, &lbs
);
1585 /* compute logical ending (c, h, s) */
1586 long2chs(get_start_sect(p
) + get_nr_sects(p
) - 1, &lec
, &leh
, &les
);
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
);
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
);
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
);
1614 /* Ending on cylinder boundary? */
1615 if (peh
!= (heads
- 1) || pes
!= sectors
) {
1616 printf(_("Partition %i does not end on cylinder boundary.\n"),
1619 printf(_(" phys=(%d, %d, %d) "), pec
, peh
, pes
);
1620 printf(_("should be (%d, %d, %d)\n"),
1621 pec
, heads
- 1, sectors
);
1627 list_disk_geometry(void) {
1628 long long bytes
= (total_number_of_sectors
<< 9);
1629 long megabytes
= bytes
/1000000;
1631 if (megabytes
< 10000)
1632 printf(_("\nDisk %s: %ld MB, %lld bytes\n"),
1633 disk_device
, megabytes
, bytes
);
1635 long hectomega
= (megabytes
+ 50) / 100;
1636 printf(_("\nDisk %s: %ld.%ld GB, %lld bytes\n"),
1637 disk_device
, hectomega
/ 10, hectomega
% 10, bytes
);
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
);
1645 printf(_("Units = %s of %d * %d = %d bytes\n"),
1647 units_per_sector
, sector_size
, units_per_sector
* sector_size
);
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.
1659 wrong_p_order(int *prev
) {
1661 struct partition
*p
;
1662 unsigned int last_p_start_pos
= 0, p_start_pos
;
1665 for (i
= 0 ; i
< partitions
; i
++) {
1668 last_p_start_pos
= 0;
1671 if ((p
= pe
->part_table
)->sys_ind
) {
1672 p_start_pos
= get_partition_start(pe
);
1674 if (last_p_start_pos
> p_start_pos
) {
1680 last_p_start_pos
= p_start_pos
;
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.
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.)
1697 * sfdisk /dev/hda > ohda; sfdisk /dev/hda < ohda
1701 fix_chain_of_logicals(void) {
1702 int j
, oj
, ojj
, sj
, sjj
;
1703 struct partition
*pj
,*pjj
,tmp
;
1705 /* Stage 1: sort sectors but leave sector of part 4 */
1706 /* (Its sector is the global extended_offset.) */
1708 for (j
= 5; j
< partitions
-1; j
++) {
1709 oj
= ptes
[j
].offset
;
1710 ojj
= ptes
[j
+1].offset
;
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
);
1726 /* Stage 2: sort starting sectors */
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
) {
1739 set_start_sect(pj
, ojj
+sjj
-oj
);
1740 set_start_sect(pjj
, oj
+sj
-ojj
);
1745 /* Probably something was changed */
1746 for (j
= 4; j
< partitions
; j
++)
1747 ptes
[j
].changed
= 1;
1751 fix_partition_table_order(void) {
1752 struct pte
*pei
, *pek
;
1755 if (!wrong_p_order(NULL
)) {
1756 printf(_("Nothing to do. Ordering is correct already.\n\n"));
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
;
1767 pe
= pei
->ext_pointer
;
1768 pei
->ext_pointer
= pek
->ext_pointer
;
1769 pek
->ext_pointer
= pe
;
1771 pi
= pei
->part_table
;
1772 pk
= pek
->part_table
;
1774 memmove(&pbuf
, pi
, sizeof(struct partition
));
1775 memmove(pi
, pk
, sizeof(struct partition
));
1776 memmove(pk
, &pbuf
, sizeof(struct partition
));
1778 pei
->changed
= pek
->changed
= 1;
1782 fix_chain_of_logicals();
1784 printf(_("Done.\n"));
1789 list_table(int xtra
) {
1790 struct partition
*p
;
1795 sun_list_table(xtra
);
1800 sgi_list_table(xtra
);
1804 list_disk_geometry();
1807 xbsd_print_disklabel(xtra
);
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"));
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]))
1825 printf(_("%*s Boot Start End Blocks Id System\n"),
1828 for (i
= 0; i
< partitions
; i
++) {
1829 struct pte
*pe
= &ptes
[i
];
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;
1837 if (sector_size
< 1024) {
1838 pblocks
/= (1024 / sector_size
);
1839 podd
= psects
% (1024 / sector_size
);
1841 if (sector_size
> 1024)
1842 pblocks
*= (sector_size
/ 1024);
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
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
);
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"));
1868 x_list_table(int extend
) {
1870 struct partition
*p
;
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
++) {
1878 p
= (extend
? pe
->ext_pointer
: pe
->part_table
);
1880 printf("%2d %02x%4d%4d%5d%4d%4d%5d%11lu%11lu %02x\n",
1881 i
+ 1, p
->boot_ind
, p
->head
,
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
);
1889 check_consistency(p
, i
);
1895 fill_bounds(unsigned long long *first
, unsigned long long *last
) {
1897 struct pte
*pe
= &ptes
[0];
1898 struct partition
*p
;
1900 for (i
= 0; i
< partitions
; pe
++,i
++) {
1902 if (!p
->sys_ind
|| IS_EXTENDED (p
->sys_ind
)) {
1903 first
[i
] = 0xffffffff;
1906 first
[i
] = get_partition_start(pe
);
1907 last
[i
] = first
[i
] + get_nr_sects(p
) - 1;
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
;
1917 real_s
= sector(s
) - 1;
1918 real_c
= cylinder(s
, c
);
1919 total
= (real_c
* sectors
+ real_s
) * heads
+ h
;
1921 fprintf(stderr
, _("Warning: partition %d contains sector 0\n"), n
);
1924 _("Partition %d: head %d greater than maximum %d\n"),
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
)
1934 _("Partition %d: previous sectors %d disagrees with "
1935 "total %d\n"), n
, start
, total
);
1941 unsigned long long total
= 1;
1942 unsigned long long n_sectors
= (total_number_of_sectors
/ sector_factor
);
1943 unsigned long long first
[partitions
], last
[partitions
];
1944 struct partition
*p
;
1946 if (warn_geometry())
1959 fill_bounds(first
, last
);
1960 for (i
= 0; i
< partitions
; i
++) {
1961 struct pte
*pe
= &ptes
[i
];
1964 if (p
->sys_ind
&& !IS_EXTENDED (p
->sys_ind
)) {
1965 check_consistency(p
, i
);
1966 if (get_partition_start(pe
) < first
[i
])
1967 printf(_("Warning: bad start-of-data in "
1968 "partition %d\n"), i
+ 1);
1969 check(i
+ 1, p
->end_head
, p
->end_sector
, p
->end_cyl
,
1971 total
+= last
[i
] + 1 - first
[i
];
1972 for (j
= 0; j
< i
; j
++)
1973 if ((first
[i
] >= first
[j
] && first
[i
] <= last
[j
])
1974 || ((last
[i
] <= last
[j
] && last
[i
] >= first
[j
]))) {
1975 printf(_("Warning: partition %d overlaps "
1976 "partition %d.\n"), j
+ 1, i
+ 1);
1977 total
+= first
[i
] >= first
[j
] ?
1978 first
[i
] : first
[j
];
1979 total
-= last
[i
] <= last
[j
] ?
1985 if (extended_offset
) {
1986 struct pte
*pex
= &ptes
[ext_index
];
1987 unsigned long long e_last
= get_start_sect(pex
->part_table
) +
1988 get_nr_sects(pex
->part_table
) - 1;
1990 for (i
= 4; i
< partitions
; i
++) {
1992 p
= ptes
[i
].part_table
;
1994 if (i
!= 4 || i
+ 1 < partitions
)
1995 printf(_("Warning: partition %d "
1996 "is empty\n"), i
+ 1);
1998 else if (first
[i
] < extended_offset
||
2000 printf(_("Logical partition %d not entirely in "
2001 "partition %d\n"), i
+ 1, ext_index
+ 1);
2005 if (total
> n_sectors
)
2006 printf(_("Total allocated sectors %llu greater than the maximum"
2007 " %llu\n"), total
, n_sectors
);
2008 else if (total
< n_sectors
)
2009 printf(_("%lld unallocated %d-byte sectors\n"),
2010 n_sectors
- total
, sector_size
);
2014 add_partition(int n
, int sys
) {
2015 char mesg
[256]; /* 48 does not suffice in Japanese */
2017 struct partition
*p
= ptes
[n
].part_table
;
2018 struct partition
*q
= ptes
[ext_index
].part_table
;
2020 unsigned long long start
, stop
= 0, limit
, temp
,
2021 first
[partitions
], last
[partitions
];
2023 if (p
&& p
->sys_ind
) {
2024 printf(_("Partition %d is already defined. Delete "
2025 "it before re-adding it.\n"), n
+ 1);
2028 fill_bounds(first
, last
);
2030 start
= sector_offset
;
2031 if (display_in_cyl_units
|| !total_number_of_sectors
)
2032 llimit
= heads
* sectors
* cylinders
- 1;
2034 llimit
= (total_number_of_sectors
/ sector_factor
) - 1;
2036 if (limit
!= llimit
)
2038 if (extended_offset
) {
2039 first
[ext_index
] = extended_offset
;
2040 last
[ext_index
] = get_start_sect(q
) +
2041 get_nr_sects(q
) - 1;
2044 start
= extended_offset
+ sector_offset
;
2045 limit
= get_start_sect(q
) + get_nr_sects(q
) - 1;
2047 if (display_in_cyl_units
)
2048 for (i
= 0; i
< partitions
; i
++)
2049 first
[i
] = (cround(first
[i
]) - 1) * units_per_sector
;
2051 snprintf(mesg
, sizeof(mesg
), _("First %s"), str_units(SINGULAR
));
2054 for (i
= 0; i
< partitions
; i
++) {
2055 unsigned long long lastplusoff
;
2057 if (start
== ptes
[i
].offset
)
2058 start
+= sector_offset
;
2059 lastplusoff
= last
[i
] + ((n
<4) ? 0 : sector_offset
);
2060 if (start
>= first
[i
] && start
<= lastplusoff
)
2061 start
= lastplusoff
+ 1;
2065 if (start
>= temp
+units_per_sector
&& read
) {
2066 printf(_("Sector %llu is already allocated\n"), temp
);
2070 if (!read
&& start
== temp
) {
2071 unsigned long long i
= start
;
2073 start
= read_int(cround(i
), cround(i
), cround(limit
),
2075 if (display_in_cyl_units
) {
2076 start
= (start
- 1) * units_per_sector
;
2077 if (start
< i
) start
= i
;
2081 } while (start
!= temp
|| !read
);
2082 if (n
> 4) { /* NOT for fifth partition */
2083 struct pte
*pe
= &ptes
[n
];
2085 pe
->offset
= start
- sector_offset
;
2086 if (pe
->offset
== extended_offset
) { /* must be corrected */
2088 if (sector_offset
== 1)
2093 for (i
= 0; i
< partitions
; i
++) {
2094 struct pte
*pe
= &ptes
[i
];
2096 if (start
< pe
->offset
&& limit
>= pe
->offset
)
2097 limit
= pe
->offset
- 1;
2098 if (start
< first
[i
] && limit
>= first
[i
])
2099 limit
= first
[i
] - 1;
2101 if (start
> limit
) {
2102 printf(_("No free sectors available\n"));
2107 if (cround(start
) == cround(limit
)) {
2110 snprintf(mesg
, sizeof(mesg
),
2111 _("Last %1$s, +%2$s or +size{K,M,G}"),
2112 str_units(SINGULAR
), str_units(PLURAL
));
2114 stop
= read_int(cround(start
), cround(limit
), cround(limit
),
2115 cround(start
), mesg
);
2116 if (display_in_cyl_units
) {
2117 stop
= stop
* units_per_sector
- 1;
2123 set_partition(n
, 0, start
, stop
, sys
);
2125 set_partition(n
- 1, 1, ptes
[n
].offset
, stop
, EXTENDED
);
2127 if (IS_EXTENDED (sys
)) {
2128 struct pte
*pe4
= &ptes
[4];
2129 struct pte
*pen
= &ptes
[n
];
2132 pen
->ext_pointer
= p
;
2133 pe4
->offset
= extended_offset
= start
;
2134 if (!(pe4
->sectorbuffer
= calloc(1, sector_size
)))
2135 fatal(out_of_memory
);
2136 pe4
->part_table
= pt_offset(pe4
->sectorbuffer
, 0);
2137 pe4
->ext_pointer
= pe4
->part_table
+ 1;
2145 if (partitions
> 5 || ptes
[4].part_table
->sys_ind
) {
2146 struct pte
*pe
= &ptes
[partitions
];
2148 if (!(pe
->sectorbuffer
= calloc(1, sector_size
)))
2149 fatal(out_of_memory
);
2150 pe
->part_table
= pt_offset(pe
->sectorbuffer
, 0);
2151 pe
->ext_pointer
= pe
->part_table
+ 1;
2156 add_partition(partitions
- 1, LINUX_NATIVE
);
2160 new_partition(void) {
2161 int i
, free_primary
= 0;
2163 if (warn_geometry())
2167 add_sun_partition(get_partition(0, partitions
), LINUX_NATIVE
);
2172 sgi_add_partition(get_partition(0, partitions
), LINUX_NATIVE
);
2177 printf(_("\tSorry - this fdisk cannot handle AIX disk labels."
2178 "\n\tIf you want to add DOS-type partitions, create"
2179 "\n\ta new empty DOS partition table first. (Use o.)"
2181 "This will destroy the present disk contents.\n"));
2186 printf(_("\tSorry - this fdisk cannot handle Mac disk labels."
2187 "\n\tIf you want to add DOS-type partitions, create"
2188 "\n\ta new empty DOS partition table first. (Use o.)"
2190 "This will destroy the present disk contents.\n"));
2194 for (i
= 0; i
< 4; i
++)
2195 free_primary
+= !ptes
[i
].part_table
->sys_ind
;
2197 if (!free_primary
&& partitions
>= MAXIMUM_PARTS
) {
2198 printf(_("The maximum number of partitions has been created\n"));
2202 if (!free_primary
) {
2203 if (extended_offset
)
2206 printf(_("You must delete some partition and add "
2207 "an extended partition first\n"));
2208 } else if (partitions
>= MAXIMUM_PARTS
) {
2209 printf(_("All logical partitions are in use\n"));
2210 printf(_("Adding a primary partition\n"));
2211 add_partition(get_partition(0, 4), LINUX_NATIVE
);
2213 char c
, line
[LINE_LENGTH
];
2214 snprintf(line
, sizeof(line
),
2215 _("Command action\n %s\n p primary "
2216 "partition (1-4)\n"), extended_offset
?
2217 _("l logical (5 or over)") : _("e extended"));
2219 if ((c
= tolower(read_char(line
))) == 'p') {
2220 int i
= get_nonexisting_partition(0, 4);
2222 add_partition(i
, LINUX_NATIVE
);
2225 else if (c
== 'l' && extended_offset
) {
2229 else if (c
== 'e' && !extended_offset
) {
2230 int i
= get_nonexisting_partition(0, 4);
2232 add_partition(i
, EXTENDED
);
2236 printf(_("Invalid partition number "
2237 "for type `%c'\n"), c
);
2248 if (ptes
[i
].changed
)
2249 ptes
[3].changed
= 1;
2250 for (i
= 3; i
< partitions
; i
++) {
2251 struct pte
*pe
= &ptes
[i
];
2254 write_part_table_flag(pe
->sectorbuffer
);
2255 write_sector(fd
, pe
->offset
, pe
->sectorbuffer
);
2259 else if (sgi_label
) {
2260 /* no test on change? the printf below might be mistaken */
2262 } else if (sun_label
) {
2266 if (ptes
[i
].changed
)
2272 printf(_("The partition table has been altered!\n\n"));
2273 reread_partition_table(1);
2277 reread_partition_table(int leave
) {
2279 struct stat statbuf
;
2281 i
= fstat(fd
, &statbuf
);
2282 if (i
== 0 && S_ISBLK(statbuf
.st_mode
)) {
2286 printf(_("Calling ioctl() to re-read partition table.\n"));
2287 i
= ioctl(fd
, BLKRRPART
);
2295 printf(_("\nWARNING: Re-reading the partition table failed with error %d: %s.\n"
2296 "The kernel still uses the old table. The new table will be used at\n"
2297 "the next reboot or after you run partprobe(8) or kpartx(8)\n"),
2298 errno
, strerror(errno
));
2303 _("\nWARNING: If you have created or modified any DOS 6.x\n"
2304 "partitions, please see the fdisk manual page for additional\n"
2308 if (fsync(fd
) || close(fd
)) {
2309 fprintf(stderr
, _("\nError closing file\n"));
2313 printf(_("Syncing disks.\n"));
2315 sleep(4); /* for sync() */
2320 #define MAX_PER_LINE 16
2322 print_buffer(unsigned char pbuffer
[]) {
2326 for (i
= 0, l
= 0; i
< sector_size
; i
++, l
++) {
2328 printf("0x%03X:", i
);
2329 printf(" %02X", pbuffer
[i
]);
2330 if (l
== MAX_PER_LINE
- 1) {
2344 printf(_("Device: %s\n"), disk_device
);
2345 if (sun_label
|| sgi_label
)
2346 print_buffer(MBRbuffer
);
2347 else for (i
= 3; i
< partitions
; i
++)
2348 print_buffer(ptes
[i
].sectorbuffer
);
2353 struct pte
*pe
= &ptes
[i
];
2354 struct partition
*p
= pe
->part_table
;
2355 unsigned int new, first
;
2357 if (warn_geometry())
2359 if (!p
->sys_ind
|| !get_nr_sects(p
) || IS_EXTENDED (p
->sys_ind
)) {
2360 printf(_("Partition %d has no data area\n"), i
+ 1);
2363 first
= get_partition_start(pe
);
2364 new = read_int(first
, first
, first
+ get_nr_sects(p
) - 1, first
,
2365 _("New beginning of data")) - pe
->offset
;
2367 if (new != get_nr_sects(p
)) {
2368 first
= get_nr_sects(p
) + get_start_sect(p
) - new;
2369 set_nr_sects(p
, first
);
2370 set_start_sect(p
, new);
2381 c
= tolower(read_char(_("Expert command (m for help): ")));
2389 move_begin(get_partition(0, partitions
));
2392 user_cylinders
= cylinders
=
2393 read_int(1, cylinders
, 1048576, 0,
2394 _("Number of cylinders"));
2396 sun_set_ncyl(cylinders
);
2414 fix_partition_table_order();
2420 user_heads
= heads
= read_int(1, heads
, 256, 0,
2421 _("Number of heads"));
2447 user_sectors
= sectors
= read_int(1, sectors
, 63, 0,
2448 _("Number of sectors"));
2449 if (dos_compatible_flag
) {
2450 sector_offset
= sectors
;
2451 fprintf(stderr
, _("Warning: setting "
2452 "sector offset for DOS "
2461 write_table(); /* does not return */
2465 sun_set_pcylcount();
2474 is_ide_cdrom_or_tape(char *device
) {
2477 struct stat statbuf
;
2480 /* No device was given explicitly, and we are trying some
2481 likely things. But opening /dev/hdc may produce errors like
2482 "hdc: tray open or drive not ready"
2483 if it happens to be a CD-ROM drive. It even happens that
2484 the process hangs on the attempt to read a music CD.
2485 So try to be careful. This only works since 2.1.73. */
2487 if (strncmp("/dev/hd", device
, 7))
2490 snprintf(buf
, sizeof(buf
), "/proc/ide/%s/media", device
+5);
2491 procf
= fopen(buf
, "r");
2492 if (procf
!= NULL
&& fgets(buf
, sizeof(buf
), procf
))
2493 is_ide
= (!strncmp(buf
, "cdrom", 5) ||
2494 !strncmp(buf
, "tape", 4));
2496 /* Now when this proc file does not exist, skip the
2497 device when it is read-only. */
2498 if (stat(device
, &statbuf
) == 0)
2499 is_ide
= ((statbuf
.st_mode
& 0222) == 0);
2507 gpt_warning(char *dev
)
2509 if (dev
&& gpt_probe_signature_devname(dev
))
2510 fprintf(stderr
, _("\nWARNING: GPT (GUID Partition Table) detected on '%s'! "
2511 "The util fdisk doesn't support GPT. Use GNU Parted.\n\n"), dev
);
2515 try(char *device
, int user_specified
) {
2518 disk_device
= device
;
2519 if (setjmp(listingbuf
))
2521 if (!user_specified
)
2522 if (is_ide_cdrom_or_tape(device
))
2524 gpt_warning(device
);
2525 if ((fd
= open(disk_device
, type_open
)) >= 0) {
2526 gb
= get_boot(try_only
);
2527 if (gb
> 0) { /* I/O error */
2528 } else if (gb
< 0) { /* no DOS signature */
2529 list_disk_geometry();
2530 if (!aix_label
&& !mac_label
&& btrydev(device
) < 0)
2532 _("Disk %s doesn't contain a valid "
2533 "partition table\n"), device
);
2539 /* Ignore other errors, since we try IDE
2540 and SCSI hard disks which may not be
2541 installed on the system. */
2542 if (errno
== EACCES
) {
2543 fprintf(stderr
, _("Cannot open %s\n"), device
);
2551 * try all things in /proc/partitions that look like a full disk
2556 char line
[100], ptname
[100], devname
[120];
2558 unsigned long long sz
;
2560 procpt
= fopen(PROC_PARTITIONS
, "r");
2561 if (procpt
== NULL
) {
2562 fprintf(stderr
, _("cannot open %s\n"), PROC_PARTITIONS
);
2566 while (fgets(line
, sizeof(line
), procpt
)) {
2567 if (sscanf (line
, " %d %d %llu %100[^\n ]",
2568 &ma
, &mi
, &sz
, ptname
) != 4)
2570 snprintf(devname
, sizeof(devname
), "/dev/%s", ptname
);
2571 if (is_probably_full_disk(devname
))
2581 unknown_command(int c
) {
2582 printf(_("%c: unknown command\n"), c
);
2588 main(int argc
, char **argv
) {
2590 int optl
= 0, opts
= 0;
2592 setlocale(LC_ALL
, "");
2593 bindtextdomain(PACKAGE
, LOCALEDIR
);
2594 textdomain(PACKAGE
);
2599 * fdisk -l [-b sectorsize] [-u] device ...
2600 * fdisk -s [partition] ...
2601 * fdisk [-b sectorsize] [-u] device
2603 * Options -C, -H, -S set the geometry.
2606 while ((c
= getopt(argc
, argv
, "b:C:H:lsS:uvV")) != -1) {
2609 /* Ugly: this sector size is really per device,
2610 so cannot be combined with multiple disks,
2611 and te same goes for the C/H/S options.
2613 sector_size
= atoi(optarg
);
2614 if (sector_size
!= 512 && sector_size
!= 1024 &&
2615 sector_size
!= 2048)
2618 user_set_sector_size
= 1;
2621 user_cylinders
= atoi(optarg
);
2624 user_heads
= atoi(optarg
);
2625 if (user_heads
<= 0 || user_heads
>= 256)
2629 user_sectors
= atoi(optarg
);
2630 if (user_sectors
<= 0 || user_sectors
>= 64)
2640 display_in_cyl_units
= 0;
2644 printf("fdisk (%s)\n", PACKAGE_STRING
);
2652 printf(_("This kernel finds the sector size itself - "
2653 "-b option ignored\n"));
2655 if (user_set_sector_size
&& argc
-optind
!= 1)
2656 printf(_("Warning: the -b (set sector size) option should"
2657 " be used with one specified device\n"));
2662 type_open
= O_RDONLY
;
2663 if (argc
> optind
) {
2665 /* avoid gcc warning:
2666 variable `k' might be clobbered by `longjmp' */
2669 for (k
= optind
; k
< argc
; k
++)
2672 /* we no longer have default device names */
2673 /* but we can use /proc/partitions instead */
2680 unsigned long long size
;
2683 type_open
= O_RDONLY
;
2685 opts
= argc
- optind
;
2689 for (j
= optind
; j
< argc
; j
++) {
2690 disk_device
= argv
[j
];
2691 if ((fd
= open(disk_device
, type_open
)) < 0)
2692 fatal(unable_to_open
);
2693 if (blkdev_get_sectors(fd
, &size
) == -1)
2697 printf("%llu\n", size
/2);
2699 printf("%s: %llu\n", argv
[j
], size
/2);
2704 if (argc
-optind
== 1)
2705 disk_device
= argv
[optind
];
2706 else if (argc
-optind
!= 0)
2711 gpt_warning(disk_device
);
2715 /* OSF label, and no DOS label */
2716 printf(_("Detected an OSF/1 disklabel on %s, entering "
2717 "disklabel mode.\n"),
2721 /* If we return we may want to make an empty DOS label? */
2726 c
= tolower(read_char(_("Command (m for help): ")));
2730 toggle_active(get_partition(1, partitions
));
2732 toggle_sunflags(get_partition(1, partitions
),
2735 sgi_set_bootpartition(
2736 get_partition(1, partitions
));
2742 printf(_("\nThe current boot file is: %s\n"),
2743 sgi_get_bootfile());
2744 if (read_chars(_("Please enter the name of the "
2745 "new boot file: ")) == '\n')
2746 printf(_("Boot file unchanged\n"));
2748 sgi_set_bootfile(line_ptr
);
2754 toggle_dos_compatibility_flag();
2756 toggle_sunflags(get_partition(1, partitions
),
2759 sgi_set_swappartition(
2760 get_partition(1, partitions
));
2765 /* If sgi_label then don't use get_existing_partition,
2766 let the user select a partition, since
2767 get_existing_partition() only works for Linux-like
2770 j
= get_existing_partition(1, partitions
);
2772 j
= get_partition(1, partitions
);
2775 delete_partition(j
);
2783 list_types(get_sys_types());
2814 write_table(); /* does not return */
2819 _("\n\tSorry, no experts menu for SGI "
2820 "partition tables available.\n\n"));