]>
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.
10 * For detailed old history, see older versions.
11 * Contributions before 2001 by faith@cs.unc.edu, Michael Bischoff,
12 * LeBlanc@mcc.ac.uk, martin@cs.unc.edu, leisner@sdsp.mc.xerox.com,
13 * esr@snark.thyrsus.com, aeb@cwi.nl, quinlan@yggdrasil.com,
14 * fasten@cs.bonn.edu, orschaer@cip.informatik.uni-erlangen.de,
15 * jj@sunsite.mff.cuni.cz, fasten@shw.com, ANeuper@GUUG.de,
16 * kgw@suse.de, kalium@gmx.de, dhuggins@linuxcare.com,
17 * michal@ellpspace.math.ualberta.ca and probably others.
36 #include "fdisksunlabel.h"
37 #include "fdisksgilabel.h"
38 #include "fdiskaixlabel.h"
40 #include "../defines.h"
42 #include <linux/blkpg.h>
45 static void delete_partition(int i
);
47 #define hex_val(c) ({ \
49 isdigit(_c) ? _c - '0' : \
50 tolower(_c) + 10 - 'a'; \
54 #define LINE_LENGTH 800
55 #define pt_offset(b, n) ((struct partition *)((b) + 0x1be + \
56 (n) * sizeof(struct partition)))
57 #define sector(s) ((s) & 0x3f)
58 #define cylinder(s, c) ((c) | (((s) & 0xc0) << 2))
60 #define hsc2sector(h,s,c) (sector(s) - 1 + sectors * \
61 ((h) + heads * cylinder(s,c)))
62 #define set_hsc(h,s,c,sector) { \
63 s = sector % sectors + 1; \
68 s |= (sector >> 2) & 0xc0; \
71 /* A valid partition table sector ends in 0x55 0xaa */
73 part_table_flag(char *b
) {
74 return ((uint
) b
[510]) + (((uint
) b
[511]) << 8);
78 valid_part_table_flag(unsigned char *b
) {
79 return (b
[510] == 0x55 && b
[511] == 0xaa);
83 write_part_table_flag(char *b
) {
88 /* start_sect and nr_sects are stored little endian on all machines */
89 /* moreover, they are not aligned correctly */
91 store4_little_endian(unsigned char *cp
, unsigned int val
) {
93 cp
[1] = ((val
>> 8) & 0xff);
94 cp
[2] = ((val
>> 16) & 0xff);
95 cp
[3] = ((val
>> 24) & 0xff);
99 read4_little_endian(unsigned char *cp
) {
100 return (uint
)(cp
[0]) + ((uint
)(cp
[1]) << 8)
101 + ((uint
)(cp
[2]) << 16) + ((uint
)(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 int nr_sects
) {
116 store4_little_endian(p
->size4
, nr_sects
);
120 get_nr_sects(struct partition
*p
) {
121 return read4_little_endian(p
->size4
);
124 /* normally O_RDWR, -l option gives O_RDONLY */
125 static int type_open
= O_RDWR
;
128 * Raw disk label. For DOS-type partition tables the MBR,
129 * with descriptions of the primary partitions.
131 char MBRbuffer
[MAX_SECTOR_SIZE
];
134 * per partition table entry data
136 * The four primary partitions have the same sectorbuffer (MBRbuffer)
137 * and have NULL ext_pointer.
138 * Each logical partition table entry has two pointers, one for the
139 * partition and one link to the next one.
142 struct partition
*part_table
; /* points into sectorbuffer */
143 struct partition
*ext_pointer
; /* points into sectorbuffer */
144 char changed
; /* boolean */
145 uint offset
; /* disk sector number */
146 char *sectorbuffer
; /* disk sector contents */
147 } ptes
[MAXIMUM_PARTS
];
149 char *disk_device
, /* must be specified */
150 *line_ptr
, /* interactive input */
151 line_buffer
[LINE_LENGTH
];
153 int fd
, /* the disk */
154 ext_index
, /* the prime extended partition */
155 listing
= 0, /* no aborts for fdisk -l */
156 nowarn
= 0, /* no warnings for fdisk -l/-s */
157 dos_compatible_flag
= ~0,
159 partitions
= 4; /* maximum partition + 1 */
161 uint user_cylinders
, user_heads
, user_sectors
;
162 uint pt_heads
, pt_sectors
;
163 uint kern_heads
, kern_sectors
;
168 sector_size
= DEFAULT_SECTOR_SIZE
,
169 user_set_sector_size
= 0,
171 units_per_sector
= 1,
172 display_in_cyl_units
= 1,
173 extended_offset
= 0; /* offset of link pointers */
175 unsigned long total_number_of_sectors
;
177 #define dos_label (!sun_label && !sgi_label && !aix_label && !osf_label)
178 int sun_label
= 0; /* looking at sun disklabel */
179 int sgi_label
= 0; /* looking at sgi disklabel */
180 int aix_label
= 0; /* looking at aix disklabel */
181 int osf_label
= 0; /* looking at OSF/1 disklabel */
182 int possibly_osf_label
= 0;
186 void fatal(enum failure why
) {
187 char error
[LINE_LENGTH
],
192 longjmp(listingbuf
, 1);
196 case usage
: message
= _(
197 "Usage: fdisk [-b SSZ] [-u] DISK Change partition table\n"
198 " fdisk -l [-b SSZ] [-u] DISK List partition table(s)\n"
199 " fdisk -s PARTITION Give partition size(s) in blocks\n"
200 " fdisk -v Give fdisk version\n"
201 "Here DISK is something like /dev/hdb or /dev/sda\n"
202 "and PARTITION is something like /dev/hda7\n"
203 "-u: give Start and End in sector (instead of cylinder) units\n"
204 "-b 2048: (for certain MO disks) use 2048-byte sectors\n");
207 /* msg in cases where fdisk used to probe */
209 "Usage: fdisk [-l] [-b SSZ] [-u] device\n"
210 "E.g.: fdisk /dev/hda (for the first IDE disk)\n"
211 " or: fdisk /dev/sdc (for the third SCSI disk)\n"
212 " or: fdisk /dev/eda (for the first PS/2 ESDI drive)\n"
213 " or: fdisk /dev/rd/c0d0 or: fdisk /dev/ida/c0d0 (for RAID devices)\n"
217 snprintf(error
, sizeof(error
),
218 _("Unable to open %s\n"), disk_device
);
221 snprintf(error
, sizeof(error
),
222 _("Unable to read %s\n"), disk_device
);
225 snprintf(error
, sizeof(error
),
226 _("Unable to seek on %s\n"),disk_device
);
228 case unable_to_write
:
229 snprintf(error
, sizeof(error
),
230 _("Unable to write %s\n"), disk_device
);
233 snprintf(error
, sizeof(error
),
234 _("BLKGETSIZE ioctl failed on %s\n"),
238 message
= _("Unable to allocate any more memory\n");
241 message
= _("Fatal error\n");
245 fputs(message
, stderr
);
250 seek_sector(int fd
, uint secno
) {
251 ext2_loff_t offset
= (ext2_loff_t
) secno
* sector_size
;
252 if (ext2_llseek(fd
, offset
, SEEK_SET
) == (ext2_loff_t
) -1)
253 fatal(unable_to_seek
);
257 read_sector(int fd
, uint secno
, char *buf
) {
258 seek_sector(fd
, secno
);
259 if (read(fd
, buf
, sector_size
) != sector_size
)
260 fatal(unable_to_read
);
264 write_sector(int fd
, uint secno
, char *buf
) {
265 seek_sector(fd
, secno
);
266 if (write(fd
, buf
, sector_size
) != sector_size
)
267 fatal(unable_to_write
);
270 /* Allocate a buffer and read a partition table sector */
272 read_pte(int fd
, int pno
, uint offset
) {
273 struct pte
*pe
= &ptes
[pno
];
276 pe
->sectorbuffer
= (char *) malloc(sector_size
);
277 if (!pe
->sectorbuffer
)
278 fatal(out_of_memory
);
279 read_sector(fd
, offset
, pe
->sectorbuffer
);
281 pe
->part_table
= pe
->ext_pointer
= NULL
;
285 get_partition_start(struct pte
*pe
) {
286 return pe
->offset
+ get_start_sect(pe
->part_table
);
290 get_part_table(int i
) {
291 return ptes
[i
].part_table
;
295 set_all_unchanged(void) {
298 for (i
= 0; i
< MAXIMUM_PARTS
; i
++)
308 * Avoid warning about DOS partitions when no DOS partition was changed.
309 * Here a heuristic "is probably dos partition".
310 * We might also do the opposite and warn in all cases except
311 * for "is probably nondos partition".
314 is_dos_partition(int t
) {
315 return (t
== 1 || t
== 4 || t
== 6 ||
316 t
== 0x0b || t
== 0x0c || t
== 0x0e ||
317 t
== 0x11 || t
== 0x12 || t
== 0x14 || t
== 0x16 ||
318 t
== 0x1b || t
== 0x1c || t
== 0x1e || t
== 0x24 ||
319 t
== 0xc1 || t
== 0xc4 || t
== 0xc6);
325 puts(_("Command action"));
326 puts(_(" a toggle a read only flag")); /* sun */
327 puts(_(" b edit bsd disklabel"));
328 puts(_(" c toggle the mountable flag")); /* sun */
329 puts(_(" d delete a partition"));
330 puts(_(" l list known partition types"));
331 puts(_(" m print this menu"));
332 puts(_(" n add a new partition"));
333 puts(_(" o create a new empty DOS partition table"));
334 puts(_(" p print the partition table"));
335 puts(_(" q quit without saving changes"));
336 puts(_(" s create a new empty Sun disklabel")); /* sun */
337 puts(_(" t change a partition's system id"));
338 puts(_(" u change display/entry units"));
339 puts(_(" v verify the partition table"));
340 puts(_(" w write table to disk and exit"));
341 puts(_(" x extra functionality (experts only)"));
343 else if (sgi_label
) {
344 puts(_("Command action"));
345 puts(_(" a select bootable partition")); /* sgi flavour */
346 puts(_(" b edit bootfile entry")); /* sgi */
347 puts(_(" c select sgi swap partition")); /* sgi flavour */
348 puts(_(" d delete a partition"));
349 puts(_(" l list known partition types"));
350 puts(_(" m print this menu"));
351 puts(_(" n add a new partition"));
352 puts(_(" o create a new empty DOS partition table"));
353 puts(_(" p print the partition table"));
354 puts(_(" q quit without saving changes"));
355 puts(_(" s create a new empty Sun disklabel")); /* sun */
356 puts(_(" t change a partition's system id"));
357 puts(_(" u change display/entry units"));
358 puts(_(" v verify the partition table"));
359 puts(_(" w write table to disk and exit"));
361 else if (aix_label
) {
362 puts(_("Command action"));
363 puts(_(" m print this menu"));
364 puts(_(" o create a new empty DOS partition table"));
365 puts(_(" q quit without saving changes"));
366 puts(_(" s create a new empty Sun disklabel")); /* sun */
369 puts(_("Command action"));
370 puts(_(" a toggle a bootable flag"));
371 puts(_(" b edit bsd disklabel"));
372 puts(_(" c toggle the dos compatibility flag"));
373 puts(_(" d delete a partition"));
374 puts(_(" l list known partition types"));
375 puts(_(" m print this menu"));
376 puts(_(" n add a new partition"));
377 puts(_(" o create a new empty DOS partition table"));
378 puts(_(" p print the partition table"));
379 puts(_(" q quit without saving changes"));
380 puts(_(" s create a new empty Sun disklabel")); /* sun */
381 puts(_(" t change a partition's system id"));
382 puts(_(" u change display/entry units"));
383 puts(_(" v verify the partition table"));
384 puts(_(" w write table to disk and exit"));
385 puts(_(" x extra functionality (experts only)"));
392 puts(_("Command action"));
393 puts(_(" a change number of alternate cylinders")); /*sun*/
394 puts(_(" c change number of cylinders"));
395 puts(_(" d print the raw data in the partition table"));
396 puts(_(" e change number of extra sectors per cylinder"));/*sun*/
397 puts(_(" h change number of heads"));
398 puts(_(" i change interleave factor")); /*sun*/
399 puts(_(" o change rotation speed (rpm)")); /*sun*/
400 puts(_(" m print this menu"));
401 puts(_(" p print the partition table"));
402 puts(_(" q quit without saving changes"));
403 puts(_(" r return to main menu"));
404 puts(_(" s change number of sectors/track"));
405 puts(_(" v verify the partition table"));
406 puts(_(" w write table to disk and exit"));
407 puts(_(" y change number of physical cylinders")); /*sun*/
409 else if (sgi_label
) {
410 puts(_("Command action"));
411 puts(_(" b move beginning of data in a partition")); /* !sun */
412 puts(_(" c change number of cylinders"));
413 puts(_(" d print the raw data in the partition table"));
414 puts(_(" e list extended partitions")); /* !sun */
415 puts(_(" g create an IRIX (SGI) partition table"));/* sgi */
416 puts(_(" h change number of heads"));
417 puts(_(" m print this menu"));
418 puts(_(" p print the partition table"));
419 puts(_(" q quit without saving changes"));
420 puts(_(" r return to main menu"));
421 puts(_(" s change number of sectors/track"));
422 puts(_(" v verify the partition table"));
423 puts(_(" w write table to disk and exit"));
425 else if (aix_label
) {
426 puts(_("Command action"));
427 puts(_(" b move beginning of data in a partition")); /* !sun */
428 puts(_(" c change number of cylinders"));
429 puts(_(" d print the raw data in the partition table"));
430 puts(_(" e list extended partitions")); /* !sun */
431 puts(_(" g create an IRIX (SGI) partition table"));/* sgi */
432 puts(_(" h change number of heads"));
433 puts(_(" m print this menu"));
434 puts(_(" p print the partition table"));
435 puts(_(" q quit without saving changes"));
436 puts(_(" r return to main menu"));
437 puts(_(" s change number of sectors/track"));
438 puts(_(" v verify the partition table"));
439 puts(_(" w write table to disk and exit"));
442 puts(_("Command action"));
443 puts(_(" b move beginning of data in a partition")); /* !sun */
444 puts(_(" c change number of cylinders"));
445 puts(_(" d print the raw data in the partition table"));
446 puts(_(" e list extended partitions")); /* !sun */
447 puts(_(" f fix partition order")); /* !sun, !aix, !sgi */
448 puts(_(" g create an IRIX (SGI) partition table"));/* sgi */
449 puts(_(" h change number of heads"));
450 puts(_(" m print this menu"));
451 puts(_(" p print the partition table"));
452 puts(_(" q quit without saving changes"));
453 puts(_(" r return to main menu"));
454 puts(_(" s change number of sectors/track"));
455 puts(_(" v verify the partition table"));
456 puts(_(" w write table to disk and exit"));
463 sun_label
? sunlabel
->infos
[i
].id
:
464 sgi_label
? sgi_get_sysid(i
) :
465 ptes
[i
].part_table
->sys_ind
);
468 static struct systypes
*
469 get_sys_types(void) {
471 sun_label
? sun_sys_types
:
472 sgi_label
? sgi_sys_types
:
476 char *partition_type(unsigned char type
)
479 struct systypes
*types
= get_sys_types();
481 for (i
=0; types
[i
].name
; i
++)
482 if (types
[i
].type
== type
)
483 return _(types
[i
].name
);
488 void list_types(struct systypes
*sys
)
490 uint last
[4], done
= 0, next
= 0, size
;
493 for (i
= 0; sys
[i
].name
; i
++);
496 for (i
= 3; i
>= 0; i
--)
497 last
[3 - i
] = done
+= (size
+ i
- done
) / (i
+ 1);
501 printf("%c%2x %-15.15s", i
? ' ' : '\n',
502 sys
[next
].type
, _(sys
[next
].name
));
503 next
= last
[i
++] + done
;
504 if (i
> 3 || next
>= last
[i
]) {
508 } while (done
< last
[0]);
513 is_cleared_partition(struct partition
*p
) {
514 return !(!p
|| p
->boot_ind
|| p
->head
|| p
->sector
|| p
->cyl
||
515 p
->sys_ind
|| p
->end_head
|| p
->end_sector
|| p
->end_cyl
||
516 get_start_sect(p
) || get_nr_sects(p
));
520 clear_partition(struct partition
*p
) {
536 set_partition(int i
, int doext
, uint start
, uint stop
, int sysid
) {
541 p
= ptes
[i
].ext_pointer
;
542 offset
= extended_offset
;
544 p
= ptes
[i
].part_table
;
545 offset
= ptes
[i
].offset
;
549 set_start_sect(p
, start
- offset
);
550 set_nr_sects(p
, stop
- start
+ 1);
551 if (dos_compatible_flag
&& (start
/(sectors
*heads
) > 1023))
552 start
= heads
*sectors
*1024 - 1;
553 set_hsc(p
->head
, p
->sector
, p
->cyl
, start
);
554 if (dos_compatible_flag
&& (stop
/(sectors
*heads
) > 1023))
555 stop
= heads
*sectors
*1024 - 1;
556 set_hsc(p
->end_head
, p
->end_sector
, p
->end_cyl
, stop
);
561 test_c(char **m
, char *mesg
) {
564 fprintf(stderr
, _("You must set"));
566 fprintf(stderr
, " %s", *m
);
574 warn_geometry(void) {
578 prev
= test_c(&m
, _("heads"));
580 prev
= test_c(&m
, _("sectors"));
582 prev
= test_c(&m
, _("cylinders"));
586 _("%s%s.\nYou can do this from the extra functions menu.\n"),
587 prev
? _(" and ") : " ", m
);
591 void update_units(void)
593 int cyl_units
= heads
* sectors
;
595 if (display_in_cyl_units
&& cyl_units
)
596 units_per_sector
= cyl_units
;
598 units_per_sector
= 1; /* in sectors */
602 warn_cylinders(void) {
603 if (dos_label
&& cylinders
> 1024 && !nowarn
)
604 fprintf(stderr
, _("\n"
605 "The number of cylinders for this disk is set to %d.\n"
606 "There is nothing wrong with that, but this is larger than 1024,\n"
607 "and could in certain setups cause problems with:\n"
608 "1) software that runs at boot time (e.g., old versions of LILO)\n"
609 "2) booting and partitioning software from other OSs\n"
610 " (e.g., DOS FDISK, OS/2 FDISK)\n"),
615 read_extended(int ext
) {
618 struct partition
*p
, *q
;
622 pex
->ext_pointer
= pex
->part_table
;
625 if (!get_start_sect(p
)) {
627 _("Bad offset in primary extended partition\n"));
631 while (IS_EXTENDED (p
->sys_ind
)) {
632 struct pte
*pe
= &ptes
[partitions
];
634 if (partitions
>= MAXIMUM_PARTS
) {
635 /* This is not a Linux restriction, but
636 this program uses arrays of size MAXIMUM_PARTS.
637 Do not try to `improve' this test. */
638 struct pte
*pre
= &ptes
[partitions
-1];
641 _("Warning: deleting partitions after %d\n"),
643 clear_partition(pre
->ext_pointer
);
648 read_pte(fd
, partitions
, extended_offset
+ get_start_sect(p
));
650 if (!extended_offset
)
651 extended_offset
= get_start_sect(p
);
653 q
= p
= pt_offset(pe
->sectorbuffer
, 0);
654 for (i
= 0; i
< 4; i
++, p
++) if (get_nr_sects(p
)) {
655 if (IS_EXTENDED (p
->sys_ind
)) {
658 _("Warning: extra link "
659 "pointer in partition table"
660 " %d\n"), partitions
+ 1);
663 } else if (p
->sys_ind
) {
666 _("Warning: ignoring extra "
667 "data in partition table"
668 " %d\n"), partitions
+ 1);
674 /* very strange code here... */
675 if (!pe
->part_table
) {
676 if (q
!= pe
->ext_pointer
)
679 pe
->part_table
= q
+ 1;
681 if (!pe
->ext_pointer
) {
682 if (q
!= pe
->part_table
)
685 pe
->ext_pointer
= q
+ 1;
692 /* remove empty links */
694 for (i
= 4; i
< partitions
; i
++) {
695 struct pte
*pe
= &ptes
[i
];
697 if (!get_nr_sects(pe
->part_table
) &&
698 (partitions
> 5 || ptes
[4].part_table
->sys_ind
)) {
699 printf("omitting empty partition (%d)\n", i
+1);
701 goto remove
; /* numbering changed */
707 create_doslabel(void) {
711 _("Building a new DOS disklabel. Changes will remain in memory only,\n"
712 "until you decide to write them. After that, of course, the previous\n"
713 "content won't be recoverable.\n\n"));
714 sun_nolabel(); /* otherwise always recognised as sun */
715 sgi_nolabel(); /* otherwise always recognised as sgi */
716 aix_label
= osf_label
= possibly_osf_label
= 0;
719 for (i
= 510-64; i
< 510; i
++)
721 write_part_table_flag(MBRbuffer
);
725 get_boot(create_empty_dos
);
728 #include <sys/utsname.h>
729 #define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r))
732 linux_version_code(void) {
733 static int kernel_version
= 0;
734 struct utsname my_utsname
;
737 if (!kernel_version
&& uname(&my_utsname
) == 0) {
738 p
= atoi(strtok(my_utsname
.release
, "."));
739 q
= atoi(strtok(NULL
, "."));
740 r
= atoi(strtok(NULL
, "."));
741 kernel_version
= MAKE_VERSION(p
,q
,r
);
743 return kernel_version
;
747 get_sectorsize(int fd
) {
748 #if defined(BLKSSZGET)
749 if (!user_set_sector_size
&&
750 linux_version_code() >= MAKE_VERSION(2,3,3)) {
752 if (ioctl(fd
, BLKSSZGET
, &arg
) == 0)
754 if (sector_size
!= DEFAULT_SECTOR_SIZE
)
755 printf(_("Note: sector size is %d (not %d)\n"),
756 sector_size
, DEFAULT_SECTOR_SIZE
);
759 /* maybe the user specified it; and otherwise we still
760 have the DEFAULT_SECTOR_SIZE default */
765 get_kernel_geometry(int fd
) {
767 struct hd_geometry geometry
;
769 if (!ioctl(fd
, HDIO_GETGEO
, &geometry
)) {
770 kern_heads
= geometry
.heads
;
771 kern_sectors
= geometry
.sectors
;
772 /* never use geometry.cylinders - it is truncated */
778 get_partition_table_geometry(void) {
779 unsigned char *bufp
= MBRbuffer
;
785 if (!(valid_part_table_flag(bufp
)))
789 for (i
=0; i
<4; i
++) {
790 p
= pt_offset(bufp
, i
);
791 if (p
->sys_ind
!= 0) {
793 s
= (p
->end_sector
& 077);
798 } else if (hh
!= h
|| ss
!= s
)
803 if (!first
&& !bad
) {
810 get_geometry(int fd
, struct geom
*g
) {
812 unsigned long longsectors
;
815 sec_fac
= sector_size
/ 512;
816 guess_device_type(fd
);
817 heads
= cylinders
= sectors
= 0;
818 kern_heads
= kern_sectors
= 0;
819 pt_heads
= pt_sectors
= 0;
821 get_kernel_geometry(fd
);
822 get_partition_table_geometry();
824 heads
= user_heads
? user_heads
:
825 pt_heads
? pt_heads
:
826 kern_heads
? kern_heads
: 255;
827 sectors
= user_sectors
? user_sectors
:
828 pt_sectors
? pt_sectors
:
829 kern_sectors
? kern_sectors
: 63;
831 if (ioctl(fd
, BLKGETSIZE
, &longsectors
))
835 if (dos_compatible_flag
)
836 sector_offset
= sectors
;
838 cylinders
= longsectors
/ (heads
* sectors
);
839 cylinders
/= sec_fac
;
841 cylinders
= user_cylinders
;
845 g
->sectors
= sectors
;
846 g
->cylinders
= cylinders
;
849 total_number_of_sectors
= longsectors
;
854 * -1: no 0xaa55 flag present (possibly entire disk BSD)
855 * 0: found or created label
859 get_boot(enum action what
) {
864 for (i
= 0; i
< 4; i
++) {
865 struct pte
*pe
= &ptes
[i
];
867 pe
->part_table
= pt_offset(MBRbuffer
, i
);
868 pe
->ext_pointer
= NULL
;
870 pe
->sectorbuffer
= MBRbuffer
;
871 pe
->changed
= (what
== create_empty_dos
);
874 if (what
== create_empty_sun
&& check_sun_label())
877 memset(MBRbuffer
, 0, 512);
879 if (what
== create_empty_dos
)
880 goto got_dos_table
; /* skip reading disk */
882 if ((fd
= open(disk_device
, type_open
)) < 0) {
883 if ((fd
= open(disk_device
, O_RDONLY
)) < 0) {
884 if (what
== try_only
)
886 fatal(unable_to_open
);
888 printf(_("You will not be able to write "
889 "the partition table.\n"));
892 if (512 != read(fd
, MBRbuffer
, 512)) {
893 if (what
== try_only
)
895 fatal(unable_to_read
);
898 get_geometry(fd
, NULL
);
902 if (check_sun_label())
905 if (check_sgi_label())
908 if (check_aix_label())
911 if (check_osf_label()) {
912 possibly_osf_label
= 1;
913 if (!valid_part_table_flag(MBRbuffer
)) {
917 printf(_("This disk has both DOS and BSD magic.\n"
918 "Give the 'b' command to go to BSD mode.\n"));
923 if (!valid_part_table_flag(MBRbuffer
)) {
927 _("Device contains neither a valid DOS "
928 "partition table, nor Sun, SGI or OSF "
940 case create_empty_dos
:
941 case create_empty_sun
:
944 fprintf(stderr
, _("Internal error\n"));
952 for (i
= 0; i
< 4; i
++) {
953 struct pte
*pe
= &ptes
[i
];
955 if (IS_EXTENDED (pe
->part_table
->sys_ind
)) {
957 fprintf(stderr
, _("Ignoring extra extended "
958 "partition %d\n"), i
+ 1);
964 for (i
= 3; i
< partitions
; i
++) {
965 struct pte
*pe
= &ptes
[i
];
967 if (!valid_part_table_flag(pe
->sectorbuffer
)) {
969 _("Warning: invalid flag 0x%04x of partition "
970 "table %d will be corrected by w(rite)\n"),
971 part_table_flag(pe
->sectorbuffer
), i
+ 1);
979 /* read line; return 0 or first char */
983 static int got_eof
= 0;
985 line_ptr
= line_buffer
;
986 if (!fgets(line_buffer
, LINE_LENGTH
, stdin
)) {
988 got_eof
++; /* user typed ^D ? */
991 fprintf(stderr
, _("\ngot EOF thrice - exiting..\n"));
996 while (*line_ptr
&& !isgraph(*line_ptr
))
1002 read_char(char *mesg
)
1005 fputs(mesg
, stdout
);
1006 fflush (stdout
); /* requested by niles@scyld.com */
1007 } while (!read_line());
1012 read_chars(char *mesg
)
1014 fputs(mesg
, stdout
);
1015 fflush (stdout
); /* niles@scyld.com */
1024 read_hex(struct systypes
*sys
)
1030 read_char(_("Hex code (type L to list codes): "));
1031 if (tolower(*line_ptr
) == 'l')
1033 else if (isxdigit (*line_ptr
))
1037 hex
= hex
<< 4 | hex_val(*line_ptr
++);
1038 while (isxdigit(*line_ptr
));
1045 * Print the message MESG, then read an integer between LOW and HIGH (inclusive).
1046 * If the user hits Enter, DFLT is returned.
1047 * Answers like +10 are interpreted as offsets from BASE.
1049 * There is no default if DFLT is not between LOW and HIGH.
1052 read_int(uint low
, uint dflt
, uint high
, uint base
, char *mesg
)
1056 static char *ms
= NULL
;
1057 static int mslen
= 0;
1059 if (!ms
|| strlen(mesg
)+100 > mslen
) {
1060 mslen
= strlen(mesg
)+200;
1061 if (!(ms
= realloc(ms
,mslen
)))
1062 fatal(out_of_memory
);
1065 if (dflt
< low
|| dflt
> high
)
1069 snprintf(ms
, mslen
, _("%s (%d-%d, default %d): "),
1070 mesg
, low
, high
, dflt
);
1072 snprintf(ms
, mslen
, "%s (%d-%d): ",
1076 int use_default
= default_ok
;
1078 /* ask question and read answer */
1079 while (read_chars(ms
) != '\n' && !isdigit(*line_ptr
)
1080 && *line_ptr
!= '-' && *line_ptr
!= '+')
1083 if (*line_ptr
== '+' || *line_ptr
== '-') {
1084 int minus
= (*line_ptr
== '-');
1087 i
= atoi(line_ptr
+1);
1089 while (isdigit(*++line_ptr
))
1092 switch (*line_ptr
) {
1095 if (!display_in_cyl_units
)
1096 i
*= heads
* sectors
;
1108 absolute
= 1000000000;
1114 unsigned long long bytes
;
1117 bytes
= (unsigned long long) i
* absolute
;
1118 unit
= sector_size
* units_per_sector
;
1119 bytes
+= unit
/2; /* round */
1128 while (isdigit(*line_ptr
)) {
1134 printf(_("Using default value %d\n"), i
= dflt
);
1135 if (i
>= low
&& i
<= high
)
1138 printf(_("Value out of range.\n"));
1144 get_partition(int warn
, int max
) {
1148 i
= read_int(1, 0, max
, 0, _("Partition number")) - 1;
1152 if ((!sun_label
&& !sgi_label
&& !pe
->part_table
->sys_ind
)
1154 (!sunlabel
->partitions
[i
].num_sectors
||
1155 !sunlabel
->infos
[i
].id
))
1156 || (sgi_label
&& (!sgi_get_num_sectors(i
)))
1159 _("Warning: partition %d has empty type\n"),
1166 get_existing_partition(int warn
, int max
) {
1170 for (i
= 0; i
< max
; i
++) {
1171 struct pte
*pe
= &ptes
[i
];
1172 struct partition
*p
= pe
->part_table
;
1174 if (p
&& !is_cleared_partition(p
)) {
1181 printf(_("Selected partition %d\n"), pno
+1);
1184 printf(_("No partition is defined yet!\n"));
1188 return get_partition(warn
, max
);
1192 get_nonexisting_partition(int warn
, int max
) {
1196 for (i
= 0; i
< max
; i
++) {
1197 struct pte
*pe
= &ptes
[i
];
1198 struct partition
*p
= pe
->part_table
;
1200 if (p
&& is_cleared_partition(p
)) {
1207 printf(_("Selected partition %d\n"), pno
+1);
1210 printf(_("All primary partitions have been defined already!\n"));
1214 return get_partition(warn
, max
);
1218 str_units(int n
) { /* n==1: use singular */
1220 return display_in_cyl_units
? _("cylinder") : _("sector");
1222 return display_in_cyl_units
? _("cylinders") : _("sectors");
1225 void change_units(void)
1227 display_in_cyl_units
= !display_in_cyl_units
;
1229 printf(_("Changing display/entry units to %s\n"),
1234 toggle_active(int i
) {
1235 struct pte
*pe
= &ptes
[i
];
1236 struct partition
*p
= pe
->part_table
;
1238 if (IS_EXTENDED (p
->sys_ind
) && !p
->boot_ind
)
1240 _("WARNING: Partition %d is an extended partition\n"),
1242 p
->boot_ind
= (p
->boot_ind
? 0 : ACTIVE_FLAG
);
1247 toggle_dos_compatibility_flag(void) {
1248 dos_compatible_flag
= ~dos_compatible_flag
;
1249 if (dos_compatible_flag
) {
1250 sector_offset
= sectors
;
1251 printf(_("DOS Compatibility flag is set\n"));
1255 printf(_("DOS Compatibility flag is not set\n"));
1260 delete_partition(int i
) {
1261 struct pte
*pe
= &ptes
[i
];
1262 struct partition
*p
= pe
->part_table
;
1263 struct partition
*q
= pe
->ext_pointer
;
1265 /* Note that for the fifth partition (i == 4) we don't actually
1266 * decrement partitions.
1269 if (warn_geometry())
1270 return; /* C/H/S not set */
1274 sun_delete_partition(i
);
1279 sgi_delete_partition(i
);
1284 if (IS_EXTENDED (p
->sys_ind
) && i
== ext_index
) {
1286 ptes
[ext_index
].ext_pointer
= NULL
;
1287 extended_offset
= 0;
1293 if (!q
->sys_ind
&& i
> 4) {
1294 /* the last one in the chain - just delete */
1297 clear_partition(ptes
[i
].ext_pointer
);
1298 ptes
[i
].changed
= 1;
1300 /* not the last one - further ones will be moved down */
1302 /* delete this link in the chain */
1303 p
= ptes
[i
-1].ext_pointer
;
1305 set_start_sect(p
, get_start_sect(q
));
1306 set_nr_sects(p
, get_nr_sects(q
));
1307 ptes
[i
-1].changed
= 1;
1308 } else if (partitions
> 5) { /* 5 will be moved to 4 */
1309 /* the first logical in a longer chain */
1310 struct pte
*pe
= &ptes
[5];
1312 if (pe
->part_table
) /* prevent SEGFAULT */
1313 set_start_sect(pe
->part_table
,
1314 get_partition_start(pe
) -
1316 pe
->offset
= extended_offset
;
1320 if (partitions
> 5) {
1322 while (i
< partitions
) {
1323 ptes
[i
] = ptes
[i
+1];
1327 /* the only logical: clear only */
1328 clear_partition(ptes
[i
].part_table
);
1333 change_sysid(void) {
1335 int i
, sys
, origsys
;
1336 struct partition
*p
;
1338 i
= get_existing_partition(0, partitions
);
1341 p
= ptes
[i
].part_table
;
1342 origsys
= sys
= get_sysid(i
);
1344 /* if changing types T to 0 is allowed, then
1345 the reverse change must be allowed, too */
1346 if (!sys
&& !sgi_label
&& !sun_label
&& !get_nr_sects(p
))
1347 printf(_("Partition %d does not exist yet!\n"), i
+ 1);
1349 sys
= read_hex (get_sys_types());
1351 if (!sys
&& !sgi_label
&& !sun_label
) {
1352 printf(_("Type 0 means free space to many systems\n"
1353 "(but not to Linux). Having partitions of\n"
1354 "type 0 is probably unwise. You can delete\n"
1355 "a partition using the `d' command.\n"));
1359 if (!sun_label
&& !sgi_label
) {
1360 if (IS_EXTENDED (sys
) != IS_EXTENDED (p
->sys_ind
)) {
1361 printf(_("You cannot change a partition into"
1362 " an extended one or vice versa\n"
1363 "Delete it first.\n"));
1369 if (sun_label
&& i
== 2 && sys
!= WHOLE_DISK
)
1370 printf(_("Consider leaving partition 3 "
1371 "as Whole disk (5),\n"
1372 "as SunOS/Solaris expects it and "
1373 "even Linux likes it.\n\n"));
1374 if (sgi_label
&& ((i
== 10 && sys
!= ENTIRE_DISK
)
1375 || (i
== 8 && sys
!= 0)))
1376 printf(_("Consider leaving partition 9 "
1377 "as volume header (0),\nand "
1378 "partition 11 as entire volume (6)"
1379 "as IRIX expects it.\n\n"));
1383 sun_change_sysid(i
, sys
);
1386 sgi_change_sysid(i
, sys
);
1389 printf (_("Changed system type of partition %d "
1390 "to %x (%s)\n"), i
+ 1, sys
,
1391 (temp
= partition_type(sys
)) ? temp
:
1393 ptes
[i
].changed
= 1;
1394 if (is_dos_partition(origsys
) ||
1395 is_dos_partition(sys
))
1402 /* check_consistency() and long2chs() added Sat Mar 6 12:28:16 1993,
1403 * faith@cs.unc.edu, based on code fragments from pfdisk by Gordon W. Ross,
1404 * Jan. 1990 (version 1.2.1 by Gordon W. Ross Aug. 1990; Modified by S.
1405 * Lubkin Oct. 1991). */
1407 static void long2chs(ulong ls
, uint
*c
, uint
*h
, uint
*s
) {
1408 int spc
= heads
* sectors
;
1413 *s
= ls
% sectors
+ 1; /* sectors count from 1 */
1416 static void check_consistency(struct partition
*p
, int partition
) {
1417 uint pbc
, pbh
, pbs
; /* physical beginning c, h, s */
1418 uint pec
, peh
, pes
; /* physical ending c, h, s */
1419 uint lbc
, lbh
, lbs
; /* logical beginning c, h, s */
1420 uint lec
, leh
, les
; /* logical ending c, h, s */
1422 if (!heads
|| !sectors
|| (partition
>= 4))
1423 return; /* do not check extended partitions */
1425 /* physical beginning c, h, s */
1426 pbc
= (p
->cyl
& 0xff) | ((p
->sector
<< 2) & 0x300);
1428 pbs
= p
->sector
& 0x3f;
1430 /* physical ending c, h, s */
1431 pec
= (p
->end_cyl
& 0xff) | ((p
->end_sector
<< 2) & 0x300);
1433 pes
= p
->end_sector
& 0x3f;
1435 /* compute logical beginning (c, h, s) */
1436 long2chs(get_start_sect(p
), &lbc
, &lbh
, &lbs
);
1438 /* compute logical ending (c, h, s) */
1439 long2chs(get_start_sect(p
) + get_nr_sects(p
) - 1, &lec
, &leh
, &les
);
1441 /* Same physical / logical beginning? */
1442 if (cylinders
<= 1024 && (pbc
!= lbc
|| pbh
!= lbh
|| pbs
!= lbs
)) {
1443 printf(_("Partition %d has different physical/logical "
1444 "beginnings (non-Linux?):\n"), partition
+ 1);
1445 printf(_(" phys=(%d, %d, %d) "), pbc
, pbh
, pbs
);
1446 printf(_("logical=(%d, %d, %d)\n"),lbc
, lbh
, lbs
);
1449 /* Same physical / logical ending? */
1450 if (cylinders
<= 1024 && (pec
!= lec
|| peh
!= leh
|| pes
!= les
)) {
1451 printf(_("Partition %d has different physical/logical "
1452 "endings:\n"), partition
+ 1);
1453 printf(_(" phys=(%d, %d, %d) "), pec
, peh
, pes
);
1454 printf(_("logical=(%d, %d, %d)\n"),lec
, leh
, les
);
1458 /* Beginning on cylinder boundary? */
1459 if (pbh
!= !pbc
|| pbs
!= 1) {
1460 printf(_("Partition %i does not start on cylinder "
1461 "boundary:\n"), partition
+ 1);
1462 printf(_(" phys=(%d, %d, %d) "), pbc
, pbh
, pbs
);
1463 printf(_("should be (%d, %d, 1)\n"), pbc
, !pbc
);
1467 /* Ending on cylinder boundary? */
1468 if (peh
!= (heads
- 1) || pes
!= sectors
) {
1469 printf(_("Partition %i does not end on cylinder boundary.\n"),
1472 printf(_(" phys=(%d, %d, %d) "), pec
, peh
, pes
);
1473 printf(_("should be (%d, %d, %d)\n"),
1474 pec
, heads
- 1, sectors
);
1480 list_disk_geometry(void) {
1481 long long bytes
= (long long) total_number_of_sectors
* 512;
1482 long megabytes
= bytes
/1000000;
1484 if (megabytes
< 10000)
1485 printf(_("\nDisk %s: %ld MB, %lld bytes\n"),
1486 disk_device
, megabytes
, bytes
);
1488 printf(_("\nDisk %s: %ld.%ld GB, %lld bytes\n"),
1489 disk_device
, megabytes
/1000, (megabytes
/100)%10, bytes
);
1490 printf(_("%d heads, %d sectors/track, %d cylinders"),
1491 heads
, sectors
, cylinders
);
1492 if (units_per_sector
== 1)
1493 printf(_(", total %lu sectors"),
1494 total_number_of_sectors
/ (sector_size
/512));
1496 printf(_("Units = %s of %d * %d = %d bytes\n\n"),
1498 units_per_sector
, sector_size
, units_per_sector
* sector_size
);
1502 * Check whether partition entries are ordered by their starting positions.
1503 * Return 0 if OK. Return i if partition i should have been earlier.
1504 * Two separate checks: primary and logical partitions.
1507 wrong_p_order(int *prev
) {
1509 struct partition
*p
;
1510 uint last_p_start_pos
= 0, p_start_pos
;
1513 for (i
= 0 ; i
< partitions
; i
++) {
1516 last_p_start_pos
= 0;
1519 if ((p
= pe
->part_table
)->sys_ind
) {
1520 p_start_pos
= get_partition_start(pe
);
1522 if (last_p_start_pos
> p_start_pos
) {
1528 last_p_start_pos
= p_start_pos
;
1536 * Fix the chain of logicals.
1537 * extended_offset is unchanged, the set of sectors used is unchanged
1538 * The chain is sorted so that sectors increase, and so that
1539 * starting sectors increase.
1541 * After this it may still be that cfdisk doesnt like the table.
1542 * (This is because cfdisk considers expanded parts, from link to
1543 * end of partition, and these may still overlap.)
1545 * sfdisk /dev/hda > ohda; sfdisk /dev/hda < ohda
1549 fix_chain_of_logicals(void) {
1550 int j
, oj
, ojj
, sj
, sjj
;
1551 struct partition
*pj
,*pjj
,tmp
;
1553 /* Stage 1: sort sectors but leave sector of part 4 */
1554 /* (Its sector is the global extended_offset.) */
1556 for (j
= 5; j
< partitions
-1; j
++) {
1557 oj
= ptes
[j
].offset
;
1558 ojj
= ptes
[j
+1].offset
;
1560 ptes
[j
].offset
= ojj
;
1561 ptes
[j
+1].offset
= oj
;
1562 pj
= ptes
[j
].part_table
;
1563 set_start_sect(pj
, get_start_sect(pj
)+oj
-ojj
);
1564 pjj
= ptes
[j
+1].part_table
;
1565 set_start_sect(pjj
, get_start_sect(pjj
)+ojj
-oj
);
1566 set_start_sect(ptes
[j
-1].ext_pointer
,
1567 ojj
-extended_offset
);
1568 set_start_sect(ptes
[j
].ext_pointer
,
1569 oj
-extended_offset
);
1574 /* Stage 2: sort starting sectors */
1576 for (j
= 4; j
< partitions
-1; j
++) {
1577 pj
= ptes
[j
].part_table
;
1578 pjj
= ptes
[j
+1].part_table
;
1579 sj
= get_start_sect(pj
);
1580 sjj
= get_start_sect(pjj
);
1581 oj
= ptes
[j
].offset
;
1582 ojj
= ptes
[j
+1].offset
;
1583 if (oj
+sj
> ojj
+sjj
) {
1587 set_start_sect(pj
, ojj
+sjj
-oj
);
1588 set_start_sect(pjj
, oj
+sj
-ojj
);
1593 /* Probably something was changed */
1594 for (j
= 4; j
< partitions
; j
++)
1595 ptes
[j
].changed
= 1;
1599 fix_partition_table_order(void) {
1600 struct pte
*pei
, *pek
;
1603 if (!wrong_p_order(NULL
)) {
1604 printf(_("Nothing to do. Ordering is correct already.\n\n"));
1608 while ((i
= wrong_p_order(&k
)) != 0 && i
< 4) {
1609 /* partition i should have come earlier, move it */
1610 /* We have to move data in the MBR */
1611 struct partition
*pi
, *pk
, *pe
, pbuf
;
1615 pe
= pei
->ext_pointer
;
1616 pei
->ext_pointer
= pek
->ext_pointer
;
1617 pek
->ext_pointer
= pe
;
1619 pi
= pei
->part_table
;
1620 pk
= pek
->part_table
;
1622 memmove(&pbuf
, pi
, sizeof(struct partition
));
1623 memmove(pi
, pk
, sizeof(struct partition
));
1624 memmove(pk
, &pbuf
, sizeof(struct partition
));
1626 pei
->changed
= pek
->changed
= 1;
1630 fix_chain_of_logicals();
1637 list_table(int xtra
) {
1638 struct partition
*p
;
1643 sun_list_table(xtra
);
1648 sgi_list_table(xtra
);
1652 list_disk_geometry();
1655 xbsd_print_disklabel(xtra
);
1659 /* Heuristic: we list partition 3 of /dev/foo as /dev/foo3,
1660 but if the device name ends in a digit, say /dev/foo1,
1661 then the partition is called /dev/foo1p3. */
1662 w
= strlen(disk_device
);
1663 if (w
&& isdigit(disk_device
[w
-1]))
1668 printf(_("%*s Boot Start End Blocks Id System\n"),
1671 for (i
= 0; i
< partitions
; i
++) {
1672 struct pte
*pe
= &ptes
[i
];
1675 if (p
&& !is_cleared_partition(p
)) {
1676 unsigned int psects
= get_nr_sects(p
);
1677 unsigned int pblocks
= psects
;
1678 unsigned int podd
= 0;
1680 if (sector_size
< 1024) {
1681 pblocks
/= (1024 / sector_size
);
1682 podd
= psects
% (1024 / sector_size
);
1684 if (sector_size
> 1024)
1685 pblocks
*= (sector_size
/ 1024);
1687 "%s %c %9ld %9ld %9ld%c %2x %s\n",
1688 partname(disk_device
, i
+1, w
+2),
1689 /* boot flag */ !p
->boot_ind
? ' ' : p
->boot_ind
== ACTIVE_FLAG
1691 /* start */ (long) cround(get_partition_start(pe
)),
1692 /* end */ (long) cround(get_partition_start(pe
) + psects
1693 - (psects
? 1 : 0)),
1694 /* odd flag on end */ (long) pblocks
, podd
? '+' : ' ',
1695 /* type id */ p
->sys_ind
,
1696 /* type name */ (type
= partition_type(p
->sys_ind
)) ?
1697 type
: _("Unknown"));
1698 check_consistency(p
, i
);
1702 /* Is partition table in disk order? It need not be, but... */
1703 /* partition table entries are not checked for correct order if this
1704 is a sgi, sun or aix labeled disk... */
1705 if (dos_label
&& wrong_p_order(NULL
)) {
1706 printf(_("\nPartition table entries are not in disk order\n"));
1711 x_list_table(int extend
) {
1713 struct partition
*p
;
1716 printf(_("\nDisk %s: %d heads, %d sectors, %d cylinders\n\n"),
1717 disk_device
, heads
, sectors
, cylinders
);
1718 printf(_("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n"));
1719 for (i
= 0 ; i
< partitions
; i
++) {
1721 p
= (extend
? pe
->ext_pointer
: pe
->part_table
);
1723 printf("%2d %02x%4d%4d%5d%4d%4d%5d%9d%9d %02x\n",
1724 i
+ 1, p
->boot_ind
, p
->head
,
1726 cylinder(p
->sector
, p
->cyl
), p
->end_head
,
1727 sector(p
->end_sector
),
1728 cylinder(p
->end_sector
, p
->end_cyl
),
1729 get_start_sect(p
), get_nr_sects(p
), p
->sys_ind
);
1731 check_consistency(p
, i
);
1737 fill_bounds(uint
*first
, uint
*last
) {
1739 struct pte
*pe
= &ptes
[0];
1740 struct partition
*p
;
1742 for (i
= 0; i
< partitions
; pe
++,i
++) {
1744 if (!p
->sys_ind
|| IS_EXTENDED (p
->sys_ind
)) {
1745 first
[i
] = 0xffffffff;
1748 first
[i
] = get_partition_start(pe
);
1749 last
[i
] = first
[i
] + get_nr_sects(p
) - 1;
1755 check(int n
, uint h
, uint s
, uint c
, uint start
) {
1756 uint total
, real_s
, real_c
;
1758 real_s
= sector(s
) - 1;
1759 real_c
= cylinder(s
, c
);
1760 total
= (real_c
* sectors
+ real_s
) * heads
+ h
;
1762 fprintf(stderr
, _("Warning: partition %d contains sector 0\n"), n
);
1765 _("Partition %d: head %d greater than maximum %d\n"),
1767 if (real_s
>= sectors
)
1768 fprintf(stderr
, _("Partition %d: sector %d greater than "
1769 "maximum %d\n"), n
, s
, sectors
);
1770 if (real_c
>= cylinders
)
1771 fprintf(stderr
, _("Partitions %d: cylinder %d greater than "
1772 "maximum %d\n"), n
, real_c
+ 1, cylinders
);
1773 if (cylinders
<= 1024 && start
!= total
)
1775 _("Partition %d: previous sectors %d disagrees with "
1776 "total %d\n"), n
, start
, total
);
1783 uint first
[partitions
], last
[partitions
];
1784 struct partition
*p
;
1786 if (warn_geometry())
1799 fill_bounds(first
, last
);
1800 for (i
= 0; i
< partitions
; i
++) {
1801 struct pte
*pe
= &ptes
[i
];
1804 if (p
->sys_ind
&& !IS_EXTENDED (p
->sys_ind
)) {
1805 check_consistency(p
, i
);
1806 if (get_partition_start(pe
) < first
[i
])
1807 printf(_("Warning: bad start-of-data in "
1808 "partition %d\n"), i
+ 1);
1809 check(i
+ 1, p
->end_head
, p
->end_sector
, p
->end_cyl
,
1811 total
+= last
[i
] + 1 - first
[i
];
1812 for (j
= 0; j
< i
; j
++)
1813 if ((first
[i
] >= first
[j
] && first
[i
] <= last
[j
])
1814 || ((last
[i
] <= last
[j
] && last
[i
] >= first
[j
]))) {
1815 printf(_("Warning: partition %d overlaps "
1816 "partition %d.\n"), j
+ 1, i
+ 1);
1817 total
+= first
[i
] >= first
[j
] ?
1818 first
[i
] : first
[j
];
1819 total
-= last
[i
] <= last
[j
] ?
1825 if (extended_offset
) {
1826 struct pte
*pex
= &ptes
[ext_index
];
1827 uint e_last
= get_start_sect(pex
->part_table
) +
1828 get_nr_sects(pex
->part_table
) - 1;
1830 for (i
= 4; i
< partitions
; i
++) {
1832 p
= ptes
[i
].part_table
;
1834 if (i
!= 4 || i
+ 1 < partitions
)
1835 printf(_("Warning: partition %d "
1836 "is empty\n"), i
+ 1);
1838 else if (first
[i
] < extended_offset
||
1840 printf(_("Logical partition %d not entirely in "
1841 "partition %d\n"), i
+ 1, ext_index
+ 1);
1845 if (total
> heads
* sectors
* cylinders
)
1846 printf(_("Total allocated sectors %d greater than the maximum "
1847 "%d\n"), total
, heads
* sectors
* cylinders
);
1848 else if ((total
= heads
* sectors
* cylinders
- total
) != 0)
1849 printf(_("%d unallocated sectors\n"), total
);
1853 add_partition(int n
, int sys
) {
1854 char mesg
[256]; /* 48 does not suffice in Japanese */
1856 struct partition
*p
= ptes
[n
].part_table
;
1857 struct partition
*q
= ptes
[ext_index
].part_table
;
1858 uint start
, stop
= 0, limit
, temp
,
1859 first
[partitions
], last
[partitions
];
1861 if (p
&& p
->sys_ind
) {
1862 printf(_("Partition %d is already defined. Delete "
1863 "it before re-adding it.\n"), n
+ 1);
1866 fill_bounds(first
, last
);
1868 start
= sector_offset
;
1869 if (display_in_cyl_units
)
1870 limit
= heads
* sectors
* cylinders
- 1;
1872 limit
= total_number_of_sectors
- 1;
1873 if (extended_offset
) {
1874 first
[ext_index
] = extended_offset
;
1875 last
[ext_index
] = get_start_sect(q
) +
1876 get_nr_sects(q
) - 1;
1879 start
= extended_offset
+ sector_offset
;
1880 limit
= get_start_sect(q
) + get_nr_sects(q
) - 1;
1882 if (display_in_cyl_units
)
1883 for (i
= 0; i
< partitions
; i
++)
1884 first
[i
] = (cround(first
[i
]) - 1) * units_per_sector
;
1886 snprintf(mesg
, sizeof(mesg
), _("First %s"), str_units(SINGULAR
));
1889 for (i
= 0; i
< partitions
; i
++) {
1892 if (start
== ptes
[i
].offset
)
1893 start
+= sector_offset
;
1894 lastplusoff
= last
[i
] + ((n
<4) ? 0 : sector_offset
);
1895 if (start
>= first
[i
] && start
<= lastplusoff
)
1896 start
= lastplusoff
+ 1;
1900 if (start
>= temp
+units_per_sector
&& read
) {
1901 printf(_("Sector %d is already allocated\n"), temp
);
1905 if (!read
&& start
== temp
) {
1908 start
= read_int(cround(i
), cround(i
), cround(limit
),
1910 if (display_in_cyl_units
) {
1911 start
= (start
- 1) * units_per_sector
;
1912 if (start
< i
) start
= i
;
1916 } while (start
!= temp
|| !read
);
1917 if (n
> 4) { /* NOT for fifth partition */
1918 struct pte
*pe
= &ptes
[n
];
1920 pe
->offset
= start
- sector_offset
;
1921 if (pe
->offset
== extended_offset
) { /* must be corrected */
1923 if (sector_offset
== 1)
1928 for (i
= 0; i
< partitions
; i
++) {
1929 struct pte
*pe
= &ptes
[i
];
1931 if (start
< pe
->offset
&& limit
>= pe
->offset
)
1932 limit
= pe
->offset
- 1;
1933 if (start
< first
[i
] && limit
>= first
[i
])
1934 limit
= first
[i
] - 1;
1936 if (start
> limit
) {
1937 printf(_("No free sectors available\n"));
1942 if (cround(start
) == cround(limit
)) {
1945 snprintf(mesg
, sizeof(mesg
),
1946 _("Last %s or +size or +sizeM or +sizeK"),
1947 str_units(SINGULAR
));
1948 stop
= read_int(cround(start
), cround(limit
), cround(limit
),
1949 cround(start
), mesg
);
1950 if (display_in_cyl_units
) {
1951 stop
= stop
* units_per_sector
- 1;
1957 set_partition(n
, 0, start
, stop
, sys
);
1959 set_partition(n
- 1, 1, ptes
[n
].offset
, stop
, EXTENDED
);
1961 if (IS_EXTENDED (sys
)) {
1962 struct pte
*pe4
= &ptes
[4];
1963 struct pte
*pen
= &ptes
[n
];
1966 pen
->ext_pointer
= p
;
1967 pe4
->offset
= extended_offset
= start
;
1968 if (!(pe4
->sectorbuffer
= calloc(1, sector_size
)))
1969 fatal(out_of_memory
);
1970 pe4
->part_table
= pt_offset(pe4
->sectorbuffer
, 0);
1971 pe4
->ext_pointer
= pe4
->part_table
+ 1;
1979 if (partitions
> 5 || ptes
[4].part_table
->sys_ind
) {
1980 struct pte
*pe
= &ptes
[partitions
];
1982 if (!(pe
->sectorbuffer
= calloc(1, sector_size
)))
1983 fatal(out_of_memory
);
1984 pe
->part_table
= pt_offset(pe
->sectorbuffer
, 0);
1985 pe
->ext_pointer
= pe
->part_table
+ 1;
1990 add_partition(partitions
- 1, LINUX_NATIVE
);
1994 new_partition(void) {
1995 int i
, free_primary
= 0;
1997 if (warn_geometry())
2001 add_sun_partition(get_partition(0, partitions
), LINUX_NATIVE
);
2006 sgi_add_partition(get_partition(0, partitions
), LINUX_NATIVE
);
2011 printf(_("\tSorry - this fdisk cannot handle AIX disk labels."
2012 "\n\tIf you want to add DOS-type partitions, create"
2013 "\n\ta new empty DOS partition table first. (Use o.)"
2015 "This will destroy the present disk contents.\n"));
2019 for (i
= 0; i
< 4; i
++)
2020 free_primary
+= !ptes
[i
].part_table
->sys_ind
;
2022 if (!free_primary
&& partitions
>= MAXIMUM_PARTS
) {
2023 printf(_("The maximum number of partitions has been created\n"));
2027 if (!free_primary
) {
2028 if (extended_offset
)
2031 printf(_("You must delete some partition and add "
2032 "an extended partition first\n"));
2034 char c
, line
[LINE_LENGTH
];
2035 snprintf(line
, sizeof(line
),
2036 _("Command action\n %s\n p primary "
2037 "partition (1-4)\n"), extended_offset
?
2038 _("l logical (5 or over)") : _("e extended"));
2040 if ((c
= tolower(read_char(line
))) == 'p') {
2041 int i
= get_nonexisting_partition(0, 4);
2043 add_partition(i
, LINUX_NATIVE
);
2046 else if (c
== 'l' && extended_offset
) {
2050 else if (c
== 'e' && !extended_offset
) {
2051 int i
= get_nonexisting_partition(0, 4);
2053 add_partition(i
, EXTENDED
);
2057 printf(_("Invalid partition number "
2058 "for type `%c'\n"), c
);
2069 if (ptes
[i
].changed
)
2070 ptes
[3].changed
= 1;
2071 for (i
= 3; i
< partitions
; i
++) {
2072 struct pte
*pe
= &ptes
[i
];
2075 write_part_table_flag(pe
->sectorbuffer
);
2076 write_sector(fd
, pe
->offset
, pe
->sectorbuffer
);
2080 else if (sgi_label
) {
2081 /* no test on change? the printf below might be mistaken */
2083 } else if (sun_label
) {
2087 if (ptes
[i
].changed
)
2093 printf(_("The partition table has been altered!\n\n"));
2094 reread_partition_table(1);
2098 reread_partition_table(int leave
) {
2102 printf(_("Calling ioctl() to re-read partition table.\n"));
2105 if ((i
= ioctl(fd
, BLKRRPART
)) != 0) {
2108 /* some kernel versions (1.2.x) seem to have trouble
2109 rereading the partition table, but if asked to do it
2110 twice, the second time works. - biro@yggdrasil.com */
2113 if ((i
= ioctl(fd
, BLKRRPART
)) != 0)
2118 printf(_("\nWARNING: Re-reading the partition table "
2119 "failed with error %d: %s.\n"
2120 "The kernel still uses the old table.\n"
2121 "The new table will be used "
2122 "at the next reboot.\n"),
2123 error
, strerror(error
));
2128 _("\nWARNING: If you have created or modified any DOS 6.x\n"
2129 "partitions, please see the fdisk manual page for additional\n"
2135 printf(_("Syncing disks.\n"));
2137 sleep(4); /* for sync() */
2142 #define MAX_PER_LINE 16
2144 print_buffer(char pbuffer
[]) {
2148 for (i
= 0, l
= 0; i
< sector_size
; i
++, l
++) {
2150 printf("0x%03X:", i
);
2151 printf(" %02X", (unsigned char) pbuffer
[i
]);
2152 if (l
== MAX_PER_LINE
- 1) {
2166 printf(_("Device: %s\n"), disk_device
);
2167 if (sun_label
|| sgi_label
)
2168 print_buffer(MBRbuffer
);
2169 else for (i
= 3; i
< partitions
; i
++)
2170 print_buffer(ptes
[i
].sectorbuffer
);
2175 struct pte
*pe
= &ptes
[i
];
2176 struct partition
*p
= pe
->part_table
;
2179 if (warn_geometry())
2181 if (!p
->sys_ind
|| !get_nr_sects(p
) || IS_EXTENDED (p
->sys_ind
)) {
2182 printf(_("Partition %d has no data area\n"), i
+ 1);
2185 first
= get_partition_start(pe
);
2186 new = read_int(first
, first
, first
+ get_nr_sects(p
) - 1, first
,
2187 _("New beginning of data")) - pe
->offset
;
2189 if (new != get_nr_sects(p
)) {
2190 first
= get_nr_sects(p
) + get_start_sect(p
) - new;
2191 set_nr_sects(p
, first
);
2192 set_start_sect(p
, new);
2203 c
= tolower(read_char(_("Expert command (m for help): ")));
2211 move_begin(get_partition(0, partitions
));
2214 user_cylinders
= cylinders
=
2215 read_int(1, cylinders
, 1048576, 0,
2216 _("Number of cylinders"));
2218 sun_set_ncyl(cylinders
);
2236 fix_partition_table_order();
2242 user_heads
= heads
= read_int(1, heads
, 256, 0,
2243 _("Number of heads"));
2267 user_sectors
= sectors
= read_int(1, sectors
, 63, 0,
2268 _("Number of sectors"));
2269 if (dos_compatible_flag
) {
2270 sector_offset
= sectors
;
2271 fprintf(stderr
, _("Warning: setting "
2272 "sector offset for DOS "
2281 write_table(); /* does not return */
2285 sun_set_pcylcount();
2294 is_ide_cdrom_or_tape(char *device
) {
2297 struct stat statbuf
;
2300 /* No device was given explicitly, and we are trying some
2301 likely things. But opening /dev/hdc may produce errors like
2302 "hdc: tray open or drive not ready"
2303 if it happens to be a CD-ROM drive. It even happens that
2304 the process hangs on the attempt to read a music CD.
2305 So try to be careful. This only works since 2.1.73. */
2307 if (strncmp("/dev/hd", device
, 7))
2310 snprintf(buf
, sizeof(buf
), "/proc/ide/%s/media", device
+5);
2311 procf
= fopen(buf
, "r");
2312 if (procf
!= NULL
&& fgets(buf
, sizeof(buf
), procf
))
2313 is_ide
= (!strncmp(buf
, "cdrom", 5) ||
2314 !strncmp(buf
, "tape", 4));
2316 /* Now when this proc file does not exist, skip the
2317 device when it is read-only. */
2318 if (stat(device
, &statbuf
) == 0)
2319 is_ide
= ((statbuf
.st_mode
& 0222) == 0);
2327 try(char *device
, int user_specified
) {
2330 disk_device
= device
;
2331 if (setjmp(listingbuf
))
2333 if (!user_specified
)
2334 if (is_ide_cdrom_or_tape(device
))
2336 if ((fd
= open(disk_device
, type_open
)) >= 0) {
2337 gb
= get_boot(try_only
);
2338 if (gb
> 0) { /* I/O error */
2340 } else if (gb
< 0) { /* no DOS signature */
2341 list_disk_geometry();
2344 if (btrydev(device
) < 0)
2346 _("Disk %s doesn't contain a valid "
2347 "partition table\n"), device
);
2352 if (!sun_label
&& partitions
> 4)
2353 delete_partition(ext_index
);
2356 /* Ignore other errors, since we try IDE
2357 and SCSI hard disks which may not be
2358 installed on the system. */
2359 if (errno
== EACCES
) {
2360 fprintf(stderr
, _("Cannot open %s\n"), device
);
2366 /* for fdisk -l: try all things in /proc/partitions
2367 that look like a partition name (do not end in a digit) */
2371 char line
[100], ptname
[100], devname
[120], *s
;
2374 procpt
= fopen(PROC_PARTITIONS
, "r");
2375 if (procpt
== NULL
) {
2376 fprintf(stderr
, _("cannot open %s\n"), PROC_PARTITIONS
);
2380 while (fgets(line
, sizeof(line
), procpt
)) {
2381 if (sscanf (line
, " %d %d %d %[^\n ]",
2382 &ma
, &mi
, &sz
, ptname
) != 4)
2384 for (s
= ptname
; *s
; s
++);
2387 snprintf(devname
, sizeof(devname
), "/dev/%s", ptname
);
2397 unknown_command(int c
) {
2398 printf(_("%c: unknown command\n"), c
);
2402 main(int argc
, char **argv
) {
2404 int optl
= 0, opts
= 0;
2406 setlocale(LC_ALL
, "");
2407 bindtextdomain(PACKAGE
, LOCALEDIR
);
2408 textdomain(PACKAGE
);
2413 * fdisk -l [-b sectorsize] [-u] device ...
2414 * fdisk -s [partition] ...
2415 * fdisk [-b sectorsize] [-u] device
2417 * Options -C, -H, -S set the geometry.
2420 while ((c
= getopt(argc
, argv
, "b:C:H:lsS:uvV")) != -1) {
2423 /* Ugly: this sector size is really per device,
2424 so cannot be combined with multiple disks,
2425 and te same goes for the C/H/S options.
2427 sector_size
= atoi(optarg
);
2428 if (sector_size
!= 512 && sector_size
!= 1024 &&
2429 sector_size
!= 2048)
2432 user_set_sector_size
= 1;
2435 user_cylinders
= atoi(optarg
);
2438 user_heads
= atoi(optarg
);
2439 if (user_heads
<= 0 || user_heads
>= 256)
2443 user_sectors
= atoi(optarg
);
2444 if (user_sectors
<= 0 || user_sectors
>= 64)
2454 display_in_cyl_units
= 0;
2458 printf("fdisk v" UTIL_LINUX_VERSION
"\n");
2466 printf(_("This kernel finds the sector size itself - "
2467 "-b option ignored\n"));
2469 if (user_set_sector_size
&& argc
-optind
!= 1)
2470 printf(_("Warning: the -b (set sector size) option should"
2471 " be used with one specified device\n"));
2476 type_open
= O_RDONLY
;
2477 if (argc
> optind
) {
2479 /* avoid gcc warning:
2480 variable `k' might be clobbered by `longjmp' */
2483 for (k
=optind
; k
<argc
; k
++)
2486 /* we no longer have default device names */
2487 /* but, we can use /proc/partitions instead */
2497 type_open
= O_RDONLY
;
2499 opts
= argc
- optind
;
2503 for (j
= optind
; j
< argc
; j
++) {
2504 disk_device
= argv
[j
];
2505 if ((fd
= open(disk_device
, type_open
)) < 0)
2506 fatal(unable_to_open
);
2507 if (ioctl(fd
, BLKGETSIZE
, &size
))
2511 printf("%ld\n", size
/2);
2513 printf("%s: %ld\n", argv
[j
], size
/2);
2518 if (argc
-optind
== 1)
2519 disk_device
= argv
[optind
];
2520 else if (argc
-optind
!= 0)
2528 /* OSF label, and no DOS label */
2529 printf(_("Detected an OSF/1 disklabel on %s, entering "
2530 "disklabel mode.\n"),
2534 /* If we return we may want to make an empty DOS label? */
2539 c
= tolower(read_char(_("Command (m for help): ")));
2543 toggle_active(get_partition(1, partitions
));
2545 toggle_sunflags(get_partition(1, partitions
),
2548 sgi_set_bootpartition(
2549 get_partition(1, partitions
));
2555 printf(_("\nThe current boot file is: %s\n"),
2556 sgi_get_bootfile());
2557 if (read_chars(_("Please enter the name of the "
2558 "new boot file: ")) == '\n')
2559 printf(_("Boot file unchanged\n"));
2561 sgi_set_bootfile(line_ptr
);
2567 toggle_dos_compatibility_flag();
2569 toggle_sunflags(get_partition(1, partitions
),
2572 sgi_set_swappartition(
2573 get_partition(1, partitions
));
2578 j
= get_existing_partition(1, partitions
);
2580 delete_partition(j
);
2588 list_types(get_sys_types());
2619 write_table(); /* does not return */
2624 _("\n\tSorry, no experts menu for SGI "
2625 "partition tables available.\n\n"));