]>
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 2000 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,
18 * Modified, Sun Feb 20 2000, kalium@gmx.de
19 * Added fix operation allowing to reorder primary/extended partition
20 * entries within the partition table. Some programs or OSes have
21 * problems using a partition table with entries not ordered
22 * according to their positions on disk.
23 * Munged this patch to also make it work for logical partitions.
26 * Wed Mar 1 14:34:53 EST 2000 David Huggins-Daines <dhuggins@linuxcare.com>
27 * Better support for OSF/1 disklabels on Alpha.
29 * 2000-04-06, Michal Jaegermann (michal@ellpspace.math.ualberta.ca)
30 * fixed and added some alpha stuff.
45 #include <linux/hdreg.h> /* for HDIO_GETGEO */
51 #include "fdisksunlabel.h"
52 #include "fdisksgilabel.h"
53 #include "fdiskaixlabel.h"
55 #include "../defines.h"
57 #include <linux/blkpg.h>
60 static void delete_partition(int i
);
62 #define hex_val(c) ({ \
64 isdigit(_c) ? _c - '0' : \
65 tolower(_c) + 10 - 'a'; \
69 #define LINE_LENGTH 80
70 #define pt_offset(b, n) ((struct partition *)((b) + 0x1be + \
71 (n) * sizeof(struct partition)))
72 #define sector(s) ((s) & 0x3f)
73 #define cylinder(s, c) ((c) | (((s) & 0xc0) << 2))
75 #define hsc2sector(h,s,c) (sector(s) - 1 + sectors * \
76 ((h) + heads * cylinder(s,c)))
77 #define set_hsc(h,s,c,sector) { \
78 s = sector % sectors + 1; \
83 s |= (sector >> 2) & 0xc0; \
86 /* A valid partition table sector ends in 0x55 0xaa */
88 part_table_flag(char *b
) {
89 return ((uint
) b
[510]) + (((uint
) b
[511]) << 8);
93 valid_part_table_flag(unsigned char *b
) {
94 return (b
[510] == 0x55 && b
[511] == 0xaa);
98 write_part_table_flag(char *b
) {
103 /* start_sect and nr_sects are stored little endian on all machines */
104 /* moreover, they are not aligned correctly */
106 store4_little_endian(unsigned char *cp
, unsigned int val
) {
107 cp
[0] = (val
& 0xff);
108 cp
[1] = ((val
>> 8) & 0xff);
109 cp
[2] = ((val
>> 16) & 0xff);
110 cp
[3] = ((val
>> 24) & 0xff);
114 read4_little_endian(unsigned char *cp
) {
115 return (uint
)(cp
[0]) + ((uint
)(cp
[1]) << 8)
116 + ((uint
)(cp
[2]) << 16) + ((uint
)(cp
[3]) << 24);
120 set_start_sect(struct partition
*p
, unsigned int start_sect
) {
121 store4_little_endian(p
->start4
, start_sect
);
125 get_start_sect(struct partition
*p
) {
126 return read4_little_endian(p
->start4
);
130 set_nr_sects(struct partition
*p
, unsigned int nr_sects
) {
131 store4_little_endian(p
->size4
, nr_sects
);
135 get_nr_sects(struct partition
*p
) {
136 return read4_little_endian(p
->size4
);
139 /* normally O_RDWR, -l option gives O_RDONLY */
140 static int type_open
= O_RDWR
;
143 * Raw disk label. For DOS-type partition tables the MBR,
144 * with descriptions of the primary partitions.
146 char MBRbuffer
[MAX_SECTOR_SIZE
];
149 * per partition table entry data
151 * The four primary partitions have the same sectorbuffer (MBRbuffer)
152 * and have NULL ext_pointer.
153 * Each logical partition table entry has two pointers, one for the
154 * partition and one link to the next one.
157 struct partition
*part_table
; /* points into sectorbuffer */
158 struct partition
*ext_pointer
; /* points into sectorbuffer */
159 char changed
; /* boolean */
160 uint offset
; /* disk sector number */
161 char *sectorbuffer
; /* disk sector contents */
162 } ptes
[MAXIMUM_PARTS
];
164 char *disk_device
, /* must be specified */
165 *line_ptr
, /* interactive input */
166 line_buffer
[LINE_LENGTH
];
168 int fd
, /* the disk */
169 ext_index
, /* the prime extended partition */
170 listing
= 0, /* no aborts for fdisk -l */
171 nowarn
= 0, /* no warnings for fdisk -l/-s */
172 dos_compatible_flag
= ~0,
173 partitions
= 4; /* maximum partition + 1 */
175 uint user_cylinders
, user_heads
, user_sectors
;
180 sector_size
= DEFAULT_SECTOR_SIZE
,
181 user_set_sector_size
= 0,
183 units_per_sector
= 1,
184 display_in_cyl_units
= 1,
185 extended_offset
= 0; /* offset of link pointers */
187 #define dos_label (!sun_label && !sgi_label && !aix_label && !osf_label)
188 int sun_label
= 0; /* looking at sun disklabel */
189 int sgi_label
= 0; /* looking at sgi disklabel */
190 int aix_label
= 0; /* looking at aix disklabel */
191 int osf_label
= 0; /* looking at osf disklabel */
194 void fatal(enum failure why
) {
195 char error
[LINE_LENGTH
],
200 longjmp(listingbuf
, 1);
204 case usage
: message
= _(
205 "Usage: fdisk [-b SSZ] [-u] DISK Change partition table\n"
206 " fdisk -l [-b SSZ] [-u] DISK List partition table(s)\n"
207 " fdisk -s PARTITION Give partition size(s) in blocks\n"
208 " fdisk -v Give fdisk version\n"
209 "Here DISK is something like /dev/hdb or /dev/sda\n"
210 "and PARTITION is something like /dev/hda7\n"
211 "-u: give Start and End in sector (instead of cylinder) units\n"
212 "-b 2048: (for certain MO drives) use 2048-byte sectors\n");
215 /* msg in cases where fdisk used to probe */
217 "Usage: fdisk [-l] [-b SSZ] [-u] device\n"
218 "E.g.: fdisk /dev/hda (for the first IDE disk)\n"
219 " or: fdisk /dev/sdc (for the third SCSI disk)\n"
220 " or: fdisk /dev/eda (for the first PS/2 ESDI drive)\n"
221 " or: fdisk /dev/rd/c0d0 or: fdisk /dev/ida/c0d0 (for RAID devices)\n"
225 sprintf(error
, _("Unable to open %s\n"), disk_device
);
228 sprintf(error
, _("Unable to read %s\n"), disk_device
);
231 sprintf(error
, _("Unable to seek on %s\n"),disk_device
);
233 case unable_to_write
:
234 sprintf(error
, _("Unable to write %s\n"), disk_device
);
237 sprintf(error
, _("BLKGETSIZE ioctl failed on %s\n"),
241 message
= _("Unable to allocate any more memory\n");
243 default: message
= _("Fatal error\n");
247 fputs(message
, stderr
);
252 seek_sector(int fd
, uint secno
) {
253 ext2_loff_t offset
= (ext2_loff_t
) secno
* sector_size
;
254 if (ext2_llseek(fd
, offset
, SEEK_SET
) == (ext2_loff_t
) -1)
255 fatal(unable_to_seek
);
259 read_sector(int fd
, uint secno
, char *buf
) {
260 seek_sector(fd
, secno
);
261 if (read(fd
, buf
, sector_size
) != sector_size
)
262 fatal(unable_to_read
);
266 write_sector(int fd
, uint secno
, char *buf
) {
267 seek_sector(fd
, secno
);
268 if (write(fd
, buf
, sector_size
) != sector_size
)
269 fatal(unable_to_write
);
272 /* Allocate a buffer and read a partition table sector */
274 read_pte(int fd
, int pno
, uint offset
) {
275 struct pte
*pe
= &ptes
[pno
];
278 pe
->sectorbuffer
= (char *) malloc(sector_size
);
279 if (!pe
->sectorbuffer
)
280 fatal(out_of_memory
);
281 read_sector(fd
, offset
, pe
->sectorbuffer
);
283 pe
->part_table
= pe
->ext_pointer
= NULL
;
287 get_partition_start(struct pte
*pe
) {
288 return pe
->offset
+ get_start_sect(pe
->part_table
);
292 get_part_table(int i
) {
293 return ptes
[i
].part_table
;
297 set_all_unchanged(void) {
300 for (i
= 0; i
< MAXIMUM_PARTS
; i
++)
312 puts(_("Command action"));
313 puts(_(" a toggle a read only flag")); /* sun */
314 puts(_(" b edit bsd disklabel"));
315 puts(_(" c toggle the mountable flag")); /* sun */
316 puts(_(" d delete a partition"));
317 puts(_(" l list known partition types"));
318 puts(_(" m print this menu"));
319 puts(_(" n add a new partition"));
320 puts(_(" o create a new empty DOS partition table"));
321 puts(_(" p print the partition table"));
322 puts(_(" q quit without saving changes"));
323 puts(_(" s create a new empty Sun disklabel")); /* sun */
324 puts(_(" t change a partition's system id"));
325 puts(_(" u change display/entry units"));
326 puts(_(" v verify the partition table"));
327 puts(_(" w write table to disk and exit"));
328 puts(_(" x extra functionality (experts only)"));
331 puts(_("Command action"));
332 puts(_(" a select bootable partition")); /* sgi flavour */
333 puts(_(" b edit bootfile entry")); /* sgi */
334 puts(_(" c select sgi swap partition")); /* sgi flavour */
335 puts(_(" d delete a partition"));
336 puts(_(" l list known partition types"));
337 puts(_(" m print this menu"));
338 puts(_(" n add a new partition"));
339 puts(_(" o create a new empty DOS partition table"));
340 puts(_(" p print the partition table"));
341 puts(_(" q quit without saving changes"));
342 puts(_(" s create a new empty Sun disklabel")); /* sun */
343 puts(_(" t change a partition's system id"));
344 puts(_(" u change display/entry units"));
345 puts(_(" v verify the partition table"));
346 puts(_(" w write table to disk and exit"));
349 puts(_("Command action"));
350 puts(_(" m print this menu"));
351 puts(_(" o create a new empty DOS partition table"));
352 puts(_(" q quit without saving changes"));
353 puts(_(" s create a new empty Sun disklabel")); /* sun */
356 puts(_("Command action"));
357 puts(_(" a toggle a bootable flag"));
358 puts(_(" b edit bsd disklabel"));
359 puts(_(" c toggle the dos compatibility flag"));
360 puts(_(" d delete a partition"));
361 puts(_(" l list known partition types"));
362 puts(_(" m print this menu"));
363 puts(_(" n add a new partition"));
364 puts(_(" o create a new empty DOS partition table"));
365 puts(_(" p print the partition table"));
366 puts(_(" q quit without saving changes"));
367 puts(_(" s create a new empty Sun disklabel")); /* sun */
368 puts(_(" t change a partition's system id"));
369 puts(_(" u change display/entry units"));
370 puts(_(" v verify the partition table"));
371 puts(_(" w write table to disk and exit"));
372 puts(_(" x extra functionality (experts only)"));
379 puts(_("Command action"));
380 puts(_(" a change number of alternate cylinders")); /*sun*/
381 puts(_(" c change number of cylinders"));
382 puts(_(" d print the raw data in the partition table"));
383 puts(_(" e change number of extra sectors per cylinder"));/*sun*/
384 puts(_(" h change number of heads"));
385 puts(_(" i change interleave factor")); /*sun*/
386 puts(_(" o change rotation speed (rpm)")); /*sun*/
387 puts(_(" m print this menu"));
388 puts(_(" p print the partition table"));
389 puts(_(" q quit without saving changes"));
390 puts(_(" r return to main menu"));
391 puts(_(" s change number of sectors/track"));
392 puts(_(" v verify the partition table"));
393 puts(_(" w write table to disk and exit"));
394 puts(_(" y change number of physical cylinders")); /*sun*/
397 puts(_("Command action"));
398 puts(_(" b move beginning of data in a partition")); /* !sun */
399 puts(_(" c change number of cylinders"));
400 puts(_(" d print the raw data in the partition table"));
401 puts(_(" e list extended partitions")); /* !sun */
402 puts(_(" g create an IRIX partition table")); /* sgi */
403 puts(_(" h change number of heads"));
404 puts(_(" m print this menu"));
405 puts(_(" p print the partition table"));
406 puts(_(" q quit without saving changes"));
407 puts(_(" r return to main menu"));
408 puts(_(" s change number of sectors/track"));
409 puts(_(" v verify the partition table"));
410 puts(_(" w write table to disk and exit"));
413 puts(_("Command action"));
414 puts(_(" b move beginning of data in a partition")); /* !sun */
415 puts(_(" c change number of cylinders"));
416 puts(_(" d print the raw data in the partition table"));
417 puts(_(" e list extended partitions")); /* !sun */
418 puts(_(" g create an IRIX partition table")); /* sgi */
419 puts(_(" h change number of heads"));
420 puts(_(" m print this menu"));
421 puts(_(" p print the partition table"));
422 puts(_(" q quit without saving changes"));
423 puts(_(" r return to main menu"));
424 puts(_(" s change number of sectors/track"));
425 puts(_(" v verify the partition table"));
426 puts(_(" w write table to disk and exit"));
429 puts(_("Command action"));
430 puts(_(" b move beginning of data in a partition")); /* !sun */
431 puts(_(" c change number of cylinders"));
432 puts(_(" d print the raw data in the partition table"));
433 puts(_(" e list extended partitions")); /* !sun */
434 puts(_(" f fix partition order")); /* !sun, !aix, !sgi */
435 puts(_(" g create an IRIX partition table")); /* sgi */
436 puts(_(" h change number of heads"));
437 puts(_(" m print this menu"));
438 puts(_(" p print the partition table"));
439 puts(_(" q quit without saving changes"));
440 puts(_(" r return to main menu"));
441 puts(_(" s change number of sectors/track"));
442 puts(_(" v verify the partition table"));
443 puts(_(" w write table to disk and exit"));
450 sun_label
? sunlabel
->infos
[i
].id
:
451 sgi_label
? sgi_get_sysid(i
) : ptes
[i
].part_table
->sys_ind
);
454 static struct systypes
*
455 get_sys_types(void) {
457 sun_label
? sun_sys_types
:
458 sgi_label
? sgi_sys_types
: i386_sys_types
);
461 char *partition_type(unsigned char type
)
464 struct systypes
*types
= get_sys_types();
466 for (i
=0; types
[i
].name
; i
++)
467 if (types
[i
].type
== type
)
468 return _(types
[i
].name
);
473 void list_types(struct systypes
*sys
)
475 uint last
[4], done
= 0, next
= 0, size
;
478 for (i
= 0; sys
[i
].name
; i
++);
481 for (i
= 3; i
>= 0; i
--)
482 last
[3 - i
] = done
+= (size
+ i
- done
) / (i
+ 1);
486 printf("%c%2x %-15.15s", i
? ' ' : '\n',
487 sys
[next
].type
, _(sys
[next
].name
));
488 next
= last
[i
++] + done
;
489 if (i
> 3 || next
>= last
[i
]) {
493 } while (done
< last
[0]);
498 clear_partition(struct partition
*p
) {
514 set_partition(int i
, struct partition
*p
, uint start
, uint stop
,
515 int sysid
, uint offset
) {
518 set_start_sect(p
, start
- offset
);
519 set_nr_sects(p
, stop
- start
+ 1);
520 if (dos_compatible_flag
&& (start
/(sectors
*heads
) > 1023))
521 start
= heads
*sectors
*1024 - 1;
522 set_hsc(p
->head
, p
->sector
, p
->cyl
, start
);
523 if (dos_compatible_flag
&& (stop
/(sectors
*heads
) > 1023))
524 stop
= heads
*sectors
*1024 - 1;
525 set_hsc(p
->end_head
, p
->end_sector
, p
->end_cyl
, stop
);
530 test_c(char **m
, char *mesg
) {
533 fprintf(stderr
, _("You must set"));
535 fprintf(stderr
, " %s", *m
);
543 warn_geometry(void) {
547 prev
= test_c(&m
, _("heads"));
549 prev
= test_c(&m
, _("sectors"));
551 prev
= test_c(&m
, _("cylinders"));
555 _("%s%s.\nYou can do this from the extra functions menu.\n"),
556 prev
? _(" and ") : " ", m
);
560 void update_units(void)
562 int cyl_units
= heads
* sectors
;
564 if (display_in_cyl_units
&& cyl_units
)
565 units_per_sector
= cyl_units
;
567 units_per_sector
= 1; /* in sectors */
571 warn_cylinders(void) {
572 if (dos_label
&& cylinders
> 1024 && !nowarn
)
573 fprintf(stderr
, _("\n"
574 "The number of cylinders for this disk is set to %d.\n"
575 "There is nothing wrong with that, but this is larger than 1024,\n"
576 "and could in certain setups cause problems with:\n"
577 "1) software that runs at boot time (e.g., old versions of LILO)\n"
578 "2) booting and partitioning software from other OSs\n"
579 " (e.g., DOS FDISK, OS/2 FDISK)\n"),
584 read_extended(int ext
) {
587 struct partition
*p
, *q
;
591 pex
->ext_pointer
= pex
->part_table
;
594 if (!get_start_sect(p
)) {
596 _("Bad offset in primary extended partition\n"));
600 while (IS_EXTENDED (p
->sys_ind
)) {
601 struct pte
*pe
= &ptes
[partitions
];
603 if (partitions
>= MAXIMUM_PARTS
) {
604 /* This is not a Linux restriction, but
605 this program uses arrays of size MAXIMUM_PARTS.
606 Do not try to `improve' this test. */
607 struct pte
*pre
= &ptes
[partitions
-1];
610 _("Warning: deleting partitions after %d\n"),
612 clear_partition(pre
->ext_pointer
);
617 read_pte(fd
, partitions
, extended_offset
+ get_start_sect(p
));
619 if (!extended_offset
)
620 extended_offset
= get_start_sect(p
);
622 q
= p
= pt_offset(pe
->sectorbuffer
, 0);
623 for (i
= 0; i
< 4; i
++, p
++) if (get_nr_sects(p
)) {
624 if (IS_EXTENDED (p
->sys_ind
)) {
626 fprintf(stderr
, _("Warning: extra link"
627 " pointer in partition table "
628 "%d\n"), partitions
+ 1);
631 } else if (p
->sys_ind
) {
634 _("Warning: ignoring extra data "
635 "in partition table %d\n"),
642 /* very strange code here... */
643 if (!pe
->part_table
) {
644 if (q
!= pe
->ext_pointer
)
647 pe
->part_table
= q
+ 1;
649 if (!pe
->ext_pointer
) {
650 if (q
!= pe
->part_table
)
653 pe
->ext_pointer
= q
+ 1;
660 /* remove empty links */
662 for (i
= 4; i
< partitions
; i
++) {
663 struct pte
*pe
= &ptes
[i
];
665 if (!get_nr_sects(pe
->part_table
)) {
666 printf("omitting empty partition (%d)\n", i
+1);
668 goto remove
; /* numbering changed */
674 create_doslabel(void) {
678 _("Building a new DOS disklabel. Changes will remain in memory only,\n"
679 "until you decide to write them. After that, of course, the previous\n"
680 "content won't be recoverable.\n\n"));
682 sun_nolabel(); /* otherwise always recognised as sun */
683 sgi_nolabel(); /* otherwise always recognised as sgi */
685 write_part_table_flag(MBRbuffer
);
686 for (i
= 0; i
< 4; i
++)
687 if (ptes
[i
].part_table
)
688 clear_partition(ptes
[i
].part_table
);
691 get_boot(create_empty
);
694 #include <sys/utsname.h>
695 #define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r))
698 linux_version_code(void) {
699 static int kernel_version
= 0;
700 struct utsname my_utsname
;
703 if (!kernel_version
&& uname(&my_utsname
) == 0) {
704 p
= atoi(strtok(my_utsname
.release
, "."));
705 q
= atoi(strtok(NULL
, "."));
706 r
= atoi(strtok(NULL
, "."));
707 kernel_version
= MAKE_VERSION(p
,q
,r
);
709 return kernel_version
;
713 get_sectorsize(int fd
) {
714 #if defined(BLKSSZGET)
715 if (!user_set_sector_size
&&
716 linux_version_code() >= MAKE_VERSION(2,3,3)) {
718 if (ioctl(fd
, BLKSSZGET
, &arg
) == 0)
720 if (sector_size
!= DEFAULT_SECTOR_SIZE
)
721 printf(_("Note: sector size is %d (not %d)\n"),
722 sector_size
, DEFAULT_SECTOR_SIZE
);
725 /* maybe the user specified it; and otherwise we still
726 have the DEFAULT_SECTOR_SIZE default */
731 * Ask kernel about geometry. Invent something reasonable
732 * in case the kernel has no opinion.
735 get_geometry(int fd
, struct geom
*g
) {
738 struct hd_geometry geometry
;
742 sec_fac
= sector_size
/ 512;
744 guess_device_type(fd
);
746 res1
= ioctl(fd
, BLKGETSIZE
, &longsectors
);
748 res2
= ioctl(fd
, HDIO_REQ
, &geometry
);
750 res2
= ioctl(fd
, HDIO_GETGEO
, &geometry
);
753 /* never use geometry.cylinders - it is truncated */
754 heads
= cylinders
= sectors
= 0;
757 heads
= geometry
.heads
;
758 sectors
= geometry
.sectors
;
759 if (heads
* sectors
== 0)
761 else if (dos_compatible_flag
)
762 sector_offset
= sectors
;
764 if (res1
== 0 && res2
== 0) { /* normal case */
765 cylinders
= longsectors
/ (heads
* sectors
);
766 cylinders
/= sec_fac
; /* do not round up */
767 } else if (res1
== 0) { /* size but no geometry */
768 heads
= cylinders
= 1;
769 sectors
= longsectors
/ sec_fac
;
773 sectors
= user_sectors
;
777 cylinders
= user_cylinders
;
781 g
->sectors
= sectors
;
782 g
->cylinders
= cylinders
;
788 * -1: no 0xaa55 flag present (possibly entire disk BSD)
789 * 0: found or created label
792 get_boot(enum action what
) {
797 if (what
== create_empty
)
798 goto got_table
; /* skip reading disk */
800 if ((fd
= open(disk_device
, type_open
)) < 0) {
801 if ((fd
= open(disk_device
, O_RDONLY
)) < 0)
802 fatal(unable_to_open
);
804 printf(_("You will not be able to write the partition table.\n"));
807 get_geometry(fd
, NULL
);
811 if (sector_size
!= read(fd
, MBRbuffer
, sector_size
))
812 fatal(unable_to_read
);
816 if (check_sun_label())
819 if (check_sgi_label())
822 if (check_aix_label())
825 if (check_osf_label())
828 if (!valid_part_table_flag(MBRbuffer
)) {
832 _("Device contains neither a valid DOS partition"
833 " table, nor Sun, SGI or OSF disklabel\n"));
848 fprintf(stderr
, _("Internal error\n"));
855 for (i
= 0; i
< 4; i
++) {
856 struct pte
*pe
= &ptes
[i
];
858 pe
->part_table
= pt_offset(MBRbuffer
, i
);
859 pe
->ext_pointer
= NULL
;
861 pe
->sectorbuffer
= MBRbuffer
;
862 pe
->changed
= (what
== create_empty
);
865 for (i
= 0; i
< 4; i
++) {
866 struct pte
*pe
= &ptes
[i
];
868 if (IS_EXTENDED (pe
->part_table
->sys_ind
)) {
870 fprintf(stderr
, _("Ignoring extra extended "
871 "partition %d\n"), i
+ 1);
877 for (i
= 3; i
< partitions
; i
++) {
878 struct pte
*pe
= &ptes
[i
];
880 if (!valid_part_table_flag(pe
->sectorbuffer
)) {
882 _("Warning: invalid flag 0x%04x of partition "
883 "table %d will be corrected by w(rite)\n"),
884 part_table_flag(pe
->sectorbuffer
), i
+ 1);
892 /* read line; return 0 or first char */
896 static int got_eof
= 0;
898 line_ptr
= line_buffer
;
899 if (!fgets(line_buffer
, LINE_LENGTH
, stdin
)) {
901 got_eof
++; /* user typed ^D ? */
904 fprintf(stderr
, _("\ngot EOF thrice - exiting..\n"));
909 while (*line_ptr
&& !isgraph(*line_ptr
))
915 read_char(char *mesg
)
919 fflush (stdout
); /* requested by niles@scyld.com */
920 } while (!read_line());
925 read_chars(char *mesg
)
928 fflush (stdout
); /* niles@scyld.com */
937 read_hex(struct systypes
*sys
)
943 read_char(_("Hex code (type L to list codes): "));
944 if (tolower(*line_ptr
) == 'l')
946 else if (isxdigit (*line_ptr
))
950 hex
= hex
<< 4 | hex_val(*line_ptr
++);
951 while (isxdigit(*line_ptr
));
958 * Print the message MESG, then read an integer between LOW and HIGH (inclusive).
959 * If the user hits Enter, DFLT is returned.
960 * Answers like +10 are interpreted as offsets from BASE.
962 * There is no default if DFLT is not between LOW and HIGH.
965 read_int(uint low
, uint dflt
, uint high
, uint base
, char *mesg
)
969 static char *ms
= NULL
;
970 static int mslen
= 0;
972 if (!ms
|| strlen(mesg
)+50 > mslen
) {
973 mslen
= strlen(mesg
)+100;
974 if (!(ms
= realloc(ms
,mslen
)))
975 fatal(out_of_memory
);
978 if (dflt
< low
|| dflt
> high
)
982 sprintf(ms
, _("%s (%d-%d, default %d): "), mesg
, low
, high
, dflt
);
984 sprintf(ms
, "%s (%d-%d): ", mesg
, low
, high
);
987 int use_default
= default_ok
;
989 /* ask question and read answer */
990 while (read_chars(ms
) != '\n' && !isdigit(*line_ptr
)
991 && *line_ptr
!= '-' && *line_ptr
!= '+')
994 if (*line_ptr
== '+' || *line_ptr
== '-') {
995 i
= atoi(line_ptr
+1);
996 if (*line_ptr
== '-')
998 while (isdigit(*++line_ptr
))
1000 switch (*line_ptr
) {
1003 if (!display_in_cyl_units
)
1004 i
*= heads
* sectors
;
1009 i
/= (sector_size
/ 512);
1010 i
/= units_per_sector
;
1015 i
/= (sector_size
/ 512);
1016 i
/= units_per_sector
;
1021 i
/= (sector_size
/ 512);
1022 i
/= units_per_sector
;
1030 while (isdigit(*line_ptr
)) {
1036 printf(_("Using default value %d\n"), i
= dflt
);
1037 if (i
>= low
&& i
<= high
)
1040 printf(_("Value out of range.\n"));
1046 get_partition(int warn
, int max
) {
1050 i
= read_int(1, 0, max
, 0, _("Partition number")) - 1;
1054 (!sun_label
&& !sgi_label
&& !pe
->part_table
->sys_ind
)
1056 (!sunlabel
->partitions
[i
].num_sectors
||
1057 !sunlabel
->infos
[i
].id
))
1058 || (sgi_label
&& (!sgi_get_num_sectors(i
)))
1059 )) fprintf(stderr
, _("Warning: partition %d has empty type\n"), i
+1);
1064 str_units(int n
) { /* n==1: use singular */
1066 return display_in_cyl_units
? _("cylinder") : _("sector");
1068 return display_in_cyl_units
? _("cylinders") : _("sectors");
1071 void change_units(void)
1073 display_in_cyl_units
= !display_in_cyl_units
;
1075 printf(_("Changing display/entry units to %s\n"),
1080 toggle_active(int i
) {
1081 struct pte
*pe
= &ptes
[i
];
1082 struct partition
*p
= pe
->part_table
;
1084 if (IS_EXTENDED (p
->sys_ind
) && !p
->boot_ind
)
1086 _("WARNING: Partition %d is an extended partition\n"),
1088 p
->boot_ind
= (p
->boot_ind
? 0 : ACTIVE_FLAG
);
1093 toggle_dos_compatibility_flag(void) {
1094 dos_compatible_flag
= ~dos_compatible_flag
;
1095 if (dos_compatible_flag
) {
1096 sector_offset
= sectors
;
1097 printf(_("DOS Compatibility flag is set\n"));
1101 printf(_("DOS Compatibility flag is not set\n"));
1106 delete_partition(int i
) {
1107 struct pte
*pe
= &ptes
[i
];
1108 struct partition
*p
= pe
->part_table
;
1109 struct partition
*q
= pe
->ext_pointer
;
1111 /* Note that for the fifth partition (i == 4) we don't actually
1112 * decrement partitions.
1115 if (warn_geometry())
1120 sun_delete_partition(i
);
1125 sgi_delete_partition(i
);
1130 if (IS_EXTENDED (p
->sys_ind
) && i
== ext_index
) {
1132 ptes
[ext_index
].ext_pointer
= NULL
;
1133 extended_offset
= 0;
1139 if (!q
->sys_ind
&& i
> 4) {
1142 clear_partition(ptes
[i
].ext_pointer
);
1143 ptes
[i
].changed
= 1;
1146 p
= ptes
[i
-1].ext_pointer
;
1149 p
->sector
= q
->sector
;
1151 p
->sys_ind
= EXTENDED
;
1152 p
->end_head
= q
->end_head
;
1153 p
->end_sector
= q
->end_sector
;
1154 p
->end_cyl
= q
->end_cyl
;
1155 set_start_sect(p
, get_start_sect(q
));
1156 set_nr_sects(p
, get_nr_sects(q
));
1157 ptes
[i
-1].changed
= 1;
1158 } else if (partitions
> 5) { /* 5 will be moved to 4 */
1159 struct pte
*pe
= &ptes
[5];
1161 if(pe
->part_table
) /* prevent SEGFAULT */
1162 set_start_sect(pe
->part_table
,
1163 get_partition_start(pe
) -
1165 pe
->offset
= extended_offset
;
1169 if (partitions
> 5) {
1171 while (i
< partitions
) {
1172 ptes
[i
] = ptes
[i
+1];
1176 clear_partition(ptes
[i
].part_table
);
1181 change_sysid(void) {
1183 int i
= get_partition(0, partitions
), sys
, origsys
;
1184 struct partition
*p
= ptes
[i
].part_table
;
1186 origsys
= sys
= get_sysid(i
);
1188 if (!sys
&& !sgi_label
)
1189 printf(_("Partition %d does not exist yet!\n"), i
+ 1);
1191 sys
= read_hex (get_sys_types());
1193 if (!sys
&& !sgi_label
) {
1194 printf(_("Type 0 means free space to many systems\n"
1195 "(but not to Linux). Having partitions of\n"
1196 "type 0 is probably unwise. You can delete\n"
1197 "a partition using the `d' command.\n"));
1201 if (!sun_label
&& !sgi_label
) {
1202 if (IS_EXTENDED (sys
) != IS_EXTENDED (p
->sys_ind
)) {
1203 printf(_("You cannot change a partition into"
1204 " an extended one or vice versa\n"
1205 "Delete it first.\n"));
1211 if (sun_label
&& i
== 2 && sys
!= WHOLE_DISK
)
1212 printf(_("Consider leaving partition 3 "
1213 "as Whole disk (5),\n"
1214 "as SunOS/Solaris expects it and "
1215 "even Linux likes it.\n\n"));
1216 if (sgi_label
&& ((i
== 10 && sys
!= ENTIRE_DISK
)
1217 || (i
== 8 && sys
!= 0)))
1218 printf(_("Consider leaving partition 9 "
1219 "as volume header (0),\nand "
1220 "partition 11 as entire volume (6)"
1221 "as IRIX expects it.\n\n"));
1226 sun_change_sysid(i
, sys
);
1229 sgi_change_sysid(i
, sys
);
1232 printf (_("Changed system type of partition %d "
1233 "to %x (%s)\n"), i
+ 1, sys
,
1234 (temp
= partition_type(sys
)) ? temp
:
1236 ptes
[i
].changed
= 1;
1242 /* check_consistency() and long2chs() added Sat Mar 6 12:28:16 1993,
1243 * faith@cs.unc.edu, based on code fragments from pfdisk by Gordon W. Ross,
1244 * Jan. 1990 (version 1.2.1 by Gordon W. Ross Aug. 1990; Modified by S.
1245 * Lubkin Oct. 1991). */
1247 static void long2chs(ulong ls
, uint
*c
, uint
*h
, uint
*s
) {
1248 int spc
= heads
* sectors
;
1253 *s
= ls
% sectors
+ 1; /* sectors count from 1 */
1256 static void check_consistency(struct partition
*p
, int partition
) {
1257 uint pbc
, pbh
, pbs
; /* physical beginning c, h, s */
1258 uint pec
, peh
, pes
; /* physical ending c, h, s */
1259 uint lbc
, lbh
, lbs
; /* logical beginning c, h, s */
1260 uint lec
, leh
, les
; /* logical ending c, h, s */
1262 if (!heads
|| !sectors
|| (partition
>= 4))
1263 return; /* do not check extended partitions */
1265 /* physical beginning c, h, s */
1266 pbc
= (p
->cyl
& 0xff) | ((p
->sector
<< 2) & 0x300);
1268 pbs
= p
->sector
& 0x3f;
1270 /* physical ending c, h, s */
1271 pec
= (p
->end_cyl
& 0xff) | ((p
->end_sector
<< 2) & 0x300);
1273 pes
= p
->end_sector
& 0x3f;
1275 /* compute logical beginning (c, h, s) */
1276 long2chs(get_start_sect(p
), &lbc
, &lbh
, &lbs
);
1278 /* compute logical ending (c, h, s) */
1279 long2chs(get_start_sect(p
) + get_nr_sects(p
) - 1, &lec
, &leh
, &les
);
1281 /* Same physical / logical beginning? */
1282 if (cylinders
<= 1024 && (pbc
!= lbc
|| pbh
!= lbh
|| pbs
!= lbs
)) {
1283 printf(_("Partition %d has different physical/logical "
1284 "beginnings (non-Linux?):\n"), partition
+ 1);
1285 printf(_(" phys=(%d, %d, %d) "), pbc
, pbh
, pbs
);
1286 printf(_("logical=(%d, %d, %d)\n"),lbc
, lbh
, lbs
);
1289 /* Same physical / logical ending? */
1290 if (cylinders
<= 1024 && (pec
!= lec
|| peh
!= leh
|| pes
!= les
)) {
1291 printf(_("Partition %d has different physical/logical "
1292 "endings:\n"), partition
+ 1);
1293 printf(_(" phys=(%d, %d, %d) "), pec
, peh
, pes
);
1294 printf(_("logical=(%d, %d, %d)\n"),lec
, leh
, les
);
1298 /* Beginning on cylinder boundary? */
1299 if (pbh
!= !pbc
|| pbs
!= 1) {
1300 printf(_("Partition %i does not start on cylinder "
1301 "boundary:\n"), partition
+ 1);
1302 printf(_(" phys=(%d, %d, %d) "), pbc
, pbh
, pbs
);
1303 printf(_("should be (%d, %d, 1)\n"), pbc
, !pbc
);
1307 /* Ending on cylinder boundary? */
1308 if (peh
!= (heads
- 1) || pes
!= sectors
) {
1309 printf(_("Partition %i does not end on cylinder boundary:\n"),
1311 printf(_(" phys=(%d, %d, %d) "), pec
, peh
, pes
);
1312 printf(_("should be (%d, %d, %d)\n"),
1313 pec
, heads
- 1, sectors
);
1318 list_disk_geometry(void) {
1319 printf(_("\nDisk %s: %d heads, %d sectors, %d cylinders\nUnits = "
1320 "%s of %d * %d bytes\n\n"), disk_device
, heads
, sectors
,
1321 cylinders
, str_units(PLURAL
), units_per_sector
, sector_size
);
1325 * Check whether partition entries are ordered by their starting positions.
1326 * Return 0 if OK. Return i if partition i should have been earlier.
1327 * Two separate checks: primary and logical partitions.
1330 wrong_p_order(int *prev
) {
1332 struct partition
*p
;
1333 uint last_p_start_pos
= 0, p_start_pos
;
1336 for (i
= 0 ; i
< partitions
; i
++) {
1339 last_p_start_pos
= 0;
1342 if ((p
= pe
->part_table
)->sys_ind
) {
1343 p_start_pos
= get_partition_start(pe
);
1345 if (last_p_start_pos
> p_start_pos
) {
1351 last_p_start_pos
= p_start_pos
;
1359 fix_partition_table_order(void) {
1360 struct pte
*pei
, *pek
, ptebuf
;
1363 if(!wrong_p_order(NULL
)) {
1364 printf(_("Nothing to do. Ordering is correct already.\n\n"));
1368 while ((i
= wrong_p_order(&k
)) != 0) {
1369 /* partition i should have come earlier, move it */
1374 /* We have to move data in the MBR */
1375 struct partition
*pi
, *pk
, *pe
, pbuf
;
1377 pe
= pei
->ext_pointer
;
1378 pei
->ext_pointer
= pek
->ext_pointer
;
1379 pek
->ext_pointer
= pe
;
1381 pi
= pei
->part_table
;
1382 pk
= pek
->part_table
;
1384 memmove(&pbuf
, pi
, sizeof(struct partition
));
1385 memmove(pi
, pk
, sizeof(struct partition
));
1386 memmove(pk
, &pbuf
, sizeof(struct partition
));
1388 /* Only change is change in numbering */
1393 pei
->changed
= pek
->changed
= 1;
1399 list_table(int xtra
) {
1400 struct partition
*p
;
1405 sun_list_table(xtra
);
1410 sgi_list_table(xtra
);
1414 list_disk_geometry();
1417 xbsd_print_disklabel(xtra
);
1421 /* Heuristic: we list partition 3 of /dev/foo as /dev/foo3,
1422 but if the device name ends in a digit, say /dev/foo1,
1423 then the partition is called /dev/foo1p3. */
1424 w
= strlen(disk_device
);
1425 if (w
&& isdigit(disk_device
[w
-1]))
1430 printf(_("%*s Boot Start End Blocks Id System\n"),
1433 for (i
= 0 ; i
< partitions
; i
++) {
1434 struct pte
*pe
= &ptes
[i
];
1437 if (p
&& p
->sys_ind
) {
1438 unsigned int psects
= get_nr_sects(p
);
1439 unsigned int pblocks
= psects
;
1440 unsigned int podd
= 0;
1442 if (sector_size
< 1024) {
1443 pblocks
/= (1024 / sector_size
);
1444 podd
= psects
% (1024 / sector_size
);
1446 if (sector_size
> 1024)
1447 pblocks
*= (sector_size
/ 1024);
1449 "%s %c %9ld %9ld %9ld%c %2x %s\n",
1450 partname(disk_device
, i
+1, w
+2),
1451 /* boot flag */ !p
->boot_ind
? ' ' : p
->boot_ind
== ACTIVE_FLAG
1453 /* start */ (long) cround(get_partition_start(pe
)),
1454 /* end */ (long) cround(get_partition_start(pe
) + psects
1455 - (psects
? 1 : 0)),
1456 /* odd flag on end */ (long) pblocks
, podd
? '+' : ' ',
1457 /* type id */ p
->sys_ind
,
1458 /* type name */ (type
= partition_type(p
->sys_ind
)) ?
1459 type
: _("Unknown"));
1460 check_consistency(p
, i
);
1464 /* Is partition table in disk order? It need not be, but... */
1465 /* partition table entries are not checked for correct order if this
1466 is a sgi, sun or aix labeled disk... */
1467 if (dos_label
&& wrong_p_order(NULL
)) {
1468 printf(_("\nPartition table entries are not in disk order\n"));
1473 x_list_table(int extend
) {
1475 struct partition
*p
;
1478 printf(_("\nDisk %s: %d heads, %d sectors, %d cylinders\n\n"),
1479 disk_device
, heads
, sectors
, cylinders
);
1480 printf(_("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n"));
1481 for (i
= 0 ; i
< partitions
; i
++) {
1483 p
= (extend
? pe
->ext_pointer
: pe
->part_table
);
1485 printf("%2d %02x%4d%4d%5d%4d%4d%5d%9d%9d %02x\n",
1486 i
+ 1, p
->boot_ind
, p
->head
,
1488 cylinder(p
->sector
, p
->cyl
), p
->end_head
,
1489 sector(p
->end_sector
),
1490 cylinder(p
->end_sector
, p
->end_cyl
),
1491 get_start_sect(p
), get_nr_sects(p
), p
->sys_ind
);
1493 check_consistency(p
, i
);
1499 fill_bounds(uint
*first
, uint
*last
) {
1501 struct pte
*pe
= &ptes
[0];
1502 struct partition
*p
;
1504 for (i
= 0; i
< partitions
; pe
++,i
++) {
1506 if (!p
->sys_ind
|| IS_EXTENDED (p
->sys_ind
)) {
1507 first
[i
] = 0xffffffff;
1510 first
[i
] = get_partition_start(pe
);
1511 last
[i
] = first
[i
] + get_nr_sects(p
) - 1;
1517 check(int n
, uint h
, uint s
, uint c
, uint start
) {
1518 uint total
, real_s
, real_c
;
1520 real_s
= sector(s
) - 1;
1521 real_c
= cylinder(s
, c
);
1522 total
= (real_c
* sectors
+ real_s
) * heads
+ h
;
1524 fprintf(stderr
, _("Warning: partition %d contains sector 0\n"), n
);
1527 _("Partition %d: head %d greater than maximum %d\n"),
1529 if (real_s
>= sectors
)
1530 fprintf(stderr
, _("Partition %d: sector %d greater than "
1531 "maximum %d\n"), n
, s
, sectors
);
1532 if (real_c
>= cylinders
)
1533 fprintf(stderr
, _("Partitions %d: cylinder %d greater than "
1534 "maximum %d\n"), n
, real_c
+ 1, cylinders
);
1535 if (cylinders
<= 1024 && start
!= total
)
1537 _("Partition %d: previous sectors %d disagrees with "
1538 "total %d\n"), n
, start
, total
);
1545 uint first
[partitions
], last
[partitions
];
1546 struct partition
*p
= part_table
[0];
1548 if (warn_geometry())
1561 fill_bounds(first
, last
);
1562 for (i
= 0; i
< partitions
; i
++) {
1563 struct pte
*pe
= &ptes
[i
];
1566 if (p
->sys_ind
&& !IS_EXTENDED (p
->sys_ind
)) {
1567 check_consistency(p
, i
);
1568 if (get_partition_start(pe
) < first
[i
])
1569 printf(_("Warning: bad start-of-data in "
1570 "partition %d\n"), i
+ 1);
1571 check(i
+ 1, p
->end_head
, p
->end_sector
, p
->end_cyl
,
1573 total
+= last
[i
] + 1 - first
[i
];
1574 for (j
= 0; j
< i
; j
++)
1575 if ((first
[i
] >= first
[j
] && first
[i
] <= last
[j
])
1576 || ((last
[i
] <= last
[j
] && last
[i
] >= first
[j
]))) {
1577 printf(_("Warning: partition %d overlaps "
1578 "partition %d.\n"), j
+ 1, i
+ 1);
1579 total
+= first
[i
] >= first
[j
] ?
1580 first
[i
] : first
[j
];
1581 total
-= last
[i
] <= last
[j
] ?
1587 if (extended_offset
) {
1588 struct pte
*pex
= &ptes
[ext_index
];
1589 uint e_last
= get_start_sect(pex
->part_table
) +
1590 get_nr_sects(pex
->part_table
) - 1;
1592 for (i
= 4; i
< partitions
; i
++) {
1594 p
= ptes
[i
].part_table
;
1596 if (i
!= 4 || i
+ 1 < partitions
)
1597 printf(_("Warning: partition %d "
1598 "is empty\n"), i
+ 1);
1600 else if (first
[i
] < extended_offset
||
1602 printf(_("Logical partition %d not entirely in "
1603 "partition %d\n"), i
+ 1, ext_index
+ 1);
1607 if (total
> heads
* sectors
* cylinders
)
1608 printf(_("Total allocated sectors %d greater than the maximum "
1609 "%d\n"), total
, heads
* sectors
* cylinders
);
1610 else if ((total
= heads
* sectors
* cylinders
- total
) != 0)
1611 printf(_("%d unallocated sectors\n"), total
);
1615 add_partition(int n
, int sys
) {
1616 char mesg
[256]; /* 48 does not suffice in Japanese */
1618 struct partition
*p
= ptes
[n
].part_table
;
1619 struct partition
*q
= ptes
[ext_index
].part_table
;
1620 uint start
, stop
= 0, limit
, temp
,
1621 first
[partitions
], last
[partitions
];
1623 if (p
&& p
->sys_ind
) {
1624 printf(_("Partition %d is already defined. Delete "
1625 "it before re-adding it.\n"), n
+ 1);
1628 fill_bounds(first
, last
);
1630 start
= sector_offset
;
1631 limit
= heads
* sectors
* cylinders
- 1;
1632 if (extended_offset
) {
1633 first
[ext_index
] = extended_offset
;
1634 last
[ext_index
] = get_start_sect(q
) +
1635 get_nr_sects(q
) - 1;
1638 start
= extended_offset
+ sector_offset
;
1639 limit
= get_start_sect(q
) + get_nr_sects(q
) - 1;
1641 if (display_in_cyl_units
)
1642 for (i
= 0; i
< partitions
; i
++)
1643 first
[i
] = (cround(first
[i
]) - 1) * units_per_sector
;
1645 sprintf(mesg
, _("First %s"), str_units(SINGULAR
));
1648 for (i
= 0; i
< partitions
; i
++) {
1651 if (start
== ptes
[i
].offset
)
1652 start
+= sector_offset
;
1653 lastplusoff
= last
[i
] + ((n
<4) ? 0 : sector_offset
);
1654 if (start
>= first
[i
] && start
<= lastplusoff
)
1655 start
= lastplusoff
+ 1;
1659 if (start
>= temp
+units_per_sector
&& read
) {
1660 printf(_("Sector %d is already allocated\n"), temp
);
1664 if (!read
&& start
== temp
) {
1667 start
= read_int(cround(i
), cround(i
), cround(limit
),
1669 if (display_in_cyl_units
) {
1670 start
= (start
- 1) * units_per_sector
;
1671 if (start
< i
) start
= i
;
1675 } while (start
!= temp
|| !read
);
1676 if (n
> 4) { /* NOT for fifth partition */
1677 struct pte
*pe
= &ptes
[n
];
1679 pe
->offset
= start
- sector_offset
;
1680 if (pe
->offset
== extended_offset
) { /* must be corrected */
1682 if (sector_offset
== 1)
1687 for (i
= 0; i
< partitions
; i
++) {
1688 struct pte
*pe
= &ptes
[i
];
1690 if (start
< pe
->offset
&& limit
>= pe
->offset
)
1691 limit
= pe
->offset
- 1;
1692 if (start
< first
[i
] && limit
>= first
[i
])
1693 limit
= first
[i
] - 1;
1695 if (start
> limit
) {
1696 printf(_("No free sectors available\n"));
1701 if (cround(start
) == cround(limit
)) {
1704 sprintf(mesg
, _("Last %s or +size or +sizeM or +sizeK"),
1705 str_units(SINGULAR
));
1706 stop
= read_int(cround(start
), cround(limit
), cround(limit
),
1707 cround(start
), mesg
);
1708 if (display_in_cyl_units
) {
1709 stop
= stop
* units_per_sector
- 1;
1715 set_partition(n
, p
, start
, stop
, sys
, ptes
[n
].offset
);
1717 if (IS_EXTENDED (sys
)) {
1718 struct pte
*pe4
= &ptes
[4];
1719 struct pte
*pen
= &ptes
[n
];
1722 pen
->ext_pointer
= p
;
1723 pe4
->offset
= extended_offset
= start
;
1724 if (!(pe4
->sectorbuffer
= calloc(1, sector_size
)))
1725 fatal(out_of_memory
);
1726 pe4
->part_table
= pt_offset(pe4
->sectorbuffer
, 0);
1727 pe4
->ext_pointer
= pe4
->part_table
+ 1;
1732 set_partition(n
- 1, ptes
[n
-1].ext_pointer
,
1733 ptes
[n
].offset
, stop
, EXTENDED
,
1736 if ((limit
= get_nr_sects(p
)) & 1)
1737 printf(_("Warning: partition %d has an odd "
1738 "number of sectors.\n"), n
+ 1);
1745 if (partitions
> 5 || ptes
[4].part_table
->sys_ind
) {
1746 struct pte
*pe
= &ptes
[partitions
];
1748 if (!(pe
->sectorbuffer
= calloc(1, sector_size
)))
1749 fatal(out_of_memory
);
1750 pe
->part_table
= pt_offset(pe
->sectorbuffer
, 0);
1751 pe
->ext_pointer
= pe
->part_table
+ 1;
1756 add_partition(partitions
- 1, LINUX_NATIVE
);
1760 new_partition(void) {
1761 int i
, free_primary
= 0;
1763 if (warn_geometry())
1767 add_sun_partition(get_partition(0, partitions
), LINUX_NATIVE
);
1772 sgi_add_partition(get_partition(0, partitions
), LINUX_NATIVE
);
1776 if (partitions
>= MAXIMUM_PARTS
) {
1777 printf(_("The maximum number of partitions has been created\n"));
1781 for (i
= 0; i
< 4; i
++)
1782 free_primary
+= !ptes
[i
].part_table
->sys_ind
;
1783 if (!free_primary
) {
1784 if (extended_offset
)
1787 printf(_("You must delete some partition and add "
1788 "an extended partition first\n"));
1790 char c
, line
[LINE_LENGTH
];
1791 sprintf(line
, _("Command action\n %s\n p primary "
1792 "partition (1-4)\n"), extended_offset
?
1793 _("l logical (5 or over)") : _("e extended"));
1795 if ((c
= tolower(read_char(line
))) == 'p') {
1796 add_partition(get_partition(0, 4),
1800 else if (c
== 'l' && extended_offset
) {
1804 else if (c
== 'e' && !extended_offset
) {
1805 add_partition(get_partition(0, 4),
1810 printf(_("Invalid partition number "
1811 "for type `%c'\n"), c
);
1823 ptes
[3].changed
= 1;
1824 for (i
= 3; i
< partitions
; i
++) {
1825 struct pte
*pe
= &ptes
[i
];
1828 write_part_table_flag(pe
->sectorbuffer
);
1829 write_sector(fd
, pe
->offset
, pe
->sectorbuffer
);
1832 } else if (sgi_label
) {
1833 /* no test on change? the printf below might be mistaken */
1835 } else if (sun_label
) {
1845 printf(_("The partition table has been altered!\n\n"));
1846 reread_partition_table(1);
1850 reread_partition_table(int leave
) {
1854 printf(_("Calling ioctl() to re-read partition table.\n"));
1857 if ((i
= ioctl(fd
, BLKRRPART
)) != 0) {
1860 /* some kernel versions (1.2.x) seem to have trouble
1861 rereading the partition table, but if asked to do it
1862 twice, the second time works. - biro@yggdrasil.com */
1865 if((i
= ioctl(fd
, BLKRRPART
)) != 0)
1870 printf(_("Re-read table failed with error %d: %s.\nReboot your "
1871 "system to ensure the partition table is updated.\n"),
1872 error
, strerror(error
));
1874 if (!sun_label
&& !sgi_label
)
1876 _("\nWARNING: If you have created or modified any DOS 6.x\n"
1877 "partitions, please see the fdisk manual page for additional\n"
1883 printf(_("Syncing disks.\n"));
1885 sleep(4); /* for sync() */
1890 #define MAX_PER_LINE 16
1892 print_buffer(char pbuffer
[]) {
1896 for (i
= 0, l
= 0; i
< sector_size
; i
++, l
++) {
1898 printf("0x%03X:", i
);
1899 printf(" %02X", (unsigned char) pbuffer
[i
]);
1900 if (l
== MAX_PER_LINE
- 1) {
1914 printf(_("Device: %s\n"), disk_device
);
1915 if (sun_label
|| sgi_label
)
1916 print_buffer(MBRbuffer
);
1917 else for (i
= 3; i
< partitions
; i
++)
1918 print_buffer(ptes
[i
].sectorbuffer
);
1923 struct pte
*pe
= &ptes
[i
];
1924 struct partition
*p
= pe
->part_table
;
1927 if (warn_geometry())
1929 if (!p
->sys_ind
|| !get_nr_sects(p
) || IS_EXTENDED (p
->sys_ind
)) {
1930 printf(_("Partition %d has no data area\n"), i
+ 1);
1933 first
= get_partition_start(pe
);
1934 new = read_int(first
, first
, first
+ get_nr_sects(p
) - 1, first
,
1935 _("New beginning of data")) - pe
->offset
;
1937 if (new != get_nr_sects(p
)) {
1938 first
= get_nr_sects(p
) + get_start_sect(p
) - new;
1939 set_nr_sects(p
, first
);
1940 set_start_sect(p
, new);
1951 c
= tolower(read_char(_("Expert command (m for help): ")));
1959 move_begin(get_partition(0, partitions
));
1962 user_cylinders
= cylinders
=
1963 read_int(1, cylinders
, 131071, 0,
1964 _("Number of cylinders"));
1966 sun_set_ncyl(cylinders
);
1983 fix_partition_table_order();
1989 user_heads
= heads
= read_int(1, heads
, 256, 0,
1990 _("Number of heads"));
2014 user_sectors
= sectors
= read_int(1, sectors
, 63, 0,
2015 _("Number of sectors"));
2016 if (dos_compatible_flag
) {
2017 sector_offset
= sectors
;
2018 fprintf(stderr
, _("Warning: setting "
2019 "sector offset for DOS "
2028 write_table(); /* does not return */
2032 sun_set_pcylcount();
2041 is_ide_cdrom(char *device
) {
2042 /* No device was given explicitly, and we are trying some
2043 likely things. But opening /dev/hdc may produce errors like
2044 "hdc: tray open or drive not ready"
2045 if it happens to be a CD-ROM drive. It even happens that
2046 the process hangs on the attempt to read a music CD.
2047 So try to be careful. This only works since 2.1.73. */
2051 struct stat statbuf
;
2053 if (strncmp("/dev/hd", device
, 7))
2055 sprintf(buf
, "/proc/ide/%s/media", device
+5);
2056 procf
= fopen(buf
, "r");
2057 if (procf
!= NULL
&& fgets(buf
, sizeof(buf
), procf
))
2058 return !strncmp(buf
, "cdrom", 5);
2060 /* Now when this proc file does not exist, skip the
2061 device when it is read-only. */
2062 if (stat(device
, &statbuf
) == 0)
2063 return (statbuf
.st_mode
& 0222) == 0;
2069 try(char *device
, int user_specified
) {
2070 disk_device
= device
;
2071 if (!setjmp(listingbuf
)) {
2072 if (!user_specified
)
2073 if (is_ide_cdrom(device
))
2075 if ((fd
= open(disk_device
, type_open
)) >= 0) {
2076 if (get_boot(try_only
) < 0) {
2077 list_disk_geometry();
2080 if (btrydev(device
) < 0)
2082 _("Disk %s doesn't contain a valid "
2083 "partition table\n"), device
);
2088 if (!sun_label
&& partitions
> 4)
2089 delete_partition(ext_index
);
2092 /* Ignore other errors, since we try IDE
2093 and SCSI hard disks which may not be
2094 installed on the system. */
2095 if(errno
== EACCES
) {
2096 fprintf(stderr
, _("Cannot open %s\n"), device
);
2103 /* for fdisk -l: try all things in /proc/partitions
2104 that look like a partition name (do not end in a digit) */
2108 char line
[100], ptname
[100], devname
[120], *s
;
2111 procpt
= fopen(PROC_PARTITIONS
, "r");
2112 if (procpt
== NULL
) {
2113 fprintf(stderr
, _("cannot open %s\n"), PROC_PARTITIONS
);
2117 while (fgets(line
, sizeof(line
), procpt
)) {
2118 if (sscanf (line
, " %d %d %d %[^\n]\n",
2119 &ma
, &mi
, &sz
, ptname
) != 4)
2121 for(s
= ptname
; *s
; s
++);
2124 sprintf(devname
, "/dev/%s", ptname
);
2133 unknown_command(int c
) {
2134 printf(_("%c: unknown command\n"), c
);
2138 main(int argc
, char **argv
) {
2140 int optl
= 0, opts
= 0;
2142 setlocale(LC_ALL
, "");
2143 bindtextdomain(PACKAGE
, LOCALEDIR
);
2144 textdomain(PACKAGE
);
2149 * fdisk -l [-b sectorsize] [-u] device ...
2150 * fdisk -s [partition] ...
2151 * fdisk [-b sectorsize] [-u] device
2153 while ((c
= getopt(argc
, argv
, "b:lsuvV")) != EOF
) {
2156 /* ugly: this sector size is really per device,
2157 so cannot be combined with multiple disks */
2158 sector_size
= atoi(optarg
);
2159 if (sector_size
!= 512 && sector_size
!= 1024 &&
2160 sector_size
!= 2048)
2163 user_set_sector_size
= 1;
2172 display_in_cyl_units
= 0;
2176 printf("fdisk v" UTIL_LINUX_VERSION
"\n");
2184 printf(_("This kernel finds the sector size itself - -b option ignored\n"));
2186 if (user_set_sector_size
&& argc
-optind
!= 1)
2187 printf(_("Warning: the -b (set sector size) option should"
2188 " be used with one specified device\n"));
2193 type_open
= O_RDONLY
;
2194 if (argc
> optind
) {
2196 /* avoid gcc warning:
2197 variable `k' might be clobbered by `longjmp' */
2200 for(k
=optind
; k
<argc
; k
++)
2203 /* we no longer have default device names */
2204 /* but, we can use /proc/partitions instead */
2214 type_open
= O_RDONLY
;
2216 opts
= argc
- optind
;
2220 for (j
= optind
; j
< argc
; j
++) {
2221 disk_device
= argv
[j
];
2222 if ((fd
= open(disk_device
, type_open
)) < 0)
2223 fatal(unable_to_open
);
2224 if (ioctl(fd
, BLKGETSIZE
, &size
))
2228 printf("%ld\n", size
/2);
2230 printf("%s: %ld\n", argv
[j
], size
/2);
2235 if (argc
-optind
== 1)
2236 disk_device
= argv
[optind
];
2237 else if (argc
-optind
!= 0)
2247 /* On alpha, if we detect a disklabel, go directly to
2248 disklabel mode (typically you'll be switching from DOS
2249 partition tables to disklabels, not the other way around)
2250 - dhuggins@linuxcare.com */
2252 printf(_("Detected an OSF/1 disklabel on %s, entering disklabel mode.\n"
2253 "To return to DOS partition table mode, use the 'r' command.\n"),
2261 c
= tolower(read_char(_("Command (m for help): ")));
2265 toggle_active(get_partition(1, partitions
));
2267 toggle_sunflags(get_partition(1, partitions
),
2270 sgi_set_bootpartition(
2271 get_partition(1, partitions
));
2277 printf(_("\nThe current boot file is: %s\n"),
2278 sgi_get_bootfile());
2279 if (read_chars(_("Please enter the name of the "
2280 "new boot file: ")) == '\n')
2281 printf(_("Boot file unchanged\n"));
2283 sgi_set_bootfile(line_ptr
);
2289 toggle_dos_compatibility_flag();
2291 toggle_sunflags(get_partition(1, partitions
),
2294 sgi_set_swappartition(
2295 get_partition(1, partitions
));
2301 get_partition(1, partitions
));
2309 list_types(get_sys_types());
2340 write_table(); /* does not return */
2345 _("\n\tSorry, no experts menu for SGI "
2346 "partition tables available.\n\n"));