]>
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
;
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 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);
693 read_extended(int ext
) {
696 struct partition
*p
, *q
;
700 pex
->ext_pointer
= pex
->part_table
;
703 if (!get_start_sect(p
)) {
705 _("Bad offset in primary extended partition\n"));
709 while (IS_EXTENDED (p
->sys_ind
)) {
710 struct pte
*pe
= &ptes
[partitions
];
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];
719 _("Warning: omitting partitions after #%d.\n"
720 "They will be deleted "
721 "if you save this partition table.\n"),
723 clear_partition(pre
->ext_pointer
);
728 read_pte(fd
, partitions
, extended_offset
+ get_start_sect(p
));
730 if (!extended_offset
)
731 extended_offset
= get_start_sect(p
);
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
)) {
738 _("Warning: extra link "
739 "pointer in partition table"
740 " %d\n"), partitions
+ 1);
743 } else if (p
->sys_ind
) {
746 _("Warning: ignoring extra "
747 "data in partition table"
748 " %d\n"), partitions
+ 1);
754 /* very strange code here... */
755 if (!pe
->part_table
) {
756 if (q
!= pe
->ext_pointer
)
759 pe
->part_table
= q
+ 1;
761 if (!pe
->ext_pointer
) {
762 if (q
!= pe
->part_table
)
765 pe
->ext_pointer
= q
+ 1;
772 /* remove empty links */
774 for (i
= 4; i
< partitions
; i
++) {
775 struct pte
*pe
= &ptes
[i
];
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);
781 goto remove
; /* numbering changed */
787 dos_write_mbr_id(unsigned char *b
, unsigned int id
) {
788 store4_little_endian(&b
[440], id
);
792 dos_read_mbr_id(const unsigned char *b
) {
793 return read4_little_endian(&b
[440]);
797 dos_print_mbr_id(void) {
798 printf(_("Disk identifier: 0x%08x\n"), dos_read_mbr_id(MBRbuffer
));
802 dos_set_mbr_id(void) {
803 unsigned long new_id
;
807 snprintf(ps
, sizeof ps
, _("New disk identifier (current 0x%08x): "),
808 dos_read_mbr_id(MBRbuffer
));
810 if (read_chars(ps
) == '\n')
813 new_id
= strtoul(line_ptr
, &ep
, 0);
817 dos_write_mbr_id(MBRbuffer
, new_id
);
822 create_doslabel(void) {
823 unsigned int id
= get_random_id();
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"),
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;
835 /* Zero out the MBR buffer */
839 get_boot(create_empty_dos
);
841 /* Generate an MBR ID for this disk */
842 dos_write_mbr_id(MBRbuffer
, id
);
844 /* Mark it bootable (unfortunately required) */
845 write_part_table_flag(MBRbuffer
);
849 get_sectorsize(int fd
) {
852 if (user_set_sector_size
)
855 if (blkdev_get_sector_size(fd
, &arg
) == 0)
857 if (sector_size
!= DEFAULT_SECTOR_SIZE
)
858 printf(_("Note: sector size is %d (not %d)\n"),
859 sector_size
, DEFAULT_SECTOR_SIZE
);
863 get_kernel_geometry(int fd
) {
865 struct hd_geometry geometry
;
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 */
876 get_partition_table_geometry(void) {
877 unsigned char *bufp
= MBRbuffer
;
883 if (!(valid_part_table_flag(bufp
)))
887 for (i
=0; i
<4; i
++) {
888 p
= pt_offset(bufp
, i
);
889 if (p
->sys_ind
!= 0) {
891 s
= (p
->end_sector
& 077);
896 } else if (hh
!= h
|| ss
!= s
)
901 if (!first
&& !bad
) {
908 get_geometry(int fd
, struct geom
*g
) {
909 unsigned long long llsectors
, llcyls
;
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;
918 get_kernel_geometry(fd
);
919 get_partition_table_geometry();
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;
928 if (blkdev_get_sectors(fd
, &llsectors
) == -1)
931 total_number_of_sectors
= llsectors
;
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 total
= 1;
1942 unsigned long long first
[partitions
], last
[partitions
];
1943 struct partition
*p
;
1945 if (warn_geometry())
1958 fill_bounds(first
, last
);
1959 for (i
= 0; i
< partitions
; i
++) {
1960 struct pte
*pe
= &ptes
[i
];
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
,
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
] ?
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;
1989 for (i
= 4; i
< partitions
; i
++) {
1991 p
= ptes
[i
].part_table
;
1993 if (i
!= 4 || i
+ 1 < partitions
)
1994 printf(_("Warning: partition %d "
1995 "is empty\n"), i
+ 1);
1997 else if (first
[i
] < extended_offset
||
1999 printf(_("Logical partition %d not entirely in "
2000 "partition %d\n"), i
+ 1, ext_index
+ 1);
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
);
2013 add_partition(int n
, int sys
) {
2014 char mesg
[256]; /* 48 does not suffice in Japanese */
2016 struct partition
*p
= ptes
[n
].part_table
;
2017 struct partition
*q
= ptes
[ext_index
].part_table
;
2019 unsigned long long start
, stop
= 0, limit
, temp
,
2020 first
[partitions
], last
[partitions
];
2022 if (p
&& p
->sys_ind
) {
2023 printf(_("Partition %d is already defined. Delete "
2024 "it before re-adding it.\n"), n
+ 1);
2027 fill_bounds(first
, last
);
2029 start
= sector_offset
;
2030 if (display_in_cyl_units
|| !total_number_of_sectors
)
2031 llimit
= heads
* sectors
* cylinders
- 1;
2033 llimit
= (total_number_of_sectors
/ sector_factor
) - 1;
2035 if (limit
!= llimit
)
2037 if (extended_offset
) {
2038 first
[ext_index
] = extended_offset
;
2039 last
[ext_index
] = get_start_sect(q
) +
2040 get_nr_sects(q
) - 1;
2043 start
= extended_offset
+ sector_offset
;
2044 limit
= get_start_sect(q
) + get_nr_sects(q
) - 1;
2046 if (display_in_cyl_units
)
2047 for (i
= 0; i
< partitions
; i
++)
2048 first
[i
] = (cround(first
[i
]) - 1) * units_per_sector
;
2050 snprintf(mesg
, sizeof(mesg
), _("First %s"), str_units(SINGULAR
));
2053 for (i
= 0; i
< partitions
; i
++) {
2054 unsigned long long lastplusoff
;
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;
2064 if (start
>= temp
+units_per_sector
&& read
) {
2065 printf(_("Sector %llu is already allocated\n"), temp
);
2069 if (!read
&& start
== temp
) {
2070 unsigned long long i
= start
;
2072 start
= read_int(cround(i
), cround(i
), cround(limit
),
2074 if (display_in_cyl_units
) {
2075 start
= (start
- 1) * units_per_sector
;
2076 if (start
< i
) start
= i
;
2080 } while (start
!= temp
|| !read
);
2081 if (n
> 4) { /* NOT for fifth partition */
2082 struct pte
*pe
= &ptes
[n
];
2084 pe
->offset
= start
- sector_offset
;
2085 if (pe
->offset
== extended_offset
) { /* must be corrected */
2087 if (sector_offset
== 1)
2092 for (i
= 0; i
< partitions
; i
++) {
2093 struct pte
*pe
= &ptes
[i
];
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;
2100 if (start
> limit
) {
2101 printf(_("No free sectors available\n"));
2106 if (cround(start
) == cround(limit
)) {
2109 snprintf(mesg
, sizeof(mesg
),
2110 _("Last %1$s, +%2$s or +size{K,M,G}"),
2111 str_units(SINGULAR
), str_units(PLURAL
));
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;
2122 set_partition(n
, 0, start
, stop
, sys
);
2124 set_partition(n
- 1, 1, ptes
[n
].offset
, stop
, EXTENDED
);
2126 if (IS_EXTENDED (sys
)) {
2127 struct pte
*pe4
= &ptes
[4];
2128 struct pte
*pen
= &ptes
[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;
2144 if (partitions
> 5 || ptes
[4].part_table
->sys_ind
) {
2145 struct pte
*pe
= &ptes
[partitions
];
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;
2155 add_partition(partitions
- 1, LINUX_NATIVE
);
2159 new_partition(void) {
2160 int i
, free_primary
= 0;
2162 if (warn_geometry())
2166 add_sun_partition(get_partition(0, partitions
), LINUX_NATIVE
);
2171 sgi_add_partition(get_partition(0, partitions
), LINUX_NATIVE
);
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.)"
2180 "This will destroy the present disk contents.\n"));
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.)"
2189 "This will destroy the present disk contents.\n"));
2193 for (i
= 0; i
< 4; i
++)
2194 free_primary
+= !ptes
[i
].part_table
->sys_ind
;
2196 if (!free_primary
&& partitions
>= MAXIMUM_PARTS
) {
2197 printf(_("The maximum number of partitions has been created\n"));
2201 if (!free_primary
) {
2202 if (extended_offset
)
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
);
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"));
2218 if ((c
= tolower(read_char(line
))) == 'p') {
2219 int i
= get_nonexisting_partition(0, 4);
2221 add_partition(i
, LINUX_NATIVE
);
2224 else if (c
== 'l' && extended_offset
) {
2228 else if (c
== 'e' && !extended_offset
) {
2229 int i
= get_nonexisting_partition(0, 4);
2231 add_partition(i
, EXTENDED
);
2235 printf(_("Invalid partition number "
2236 "for type `%c'\n"), c
);
2247 if (ptes
[i
].changed
)
2248 ptes
[3].changed
= 1;
2249 for (i
= 3; i
< partitions
; i
++) {
2250 struct pte
*pe
= &ptes
[i
];
2253 write_part_table_flag(pe
->sectorbuffer
);
2254 write_sector(fd
, pe
->offset
, pe
->sectorbuffer
);
2258 else if (sgi_label
) {
2259 /* no test on change? the printf below might be mistaken */
2261 } else if (sun_label
) {
2265 if (ptes
[i
].changed
)
2271 printf(_("The partition table has been altered!\n\n"));
2272 reread_partition_table(1);
2276 reread_partition_table(int leave
) {
2278 struct stat statbuf
;
2280 i
= fstat(fd
, &statbuf
);
2281 if (i
== 0 && S_ISBLK(statbuf
.st_mode
)) {
2285 printf(_("Calling ioctl() to re-read partition table.\n"));
2286 i
= ioctl(fd
, BLKRRPART
);
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
));
2302 _("\nWARNING: If you have created or modified any DOS 6.x\n"
2303 "partitions, please see the fdisk manual page for additional\n"
2307 if (fsync(fd
) || close(fd
)) {
2308 fprintf(stderr
, _("\nError closing file\n"));
2312 printf(_("Syncing disks.\n"));
2314 sleep(4); /* for sync() */
2319 #define MAX_PER_LINE 16
2321 print_buffer(unsigned char pbuffer
[]) {
2325 for (i
= 0, l
= 0; i
< sector_size
; i
++, l
++) {
2327 printf("0x%03X:", i
);
2328 printf(" %02X", pbuffer
[i
]);
2329 if (l
== MAX_PER_LINE
- 1) {
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
);
2352 struct pte
*pe
= &ptes
[i
];
2353 struct partition
*p
= pe
->part_table
;
2354 unsigned int new, first
;
2356 if (warn_geometry())
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);
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
;
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);
2380 c
= tolower(read_char(_("Expert command (m for help): ")));
2388 move_begin(get_partition(0, partitions
));
2391 user_cylinders
= cylinders
=
2392 read_int(1, cylinders
, 1048576, 0,
2393 _("Number of cylinders"));
2395 sun_set_ncyl(cylinders
);
2413 fix_partition_table_order();
2419 user_heads
= heads
= read_int(1, heads
, 256, 0,
2420 _("Number of heads"));
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 "
2460 write_table(); /* does not return */
2464 sun_set_pcylcount();
2473 is_ide_cdrom_or_tape(char *device
) {
2476 struct stat statbuf
;
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. */
2486 if (strncmp("/dev/hd", device
, 7))
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));
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);
2506 gpt_warning(char *dev
)
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
);
2514 try(char *device
, int user_specified
) {
2517 disk_device
= device
;
2518 if (setjmp(listingbuf
))
2520 if (!user_specified
)
2521 if (is_ide_cdrom_or_tape(device
))
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)
2531 _("Disk %s doesn't contain a valid "
2532 "partition table\n"), device
);
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
);
2550 * try all things in /proc/partitions that look like a full disk
2555 char line
[100], ptname
[100], devname
[120];
2557 unsigned long long sz
;
2559 procpt
= fopen(PROC_PARTITIONS
, "r");
2560 if (procpt
== NULL
) {
2561 fprintf(stderr
, _("cannot open %s\n"), PROC_PARTITIONS
);
2565 while (fgets(line
, sizeof(line
), procpt
)) {
2566 if (sscanf (line
, " %d %d %llu %100[^\n ]",
2567 &ma
, &mi
, &sz
, ptname
) != 4)
2569 snprintf(devname
, sizeof(devname
), "/dev/%s", ptname
);
2570 if (is_probably_full_disk(devname
))
2580 unknown_command(int c
) {
2581 printf(_("%c: unknown command\n"), c
);
2587 main(int argc
, char **argv
) {
2589 int optl
= 0, opts
= 0;
2591 setlocale(LC_ALL
, "");
2592 bindtextdomain(PACKAGE
, LOCALEDIR
);
2593 textdomain(PACKAGE
);
2598 * fdisk -l [-b sectorsize] [-u] device ...
2599 * fdisk -s [partition] ...
2600 * fdisk [-b sectorsize] [-u] device
2602 * Options -C, -H, -S set the geometry.
2605 while ((c
= getopt(argc
, argv
, "b:C:H:lsS:uvV")) != -1) {
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.
2612 sector_size
= atoi(optarg
);
2613 if (sector_size
!= 512 && sector_size
!= 1024 &&
2614 sector_size
!= 2048)
2617 user_set_sector_size
= 1;
2620 user_cylinders
= atoi(optarg
);
2623 user_heads
= atoi(optarg
);
2624 if (user_heads
<= 0 || user_heads
>= 256)
2628 user_sectors
= atoi(optarg
);
2629 if (user_sectors
<= 0 || user_sectors
>= 64)
2639 display_in_cyl_units
= 0;
2643 printf("fdisk (%s)\n", PACKAGE_STRING
);
2651 printf(_("This kernel finds the sector size itself - "
2652 "-b option ignored\n"));
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"));
2661 type_open
= O_RDONLY
;
2662 if (argc
> optind
) {
2664 /* avoid gcc warning:
2665 variable `k' might be clobbered by `longjmp' */
2668 for (k
= optind
; k
< argc
; k
++)
2671 /* we no longer have default device names */
2672 /* but we can use /proc/partitions instead */
2679 unsigned long long size
;
2682 type_open
= O_RDONLY
;
2684 opts
= argc
- optind
;
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)
2696 printf("%llu\n", size
/2);
2698 printf("%s: %llu\n", argv
[j
], size
/2);
2703 if (argc
-optind
== 1)
2704 disk_device
= argv
[optind
];
2705 else if (argc
-optind
!= 0)
2710 gpt_warning(disk_device
);
2714 /* OSF label, and no DOS label */
2715 printf(_("Detected an OSF/1 disklabel on %s, entering "
2716 "disklabel mode.\n"),
2720 /* If we return we may want to make an empty DOS label? */
2725 c
= tolower(read_char(_("Command (m for help): ")));
2729 toggle_active(get_partition(1, partitions
));
2731 toggle_sunflags(get_partition(1, partitions
),
2734 sgi_set_bootpartition(
2735 get_partition(1, partitions
));
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"));
2747 sgi_set_bootfile(line_ptr
);
2753 toggle_dos_compatibility_flag();
2755 toggle_sunflags(get_partition(1, partitions
),
2758 sgi_set_swappartition(
2759 get_partition(1, partitions
));
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
2769 j
= get_existing_partition(1, partitions
);
2771 j
= get_partition(1, partitions
);
2774 delete_partition(j
);
2782 list_types(get_sys_types());
2813 write_table(); /* does not return */
2818 _("\n\tSorry, no experts menu for SGI "
2819 "partition tables available.\n\n"));