1 /* fdisk.c -- Partition table manipulator for Linux.
3 * Copyright (C) 1992 A. V. Le Blanc (LeBlanc@mcc.ac.uk)
4 * Copyright (C) 2001,2002 Vladimir Oleynik <dzo@simtreas.ru> (initial bb port)
6 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
9 /* Current changes have not compatibility with this version */
10 #define UTIL_LINUX_VERSION "2.12"
15 #define PROC_PARTITIONS "/proc/partitions"
18 #include <sys/types.h>
19 #include <sys/stat.h> /* stat */
28 #include <assert.h> /* assert */
31 #include <sys/ioctl.h>
32 #include <sys/param.h>
33 #include <sys/sysmacros.h> /* major */
35 #include <stdint.h> /* for uint32_t, uint16_t, uint8_t, int16_t, etc */
37 /* Copied from linux/major.h */
38 #define FLOPPY_MAJOR 2
40 #include <sys/utsname.h>
50 #define DEFAULT_SECTOR_SIZE 512
51 #define MAX_SECTOR_SIZE 2048
52 #define SECTOR_SIZE 512 /* still used in BSD code */
53 #define MAXIMUM_PARTS 60
55 #define ACTIVE_FLAG 0x80
58 #define WIN98_EXTENDED 0x0f
59 #define LINUX_PARTITION 0x81
60 #define LINUX_SWAP 0x82
61 #define LINUX_NATIVE 0x83
62 #define LINUX_EXTENDED 0x85
63 #define LINUX_LVM 0x8e
64 #define LINUX_RAID 0xfd
69 #define IS_EXTENDED(i) \
70 ((i) == EXTENDED || (i) == WIN98_EXTENDED || (i) == LINUX_EXTENDED)
72 #define SIZE(a) (sizeof(a)/sizeof((a)[0]))
74 #define cround(n) (display_in_cyl_units ? ((n)/units_per_sector)+1 : (n))
75 #define scround(x) (((x)+units_per_sector-1)/units_per_sector)
77 #ifdef CONFIG_FEATURE_SUN_LABEL
78 #define SCSI_IOCTL_GET_IDLUN 0x5382
82 /* including <linux/hdreg.h> also fails */
85 unsigned char sectors;
86 unsigned short cylinders;
90 #define HDIO_GETGEO 0x0301 /* get device geometry */
97 static uint sector_size = DEFAULT_SECTOR_SIZE;
98 static uint user_set_sector_size;
99 static uint sector_offset = 1;
102 * Raw disk label. For DOS-type partition tables the MBR,
103 * with descriptions of the primary partitions.
105 #if (MAX_SECTOR_SIZE) > (BUFSIZ+1)
106 static char MBRbuffer[MAX_SECTOR_SIZE];
108 # define MBRbuffer bb_common_bufsiz1
111 #ifdef CONFIG_FEATURE_OSF_LABEL
112 static int possibly_osf_label;
115 static uint heads, sectors, cylinders;
116 static void update_units(void);
120 * return partition name - uses static storage unless buf is supplied
123 partname(const char *dev, int pno, int lth)
125 static char buffer[80];
132 bufsiz = sizeof(buffer);
137 if (isdigit(dev[w-1]))
140 /* devfs kludge - note: fdisk partition names are not supposed
141 to equal kernel names, so there is no reason to do this */
142 if (strcmp(dev + w - 4, "disc") == 0) {
150 snprintf(bufp, bufsiz, "%*.*s%s%-2u",
151 lth-wp-2, w, dev, p, pno);
153 snprintf(bufp, bufsiz, "%.*s%s%-2u", w, dev, p, pno);
159 unsigned char boot_ind; /* 0x80 - active */
160 unsigned char head; /* starting head */
161 unsigned char sector; /* starting sector */
162 unsigned char cyl; /* starting cylinder */
163 unsigned char sys_ind; /* What partition type */
164 unsigned char end_head; /* end head */
165 unsigned char end_sector; /* end sector */
166 unsigned char end_cyl; /* end cylinder */
167 unsigned char start4[4]; /* starting sector counting from 0 */
168 unsigned char size4[4]; /* nr of sectors in partition */
172 ioctl_error, unable_to_open, unable_to_read, unable_to_seek,
177 label_dos, label_sun, label_sgi, label_aix, label_osf
180 enum action { fdisk, require, try_only, create_empty_dos, create_empty_sun };
182 static enum label_type current_label_type;
184 static const char *disk_device;
185 static int fd; /* the disk */
186 static int partitions = 4; /* maximum partition + 1 */
187 static uint display_in_cyl_units = 1;
188 static uint units_per_sector = 1;
189 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
190 static char *line_ptr;
191 static void change_units(void);
192 static void reread_partition_table(int leave);
193 static void delete_partition(int i);
194 static int get_partition(int warn, int max);
195 static void list_types(const struct systypes *sys);
196 static uint read_int(uint low, uint dflt, uint high, uint base, char *mesg);
198 static const char *partition_type(unsigned char type);
199 static void fdisk_fatal(enum failure why) ATTRIBUTE_NORETURN;
200 static void get_geometry(void);
201 static int get_boot(enum action what);
206 #define hex_val(c) ({ \
208 isdigit(_c) ? _c - '0' : \
209 tolower(_c) + 10 - 'a'; \
213 #define LINE_LENGTH 800
214 #define pt_offset(b, n) ((struct partition *)((b) + 0x1be + \
215 (n) * sizeof(struct partition)))
216 #define sector(s) ((s) & 0x3f)
217 #define cylinder(s, c) ((c) | (((s) & 0xc0) << 2))
219 #define hsc2sector(h,s,c) (sector(s) - 1 + sectors * \
220 ((h) + heads * cylinder(s,c)))
221 #define set_hsc(h,s,c,sector) { \
222 s = sector % sectors + 1; \
224 h = sector % heads; \
227 s |= (sector >> 2) & 0xc0; \
231 static int32_t get_start_sect(const struct partition *p);
232 static int32_t get_nr_sects(const struct partition *p);
235 * per partition table entry data
237 * The four primary partitions have the same sectorbuffer (MBRbuffer)
238 * and have NULL ext_pointer.
239 * Each logical partition table entry has two pointers, one for the
240 * partition and one link to the next one.
243 struct partition *part_table; /* points into sectorbuffer */
244 struct partition *ext_pointer; /* points into sectorbuffer */
245 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
246 char changed; /* boolean */
248 off_t offset; /* disk sector number */
249 char *sectorbuffer; /* disk sector contents */
250 } ptes[MAXIMUM_PARTS];
253 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
255 set_all_unchanged(void)
259 for (i = 0; i < MAXIMUM_PARTS; i++)
268 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
270 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_OSF_LABEL)
271 static struct partition *
272 get_part_table(int i)
274 return ptes[i].part_table;
280 { /* n==1: use singular */
282 return display_in_cyl_units ? _("cylinder") : _("sector");
284 return display_in_cyl_units ? _("cylinders") : _("sectors");
288 valid_part_table_flag(const char *mbuffer) {
289 const unsigned char *b = (const unsigned char *)mbuffer;
290 return (b[510] == 0x55 && b[511] == 0xaa);
293 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
294 static char line_buffer[LINE_LENGTH];
296 /* read line; return 0 or first char */
300 static int got_eof = 0;
302 fflush (stdout); /* requested by niles@scyld.com */
303 line_ptr = line_buffer;
304 if (!fgets(line_buffer, LINE_LENGTH, stdin)) {
306 got_eof++; /* user typed ^D ? */
308 fprintf(stderr, _("\ngot EOF thrice - exiting..\n"));
313 while (*line_ptr && !isgraph(*line_ptr))
319 read_char(const char *mesg)
323 } while (!read_line());
328 read_chars(const char *mesg)
339 read_hex(const struct systypes *sys)
344 read_char(_("Hex code (type L to list codes): "));
345 if (*line_ptr == 'l' || *line_ptr == 'L')
347 else if (isxdigit (*line_ptr)) {
350 hex = hex << 4 | hex_val(*line_ptr++);
351 while (isxdigit(*line_ptr));
356 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
358 #ifdef CONFIG_FEATURE_AIX_LABEL
360 * Copyright (C) Andreas Neuper, Sep 1998.
361 * This file may be redistributed under
362 * the terms of the GNU Public License.
366 unsigned int magic; /* expect AIX_LABEL_MAGIC */
367 unsigned int fillbytes1[124];
368 unsigned int physical_volume_id;
369 unsigned int fillbytes2[124];
372 #define AIX_LABEL_MAGIC 0xc9c2d4c1
373 #define AIX_LABEL_MAGIC_SWAPPED 0xc1d4c2c9
374 #define AIX_INFO_MAGIC 0x00072959
375 #define AIX_INFO_MAGIC_SWAPPED 0x59290700
377 #define aixlabel ((aix_partition *)MBRbuffer)
382 * 1999-03-20 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
383 * Internationalization
385 * 2003-03-20 Phillip Kesling <pkesling@sgi.com>
389 static int aix_other_endian;
390 static short aix_volumes = 1;
393 * only dealing with free blocks here
400 _("\n\tThere is a valid AIX label on this disk.\n"
401 "\tUnfortunately Linux cannot handle these\n"
402 "\tdisks at the moment. Nevertheless some\n"
404 "\t1. fdisk will destroy its contents on write.\n"
405 "\t2. Be sure that this disk is NOT a still vital\n"
406 "\t part of a volume group. (Otherwise you may\n"
407 "\t erase the other disks as well, if unmirrored.)\n"
408 "\t3. Before deleting this physical volume be sure\n"
409 "\t to remove the disk logically from your AIX\n"
410 "\t machine. (Otherwise you become an AIXpert).")
415 check_aix_label(void)
417 if (aixlabel->magic != AIX_LABEL_MAGIC &&
418 aixlabel->magic != AIX_LABEL_MAGIC_SWAPPED) {
419 current_label_type = 0;
420 aix_other_endian = 0;
423 aix_other_endian = (aixlabel->magic == AIX_LABEL_MAGIC_SWAPPED);
425 current_label_type = label_aix;
429 /*aix_nolabel();*/ /* %% */
430 /*aix_label = 1;*/ /* %% */
433 #endif /* AIX_LABEL */
435 #ifdef CONFIG_FEATURE_OSF_LABEL
437 * Copyright (c) 1987, 1988 Regents of the University of California.
438 * All rights reserved.
440 * Redistribution and use in source and binary forms, with or without
441 * modification, are permitted provided that the following conditions
443 * 1. Redistributions of source code must retain the above copyright
444 * notice, this list of conditions and the following disclaimer.
445 * 2. Redistributions in binary form must reproduce the above copyright
446 * notice, this list of conditions and the following disclaimer in the
447 * documentation and/or other materials provided with the distribution.
448 * 3. All advertising materials mentioning features or use of this software
449 * must display the following acknowledgment:
450 * This product includes software developed by the University of
451 * California, Berkeley and its contributors.
452 * 4. Neither the name of the University nor the names of its contributors
453 * may be used to endorse or promote products derived from this software
454 * without specific prior written permission.
456 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
457 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
458 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
459 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
460 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
461 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
462 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
463 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
464 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
465 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
470 #ifndef BSD_DISKMAGIC
471 #define BSD_DISKMAGIC ((uint32_t) 0x82564557)
474 #ifndef BSD_MAXPARTITIONS
475 #define BSD_MAXPARTITIONS 16
478 #define BSD_LINUX_BOOTDIR "/usr/ucb/mdec"
480 #if defined (i386) || defined (__sparc__) || defined (__arm__) || defined (__mips__) || defined (__s390__) || defined (__sh__) || defined(__x86_64__)
481 #define BSD_LABELSECTOR 1
482 #define BSD_LABELOFFSET 0
483 #elif defined (__alpha__) || defined (__powerpc__) || defined (__ia64__) || defined (__hppa__)
484 #define BSD_LABELSECTOR 0
485 #define BSD_LABELOFFSET 64
486 #elif defined (__s390__) || defined (__s390x__)
487 #define BSD_LABELSECTOR 1
488 #define BSD_LABELOFFSET 0
490 #error unknown architecture
493 #define BSD_BBSIZE 8192 /* size of boot area, with label */
494 #define BSD_SBSIZE 8192 /* max size of fs superblock */
496 struct xbsd_disklabel {
497 uint32_t d_magic; /* the magic number */
498 int16_t d_type; /* drive type */
499 int16_t d_subtype; /* controller/d_type specific */
500 char d_typename[16]; /* type name, e.g. "eagle" */
501 char d_packname[16]; /* pack identifier */
503 uint32_t d_secsize; /* # of bytes per sector */
504 uint32_t d_nsectors; /* # of data sectors per track */
505 uint32_t d_ntracks; /* # of tracks per cylinder */
506 uint32_t d_ncylinders; /* # of data cylinders per unit */
507 uint32_t d_secpercyl; /* # of data sectors per cylinder */
508 uint32_t d_secperunit; /* # of data sectors per unit */
510 * Spares (bad sector replacements) below
511 * are not counted in d_nsectors or d_secpercyl.
512 * Spare sectors are assumed to be physical sectors
513 * which occupy space at the end of each track and/or cylinder.
515 uint16_t d_sparespertrack; /* # of spare sectors per track */
516 uint16_t d_sparespercyl; /* # of spare sectors per cylinder */
518 * Alternate cylinders include maintenance, replacement,
519 * configuration description areas, etc.
521 uint32_t d_acylinders; /* # of alt. cylinders per unit */
523 /* hardware characteristics: */
525 * d_interleave, d_trackskew and d_cylskew describe perturbations
526 * in the media format used to compensate for a slow controller.
527 * Interleave is physical sector interleave, set up by the formatter
528 * or controller when formatting. When interleaving is in use,
529 * logically adjacent sectors are not physically contiguous,
530 * but instead are separated by some number of sectors.
531 * It is specified as the ratio of physical sectors traversed
532 * per logical sector. Thus an interleave of 1:1 implies contiguous
533 * layout, while 2:1 implies that logical sector 0 is separated
534 * by one sector from logical sector 1.
535 * d_trackskew is the offset of sector 0 on track N
536 * relative to sector 0 on track N-1 on the same cylinder.
537 * Finally, d_cylskew is the offset of sector 0 on cylinder N
538 * relative to sector 0 on cylinder N-1.
540 uint16_t d_rpm; /* rotational speed */
541 uint16_t d_interleave; /* hardware sector interleave */
542 uint16_t d_trackskew; /* sector 0 skew, per track */
543 uint16_t d_cylskew; /* sector 0 skew, per cylinder */
544 uint32_t d_headswitch; /* head switch time, usec */
545 uint32_t d_trkseek; /* track-to-track seek, usec */
546 uint32_t d_flags; /* generic flags */
548 uint32_t d_drivedata[NDDATA]; /* drive-type specific information */
550 uint32_t d_spare[NSPARE]; /* reserved for future use */
551 uint32_t d_magic2; /* the magic number (again) */
552 uint16_t d_checksum; /* xor of data incl. partitions */
553 /* filesystem and partition information: */
554 uint16_t d_npartitions; /* number of partitions in following */
555 uint32_t d_bbsize; /* size of boot area at sn0, bytes */
556 uint32_t d_sbsize; /* max size of fs superblock, bytes */
557 struct xbsd_partition { /* the partition table */
558 uint32_t p_size; /* number of sectors in partition */
559 uint32_t p_offset; /* starting sector */
560 uint32_t p_fsize; /* filesystem basic fragment size */
561 uint8_t p_fstype; /* filesystem type, see below */
562 uint8_t p_frag; /* filesystem fragments per block */
563 uint16_t p_cpg; /* filesystem cylinders per group */
564 } d_partitions[BSD_MAXPARTITIONS]; /* actually may be more */
568 #define BSD_DTYPE_SMD 1 /* SMD, XSMD; VAX hp/up */
569 #define BSD_DTYPE_MSCP 2 /* MSCP */
570 #define BSD_DTYPE_DEC 3 /* other DEC (rk, rl) */
571 #define BSD_DTYPE_SCSI 4 /* SCSI */
572 #define BSD_DTYPE_ESDI 5 /* ESDI interface */
573 #define BSD_DTYPE_ST506 6 /* ST506 etc. */
574 #define BSD_DTYPE_HPIB 7 /* CS/80 on HP-IB */
575 #define BSD_DTYPE_HPFL 8 /* HP Fiber-link */
576 #define BSD_DTYPE_FLOPPY 10 /* floppy */
578 /* d_subtype values: */
579 #define BSD_DSTYPE_INDOSPART 0x8 /* is inside dos partition */
580 #define BSD_DSTYPE_DOSPART(s) ((s) & 3) /* dos partition number */
581 #define BSD_DSTYPE_GEOMETRY 0x10 /* drive params in label */
584 static const char * const xbsd_dktypenames[] = {
598 #define BSD_DKMAXTYPES (sizeof(xbsd_dktypenames) / sizeof(xbsd_dktypenames[0]) - 1)
602 * Filesystem type and version.
603 * Used to interpret other filesystem-specific
604 * per-partition information.
606 #define BSD_FS_UNUSED 0 /* unused */
607 #define BSD_FS_SWAP 1 /* swap */
608 #define BSD_FS_V6 2 /* Sixth Edition */
609 #define BSD_FS_V7 3 /* Seventh Edition */
610 #define BSD_FS_SYSV 4 /* System V */
611 #define BSD_FS_V71K 5 /* V7 with 1K blocks (4.1, 2.9) */
612 #define BSD_FS_V8 6 /* Eighth Edition, 4K blocks */
613 #define BSD_FS_BSDFFS 7 /* 4.2BSD fast file system */
614 #define BSD_FS_BSDLFS 9 /* 4.4BSD log-structured file system */
615 #define BSD_FS_OTHER 10 /* in use, but unknown/unsupported */
616 #define BSD_FS_HPFS 11 /* OS/2 high-performance file system */
617 #define BSD_FS_ISO9660 12 /* ISO-9660 filesystem (cdrom) */
618 #define BSD_FS_ISOFS BSD_FS_ISO9660
619 #define BSD_FS_BOOT 13 /* partition contains bootstrap */
620 #define BSD_FS_ADOS 14 /* AmigaDOS fast file system */
621 #define BSD_FS_HFS 15 /* Macintosh HFS */
622 #define BSD_FS_ADVFS 16 /* Digital Unix AdvFS */
624 /* this is annoying, but it's also the way it is :-( */
626 #define BSD_FS_EXT2 8 /* ext2 file system */
628 #define BSD_FS_MSDOS 8 /* MS-DOS file system */
632 static const struct systypes xbsd_fstypes[] = {
633 { "\x00" "unused" }, /* BSD_FS_UNUSED */
634 { "\x01" "swap" }, /* BSD_FS_SWAP */
635 { "\x02" "Version 6" }, /* BSD_FS_V6 */
636 { "\x03" "Version 7" }, /* BSD_FS_V7 */
637 { "\x04" "System V" }, /* BSD_FS_SYSV */
638 { "\x05" "4.1BSD" }, /* BSD_FS_V71K */
639 { "\x06" "Eighth Edition" }, /* BSD_FS_V8 */
640 { "\x07" "4.2BSD" }, /* BSD_FS_BSDFFS */
642 { "\x08" "ext2" }, /* BSD_FS_EXT2 */
644 { "\x08" "MS-DOS" }, /* BSD_FS_MSDOS */
646 { "\x09" "4.4LFS" }, /* BSD_FS_BSDLFS */
647 { "\x0a" "unknown" }, /* BSD_FS_OTHER */
648 { "\x0b" "HPFS" }, /* BSD_FS_HPFS */
649 { "\x0c" "ISO-9660" }, /* BSD_FS_ISO9660 */
650 { "\x0d" "boot" }, /* BSD_FS_BOOT */
651 { "\x0e" "ADOS" }, /* BSD_FS_ADOS */
652 { "\x0f" "HFS" }, /* BSD_FS_HFS */
653 { "\x10" "AdvFS" }, /* BSD_FS_ADVFS */
656 #define BSD_FSMAXTYPES (SIZE(xbsd_fstypes)-1)
661 * flags shared by various drives:
663 #define BSD_D_REMOVABLE 0x01 /* removable media */
664 #define BSD_D_ECC 0x02 /* supports ECC */
665 #define BSD_D_BADSECT 0x04 /* supports bad sector forw. */
666 #define BSD_D_RAMDISK 0x08 /* disk emulator */
667 #define BSD_D_CHAIN 0x10 /* can do back-back transfers */
668 #define BSD_D_DOSPART 0x20 /* within MSDOS partition */
670 #endif /* OSF_LABEL */
673 * Copyright (C) Andreas Neuper, Sep 1998.
674 * This file may be modified and redistributed under
675 * the terms of the GNU Public License.
678 struct device_parameter { /* 48 bytes */
682 unsigned char sparecyl;
683 unsigned short pcylcount;
684 unsigned short head_vol0;
685 unsigned short ntrks; /* tracks in cyl 0 or vol 0 */
686 unsigned char cmd_tag_queue_depth;
687 unsigned char unused0;
688 unsigned short unused1;
689 unsigned short nsect; /* sectors/tracks in cyl 0 or vol 0 */
690 unsigned short bytes;
691 unsigned short ilfact;
692 unsigned int flags; /* controller flags */
693 unsigned int datarate;
694 unsigned int retries_on_error;
695 unsigned int ms_per_word;
696 unsigned short xylogics_gap1;
697 unsigned short xylogics_syncdelay;
698 unsigned short xylogics_readdelay;
699 unsigned short xylogics_gap2;
700 unsigned short xylogics_readgate;
701 unsigned short xylogics_writecont;
704 #define SGI_VOLHDR 0x00
705 /* 1 and 2 were used for drive types no longer supported by SGI */
706 #define SGI_SWAP 0x03
707 /* 4 and 5 were for filesystem types SGI haven't ever supported on MIPS CPUs */
708 #define SGI_VOLUME 0x06
710 #define SGI_LVOL 0x08
711 #define SGI_RLVOL 0x09
713 #define SGI_XFSLOG 0x0b
716 #define ENTIRE_DISK SGI_VOLUME
720 #define SECTOR_SLIP 0x01
721 #define SECTOR_FWD 0x02
722 #define TRACK_FWD 0x04
723 #define TRACK_MULTIVOL 0x08
724 #define IGNORE_ERRORS 0x10
726 #define ENABLE_CMDTAGQ 0x40
729 unsigned int magic; /* expect SGI_LABEL_MAGIC */
730 unsigned short boot_part; /* active boot partition */
731 unsigned short swap_part; /* active swap partition */
732 unsigned char boot_file[16]; /* name of the bootfile */
733 struct device_parameter devparam; /* 1 * 48 bytes */
734 struct volume_directory { /* 15 * 16 bytes */
735 unsigned char vol_file_name[8]; /* a character array */
736 unsigned int vol_file_start; /* number of logical block */
737 unsigned int vol_file_size; /* number of bytes */
739 struct sgi_partition { /* 16 * 12 bytes */
740 unsigned int num_sectors; /* number of blocks */
741 unsigned int start_sector; /* must be cylinder aligned */
745 unsigned int fillbytes;
749 unsigned int magic; /* looks like a magic number */
758 unsigned char scsi_string[50];
759 unsigned char serial[137];
760 unsigned short check1816;
761 unsigned char installer[225];
764 #define SGI_LABEL_MAGIC 0x0be5a941
765 #define SGI_LABEL_MAGIC_SWAPPED 0x41a9e50b
766 #define SGI_INFO_MAGIC 0x00072959
767 #define SGI_INFO_MAGIC_SWAPPED 0x59290700
768 #define SGI_SSWAP16(x) (sgi_other_endian ? __swap16(x) \
770 #define SGI_SSWAP32(x) (sgi_other_endian ? __swap32(x) \
773 #define sgilabel ((sgi_partition *)MBRbuffer)
774 #define sgiparam (sgilabel->devparam)
777 unsigned char info[128]; /* Informative text string */
778 unsigned char spare0[14];
780 unsigned char spare1;
782 unsigned char spare2;
785 unsigned char spare1[246]; /* Boot information etc. */
786 unsigned short rspeed; /* Disk rotational speed */
787 unsigned short pcylcount; /* Physical cylinder count */
788 unsigned short sparecyl; /* extra sects per cylinder */
789 unsigned char spare2[4]; /* More magic... */
790 unsigned short ilfact; /* Interleave factor */
791 unsigned short ncyl; /* Data cylinder count */
792 unsigned short nacyl; /* Alt. cylinder count */
793 unsigned short ntrks; /* Tracks per cylinder */
794 unsigned short nsect; /* Sectors per track */
795 unsigned char spare3[4]; /* Even more magic... */
796 struct sun_partition {
797 uint32_t start_cylinder;
798 uint32_t num_sectors;
800 unsigned short magic; /* Magic number */
801 unsigned short csum; /* Label xor'd checksum */
805 #define SUN_LABEL_MAGIC 0xDABE
806 #define SUN_LABEL_MAGIC_SWAPPED 0xBEDA
807 #define sunlabel ((sun_partition *)MBRbuffer)
808 #define SUN_SSWAP16(x) (sun_other_endian ? __swap16(x) \
810 #define SUN_SSWAP32(x) (sun_other_endian ? __swap32(x) \
814 #ifdef CONFIG_FEATURE_OSF_LABEL
817 19990319 - Arnaldo Carvalho de Melo <acme@conectiva.com.br> - i18n/nls
819 20000101 - David Huggins-Daines <dhuggins@linuxcare.com> - Better
820 support for OSF/1 disklabels on Alpha.
821 Also fixed unaligned accesses in alpha_bootblock_checksum()
824 #define FREEBSD_PARTITION 0xa5
825 #define NETBSD_PARTITION 0xa9
827 static void xbsd_delete_part(void);
828 static void xbsd_new_part(void);
829 static void xbsd_write_disklabel(void);
830 static int xbsd_create_disklabel(void);
831 static void xbsd_edit_disklabel(void);
832 static void xbsd_write_bootstrap(void);
833 static void xbsd_change_fstype(void);
834 static int xbsd_get_part_index(int max);
835 static int xbsd_check_new_partition(int *i);
836 static void xbsd_list_types(void);
837 static u_short xbsd_dkcksum(struct xbsd_disklabel *lp);
838 static int xbsd_initlabel(struct partition *p, struct xbsd_disklabel *d);
839 static int xbsd_readlabel(struct partition *p, struct xbsd_disklabel *d);
840 static int xbsd_writelabel(struct partition *p, struct xbsd_disklabel *d);
842 #if defined (__alpha__)
843 static void alpha_bootblock_checksum(char *boot);
846 #if !defined (__alpha__)
847 static int xbsd_translate_fstype(int linux_type);
848 static void xbsd_link_part(void);
849 static struct partition *xbsd_part;
850 static int xbsd_part_index;
853 #if defined (__alpha__)
854 /* We access this through a uint64_t * when checksumming */
855 static char disklabelbuffer[BSD_BBSIZE] ATTRIBUTE_ALIGNED(8);
857 static char disklabelbuffer[BSD_BBSIZE];
860 static struct xbsd_disklabel xbsd_dlabel;
862 #define bsd_cround(n) \
863 (display_in_cyl_units ? ((n)/xbsd_dlabel.d_secpercyl) + 1 : (n))
866 * Test whether the whole disk has BSD disk label magic.
868 * Note: often reformatting with DOS-type label leaves the BSD magic,
869 * so this does not mean that there is a BSD disk label.
872 check_osf_label(void)
874 if (xbsd_readlabel(NULL, &xbsd_dlabel) == 0)
879 static void xbsd_print_disklabel(int);
882 btrydev(const char * dev)
884 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
886 printf(_("\nBSD label for device: %s\n"), dev);
887 xbsd_print_disklabel (0);
894 puts (_("Command action"));
895 puts (_("\td\tdelete a BSD partition"));
896 puts (_("\te\tedit drive data"));
897 puts (_("\ti\tinstall bootstrap"));
898 puts (_("\tl\tlist known filesystem types"));
899 puts (_("\tm\tprint this menu"));
900 puts (_("\tn\tadd a new BSD partition"));
901 puts (_("\tp\tprint BSD partition table"));
902 puts (_("\tq\tquit without saving changes"));
903 puts (_("\tr\treturn to main menu"));
904 puts (_("\ts\tshow complete disklabel"));
905 puts (_("\tt\tchange a partition's filesystem id"));
906 puts (_("\tu\tchange units (cylinders/sectors)"));
907 puts (_("\tw\twrite disklabel to disk"));
908 #if !defined (__alpha__)
909 puts (_("\tx\tlink BSD partition to non-BSD partition"));
913 #if !defined (__alpha__)
921 is_bsd_partition_type(int type)
923 return (type == FREEBSD_PARTITION ||
924 type == hidden(FREEBSD_PARTITION) ||
925 type == NETBSD_PARTITION ||
926 type == hidden(NETBSD_PARTITION));
933 #if !defined (__alpha__)
937 for (t = 0; t < 4; t++) {
938 p = get_part_table(t);
939 if (p && is_bsd_partition_type(p->sys_ind)) {
942 ss = get_start_sect(xbsd_part);
944 fprintf(stderr, _("Partition %s has invalid starting sector 0.\n"),
945 partname(disk_device, t+1, 0));
948 printf(_("Reading disklabel of %s at sector %d.\n"),
949 partname(disk_device, t+1, 0), ss + BSD_LABELSECTOR);
950 if (xbsd_readlabel(xbsd_part, &xbsd_dlabel) == 0)
951 if (xbsd_create_disklabel() == 0)
958 printf(_("There is no *BSD partition on %s.\n"), disk_device);
962 #elif defined (__alpha__)
964 if (xbsd_readlabel(NULL, &xbsd_dlabel) == 0)
965 if (xbsd_create_disklabel() == 0)
972 switch (tolower(read_char(_("BSD disklabel command (m for help): ")))) {
977 xbsd_edit_disklabel();
980 xbsd_write_bootstrap();
989 xbsd_print_disklabel(0);
997 xbsd_print_disklabel(1);
1000 xbsd_change_fstype();
1006 xbsd_write_disklabel();
1008 #if !defined (__alpha__)
1021 xbsd_delete_part(void)
1025 i = xbsd_get_part_index(xbsd_dlabel.d_npartitions);
1026 xbsd_dlabel.d_partitions[i].p_size = 0;
1027 xbsd_dlabel.d_partitions[i].p_offset = 0;
1028 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
1029 if (xbsd_dlabel.d_npartitions == i + 1)
1030 while (xbsd_dlabel.d_partitions[xbsd_dlabel.d_npartitions-1].p_size == 0)
1031 xbsd_dlabel.d_npartitions--;
1041 if (!xbsd_check_new_partition(&i))
1044 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
1045 begin = get_start_sect(xbsd_part);
1046 end = begin + get_nr_sects(xbsd_part) - 1;
1049 end = xbsd_dlabel.d_secperunit - 1;
1052 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
1053 begin = read_int(bsd_cround(begin), bsd_cround(begin), bsd_cround(end),
1056 if (display_in_cyl_units)
1057 begin = (begin - 1) * xbsd_dlabel.d_secpercyl;
1059 snprintf(mesg, sizeof(mesg), _("Last %s or +size or +sizeM or +sizeK"),
1060 str_units(SINGULAR));
1061 end = read_int(bsd_cround (begin), bsd_cround (end), bsd_cround (end),
1062 bsd_cround (begin), mesg);
1064 if (display_in_cyl_units)
1065 end = end * xbsd_dlabel.d_secpercyl - 1;
1067 xbsd_dlabel.d_partitions[i].p_size = end - begin + 1;
1068 xbsd_dlabel.d_partitions[i].p_offset = begin;
1069 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
1073 xbsd_print_disklabel(int show_all)
1075 struct xbsd_disklabel *lp = &xbsd_dlabel;
1076 struct xbsd_partition *pp;
1080 #if defined (__alpha__)
1081 printf("# %s:\n", disk_device);
1083 printf("# %s:\n", partname(disk_device, xbsd_part_index+1, 0));
1085 if ((unsigned) lp->d_type < BSD_DKMAXTYPES)
1086 printf(_("type: %s\n"), xbsd_dktypenames[lp->d_type]);
1088 printf(_("type: %d\n"), lp->d_type);
1089 printf(_("disk: %.*s\n"), (int) sizeof(lp->d_typename), lp->d_typename);
1090 printf(_("label: %.*s\n"), (int) sizeof(lp->d_packname), lp->d_packname);
1091 printf(_("flags:"));
1092 if (lp->d_flags & BSD_D_REMOVABLE)
1093 printf(_(" removable"));
1094 if (lp->d_flags & BSD_D_ECC)
1096 if (lp->d_flags & BSD_D_BADSECT)
1097 printf(_(" badsect"));
1099 /* On various machines the fields of *lp are short/int/long */
1100 /* In order to avoid problems, we cast them all to long. */
1101 printf(_("bytes/sector: %ld\n"), (long) lp->d_secsize);
1102 printf(_("sectors/track: %ld\n"), (long) lp->d_nsectors);
1103 printf(_("tracks/cylinder: %ld\n"), (long) lp->d_ntracks);
1104 printf(_("sectors/cylinder: %ld\n"), (long) lp->d_secpercyl);
1105 printf(_("cylinders: %ld\n"), (long) lp->d_ncylinders);
1106 printf(_("rpm: %d\n"), lp->d_rpm);
1107 printf(_("interleave: %d\n"), lp->d_interleave);
1108 printf(_("trackskew: %d\n"), lp->d_trackskew);
1109 printf(_("cylinderskew: %d\n"), lp->d_cylskew);
1110 printf(_("headswitch: %ld\t\t# milliseconds\n"),
1111 (long) lp->d_headswitch);
1112 printf(_("track-to-track seek: %ld\t# milliseconds\n"),
1113 (long) lp->d_trkseek);
1114 printf(_("drivedata: "));
1115 for (i = NDDATA - 1; i >= 0; i--)
1116 if (lp->d_drivedata[i])
1120 for (j = 0; j <= i; j++)
1121 printf("%ld ", (long) lp->d_drivedata[j]);
1123 printf(_("\n%d partitions:\n"), lp->d_npartitions);
1124 printf(_("# start end size fstype [fsize bsize cpg]\n"));
1125 pp = lp->d_partitions;
1126 for (i = 0; i < lp->d_npartitions; i++, pp++) {
1128 if (display_in_cyl_units && lp->d_secpercyl) {
1129 printf(" %c: %8ld%c %8ld%c %8ld%c ",
1131 (long) pp->p_offset / lp->d_secpercyl + 1,
1132 (pp->p_offset % lp->d_secpercyl) ? '*' : ' ',
1133 (long) (pp->p_offset + pp->p_size + lp->d_secpercyl - 1) / lp->d_secpercyl,
1134 ((pp->p_offset + pp->p_size) % lp->d_secpercyl) ? '*' : ' ',
1135 (long) pp->p_size / lp->d_secpercyl,
1136 (pp->p_size % lp->d_secpercyl) ? '*' : ' '
1139 printf(" %c: %8ld %8ld %8ld ",
1141 (long) pp->p_offset,
1142 (long) pp->p_offset + pp->p_size - 1,
1147 if ((unsigned) pp->p_fstype < BSD_FSMAXTYPES)
1148 printf("%8.8s", xbsd_fstypes[pp->p_fstype].name);
1150 printf("%8x", pp->p_fstype);
1152 switch (pp->p_fstype) {
1154 printf(" %5ld %5ld %5.5s ",
1155 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, "");
1158 printf(" %5ld %5ld %5d ",
1159 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, pp->p_cpg);
1162 printf("%22.22s", "");
1171 xbsd_write_disklabel(void)
1173 #if defined (__alpha__)
1174 printf(_("Writing disklabel to %s.\n"), disk_device);
1175 xbsd_writelabel(NULL, &xbsd_dlabel);
1177 printf(_("Writing disklabel to %s.\n"),
1178 partname(disk_device, xbsd_part_index + 1, 0));
1179 xbsd_writelabel(xbsd_part, &xbsd_dlabel);
1181 reread_partition_table(0); /* no exit yet */
1185 xbsd_create_disklabel(void)
1189 #if defined (__alpha__)
1190 fprintf(stderr, _("%s contains no disklabel.\n"), disk_device);
1192 fprintf(stderr, _("%s contains no disklabel.\n"),
1193 partname(disk_device, xbsd_part_index + 1, 0));
1197 c = read_char(_("Do you want to create a disklabel? (y/n) "));
1198 if (c == 'y' || c == 'Y') {
1200 #if defined (__alpha__) || defined (__powerpc__) || defined (__hppa__) || \
1201 defined (__s390__) || defined (__s390x__)
1204 xbsd_part, &xbsd_dlabel/* not used, xbsd_part_index*/
1207 xbsd_print_disklabel (1);
1211 } else if (c == 'n')
1217 edit_int(int def, char *mesg)
1220 fputs(mesg, stdout);
1221 printf(" (%d): ", def);
1225 while (!isdigit(*line_ptr)); /* FIXME: ?!! */
1226 return atoi(line_ptr);
1230 xbsd_edit_disklabel(void)
1232 struct xbsd_disklabel *d;
1236 #if defined (__alpha__) || defined (__ia64__)
1237 d->d_secsize = (u_long) edit_int((u_long) d->d_secsize ,_("bytes/sector"));
1238 d->d_nsectors = (u_long) edit_int((u_long) d->d_nsectors ,_("sectors/track"));
1239 d->d_ntracks = (u_long) edit_int((u_long) d->d_ntracks ,_("tracks/cylinder"));
1240 d->d_ncylinders = (u_long) edit_int((u_long) d->d_ncylinders ,_("cylinders"));
1243 /* d->d_secpercyl can be != d->d_nsectors * d->d_ntracks */
1245 d->d_secpercyl = (u_long) edit_int((u_long) d->d_nsectors * d->d_ntracks,
1246 _("sectors/cylinder"));
1247 if (d->d_secpercyl <= d->d_nsectors * d->d_ntracks)
1250 printf(_("Must be <= sectors/track * tracks/cylinder (default).\n"));
1252 d->d_rpm = (u_short) edit_int((u_short) d->d_rpm ,_("rpm"));
1253 d->d_interleave = (u_short) edit_int((u_short) d->d_interleave,_("interleave"));
1254 d->d_trackskew = (u_short) edit_int((u_short) d->d_trackskew ,_("trackskew"));
1255 d->d_cylskew = (u_short) edit_int((u_short) d->d_cylskew ,_("cylinderskew"));
1256 d->d_headswitch = (u_long) edit_int((u_long) d->d_headswitch ,_("headswitch"));
1257 d->d_trkseek = (u_long) edit_int((u_long) d->d_trkseek ,_("track-to-track seek"));
1259 d->d_secperunit = d->d_secpercyl * d->d_ncylinders;
1263 xbsd_get_bootstrap (char *path, void *ptr, int size)
1267 if ((fdb = open (path, O_RDONLY)) < 0) {
1271 if (read(fdb, ptr, size) < 0) {
1276 printf(" ... %s\n", path);
1284 printf(_("\nSyncing disks.\n"));
1286 sleep(4); /* What? */
1290 xbsd_write_bootstrap(void)
1292 char *bootdir = BSD_LINUX_BOOTDIR;
1293 char path[MAXPATHLEN];
1295 struct xbsd_disklabel dl;
1299 if (xbsd_dlabel.d_type == BSD_DTYPE_SCSI)
1304 printf(_("Bootstrap: %sboot -> boot%s (%s): "),
1305 dkbasename, dkbasename, dkbasename);
1307 line_ptr[strlen(line_ptr)-1] = '\0';
1308 dkbasename = line_ptr;
1310 snprintf(path, sizeof(path), "%s/%sboot", bootdir, dkbasename);
1311 if (!xbsd_get_bootstrap(path, disklabelbuffer, (int) xbsd_dlabel.d_secsize))
1314 /* We need a backup of the disklabel (xbsd_dlabel might have changed). */
1315 d = &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE];
1316 memmove(&dl, d, sizeof(struct xbsd_disklabel));
1318 /* The disklabel will be overwritten by 0's from bootxx anyway */
1319 memset(d, 0, sizeof(struct xbsd_disklabel));
1321 snprintf(path, sizeof(path), "%s/boot%s", bootdir, dkbasename);
1322 if (!xbsd_get_bootstrap (path, &disklabelbuffer[xbsd_dlabel.d_secsize],
1323 (int) xbsd_dlabel.d_bbsize - xbsd_dlabel.d_secsize))
1326 e = d + sizeof(struct xbsd_disklabel);
1327 for (p = d; p < e; p++)
1329 fprintf(stderr, _("Bootstrap overlaps with disk label!\n"));
1333 memmove(d, &dl, sizeof(struct xbsd_disklabel));
1335 #if defined (__powerpc__) || defined (__hppa__)
1337 #elif defined (__alpha__)
1339 alpha_bootblock_checksum(disklabelbuffer);
1341 sector = get_start_sect(xbsd_part);
1344 if (lseek(fd, sector * SECTOR_SIZE, SEEK_SET) == -1)
1345 fdisk_fatal(unable_to_seek);
1346 if (BSD_BBSIZE != write(fd, disklabelbuffer, BSD_BBSIZE))
1347 fdisk_fatal(unable_to_write);
1349 #if defined (__alpha__)
1350 printf(_("Bootstrap installed on %s.\n"), disk_device);
1352 printf(_("Bootstrap installed on %s.\n"),
1353 partname (disk_device, xbsd_part_index+1, 0));
1360 xbsd_change_fstype(void)
1364 i = xbsd_get_part_index(xbsd_dlabel.d_npartitions);
1365 xbsd_dlabel.d_partitions[i].p_fstype = read_hex(xbsd_fstypes);
1369 xbsd_get_part_index(int max)
1374 snprintf(prompt, sizeof(prompt), _("Partition (a-%c): "), 'a' + max - 1);
1376 l = tolower(read_char(prompt));
1377 while (l < 'a' || l > 'a' + max - 1);
1382 xbsd_check_new_partition(int *i)
1384 /* room for more? various BSD flavours have different maxima */
1385 if (xbsd_dlabel.d_npartitions == BSD_MAXPARTITIONS) {
1388 for (t = 0; t < BSD_MAXPARTITIONS; t++)
1389 if (xbsd_dlabel.d_partitions[t].p_size == 0)
1392 if (t == BSD_MAXPARTITIONS) {
1393 fprintf(stderr, _("The maximum number of partitions "
1394 "has been created\n"));
1399 *i = xbsd_get_part_index (BSD_MAXPARTITIONS);
1401 if (*i >= xbsd_dlabel.d_npartitions)
1402 xbsd_dlabel.d_npartitions = (*i) + 1;
1404 if (xbsd_dlabel.d_partitions[*i].p_size != 0) {
1405 fprintf(stderr, _("This partition already exists.\n"));
1413 xbsd_list_types(void)
1415 list_types(xbsd_fstypes);
1419 xbsd_dkcksum(struct xbsd_disklabel *lp)
1421 u_short *start, *end;
1424 start = (u_short *) lp;
1425 end = (u_short *) &lp->d_partitions[lp->d_npartitions];
1432 xbsd_initlabel(struct partition *p, struct xbsd_disklabel *d)
1434 struct xbsd_partition *pp;
1437 memset(d, 0, sizeof(struct xbsd_disklabel));
1439 d->d_magic = BSD_DISKMAGIC;
1441 if (strncmp(disk_device, "/dev/sd", 7) == 0)
1442 d->d_type = BSD_DTYPE_SCSI;
1444 d->d_type = BSD_DTYPE_ST506;
1446 #if 0 /* not used (at least not written to disk) by NetBSD/i386 1.0 */
1447 d->d_subtype = BSD_DSTYPE_INDOSPART & pindex;
1450 #if !defined (__alpha__)
1451 d->d_flags = BSD_D_DOSPART;
1455 d->d_secsize = SECTOR_SIZE; /* bytes/sector */
1456 d->d_nsectors = sectors; /* sectors/track */
1457 d->d_ntracks = heads; /* tracks/cylinder (heads) */
1458 d->d_ncylinders = cylinders;
1459 d->d_secpercyl = sectors * heads;/* sectors/cylinder */
1460 if (d->d_secpercyl == 0)
1461 d->d_secpercyl = 1; /* avoid segfaults */
1462 d->d_secperunit = d->d_secpercyl * d->d_ncylinders;
1465 d->d_interleave = 1;
1468 d->d_headswitch = 0;
1471 d->d_magic2 = BSD_DISKMAGIC;
1472 d->d_bbsize = BSD_BBSIZE;
1473 d->d_sbsize = BSD_SBSIZE;
1475 #if !defined (__alpha__)
1476 d->d_npartitions = 4;
1477 pp = &d->d_partitions[2]; /* Partition C should be
1478 the NetBSD partition */
1479 pp->p_offset = get_start_sect(p);
1480 pp->p_size = get_nr_sects(p);
1481 pp->p_fstype = BSD_FS_UNUSED;
1482 pp = &d->d_partitions[3]; /* Partition D should be
1485 pp->p_size = d->d_secperunit;
1486 pp->p_fstype = BSD_FS_UNUSED;
1487 #elif defined (__alpha__)
1488 d->d_npartitions = 3;
1489 pp = &d->d_partitions[2]; /* Partition C should be
1492 pp->p_size = d->d_secperunit;
1493 pp->p_fstype = BSD_FS_UNUSED;
1500 * Read a xbsd_disklabel from sector 0 or from the starting sector of p.
1501 * If it has the right magic, return 1.
1504 xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d)
1508 /* p is used only to get the starting sector */
1509 #if !defined (__alpha__)
1510 sector = (p ? get_start_sect(p) : 0);
1511 #elif defined (__alpha__)
1515 if (lseek(fd, sector * SECTOR_SIZE, SEEK_SET) == -1)
1516 fdisk_fatal(unable_to_seek);
1517 if (BSD_BBSIZE != read(fd, disklabelbuffer, BSD_BBSIZE))
1518 fdisk_fatal(unable_to_read);
1520 memmove(d, &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
1521 sizeof(struct xbsd_disklabel));
1523 if (d->d_magic != BSD_DISKMAGIC || d->d_magic2 != BSD_DISKMAGIC)
1526 for (t = d->d_npartitions; t < BSD_MAXPARTITIONS; t++) {
1527 d->d_partitions[t].p_size = 0;
1528 d->d_partitions[t].p_offset = 0;
1529 d->d_partitions[t].p_fstype = BSD_FS_UNUSED;
1532 if (d->d_npartitions > BSD_MAXPARTITIONS)
1533 fprintf(stderr, _("Warning: too many partitions "
1534 "(%d, maximum is %d).\n"),
1535 d->d_npartitions, BSD_MAXPARTITIONS);
1540 xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d)
1542 unsigned int sector;
1544 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
1545 sector = get_start_sect(p) + BSD_LABELSECTOR;
1547 sector = BSD_LABELSECTOR;
1551 d->d_checksum = xbsd_dkcksum (d);
1553 /* This is necessary if we want to write the bootstrap later,
1554 otherwise we'd write the old disklabel with the bootstrap.
1556 memmove(&disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
1557 d, sizeof(struct xbsd_disklabel));
1559 #if defined (__alpha__) && BSD_LABELSECTOR == 0
1560 alpha_bootblock_checksum (disklabelbuffer);
1561 if (lseek(fd, 0, SEEK_SET) == -1)
1562 fdisk_fatal(unable_to_seek);
1563 if (BSD_BBSIZE != write(fd, disklabelbuffer, BSD_BBSIZE))
1564 fdisk_fatal(unable_to_write);
1566 if (lseek(fd, sector * SECTOR_SIZE + BSD_LABELOFFSET, SEEK_SET) == -1)
1567 fdisk_fatal(unable_to_seek);
1568 if (sizeof(struct xbsd_disklabel) != write(fd, d, sizeof(struct xbsd_disklabel)))
1569 fdisk_fatal(unable_to_write);
1576 #if !defined (__alpha__)
1578 xbsd_translate_fstype(int linux_type)
1580 switch (linux_type) {
1581 case 0x01: /* DOS 12-bit FAT */
1582 case 0x04: /* DOS 16-bit <32M */
1583 case 0x06: /* DOS 16-bit >=32M */
1584 case 0xe1: /* DOS access */
1585 case 0xe3: /* DOS R/O */
1586 case 0xf2: /* DOS secondary */
1587 return BSD_FS_MSDOS;
1588 case 0x07: /* OS/2 HPFS */
1591 return BSD_FS_OTHER;
1596 xbsd_link_part(void)
1599 struct partition *p;
1601 k = get_partition(1, partitions);
1603 if (!xbsd_check_new_partition(&i))
1606 p = get_part_table(k);
1608 xbsd_dlabel.d_partitions[i].p_size = get_nr_sects(p);
1609 xbsd_dlabel.d_partitions[i].p_offset = get_start_sect(p);
1610 xbsd_dlabel.d_partitions[i].p_fstype = xbsd_translate_fstype(p->sys_ind);
1614 #if defined (__alpha__)
1616 #if !defined(__GLIBC__)
1617 typedef unsigned long long uint64_t;
1621 alpha_bootblock_checksum(char *boot)
1626 dp = (uint64_t *)boot;
1628 for (i = 0; i < 63; i++)
1632 #endif /* __alpha__ */
1634 #endif /* OSF_LABEL */
1636 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
1637 static inline unsigned short
1638 __swap16(unsigned short x)
1640 return (((uint16_t)(x) & 0xFF) << 8) | (((uint16_t)(x) & 0xFF00) >> 8);
1643 static inline uint32_t
1644 __swap32(uint32_t x)
1646 return (((x & 0xFF) << 24) |
1647 ((x & 0xFF00) << 8) |
1648 ((x & 0xFF0000) >> 8) |
1649 ((x & 0xFF000000) >> 24));
1653 #ifdef CONFIG_FEATURE_SGI_LABEL
1658 * Copyright (C) Andreas Neuper, Sep 1998.
1659 * This file may be modified and redistributed under
1660 * the terms of the GNU Public License.
1662 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
1663 * Internationalization
1667 static int sgi_other_endian;
1669 static short sgi_volumes = 1;
1672 * only dealing with free blocks here
1679 static freeblocks freelist[17]; /* 16 partitions can produce 17 vacant slots */
1682 setfreelist(int i, unsigned int f, unsigned int l)
1684 freelist[i].first = f;
1685 freelist[i].last = l;
1689 add2freelist(unsigned int f, unsigned int l)
1692 for (i = 0; i < 17 ; i++)
1693 if (freelist[i].last == 0)
1695 setfreelist(i, f, l);
1703 for (i = 0; i < 17 ; i++)
1704 setfreelist(i, 0, 0);
1708 isinfreelist(unsigned int b)
1712 for (i = 0; i < 17 ; i++)
1713 if (freelist[i].first <= b && freelist[i].last >= b)
1714 return freelist[i].last;
1717 /* return last vacant block of this stride (never 0). */
1718 /* the '>=' is not quite correct, but simplifies the code */
1720 * end of free blocks section
1723 static const struct systypes sgi_sys_types[] = {
1724 /* SGI_VOLHDR */ { "\x00" "SGI volhdr" },
1725 /* 0x01 */ { "\x01" "SGI trkrepl" },
1726 /* 0x02 */ { "\x02" "SGI secrepl" },
1727 /* SGI_SWAP */ { "\x03" "SGI raw" },
1728 /* 0x04 */ { "\x04" "SGI bsd" },
1729 /* 0x05 */ { "\x05" "SGI sysv" },
1730 /* ENTIRE_DISK */ { "\x06" "SGI volume" },
1731 /* SGI_EFS */ { "\x07" "SGI efs" },
1732 /* 0x08 */ { "\x08" "SGI lvol" },
1733 /* 0x09 */ { "\x09" "SGI rlvol" },
1734 /* SGI_XFS */ { "\x0a" "SGI xfs" },
1735 /* SGI_XFSLOG */ { "\x0b" "SGI xfslog" },
1736 /* SGI_XLV */ { "\x0c" "SGI xlv" },
1737 /* SGI_XVM */ { "\x0d" "SGI xvm" },
1738 /* LINUX_SWAP */ { "\x82" "Linux swap" },
1739 /* LINUX_NATIVE */ { "\x83" "Linux native" },
1740 /* LINUX_LVM */ { "\x8d" "Linux LVM" },
1741 /* LINUX_RAID */ { "\xfd" "Linux RAID" },
1749 return SGI_SSWAP16(sgilabel->devparam.nsect);
1755 return SGI_SSWAP16(sgilabel->devparam.ntrks);
1759 two_s_complement_32bit_sum(unsigned int* base, int size /* in bytes */)
1762 unsigned int sum = 0;
1764 size /= sizeof(unsigned int);
1765 for (i = 0; i < size; i++)
1766 sum -= SGI_SSWAP32(base[i]);
1771 check_sgi_label(void)
1773 if (sizeof(sgilabel) > 512) {
1775 _("According to MIPS Computer Systems, Inc the "
1776 "Label must not contain more than 512 bytes\n"));
1780 if (sgilabel->magic != SGI_LABEL_MAGIC
1781 && sgilabel->magic != SGI_LABEL_MAGIC_SWAPPED) {
1782 current_label_type = label_dos;
1786 sgi_other_endian = (sgilabel->magic == SGI_LABEL_MAGIC_SWAPPED);
1788 * test for correct checksum
1790 if (two_s_complement_32bit_sum((unsigned int*)sgilabel,
1791 sizeof(*sgilabel))) {
1793 _("Detected sgi disklabel with wrong checksum.\n"));
1796 current_label_type = label_sgi;
1803 sgi_get_start_sector(int i)
1805 return SGI_SSWAP32(sgilabel->partitions[i].start_sector);
1809 sgi_get_num_sectors(int i)
1811 return SGI_SSWAP32(sgilabel->partitions[i].num_sectors);
1815 sgi_get_sysid(int i)
1817 return SGI_SSWAP32(sgilabel->partitions[i].id);
1821 sgi_get_bootpartition(void)
1823 return SGI_SSWAP16(sgilabel->boot_part);
1827 sgi_get_swappartition(void)
1829 return SGI_SSWAP16(sgilabel->swap_part);
1833 sgi_list_table(int xtra)
1836 int kpi = 0; /* kernel partition ID */
1839 printf(_("\nDisk %s (SGI disk label): %d heads, %d sectors\n"
1840 "%d cylinders, %d physical cylinders\n"
1841 "%d extra sects/cyl, interleave %d:1\n"
1843 "Units = %s of %d * 512 bytes\n\n"),
1844 disk_device, heads, sectors, cylinders,
1845 SGI_SSWAP16(sgiparam.pcylcount),
1846 SGI_SSWAP16(sgiparam.sparecyl),
1847 SGI_SSWAP16(sgiparam.ilfact),
1849 str_units(PLURAL), units_per_sector);
1851 printf( _("\nDisk %s (SGI disk label): "
1852 "%d heads, %d sectors, %d cylinders\n"
1853 "Units = %s of %d * 512 bytes\n\n"),
1854 disk_device, heads, sectors, cylinders,
1855 str_units(PLURAL), units_per_sector );
1858 w = strlen(disk_device);
1859 wd = strlen(_("Device"));
1863 printf(_("----- partitions -----\n"
1864 "Pt# %*s Info Start End Sectors Id System\n"),
1865 w + 2, _("Device"));
1866 for (i = 0 ; i < partitions; i++) {
1867 if( sgi_get_num_sectors(i) || debug ) {
1868 uint32_t start = sgi_get_start_sector(i);
1869 uint32_t len = sgi_get_num_sectors(i);
1870 kpi++; /* only count nonempty partitions */
1872 "%2d: %s %4s %9ld %9ld %9ld %2x %s\n",
1873 /* fdisk part number */ i+1,
1874 /* device */ partname(disk_device, kpi, w+3),
1875 /* flags */ (sgi_get_swappartition() == i) ? "swap" :
1876 /* flags */ (sgi_get_bootpartition() == i) ? "boot" : " ",
1877 /* start */ (long) scround(start),
1878 /* end */ (long) scround(start+len)-1,
1879 /* no odd flag on end */(long) len,
1880 /* type id */ sgi_get_sysid(i),
1881 /* type name */ partition_type(sgi_get_sysid(i)));
1884 printf(_("----- Bootinfo -----\nBootfile: %s\n"
1885 "----- Directory Entries -----\n"),
1886 sgilabel->boot_file);
1887 for (i = 0 ; i < sgi_volumes; i++) {
1888 if (sgilabel->directory[i].vol_file_size) {
1889 uint32_t start = SGI_SSWAP32(sgilabel->directory[i].vol_file_start);
1890 uint32_t len = SGI_SSWAP32(sgilabel->directory[i].vol_file_size);
1891 unsigned char *name = sgilabel->directory[i].vol_file_name;
1893 printf(_("%2d: %-10s sector%5u size%8u\n"),
1894 i, (char*)name, (unsigned int) start, (unsigned int) len);
1900 sgi_set_bootpartition(int i)
1902 sgilabel->boot_part = SGI_SSWAP16(((short)i));
1906 sgi_get_lastblock(void)
1908 return heads * sectors * cylinders;
1912 sgi_set_swappartition(int i)
1914 sgilabel->swap_part = SGI_SSWAP16(((short)i));
1918 sgi_check_bootfile(const char* aFile)
1920 if (strlen(aFile) < 3) /* "/a\n" is minimum */ {
1921 printf(_("\nInvalid Bootfile!\n"
1922 "\tThe bootfile must be an absolute non-zero pathname,\n"
1923 "\te.g. \"/unix\" or \"/unix.save\".\n"));
1926 if (strlen(aFile) > 16) {
1927 printf(_("\n\tName of Bootfile too long: "
1928 "16 bytes maximum.\n"));
1931 if (aFile[0] != '/') {
1932 printf(_("\n\tBootfile must have a "
1933 "fully qualified pathname.\n"));
1938 if (strncmp(aFile, (char*)sgilabel->boot_file, 16)) {
1939 printf(_("\n\tBe aware, that the bootfile is not checked for existence.\n\t"
1940 "SGI's default is \"/unix\" and for backup \"/unix.save\".\n"));
1941 /* filename is correct and did change */
1944 return 0; /* filename did not change */
1948 sgi_get_bootfile(void)
1950 return (char*)sgilabel->boot_file;
1954 sgi_set_bootfile(const char* aFile)
1958 if (sgi_check_bootfile(aFile)) {
1960 if ((aFile[i] != '\n') /* in principle caught again by next line */
1961 && (strlen(aFile) > i))
1962 sgilabel->boot_file[i] = aFile[i];
1964 sgilabel->boot_file[i] = 0;
1967 printf(_("\n\tBootfile is changed to \"%s\".\n"), sgilabel->boot_file);
1972 create_sgiinfo(void)
1974 /* I keep SGI's habit to write the sgilabel to the second block */
1975 sgilabel->directory[0].vol_file_start = SGI_SSWAP32(2);
1976 sgilabel->directory[0].vol_file_size = SGI_SSWAP32(sizeof(sgiinfo));
1977 strcpy((char*)sgilabel->directory[0].vol_file_name, "sgilabel");
1980 static sgiinfo *fill_sgiinfo(void);
1983 sgi_write_table(void)
1986 sgilabel->csum = SGI_SSWAP32(two_s_complement_32bit_sum(
1987 (unsigned int*)sgilabel, sizeof(*sgilabel)));
1988 assert(two_s_complement_32bit_sum(
1989 (unsigned int*)sgilabel, sizeof(*sgilabel)) == 0);
1991 if (lseek(fd, 0, SEEK_SET) < 0)
1992 fdisk_fatal(unable_to_seek);
1993 if (write(fd, sgilabel, SECTOR_SIZE) != SECTOR_SIZE)
1994 fdisk_fatal(unable_to_write);
1995 if (!strncmp((char*)sgilabel->directory[0].vol_file_name, "sgilabel", 8)) {
1997 * keep this habit of first writing the "sgilabel".
1998 * I never tested whether it works without (AN 981002).
2000 sgiinfo *info = fill_sgiinfo();
2001 int infostartblock = SGI_SSWAP32(sgilabel->directory[0].vol_file_start);
2002 if (lseek(fd, infostartblock*SECTOR_SIZE, SEEK_SET) < 0)
2003 fdisk_fatal(unable_to_seek);
2004 if (write(fd, info, SECTOR_SIZE) != SECTOR_SIZE)
2005 fdisk_fatal(unable_to_write);
2011 compare_start(int *x, int *y)
2014 * sort according to start sectors
2015 * and prefers largest partition:
2016 * entry zero is entire disk entry
2018 unsigned int i = *x;
2019 unsigned int j = *y;
2020 unsigned int a = sgi_get_start_sector(i);
2021 unsigned int b = sgi_get_start_sector(j);
2022 unsigned int c = sgi_get_num_sectors(i);
2023 unsigned int d = sgi_get_num_sectors(j);
2026 return (d > c) ? 1 : (d == c) ? 0 : -1;
2027 return (a > b) ? 1 : -1;
2032 verify_sgi(int verbose)
2034 int Index[16]; /* list of valid partitions */
2035 int sortcount = 0; /* number of used partitions, i.e. non-zero lengths */
2036 int entire = 0, i = 0;
2037 unsigned int start = 0;
2038 long long gap = 0; /* count unused blocks */
2039 unsigned int lastblock = sgi_get_lastblock();
2042 for (i = 0; i < 16; i++) {
2043 if (sgi_get_num_sectors(i) != 0) {
2044 Index[sortcount++] = i;
2045 if (sgi_get_sysid(i) == ENTIRE_DISK) {
2046 if (entire++ == 1) {
2048 printf(_("More than one entire disk entry present.\n"));
2053 if (sortcount == 0) {
2055 printf(_("No partitions defined\n"));
2056 return (lastblock > 0) ? 1 : (lastblock == 0) ? 0 : -1;
2058 qsort(Index, sortcount, sizeof(Index[0]), (void*)compare_start);
2059 if (sgi_get_sysid(Index[0]) == ENTIRE_DISK) {
2060 if ((Index[0] != 10) && verbose)
2061 printf(_("IRIX likes when Partition 11 covers the entire disk.\n"));
2062 if ((sgi_get_start_sector(Index[0]) != 0) && verbose)
2063 printf(_("The entire disk partition should start "
2065 "not at diskblock %d.\n"),
2066 sgi_get_start_sector(Index[0]));
2067 if (debug) /* I do not understand how some disks fulfil it */
2068 if ((sgi_get_num_sectors(Index[0]) != lastblock) && verbose)
2069 printf(_("The entire disk partition is only %d diskblock large,\n"
2070 "but the disk is %d diskblocks long.\n"),
2071 sgi_get_num_sectors(Index[0]), lastblock);
2072 lastblock = sgi_get_num_sectors(Index[0]);
2075 printf(_("One Partition (#11) should cover the entire disk.\n"));
2077 printf("sysid=%d\tpartition=%d\n",
2078 sgi_get_sysid(Index[0]), Index[0]+1);
2080 for (i = 1, start = 0; i < sortcount; i++) {
2081 int cylsize = sgi_get_nsect() * sgi_get_ntrks();
2083 if ((sgi_get_start_sector(Index[i]) % cylsize) != 0) {
2084 if (debug) /* I do not understand how some disks fulfil it */
2086 printf(_("Partition %d does not start on cylinder boundary.\n"),
2089 if (sgi_get_num_sectors(Index[i]) % cylsize != 0) {
2090 if (debug) /* I do not understand how some disks fulfil it */
2092 printf(_("Partition %d does not end on cylinder boundary.\n"),
2095 /* We cannot handle several "entire disk" entries. */
2096 if (sgi_get_sysid(Index[i]) == ENTIRE_DISK) continue;
2097 if (start > sgi_get_start_sector(Index[i])) {
2099 printf(_("The Partition %d and %d overlap by %d sectors.\n"),
2100 Index[i-1]+1, Index[i]+1,
2101 start - sgi_get_start_sector(Index[i]));
2102 if (gap > 0) gap = -gap;
2103 if (gap == 0) gap = -1;
2105 if (start < sgi_get_start_sector(Index[i])) {
2107 printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"),
2108 sgi_get_start_sector(Index[i]) - start,
2109 start, sgi_get_start_sector(Index[i])-1);
2110 gap += sgi_get_start_sector(Index[i]) - start;
2111 add2freelist(start, sgi_get_start_sector(Index[i]));
2113 start = sgi_get_start_sector(Index[i])
2114 + sgi_get_num_sectors(Index[i]);
2117 printf("%2d:%12d\t%12d\t%12d\n", Index[i],
2118 sgi_get_start_sector(Index[i]),
2119 sgi_get_num_sectors(Index[i]),
2120 sgi_get_sysid(Index[i]));
2123 if (start < lastblock) {
2125 printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"),
2126 lastblock - start, start, lastblock-1);
2127 gap += lastblock - start;
2128 add2freelist(start, lastblock);
2131 * Done with arithmetics
2132 * Go for details now
2135 if (!sgi_get_num_sectors(sgi_get_bootpartition())) {
2136 printf(_("\nThe boot partition does not exist.\n"));
2138 if (!sgi_get_num_sectors(sgi_get_swappartition())) {
2139 printf(_("\nThe swap partition does not exist.\n"));
2141 if ((sgi_get_sysid(sgi_get_swappartition()) != SGI_SWAP)
2142 && (sgi_get_sysid(sgi_get_swappartition()) != LINUX_SWAP))
2143 printf(_("\nThe swap partition has no swap type.\n"));
2145 if (sgi_check_bootfile("/unix"))
2146 printf(_("\tYou have chosen an unusual boot file name.\n"));
2148 return (gap > 0) ? 1 : (gap == 0) ? 0 : -1;
2155 * returned value is:
2156 * = 0 : disk is properly filled to the rim
2157 * < 0 : there is an overlap
2158 * > 0 : there is still some vacant space
2160 return verify_sgi(0);
2164 sgi_change_sysid(int i, int sys)
2166 if( sgi_get_num_sectors(i) == 0 ) { /* caught already before, ... */
2167 printf(_("Sorry You may change the Tag of non-empty partitions.\n"));
2170 if (((sys != ENTIRE_DISK ) && (sys != SGI_VOLHDR))
2171 && (sgi_get_start_sector(i) < 1) ) {
2173 _("It is highly recommended that the partition at offset 0\n"
2174 "is of type \"SGI volhdr\", the IRIX system will rely on it to\n"
2175 "retrieve from its directory standalone tools like sash and fx.\n"
2176 "Only the \"SGI volume\" entire disk section may violate this.\n"
2177 "Type YES if you are sure about tagging this partition differently.\n"));
2178 if (strcmp(line_ptr, _("YES\n")))
2181 sgilabel->partitions[i].id = SGI_SSWAP32(sys);
2184 /* returns partition index of first entry marked as entire disk */
2190 for (i = 0; i < 16; i++)
2191 if (sgi_get_sysid(i) == SGI_VOLUME)
2197 sgi_set_partition(int i, unsigned int start, unsigned int length, int sys)
2199 sgilabel->partitions[i].id = SGI_SSWAP32(sys);
2200 sgilabel->partitions[i].num_sectors = SGI_SSWAP32(length);
2201 sgilabel->partitions[i].start_sector = SGI_SSWAP32(start);
2203 if (sgi_gaps() < 0) /* rebuild freelist */
2204 printf(_("Do You know, You got a partition overlap on the disk?\n"));
2208 sgi_set_entire(void)
2212 for (n = 10; n < partitions; n++) {
2213 if(!sgi_get_num_sectors(n) ) {
2214 sgi_set_partition(n, 0, sgi_get_lastblock(), SGI_VOLUME);
2221 sgi_set_volhdr(void)
2225 for (n = 8; n < partitions; n++) {
2226 if (!sgi_get_num_sectors(n)) {
2228 * 5 cylinders is an arbitrary value I like
2229 * IRIX 5.3 stored files in the volume header
2230 * (like sash, symmon, fx, ide) with ca. 3200
2233 if (heads * sectors * 5 < sgi_get_lastblock())
2234 sgi_set_partition(n, 0, heads * sectors * 5, SGI_VOLHDR);
2241 sgi_delete_partition(int i)
2243 sgi_set_partition(i, 0, 0, 0);
2247 sgi_add_partition(int n, int sys)
2250 unsigned int first = 0, last = 0;
2254 } else if (n == 8) {
2257 if(sgi_get_num_sectors(n)) {
2258 printf(_("Partition %d is already defined. Delete "
2259 "it before re-adding it.\n"), n + 1);
2262 if ((sgi_entire() == -1) && (sys != SGI_VOLUME)) {
2263 printf(_("Attempting to generate entire disk entry automatically.\n"));
2267 if ((sgi_gaps() == 0) && (sys != SGI_VOLUME)) {
2268 printf(_("The entire disk is already covered with partitions.\n"));
2271 if (sgi_gaps() < 0) {
2272 printf(_("You got a partition overlap on the disk. Fix it first!\n"));
2275 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
2277 if(sys == SGI_VOLUME) {
2278 last = sgi_get_lastblock();
2279 first = read_int(0, 0, last-1, 0, mesg);
2281 printf(_("It is highly recommended that eleventh partition\n"
2282 "covers the entire disk and is of type `SGI volume'\n"));
2285 first = freelist[0].first;
2286 last = freelist[0].last;
2287 first = read_int(scround(first), scround(first), scround(last)-1,
2290 if (display_in_cyl_units)
2291 first *= units_per_sector;
2293 first = first; /* align to cylinder if you know how ... */
2295 last = isinfreelist(first);
2297 printf(_("You will get a partition overlap on the disk. "
2298 "Fix it first!\n"));
2302 snprintf(mesg, sizeof(mesg), _(" Last %s"), str_units(SINGULAR));
2303 last = read_int(scround(first), scround(last)-1, scround(last)-1,
2304 scround(first), mesg)+1;
2305 if (display_in_cyl_units)
2306 last *= units_per_sector;
2308 last = last; /* align to cylinder if You know how ... */
2309 if ( (sys == SGI_VOLUME) && (first != 0 || last != sgi_get_lastblock() ) )
2310 printf(_("It is highly recommended that eleventh partition\n"
2311 "covers the entire disk and is of type `SGI volume'\n"));
2312 sgi_set_partition(n, first, last-first, sys);
2315 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
2317 create_sgilabel(void)
2319 struct hd_geometry geometry;
2326 long longsectors; /* the number of sectors on the device */
2327 int res; /* the result from the ioctl */
2328 int sec_fac; /* the sector factor */
2330 sec_fac = sector_size / 512; /* determine the sector factor */
2333 _("Building a new SGI disklabel. Changes will remain in memory only,\n"
2334 "until you decide to write them. After that, of course, the previous\n"
2335 "content will be unrecoverably lost.\n\n"));
2337 sgi_other_endian = (BB_LITTLE_ENDIAN);
2338 res = ioctl(fd, BLKGETSIZE, &longsectors);
2339 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
2340 heads = geometry.heads;
2341 sectors = geometry.sectors;
2343 /* the get device size ioctl was successful */
2344 cylinders = longsectors / (heads * sectors);
2345 cylinders /= sec_fac;
2347 /* otherwise print error and use truncated version */
2348 cylinders = geometry.cylinders;
2350 _("Warning: BLKGETSIZE ioctl failed on %s. "
2351 "Using geometry cylinder value of %d.\n"
2352 "This value may be truncated for devices"
2353 " > 33.8 GB.\n"), disk_device, cylinders);
2356 for (i = 0; i < 4; i++) {
2358 if (valid_part_table_flag(MBRbuffer)) {
2359 if(get_part_table(i)->sys_ind) {
2360 old[i].sysid = get_part_table(i)->sys_ind;
2361 old[i].start = get_start_sect(get_part_table(i));
2362 old[i].nsect = get_nr_sects(get_part_table(i));
2363 printf(_("Trying to keep parameters of partition %d.\n"), i);
2365 printf(_("ID=%02x\tSTART=%d\tLENGTH=%d\n"),
2366 old[i].sysid, old[i].start, old[i].nsect);
2371 memset(MBRbuffer, 0, sizeof(MBRbuffer));
2372 sgilabel->magic = SGI_SSWAP32(SGI_LABEL_MAGIC);
2373 sgilabel->boot_part = SGI_SSWAP16(0);
2374 sgilabel->swap_part = SGI_SSWAP16(1);
2376 /* sizeof(sgilabel->boot_file) = 16 > 6 */
2377 memset(sgilabel->boot_file, 0, 16);
2378 strcpy((char*)sgilabel->boot_file, "/unix");
2380 sgilabel->devparam.skew = (0);
2381 sgilabel->devparam.gap1 = (0);
2382 sgilabel->devparam.gap2 = (0);
2383 sgilabel->devparam.sparecyl = (0);
2384 sgilabel->devparam.pcylcount = SGI_SSWAP16(geometry.cylinders);
2385 sgilabel->devparam.head_vol0 = SGI_SSWAP16(0);
2386 sgilabel->devparam.ntrks = SGI_SSWAP16(geometry.heads);
2387 /* tracks/cylinder (heads) */
2388 sgilabel->devparam.cmd_tag_queue_depth = (0);
2389 sgilabel->devparam.unused0 = (0);
2390 sgilabel->devparam.unused1 = SGI_SSWAP16(0);
2391 sgilabel->devparam.nsect = SGI_SSWAP16(geometry.sectors);
2393 sgilabel->devparam.bytes = SGI_SSWAP16(512);
2394 sgilabel->devparam.ilfact = SGI_SSWAP16(1);
2395 sgilabel->devparam.flags = SGI_SSWAP32(TRACK_FWD|
2396 IGNORE_ERRORS|RESEEK);
2397 sgilabel->devparam.datarate = SGI_SSWAP32(0);
2398 sgilabel->devparam.retries_on_error = SGI_SSWAP32(1);
2399 sgilabel->devparam.ms_per_word = SGI_SSWAP32(0);
2400 sgilabel->devparam.xylogics_gap1 = SGI_SSWAP16(0);
2401 sgilabel->devparam.xylogics_syncdelay = SGI_SSWAP16(0);
2402 sgilabel->devparam.xylogics_readdelay = SGI_SSWAP16(0);
2403 sgilabel->devparam.xylogics_gap2 = SGI_SSWAP16(0);
2404 sgilabel->devparam.xylogics_readgate = SGI_SSWAP16(0);
2405 sgilabel->devparam.xylogics_writecont = SGI_SSWAP16(0);
2406 memset( &(sgilabel->directory), 0, sizeof(struct volume_directory)*15 );
2407 memset( &(sgilabel->partitions), 0, sizeof(struct sgi_partition)*16 );
2408 current_label_type = label_sgi;
2413 for (i = 0; i < 4; i++) {
2415 sgi_set_partition(i, old[i].start, old[i].nsect, old[i].sysid);
2423 /* do nothing in the beginning */
2425 #endif /* CONFIG_FEATURE_FDISK_ADVANCED */
2427 /* _____________________________________________________________
2433 sgiinfo *info = calloc(1, sizeof(sgiinfo));
2435 info->magic = SGI_SSWAP32(SGI_INFO_MAGIC);
2436 info->b1 = SGI_SSWAP32(-1);
2437 info->b2 = SGI_SSWAP16(-1);
2438 info->b3 = SGI_SSWAP16(1);
2439 /* You may want to replace this string !!!!!!! */
2440 strcpy( (char*)info->scsi_string, "IBM OEM 0662S12 3 30" );
2441 strcpy( (char*)info->serial, "0000" );
2442 info->check1816 = SGI_SSWAP16(18*256 +16 );
2443 strcpy( (char*)info->installer, "Sfx version 5.3, Oct 18, 1994" );
2446 #endif /* SGI_LABEL */
2449 #ifdef CONFIG_FEATURE_SUN_LABEL
2453 * I think this is mostly, or entirely, due to
2454 * Jakub Jelinek (jj@sunsite.mff.cuni.cz), July 1996
2456 * Merged with fdisk for other architectures, aeb, June 1998.
2458 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
2459 * Internationalization
2463 static int sun_other_endian;
2464 static int scsi_disk;
2468 #define IDE0_MAJOR 3
2471 #define IDE1_MAJOR 22
2475 guess_device_type(void)
2477 struct stat bootstat;
2479 if (fstat(fd, &bootstat) < 0) {
2482 } else if (S_ISBLK(bootstat.st_mode)
2483 && (major(bootstat.st_rdev) == IDE0_MAJOR ||
2484 major(bootstat.st_rdev) == IDE1_MAJOR)) {
2487 } else if (S_ISBLK(bootstat.st_mode)
2488 && major(bootstat.st_rdev) == FLOPPY_MAJOR) {
2497 static const struct systypes sun_sys_types[] = {
2498 { "\x00" "Empty" }, /* 0 */
2499 { "\x01" "Boot" }, /* 1 */
2500 { "\x02" "SunOS root" }, /* 2 */
2501 { "\x03" "SunOS swap" }, /* SUNOS_SWAP */
2502 { "\x04" "SunOS usr" }, /* 4 */
2503 { "\x05" "Whole disk" }, /* WHOLE_DISK */
2504 { "\x06" "SunOS stand" }, /* 6 */
2505 { "\x07" "SunOS var" }, /* 7 */
2506 { "\x08" "SunOS home" }, /* 8 */
2507 { "\x82" "Linux swap" }, /* LINUX_SWAP */
2508 { "\x83" "Linux native" }, /* LINUX_NATIVE */
2509 { "\x8e" "Linux LVM" }, /* 0x8e */
2510 /* New (2.2.x) raid partition with autodetect using persistent superblock */
2511 { "\xfd" "Linux raid autodetect" }, /* 0xfd */
2517 set_sun_partition(int i, uint start, uint stop, int sysid)
2519 sunlabel->infos[i].id = sysid;
2520 sunlabel->partitions[i].start_cylinder =
2521 SUN_SSWAP32(start / (heads * sectors));
2522 sunlabel->partitions[i].num_sectors =
2523 SUN_SSWAP32(stop - start);
2528 check_sun_label(void)
2530 unsigned short *ush;
2533 if (sunlabel->magic != SUN_LABEL_MAGIC
2534 && sunlabel->magic != SUN_LABEL_MAGIC_SWAPPED) {
2535 current_label_type = label_dos;
2536 sun_other_endian = 0;
2539 sun_other_endian = (sunlabel->magic == SUN_LABEL_MAGIC_SWAPPED);
2540 ush = ((unsigned short *) (sunlabel + 1)) - 1;
2541 for (csum = 0; ush >= (unsigned short *)sunlabel;) csum ^= *ush--;
2543 fprintf(stderr,_("Detected sun disklabel with wrong checksum.\n"
2544 "Probably you'll have to set all the values,\n"
2545 "e.g. heads, sectors, cylinders and partitions\n"
2546 "or force a fresh label (s command in main menu)\n"));
2548 heads = SUN_SSWAP16(sunlabel->ntrks);
2549 cylinders = SUN_SSWAP16(sunlabel->ncyl);
2550 sectors = SUN_SSWAP16(sunlabel->nsect);
2553 current_label_type = label_sun;
2558 static const struct sun_predefined_drives {
2561 unsigned short sparecyl;
2562 unsigned short ncyl;
2563 unsigned short nacyl;
2564 unsigned short pcylcount;
2565 unsigned short ntrks;
2566 unsigned short nsect;
2567 unsigned short rspeed;
2569 { "Quantum","ProDrive 80S",1,832,2,834,6,34,3662},
2570 { "Quantum","ProDrive 105S",1,974,2,1019,6,35,3662},
2571 { "CDC","Wren IV 94171-344",3,1545,2,1549,9,46,3600},
2572 { "IBM","DPES-31080",0,4901,2,4903,4,108,5400},
2573 { "IBM","DORS-32160",0,1015,2,1017,67,62,5400},
2574 { "IBM","DNES-318350",0,11199,2,11474,10,320,7200},
2575 { "SEAGATE","ST34371",0,3880,2,3882,16,135,7228},
2576 { "","SUN0104",1,974,2,1019,6,35,3662},
2577 { "","SUN0207",4,1254,2,1272,9,36,3600},
2578 { "","SUN0327",3,1545,2,1549,9,46,3600},
2579 { "","SUN0340",0,1538,2,1544,6,72,4200},
2580 { "","SUN0424",2,1151,2,2500,9,80,4400},
2581 { "","SUN0535",0,1866,2,2500,7,80,5400},
2582 { "","SUN0669",5,1614,2,1632,15,54,3600},
2583 { "","SUN1.0G",5,1703,2,1931,15,80,3597},
2584 { "","SUN1.05",0,2036,2,2038,14,72,5400},
2585 { "","SUN1.3G",6,1965,2,3500,17,80,5400},
2586 { "","SUN2.1G",0,2733,2,3500,19,80,5400},
2587 { "IOMEGA","Jaz",0,1019,2,1021,64,32,5394},
2590 static const struct sun_predefined_drives *
2591 sun_autoconfigure_scsi(void)
2593 const struct sun_predefined_drives *p = NULL;
2595 #ifdef SCSI_IOCTL_GET_IDLUN
2605 if (!ioctl(fd, SCSI_IOCTL_GET_IDLUN, &id)) {
2607 "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n",
2609 ((id[0]>>24)&0xff)-/*PROC_SCSI_SCSI+PROC_SCSI_FILE*/33,
2611 /* This is very wrong (works only if you have one HBA),
2612 but I haven't found a way how to get hostno
2613 from the current kernel */
2620 pfd = fopen("/proc/scsi/scsi","r");
2622 while (fgets(buffer2, 2048, pfd)) {
2623 if (!strcmp(buffer, buffer2)) {
2624 if (fgets(buffer2,2048,pfd)) {
2625 q = strstr(buffer2,"Vendor: ");
2630 *q++ = 0; /* truncate vendor name */
2631 q = strstr(q,"Model: ");
2636 q = strstr(q," Rev: ");
2639 for (i = 0; i < SIZE(sun_drives); i++) {
2640 if (*sun_drives[i].vendor && strcasecmp(sun_drives[i].vendor, vendor))
2642 if (!strstr(model, sun_drives[i].model))
2644 printf(_("Autoconfigure found a %s%s%s\n"),sun_drives[i].vendor,(*sun_drives[i].vendor) ? " " : "",sun_drives[i].model);
2663 create_sunlabel(void)
2665 struct hd_geometry geometry;
2669 const struct sun_predefined_drives *p = NULL;
2672 _("Building a new sun disklabel. Changes will remain in memory only,\n"
2673 "until you decide to write them. After that, of course, the previous\n"
2674 "content won't be recoverable.\n\n"));
2675 sun_other_endian = BB_LITTLE_ENDIAN;
2676 memset(MBRbuffer, 0, sizeof(MBRbuffer));
2677 sunlabel->magic = SUN_SSWAP16(SUN_LABEL_MAGIC);
2679 puts(_("Drive type\n"
2680 " ? auto configure\n"
2681 " 0 custom (with hardware detected defaults)"));
2682 for (i = 0; i < SIZE(sun_drives); i++) {
2683 printf(" %c %s%s%s\n",
2684 i + 'a', sun_drives[i].vendor,
2685 (*sun_drives[i].vendor) ? " " : "",
2686 sun_drives[i].model);
2689 c = read_char(_("Select type (? for auto, 0 for custom): "));
2690 if (c >= 'a' && c < 'a' + SIZE(sun_drives)) {
2691 p = sun_drives + c - 'a';
2693 } else if (c >= 'A' && c < 'A' + SIZE(sun_drives)) {
2694 p = sun_drives + c - 'A';
2696 } else if (c == '0') {
2698 } else if (c == '?' && scsi_disk) {
2699 p = sun_autoconfigure_scsi();
2701 printf(_("Autoconfigure failed.\n"));
2708 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
2709 heads = geometry.heads;
2710 sectors = geometry.sectors;
2711 cylinders = geometry.cylinders;
2718 sunlabel->nacyl = 0;
2719 sunlabel->pcylcount = SUN_SSWAP16(cylinders);
2720 sunlabel->rspeed = SUN_SSWAP16(300);
2721 sunlabel->ilfact = SUN_SSWAP16(1);
2722 sunlabel->sparecyl = 0;
2724 heads = read_int(1,heads,1024,0,_("Heads"));
2725 sectors = read_int(1,sectors,1024,0,_("Sectors/track"));
2727 cylinders = read_int(1,cylinders-2,65535,0,_("Cylinders"));
2729 cylinders = read_int(1,0,65535,0,_("Cylinders"));
2730 sunlabel->nacyl = SUN_SSWAP16(read_int(0,2,65535,0, _("Alternate cylinders")));
2731 sunlabel->pcylcount = SUN_SSWAP16(read_int(0,cylinders+SUN_SSWAP16(sunlabel->nacyl), 65535,0, _("Physical cylinders")));
2732 sunlabel->rspeed = SUN_SSWAP16(read_int(1,5400,100000,0, _("Rotation speed (rpm)")));
2733 sunlabel->ilfact = SUN_SSWAP16(read_int(1,1,32,0, _("Interleave factor")));
2734 sunlabel->sparecyl = SUN_SSWAP16(read_int(0,0,sectors,0, _("Extra sectors per cylinder")));
2737 sunlabel->sparecyl = SUN_SSWAP16(p->sparecyl);
2738 sunlabel->ncyl = SUN_SSWAP16(p->ncyl);
2739 sunlabel->nacyl = SUN_SSWAP16(p->nacyl);
2740 sunlabel->pcylcount = SUN_SSWAP16(p->pcylcount);
2741 sunlabel->ntrks = SUN_SSWAP16(p->ntrks);
2742 sunlabel->nsect = SUN_SSWAP16(p->nsect);
2743 sunlabel->rspeed = SUN_SSWAP16(p->rspeed);
2744 sunlabel->ilfact = SUN_SSWAP16(1);
2745 cylinders = p->ncyl;
2748 puts(_("You may change all the disk params from the x menu"));
2751 snprintf((char *)(sunlabel->info), sizeof(sunlabel->info),
2752 "%s%s%s cyl %d alt %d hd %d sec %d",
2753 p ? p->vendor : "", (p && *p->vendor) ? " " : "",
2754 p ? p->model : (floppy ? _("3,5\" floppy") : _("Linux custom")),
2755 cylinders, SUN_SSWAP16(sunlabel->nacyl), heads, sectors);
2757 sunlabel->ntrks = SUN_SSWAP16(heads);
2758 sunlabel->nsect = SUN_SSWAP16(sectors);
2759 sunlabel->ncyl = SUN_SSWAP16(cylinders);
2761 set_sun_partition(0, 0, cylinders * heads * sectors, LINUX_NATIVE);
2763 if (cylinders * heads * sectors >= 150 * 2048) {
2764 ndiv = cylinders - (50 * 2048 / (heads * sectors)); /* 50M swap */
2766 ndiv = cylinders * 2 / 3;
2767 set_sun_partition(0, 0, ndiv * heads * sectors, LINUX_NATIVE);
2768 set_sun_partition(1, ndiv * heads * sectors, cylinders * heads * sectors, LINUX_SWAP);
2769 sunlabel->infos[1].flags |= 0x01; /* Not mountable */
2771 set_sun_partition(2, 0, cylinders * heads * sectors, WHOLE_DISK);
2773 unsigned short *ush = (unsigned short *)sunlabel;
2774 unsigned short csum = 0;
2775 while (ush < (unsigned short *)(&sunlabel->csum))
2777 sunlabel->csum = csum;
2780 set_all_unchanged();
2782 get_boot(create_empty_sun);
2786 toggle_sunflags(int i, unsigned char mask)
2788 if (sunlabel->infos[i].flags & mask)
2789 sunlabel->infos[i].flags &= ~mask;
2791 sunlabel->infos[i].flags |= mask;
2796 fetch_sun(uint *starts, uint *lens, uint *start, uint *stop)
2798 int i, continuous = 1;
2801 *stop = cylinders * heads * sectors;
2802 for (i = 0; i < partitions; i++) {
2803 if (sunlabel->partitions[i].num_sectors
2804 && sunlabel->infos[i].id
2805 && sunlabel->infos[i].id != WHOLE_DISK) {
2806 starts[i] = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
2807 lens[i] = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
2809 if (starts[i] == *start)
2811 else if (starts[i] + lens[i] >= *stop)
2815 /* There will be probably more gaps
2816 than one, so lets check afterwards */
2825 static uint *verify_sun_starts;
2828 verify_sun_cmp(int *a, int *b)
2830 if (*a == -1) return 1;
2831 if (*b == -1) return -1;
2832 if (verify_sun_starts[*a] > verify_sun_starts[*b]) return 1;
2839 uint starts[8], lens[8], start, stop;
2840 int i,j,k,starto,endo;
2843 verify_sun_starts = starts;
2844 fetch_sun(starts,lens,&start,&stop);
2845 for (k = 0; k < 7; k++) {
2846 for (i = 0; i < 8; i++) {
2847 if (k && (lens[i] % (heads * sectors))) {
2848 printf(_("Partition %d doesn't end on cylinder boundary\n"), i+1);
2851 for (j = 0; j < i; j++)
2853 if (starts[j] == starts[i]+lens[i]) {
2854 starts[j] = starts[i]; lens[j] += lens[i];
2856 } else if (starts[i] == starts[j]+lens[j]){
2860 if (starts[i] < starts[j]+lens[j]
2861 && starts[j] < starts[i]+lens[i]) {
2863 if (starts[j] > starto)
2865 endo = starts[i]+lens[i];
2866 if (starts[j]+lens[j] < endo)
2867 endo = starts[j]+lens[j];
2868 printf(_("Partition %d overlaps with others in "
2869 "sectors %d-%d\n"), i+1, starto, endo);
2876 for (i = 0; i < 8; i++) {
2882 qsort(array,SIZE(array),sizeof(array[0]),
2883 (int (*)(const void *,const void *)) verify_sun_cmp);
2884 if (array[0] == -1) {
2885 printf(_("No partitions defined\n"));
2888 stop = cylinders * heads * sectors;
2889 if (starts[array[0]])
2890 printf(_("Unused gap - sectors 0-%d\n"),starts[array[0]]);
2891 for (i = 0; i < 7 && array[i+1] != -1; i++) {
2892 printf(_("Unused gap - sectors %d-%d\n"),starts[array[i]]+lens[array[i]],starts[array[i+1]]);
2894 start = starts[array[i]] + lens[array[i]];
2896 printf(_("Unused gap - sectors %d-%d\n"),start,stop);
2900 add_sun_partition(int n, int sys)
2902 uint start, stop, stop2;
2903 uint starts[8], lens[8];
2909 if (sunlabel->partitions[n].num_sectors && sunlabel->infos[n].id) {
2910 printf(_("Partition %d is already defined. Delete "
2911 "it before re-adding it.\n"), n + 1);
2915 fetch_sun(starts,lens,&start,&stop);
2916 if (stop <= start) {
2920 printf(_("Other partitions already cover the whole disk.\nDelete "
2921 "some/shrink them before retry.\n"));
2925 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
2928 first = read_int(0, 0, 0, 0, mesg);
2930 first = read_int(scround(start), scround(stop)+1,
2931 scround(stop), 0, mesg);
2932 if (display_in_cyl_units)
2933 first *= units_per_sector;
2935 /* Starting sector has to be properly aligned */
2936 first = (first + heads * sectors - 1) / (heads * sectors);
2937 if (n == 2 && first != 0)
2939 It is highly recommended that the third partition covers the whole disk\n\
2940 and is of type `Whole disk'\n");
2941 /* ewt asks to add: "don't start a partition at cyl 0"
2942 However, edmundo@rano.demon.co.uk writes:
2943 "In addition to having a Sun partition table, to be able to
2944 boot from the disc, the first partition, /dev/sdX1, must
2945 start at cylinder 0. This means that /dev/sdX1 contains
2946 the partition table and the boot block, as these are the
2947 first two sectors of the disc. Therefore you must be
2948 careful what you use /dev/sdX1 for. In particular, you must
2949 not use a partition starting at cylinder 0 for Linux swap,
2950 as that would overwrite the partition table and the boot
2951 block. You may, however, use such a partition for a UFS
2952 or EXT2 file system, as these file systems leave the first
2953 1024 bytes undisturbed. */
2954 /* On the other hand, one should not use partitions
2955 starting at block 0 in an md, or the label will
2957 for (i = 0; i < partitions; i++)
2958 if (lens[i] && starts[i] <= first && starts[i] + lens[i] > first)
2960 if (i < partitions && !whole_disk) {
2961 if (n == 2 && !first) {
2965 printf(_("Sector %d is already allocated\n"), first);
2969 stop = cylinders * heads * sectors;
2971 for (i = 0; i < partitions; i++) {
2972 if (starts[i] > first && starts[i] < stop)
2975 snprintf(mesg, sizeof(mesg),
2976 _("Last %s or +size or +sizeM or +sizeK"),
2977 str_units(SINGULAR));
2979 last = read_int(scround(stop2), scround(stop2), scround(stop2),
2981 else if (n == 2 && !first)
2982 last = read_int(scround(first), scround(stop2), scround(stop2),
2983 scround(first), mesg);
2985 last = read_int(scround(first), scround(stop), scround(stop),
2986 scround(first), mesg);
2987 if (display_in_cyl_units)
2988 last *= units_per_sector;
2989 if (n == 2 && !first) {
2990 if (last >= stop2) {
2993 } else if (last > stop) {
2994 printf(_("You haven't covered the whole disk with "
2995 "the 3rd partition, but your value\n"
2996 "%d %s covers some other partition. "
2997 "Your entry has been changed\n"
2999 scround(last), str_units(SINGULAR),
3000 scround(stop), str_units(SINGULAR));
3003 } else if (!whole_disk && last > stop)
3008 set_sun_partition(n, first, last, sys);
3012 sun_delete_partition(int i)
3017 && sunlabel->infos[i].id == WHOLE_DISK
3018 && !sunlabel->partitions[i].start_cylinder
3019 && (nsec = SUN_SSWAP32(sunlabel->partitions[i].num_sectors)) == heads * sectors * cylinders)
3020 printf(_("If you want to maintain SunOS/Solaris compatibility, "
3021 "consider leaving this\n"
3022 "partition as Whole disk (5), starting at 0, with %u "
3023 "sectors\n"), nsec);
3024 sunlabel->infos[i].id = 0;
3025 sunlabel->partitions[i].num_sectors = 0;
3029 sun_change_sysid(int i, int sys)
3031 if (sys == LINUX_SWAP && !sunlabel->partitions[i].start_cylinder) {
3033 _("It is highly recommended that the partition at offset 0\n"
3034 "is UFS, EXT2FS filesystem or SunOS swap. Putting Linux swap\n"
3035 "there may destroy your partition table and bootblock.\n"
3036 "Type YES if you're very sure you would like that partition\n"
3037 "tagged with 82 (Linux swap): "));
3038 if (strcmp (line_ptr, _("YES\n")))
3044 /* swaps are not mountable by default */
3045 sunlabel->infos[i].flags |= 0x01;
3048 /* assume other types are mountable;
3049 user can change it anyway */
3050 sunlabel->infos[i].flags &= ~0x01;
3053 sunlabel->infos[i].id = sys;
3057 sun_list_table(int xtra)
3061 w = strlen(disk_device);
3064 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d rpm\n"
3065 "%d cylinders, %d alternate cylinders, %d physical cylinders\n"
3066 "%d extra sects/cyl, interleave %d:1\n"
3068 "Units = %s of %d * 512 bytes\n\n"),
3069 disk_device, heads, sectors, SUN_SSWAP16(sunlabel->rspeed),
3070 cylinders, SUN_SSWAP16(sunlabel->nacyl),
3071 SUN_SSWAP16(sunlabel->pcylcount),
3072 SUN_SSWAP16(sunlabel->sparecyl),
3073 SUN_SSWAP16(sunlabel->ilfact),
3075 str_units(PLURAL), units_per_sector);
3078 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d cylinders\n"
3079 "Units = %s of %d * 512 bytes\n\n"),
3080 disk_device, heads, sectors, cylinders,
3081 str_units(PLURAL), units_per_sector);
3083 printf(_("%*s Flag Start End Blocks Id System\n"),
3084 w + 1, _("Device"));
3085 for (i = 0 ; i < partitions; i++) {
3086 if (sunlabel->partitions[i].num_sectors) {
3087 uint32_t start = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
3088 uint32_t len = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
3089 printf("%s %c%c %9ld %9ld %9ld%c %2x %s\n",
3090 partname(disk_device, i+1, w), /* device */
3091 (sunlabel->infos[i].flags & 0x01) ? 'u' : ' ', /* flags */
3092 (sunlabel->infos[i].flags & 0x10) ? 'r' : ' ',
3093 (long) scround(start), /* start */
3094 (long) scround(start+len), /* end */
3095 (long) len / 2, len & 1 ? '+' : ' ', /* odd flag on end */
3096 sunlabel->infos[i].id, /* type id */
3097 partition_type(sunlabel->infos[i].id)); /* type name */
3102 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3105 sun_set_alt_cyl(void)
3108 SUN_SSWAP16(read_int(0,SUN_SSWAP16(sunlabel->nacyl), 65535, 0,
3109 _("Number of alternate cylinders")));
3113 sun_set_ncyl(int cyl)
3115 sunlabel->ncyl = SUN_SSWAP16(cyl);
3121 sunlabel->sparecyl =
3122 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->sparecyl), sectors, 0,
3123 _("Extra sectors per cylinder")));
3127 sun_set_ilfact(void)
3130 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->ilfact), 32, 0,
3131 _("Interleave factor")));
3135 sun_set_rspeed(void)
3138 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->rspeed), 100000, 0,
3139 _("Rotation speed (rpm)")));
3143 sun_set_pcylcount(void)
3145 sunlabel->pcylcount =
3146 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->pcylcount), 65535, 0,
3147 _("Number of physical cylinders")));
3149 #endif /* CONFIG_FEATURE_FDISK_ADVANCED */
3152 sun_write_table(void)
3154 unsigned short *ush = (unsigned short *)sunlabel;
3155 unsigned short csum = 0;
3157 while (ush < (unsigned short *)(&sunlabel->csum))
3159 sunlabel->csum = csum;
3160 if (lseek(fd, 0, SEEK_SET) < 0)
3161 fdisk_fatal(unable_to_seek);
3162 if (write(fd, sunlabel, SECTOR_SIZE) != SECTOR_SIZE)
3163 fdisk_fatal(unable_to_write);
3165 #endif /* SUN_LABEL */
3167 /* DOS partition types */
3169 static const struct systypes i386_sys_types[] = {
3172 { "\x04" "FAT16 <32M" },
3173 { "\x05" "Extended" }, /* DOS 3.3+ extended partition */
3174 { "\x06" "FAT16" }, /* DOS 16-bit >=32M */
3175 { "\x07" "HPFS/NTFS" }, /* OS/2 IFS, eg, HPFS or NTFS or QNX */
3176 { "\x0a" "OS/2 Boot Manager" },/* OS/2 Boot Manager */
3177 { "\x0b" "Win95 FAT32" },
3178 { "\x0c" "Win95 FAT32 (LBA)" },/* LBA really is `Extended Int 13h' */
3179 { "\x0e" "Win95 FAT16 (LBA)" },
3180 { "\x0f" "Win95 Ext'd (LBA)" },
3181 { "\x11" "Hidden FAT12" },
3182 { "\x12" "Compaq diagnostics" },
3183 { "\x14" "Hidden FAT16 <32M" },
3184 { "\x16" "Hidden FAT16" },
3185 { "\x17" "Hidden HPFS/NTFS" },
3186 { "\x1b" "Hidden Win95 FAT32" },
3187 { "\x1c" "Hidden Win95 FAT32 (LBA)" },
3188 { "\x1e" "Hidden Win95 FAT16 (LBA)" },
3189 { "\x3c" "PartitionMagic recovery" },
3190 { "\x41" "PPC PReP Boot" },
3192 { "\x63" "GNU HURD or SysV" }, /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */
3193 { "\x80" "Old Minix" }, /* Minix 1.4a and earlier */
3194 { "\x81" "Minix / old Linux" },/* Minix 1.4b and later */
3195 { "\x82" "Linux swap" }, /* also Solaris */
3197 { "\x84" "OS/2 hidden C: drive" },
3198 { "\x85" "Linux extended" },
3199 { "\x86" "NTFS volume set" },
3200 { "\x87" "NTFS volume set" },
3201 { "\x8e" "Linux LVM" },
3202 { "\x9f" "BSD/OS" }, /* BSDI */
3203 { "\xa0" "IBM Thinkpad hibernation" },
3204 { "\xa5" "FreeBSD" }, /* various BSD flavours */
3205 { "\xa6" "OpenBSD" },
3206 { "\xa8" "Darwin UFS" },
3207 { "\xa9" "NetBSD" },
3208 { "\xab" "Darwin boot" },
3209 { "\xb7" "BSDI fs" },
3210 { "\xb8" "BSDI swap" },
3211 { "\xbe" "Solaris boot" },
3212 { "\xeb" "BeOS fs" },
3213 { "\xee" "EFI GPT" }, /* Intel EFI GUID Partition Table */
3214 { "\xef" "EFI (FAT-12/16/32)" },/* Intel EFI System Partition */
3215 { "\xf0" "Linux/PA-RISC boot" },/* Linux/PA-RISC boot loader */
3216 { "\xf2" "DOS secondary" }, /* DOS 3.3+ secondary */
3217 { "\xfd" "Linux raid autodetect" },/* New (2.2.x) raid partition with
3218 autodetect using persistent
3220 #ifdef CONFIG_WEIRD_PARTITION_TYPES
3221 { "\x02" "XENIX root" },
3222 { "\x03" "XENIX usr" },
3223 { "\x08" "AIX" }, /* AIX boot (AIX -- PS/2 port) or SplitDrive */
3224 { "\x09" "AIX bootable" }, /* AIX data or Coherent */
3226 { "\x18" "AST SmartSleep" },
3227 { "\x24" "NEC DOS" },
3228 { "\x39" "Plan 9" },
3229 { "\x40" "Venix 80286" },
3230 { "\x4d" "QNX4.x" },
3231 { "\x4e" "QNX4.x 2nd part" },
3232 { "\x4f" "QNX4.x 3rd part" },
3233 { "\x50" "OnTrack DM" },
3234 { "\x51" "OnTrack DM6 Aux1" }, /* (or Novell) */
3235 { "\x52" "CP/M" }, /* CP/M or Microport SysV/AT */
3236 { "\x53" "OnTrack DM6 Aux3" },
3237 { "\x54" "OnTrackDM6" },
3238 { "\x55" "EZ-Drive" },
3239 { "\x56" "Golden Bow" },
3240 { "\x5c" "Priam Edisk" },
3241 { "\x61" "SpeedStor" },
3242 { "\x64" "Novell Netware 286" },
3243 { "\x65" "Novell Netware 386" },
3244 { "\x70" "DiskSecure Multi-Boot" },
3246 { "\x93" "Amoeba" },
3247 { "\x94" "Amoeba BBT" }, /* (bad block table) */
3248 { "\xa7" "NeXTSTEP" },
3249 { "\xbb" "Boot Wizard hidden" },
3250 { "\xc1" "DRDOS/sec (FAT-12)" },
3251 { "\xc4" "DRDOS/sec (FAT-16 < 32M)" },
3252 { "\xc6" "DRDOS/sec (FAT-16)" },
3253 { "\xc7" "Syrinx" },
3254 { "\xda" "Non-FS data" },
3255 { "\xdb" "CP/M / CTOS / ..." },/* CP/M or Concurrent CP/M or
3256 Concurrent DOS or CTOS */
3257 { "\xde" "Dell Utility" }, /* Dell PowerEdge Server utilities */
3258 { "\xdf" "BootIt" }, /* BootIt EMBRM */
3259 { "\xe1" "DOS access" }, /* DOS access or SpeedStor 12-bit FAT
3260 extended partition */
3261 { "\xe3" "DOS R/O" }, /* DOS R/O or SpeedStor */
3262 { "\xe4" "SpeedStor" }, /* SpeedStor 16-bit FAT extended
3263 partition < 1024 cyl. */
3264 { "\xf1" "SpeedStor" },
3265 { "\xf4" "SpeedStor" }, /* SpeedStor large partition */
3266 { "\xfe" "LANstep" }, /* SpeedStor >1024 cyl. or LANstep */
3267 { "\xff" "BBT" }, /* Xenix Bad Block Table */
3274 /* A valid partition table sector ends in 0x55 0xaa */
3276 part_table_flag(const char *b)
3278 return ((uint) b[510]) + (((uint) b[511]) << 8);
3282 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3284 write_part_table_flag(char *b)
3290 /* start_sect and nr_sects are stored little endian on all machines */
3291 /* moreover, they are not aligned correctly */
3293 store4_little_endian(unsigned char *cp, unsigned int val)
3295 cp[0] = (val & 0xff);
3296 cp[1] = ((val >> 8) & 0xff);
3297 cp[2] = ((val >> 16) & 0xff);
3298 cp[3] = ((val >> 24) & 0xff);
3300 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3303 read4_little_endian(const unsigned char *cp)
3305 return (uint)(cp[0]) + ((uint)(cp[1]) << 8)
3306 + ((uint)(cp[2]) << 16) + ((uint)(cp[3]) << 24);
3309 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3311 set_start_sect(struct partition *p, unsigned int start_sect)
3313 store4_little_endian(p->start4, start_sect);
3318 get_start_sect(const struct partition *p)
3320 return read4_little_endian(p->start4);
3323 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3325 set_nr_sects(struct partition *p, int32_t nr_sects)
3327 store4_little_endian(p->size4, nr_sects);
3332 get_nr_sects(const struct partition *p)
3334 return read4_little_endian(p->size4);
3337 /* normally O_RDWR, -l option gives O_RDONLY */
3338 static int type_open = O_RDWR;
3341 static int ext_index; /* the prime extended partition */
3342 static int listing; /* no aborts for fdisk -l */
3343 static int dos_compatible_flag = ~0;
3344 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3345 static int dos_changed;
3346 static int nowarn; /* no warnings for fdisk -l/-s */
3351 static uint user_cylinders, user_heads, user_sectors;
3352 static uint pt_heads, pt_sectors;
3353 static uint kern_heads, kern_sectors;
3355 static off_t extended_offset; /* offset of link pointers */
3357 static unsigned long long total_number_of_sectors;
3360 static jmp_buf listingbuf;
3362 static void fdisk_fatal(enum failure why)
3364 const char *message;
3368 longjmp(listingbuf, 1);
3372 case unable_to_open:
3373 message = "Unable to open %s\n";
3375 case unable_to_read:
3376 message = "Unable to read %s\n";
3378 case unable_to_seek:
3379 message = "Unable to seek on %s\n";
3381 case unable_to_write:
3382 message = "Unable to write %s\n";
3385 message = "BLKGETSIZE ioctl failed on %s\n";
3388 message = "Fatal error\n";
3391 fputc('\n', stderr);
3392 fprintf(stderr, message, disk_device);
3397 seek_sector(off_t secno)
3399 off_t offset = secno * sector_size;
3400 if (lseek(fd, offset, SEEK_SET) == (off_t) -1)
3401 fdisk_fatal(unable_to_seek);
3404 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3406 write_sector(off_t secno, char *buf)
3409 if (write(fd, buf, sector_size) != sector_size)
3410 fdisk_fatal(unable_to_write);
3414 /* Allocate a buffer and read a partition table sector */
3416 read_pte(struct pte *pe, off_t offset)
3418 pe->offset = offset;
3419 pe->sectorbuffer = (char *) xmalloc(sector_size);
3420 seek_sector(offset);
3421 if (read(fd, pe->sectorbuffer, sector_size) != sector_size)
3422 fdisk_fatal(unable_to_read);
3423 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3426 pe->part_table = pe->ext_pointer = NULL;
3430 get_partition_start(const struct pte *pe)
3432 return pe->offset + get_start_sect(pe->part_table);
3435 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3437 * Avoid warning about DOS partitions when no DOS partition was changed.
3438 * Here a heuristic "is probably dos partition".
3439 * We might also do the opposite and warn in all cases except
3440 * for "is probably nondos partition".
3443 is_dos_partition(int t)
3445 return (t == 1 || t == 4 || t == 6 ||
3446 t == 0x0b || t == 0x0c || t == 0x0e ||
3447 t == 0x11 || t == 0x12 || t == 0x14 || t == 0x16 ||
3448 t == 0x1b || t == 0x1c || t == 0x1e || t == 0x24 ||
3449 t == 0xc1 || t == 0xc4 || t == 0xc6);
3455 #ifdef CONFIG_FEATURE_SUN_LABEL
3456 if (label_sun == current_label_type) {
3457 puts(_("Command action"));
3458 puts(_("\ta\ttoggle a read only flag")); /* sun */
3459 puts(_("\tb\tedit bsd disklabel"));
3460 puts(_("\tc\ttoggle the mountable flag")); /* sun */
3461 puts(_("\td\tdelete a partition"));
3462 puts(_("\tl\tlist known partition types"));
3463 puts(_("\tm\tprint this menu"));
3464 puts(_("\tn\tadd a new partition"));
3465 puts(_("\to\tcreate a new empty DOS partition table"));
3466 puts(_("\tp\tprint the partition table"));
3467 puts(_("\tq\tquit without saving changes"));
3468 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3469 puts(_("\tt\tchange a partition's system id"));
3470 puts(_("\tu\tchange display/entry units"));
3471 puts(_("\tv\tverify the partition table"));
3472 puts(_("\tw\twrite table to disk and exit"));
3473 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3474 puts(_("\tx\textra functionality (experts only)"));
3478 #ifdef CONFIG_FEATURE_SGI_LABEL
3479 if (label_sgi == current_label_type) {
3480 puts(_("Command action"));
3481 puts(_("\ta\tselect bootable partition")); /* sgi flavour */
3482 puts(_("\tb\tedit bootfile entry")); /* sgi */
3483 puts(_("\tc\tselect sgi swap partition")); /* sgi flavour */
3484 puts(_("\td\tdelete a partition"));
3485 puts(_("\tl\tlist known partition types"));
3486 puts(_("\tm\tprint this menu"));
3487 puts(_("\tn\tadd a new partition"));
3488 puts(_("\to\tcreate a new empty DOS partition table"));
3489 puts(_("\tp\tprint the partition table"));
3490 puts(_("\tq\tquit without saving changes"));
3491 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3492 puts(_("\tt\tchange a partition's system id"));
3493 puts(_("\tu\tchange display/entry units"));
3494 puts(_("\tv\tverify the partition table"));
3495 puts(_("\tw\twrite table to disk and exit"));
3498 #ifdef CONFIG_FEATURE_AIX_LABEL
3499 if (label_aix == current_label_type) {
3500 puts(_("Command action"));
3501 puts(_("\tm\tprint this menu"));
3502 puts(_("\to\tcreate a new empty DOS partition table"));
3503 puts(_("\tq\tquit without saving changes"));
3504 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3508 puts(_("Command action"));
3509 puts(_("\ta\ttoggle a bootable flag"));
3510 puts(_("\tb\tedit bsd disklabel"));
3511 puts(_("\tc\ttoggle the dos compatibility flag"));
3512 puts(_("\td\tdelete a partition"));
3513 puts(_("\tl\tlist known partition types"));
3514 puts(_("\tm\tprint this menu"));
3515 puts(_("\tn\tadd a new partition"));
3516 puts(_("\to\tcreate a new empty DOS partition table"));
3517 puts(_("\tp\tprint the partition table"));
3518 puts(_("\tq\tquit without saving changes"));
3519 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3520 puts(_("\tt\tchange a partition's system id"));
3521 puts(_("\tu\tchange display/entry units"));
3522 puts(_("\tv\tverify the partition table"));
3523 puts(_("\tw\twrite table to disk and exit"));
3524 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3525 puts(_("\tx\textra functionality (experts only)"));
3529 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3532 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3536 #ifdef CONFIG_FEATURE_SUN_LABEL
3537 if (label_sun == current_label_type) {
3538 puts(_("Command action"));
3539 puts(_("\ta\tchange number of alternate cylinders")); /*sun*/
3540 puts(_("\tc\tchange number of cylinders"));
3541 puts(_("\td\tprint the raw data in the partition table"));
3542 puts(_("\te\tchange number of extra sectors per cylinder"));/*sun*/
3543 puts(_("\th\tchange number of heads"));
3544 puts(_("\ti\tchange interleave factor")); /*sun*/
3545 puts(_("\to\tchange rotation speed (rpm)")); /*sun*/
3546 puts(_("\tm\tprint this menu"));
3547 puts(_("\tp\tprint the partition table"));
3548 puts(_("\tq\tquit without saving changes"));
3549 puts(_("\tr\treturn to main menu"));
3550 puts(_("\ts\tchange number of sectors/track"));
3551 puts(_("\tv\tverify the partition table"));
3552 puts(_("\tw\twrite table to disk and exit"));
3553 puts(_("\ty\tchange number of physical cylinders")); /*sun*/
3556 #ifdef CONFIG_FEATURE_SGI_LABEL
3557 if (label_sgi == current_label_type) {
3558 puts(_("Command action"));
3559 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3560 puts(_("\tc\tchange number of cylinders"));
3561 puts(_("\td\tprint the raw data in the partition table"));
3562 puts(_("\te\tlist extended partitions")); /* !sun */
3563 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3564 puts(_("\th\tchange number of heads"));
3565 puts(_("\tm\tprint this menu"));
3566 puts(_("\tp\tprint the partition table"));
3567 puts(_("\tq\tquit without saving changes"));
3568 puts(_("\tr\treturn to main menu"));
3569 puts(_("\ts\tchange number of sectors/track"));
3570 puts(_("\tv\tverify the partition table"));
3571 puts(_("\tw\twrite table to disk and exit"));
3574 #ifdef CONFIG_FEATURE_AIX_LABEL
3575 if (label_aix == current_label_type) {
3576 puts(_("Command action"));
3577 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3578 puts(_("\tc\tchange number of cylinders"));
3579 puts(_("\td\tprint the raw data in the partition table"));
3580 puts(_("\te\tlist extended partitions")); /* !sun */
3581 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3582 puts(_("\th\tchange number of heads"));
3583 puts(_("\tm\tprint this menu"));
3584 puts(_("\tp\tprint the partition table"));
3585 puts(_("\tq\tquit without saving changes"));
3586 puts(_("\tr\treturn to main menu"));
3587 puts(_("\ts\tchange number of sectors/track"));
3588 puts(_("\tv\tverify the partition table"));
3589 puts(_("\tw\twrite table to disk and exit"));
3593 puts(_("Command action"));
3594 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3595 puts(_("\tc\tchange number of cylinders"));
3596 puts(_("\td\tprint the raw data in the partition table"));
3597 puts(_("\te\tlist extended partitions")); /* !sun */
3598 puts(_("\tf\tfix partition order")); /* !sun, !aix, !sgi */
3599 #ifdef CONFIG_FEATURE_SGI_LABEL
3600 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3602 puts(_("\th\tchange number of heads"));
3603 puts(_("\tm\tprint this menu"));
3604 puts(_("\tp\tprint the partition table"));
3605 puts(_("\tq\tquit without saving changes"));
3606 puts(_("\tr\treturn to main menu"));
3607 puts(_("\ts\tchange number of sectors/track"));
3608 puts(_("\tv\tverify the partition table"));
3609 puts(_("\tw\twrite table to disk and exit"));
3612 #endif /* ADVANCED mode */
3614 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3615 static const struct systypes *
3619 #ifdef CONFIG_FEATURE_SUN_LABEL
3620 label_sun == current_label_type ? sun_sys_types :
3622 #ifdef CONFIG_FEATURE_SGI_LABEL
3623 label_sgi == current_label_type ? sgi_sys_types :
3628 #define get_sys_types() i386_sys_types
3629 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3631 static const char *partition_type(unsigned char type)
3634 const struct systypes *types = get_sys_types();
3636 for (i = 0; types[i].name; i++)
3637 if ((unsigned char )types[i].name[0] == type)
3638 return types[i].name + 1;
3640 return _("Unknown");
3644 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3649 #ifdef CONFIG_FEATURE_SUN_LABEL
3650 label_sun == current_label_type ? sunlabel->infos[i].id :
3652 #ifdef CONFIG_FEATURE_SGI_LABEL
3653 label_sgi == current_label_type ? sgi_get_sysid(i) :
3655 ptes[i].part_table->sys_ind);
3658 void list_types(const struct systypes *sys)
3660 uint last[4], done = 0, next = 0, size;
3663 for (i = 0; sys[i].name; i++);
3666 for (i = 3; i >= 0; i--)
3667 last[3 - i] = done += (size + i - done) / (i + 1);
3671 printf("%c%2x %-15.15s", i ? ' ' : '\n',
3672 (unsigned char)sys[next].name[0],
3673 partition_type((unsigned char)sys[next].name[0]));
3674 next = last[i++] + done;
3675 if (i > 3 || next >= last[i]) {
3679 } while (done < last[0]);
3682 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3685 is_cleared_partition(const struct partition *p)
3687 return !(!p || p->boot_ind || p->head || p->sector || p->cyl ||
3688 p->sys_ind || p->end_head || p->end_sector || p->end_cyl ||
3689 get_start_sect(p) || get_nr_sects(p));
3693 clear_partition(struct partition *p)
3697 memset(p, 0, sizeof(struct partition));
3700 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3702 set_partition(int i, int doext, off_t start, off_t stop, int sysid)
3704 struct partition *p;
3708 p = ptes[i].ext_pointer;
3709 offset = extended_offset;
3711 p = ptes[i].part_table;
3712 offset = ptes[i].offset;
3716 set_start_sect(p, start - offset);
3717 set_nr_sects(p, stop - start + 1);
3718 if (dos_compatible_flag && (start/(sectors*heads) > 1023))
3719 start = heads*sectors*1024 - 1;
3720 set_hsc(p->head, p->sector, p->cyl, start);
3721 if (dos_compatible_flag && (stop/(sectors*heads) > 1023))
3722 stop = heads*sectors*1024 - 1;
3723 set_hsc(p->end_head, p->end_sector, p->end_cyl, stop);
3724 ptes[i].changed = 1;
3729 test_c(const char **m, const char *mesg)
3733 fprintf(stderr, _("You must set"));
3735 fprintf(stderr, " %s", *m);
3745 const char *m = NULL;
3749 prev = test_c(&m, _("heads"));
3751 prev = test_c(&m, _("sectors"));
3753 prev = test_c(&m, _("cylinders"));
3757 fprintf(stderr, "%s%s.\n"
3758 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3759 "You can do this from the extra functions menu.\n"
3761 , prev ? _(" and ") : " ", m);
3766 static void update_units(void)
3768 int cyl_units = heads * sectors;
3770 if (display_in_cyl_units && cyl_units)
3771 units_per_sector = cyl_units;
3773 units_per_sector = 1; /* in sectors */
3776 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3778 warn_cylinders(void)
3780 if (label_dos == current_label_type && cylinders > 1024 && !nowarn)
3781 fprintf(stderr, _("\n"
3782 "The number of cylinders for this disk is set to %d.\n"
3783 "There is nothing wrong with that, but this is larger than 1024,\n"
3784 "and could in certain setups cause problems with:\n"
3785 "1) software that runs at boot time (e.g., old versions of LILO)\n"
3786 "2) booting and partitioning software from other OSs\n"
3787 " (e.g., DOS FDISK, OS/2 FDISK)\n"),
3793 read_extended(int ext)
3797 struct partition *p, *q;
3801 pex->ext_pointer = pex->part_table;
3803 p = pex->part_table;
3804 if (!get_start_sect(p)) {
3806 _("Bad offset in primary extended partition\n"));
3810 while (IS_EXTENDED(p->sys_ind)) {
3811 struct pte *pe = &ptes[partitions];
3813 if (partitions >= MAXIMUM_PARTS) {
3814 /* This is not a Linux restriction, but
3815 this program uses arrays of size MAXIMUM_PARTS.
3816 Do not try to `improve' this test. */
3817 struct pte *pre = &ptes[partitions-1];
3818 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3820 _("Warning: deleting partitions after %d\n"),
3824 clear_partition(pre->ext_pointer);
3828 read_pte(pe, extended_offset + get_start_sect(p));
3830 if (!extended_offset)
3831 extended_offset = get_start_sect(p);
3833 q = p = pt_offset(pe->sectorbuffer, 0);
3834 for (i = 0; i < 4; i++, p++) if (get_nr_sects(p)) {
3835 if (IS_EXTENDED(p->sys_ind)) {
3836 if (pe->ext_pointer)
3838 _("Warning: extra link "
3839 "pointer in partition table"
3840 " %d\n"), partitions + 1);
3842 pe->ext_pointer = p;
3843 } else if (p->sys_ind) {
3846 _("Warning: ignoring extra "
3847 "data in partition table"
3848 " %d\n"), partitions + 1);
3854 /* very strange code here... */
3855 if (!pe->part_table) {
3856 if (q != pe->ext_pointer)
3859 pe->part_table = q + 1;
3861 if (!pe->ext_pointer) {
3862 if (q != pe->part_table)
3863 pe->ext_pointer = q;
3865 pe->ext_pointer = q + 1;
3868 p = pe->ext_pointer;
3872 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3873 /* remove empty links */
3875 for (i = 4; i < partitions; i++) {
3876 struct pte *pe = &ptes[i];
3878 if (!get_nr_sects(pe->part_table) &&
3879 (partitions > 5 || ptes[4].part_table->sys_ind)) {
3880 printf("omitting empty partition (%d)\n", i+1);
3881 delete_partition(i);
3882 goto remove; /* numbering changed */
3888 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3890 create_doslabel(void)
3895 _("Building a new DOS disklabel. Changes will remain in memory only,\n"
3896 "until you decide to write them. After that, of course, the previous\n"
3897 "content won't be recoverable.\n\n"));
3899 current_label_type = label_dos;
3901 #ifdef CONFIG_FEATURE_OSF_LABEL
3902 possibly_osf_label = 0;
3906 for (i = 510-64; i < 510; i++)
3908 write_part_table_flag(MBRbuffer);
3909 extended_offset = 0;
3910 set_all_unchanged();
3912 get_boot(create_empty_dos);
3914 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3917 get_sectorsize(void)
3919 if (!user_set_sector_size) {
3921 if (ioctl(fd, BLKSSZGET, &arg) == 0)
3923 if (sector_size != DEFAULT_SECTOR_SIZE)
3924 printf(_("Note: sector size is %d (not %d)\n"),
3925 sector_size, DEFAULT_SECTOR_SIZE);
3930 get_kernel_geometry(void)
3932 struct hd_geometry geometry;
3934 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
3935 kern_heads = geometry.heads;
3936 kern_sectors = geometry.sectors;
3937 /* never use geometry.cylinders - it is truncated */
3942 get_partition_table_geometry(void)
3944 const unsigned char *bufp = (const unsigned char *)MBRbuffer;
3945 struct partition *p;
3946 int i, h, s, hh, ss;
3950 if (!(valid_part_table_flag((char*)bufp)))
3954 for (i = 0; i < 4; i++) {
3955 p = pt_offset(bufp, i);
3956 if (p->sys_ind != 0) {
3957 h = p->end_head + 1;
3958 s = (p->end_sector & 077);
3963 } else if (hh != h || ss != s)
3968 if (!first && !bad) {
3978 unsigned long long bytes; /* really u64 */
3981 sec_fac = sector_size / 512;
3982 #ifdef CONFIG_FEATURE_SUN_LABEL
3983 guess_device_type();
3985 heads = cylinders = sectors = 0;
3986 kern_heads = kern_sectors = 0;
3987 pt_heads = pt_sectors = 0;
3989 get_kernel_geometry();
3990 get_partition_table_geometry();
3992 heads = user_heads ? user_heads :
3993 pt_heads ? pt_heads :
3994 kern_heads ? kern_heads : 255;
3995 sectors = user_sectors ? user_sectors :
3996 pt_sectors ? pt_sectors :
3997 kern_sectors ? kern_sectors : 63;
3998 if (ioctl(fd, BLKGETSIZE64, &bytes) == 0) {
4001 unsigned long longsectors;
4003 if (ioctl(fd, BLKGETSIZE, &longsectors))
4005 bytes = ((unsigned long long) longsectors) << 9;
4008 total_number_of_sectors = (bytes >> 9);
4011 if (dos_compatible_flag)
4012 sector_offset = sectors;
4014 cylinders = total_number_of_sectors / (heads * sectors * sec_fac);
4016 cylinders = user_cylinders;
4020 * Read MBR. Returns:
4021 * -1: no 0xaa55 flag present (possibly entire disk BSD)
4022 * 0: found or created label
4026 get_boot(enum action what)
4032 for (i = 0; i < 4; i++) {
4033 struct pte *pe = &ptes[i];
4035 pe->part_table = pt_offset(MBRbuffer, i);
4036 pe->ext_pointer = NULL;
4038 pe->sectorbuffer = MBRbuffer;
4039 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4040 pe->changed = (what == create_empty_dos);
4044 #ifdef CONFIG_FEATURE_SUN_LABEL
4045 if (what == create_empty_sun && check_sun_label())
4049 memset(MBRbuffer, 0, 512);
4051 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4052 if (what == create_empty_dos)
4053 goto got_dos_table; /* skip reading disk */
4055 if ((fd = open(disk_device, type_open)) < 0) {
4056 if ((fd = open(disk_device, O_RDONLY)) < 0) {
4057 if (what == try_only)
4059 fdisk_fatal(unable_to_open);
4061 printf(_("You will not be able to write "
4062 "the partition table.\n"));
4065 if (512 != read(fd, MBRbuffer, 512)) {
4066 if (what == try_only)
4068 fdisk_fatal(unable_to_read);
4071 if ((fd = open(disk_device, O_RDONLY)) < 0)
4073 if (512 != read(fd, MBRbuffer, 512))
4081 #ifdef CONFIG_FEATURE_SUN_LABEL
4082 if (check_sun_label())
4086 #ifdef CONFIG_FEATURE_SGI_LABEL
4087 if (check_sgi_label())
4091 #ifdef CONFIG_FEATURE_AIX_LABEL
4092 if (check_aix_label())
4096 #ifdef CONFIG_FEATURE_OSF_LABEL
4097 if (check_osf_label()) {
4098 possibly_osf_label = 1;
4099 if (!valid_part_table_flag(MBRbuffer)) {
4100 current_label_type = label_osf;
4103 printf(_("This disk has both DOS and BSD magic.\n"
4104 "Give the 'b' command to go to BSD mode.\n"));
4108 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4112 if (!valid_part_table_flag(MBRbuffer)) {
4113 #ifndef CONFIG_FEATURE_FDISK_WRITABLE
4119 _("Device contains neither a valid DOS "
4120 "partition table, nor Sun, SGI or OSF "
4123 #ifdef CONFIG_FEATURE_SUN_LABEL
4132 case create_empty_dos:
4133 #ifdef CONFIG_FEATURE_SUN_LABEL
4134 case create_empty_sun:
4138 fprintf(stderr, _("Internal error\n"));
4141 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
4144 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4149 for (i = 0; i < 4; i++) {
4150 struct pte *pe = &ptes[i];
4152 if (IS_EXTENDED(pe->part_table->sys_ind)) {
4153 if (partitions != 4)
4154 fprintf(stderr, _("Ignoring extra extended "
4155 "partition %d\n"), i + 1);
4161 for (i = 3; i < partitions; i++) {
4162 struct pte *pe = &ptes[i];
4164 if (!valid_part_table_flag(pe->sectorbuffer)) {
4166 _("Warning: invalid flag 0x%04x of partition "
4167 "table %d will be corrected by w(rite)\n"),
4168 part_table_flag(pe->sectorbuffer), i + 1);
4169 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4178 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4180 * Print the message MESG, then read an integer between LOW and HIGH (inclusive).
4181 * If the user hits Enter, DFLT is returned.
4182 * Answers like +10 are interpreted as offsets from BASE.
4184 * There is no default if DFLT is not between LOW and HIGH.
4187 read_int(uint low, uint dflt, uint high, uint base, char *mesg)
4191 static char *ms = NULL;
4192 static int mslen = 0;
4194 if (!ms || strlen(mesg)+100 > mslen) {
4195 mslen = strlen(mesg)+200;
4196 ms = xrealloc(ms,mslen);
4199 if (dflt < low || dflt > high)
4203 snprintf(ms, mslen, _("%s (%u-%u, default %u): "),
4204 mesg, low, high, dflt);
4206 snprintf(ms, mslen, "%s (%u-%u): ", mesg, low, high);
4209 int use_default = default_ok;
4211 /* ask question and read answer */
4212 while (read_chars(ms) != '\n' && !isdigit(*line_ptr)
4213 && *line_ptr != '-' && *line_ptr != '+')
4216 if (*line_ptr == '+' || *line_ptr == '-') {
4217 int minus = (*line_ptr == '-');
4220 i = atoi(line_ptr+1);
4222 while (isdigit(*++line_ptr))
4225 switch (*line_ptr) {
4228 if (!display_in_cyl_units)
4229 i *= heads * sectors;
4243 absolute = 1000000000;
4249 unsigned long long bytes;
4252 bytes = (unsigned long long) i * absolute;
4253 unit = sector_size * units_per_sector;
4254 bytes += unit/2; /* round */
4263 while (isdigit(*line_ptr)) {
4269 printf(_("Using default value %u\n"), i = dflt);
4270 if (i >= low && i <= high)
4273 printf(_("Value out of range.\n"));
4279 get_partition(int warn, int max)
4284 i = read_int(1, 0, max, 0, _("Partition number")) - 1;
4290 label_sun != current_label_type &&
4291 label_sgi != current_label_type &&
4292 !pe->part_table->sys_ind
4294 #ifdef CONFIG_FEATURE_SUN_LABEL
4296 label_sun == current_label_type &&
4298 !sunlabel->partitions[i].num_sectors
4299 || !sunlabel->infos[i].id
4303 #ifdef CONFIG_FEATURE_SGI_LABEL
4305 label_sgi == current_label_type &&
4306 !sgi_get_num_sectors(i)
4311 _("Warning: partition %d has empty type\n"),
4320 get_existing_partition(int warn, int max)
4325 for (i = 0; i < max; i++) {
4326 struct pte *pe = &ptes[i];
4327 struct partition *p = pe->part_table;
4329 if (p && !is_cleared_partition(p)) {
4336 printf(_("Selected partition %d\n"), pno+1);
4339 printf(_("No partition is defined yet!\n"));
4343 return get_partition(warn, max);
4347 get_nonexisting_partition(int warn, int max)
4352 for (i = 0; i < max; i++) {
4353 struct pte *pe = &ptes[i];
4354 struct partition *p = pe->part_table;
4356 if (p && is_cleared_partition(p)) {
4363 printf(_("Selected partition %d\n"), pno+1);
4366 printf(_("All primary partitions have been defined already!\n"));
4370 return get_partition(warn, max);
4374 void change_units(void)
4376 display_in_cyl_units = !display_in_cyl_units;
4378 printf(_("Changing display/entry units to %s\n"),
4383 toggle_active(int i)
4385 struct pte *pe = &ptes[i];
4386 struct partition *p = pe->part_table;
4388 if (IS_EXTENDED(p->sys_ind) && !p->boot_ind)
4390 _("WARNING: Partition %d is an extended partition\n"),
4392 p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG);
4397 toggle_dos_compatibility_flag(void)
4399 dos_compatible_flag = ~dos_compatible_flag;
4400 if (dos_compatible_flag) {
4401 sector_offset = sectors;
4402 printf(_("DOS Compatibility flag is set\n"));
4406 printf(_("DOS Compatibility flag is not set\n"));
4411 delete_partition(int i)
4413 struct pte *pe = &ptes[i];
4414 struct partition *p = pe->part_table;
4415 struct partition *q = pe->ext_pointer;
4417 /* Note that for the fifth partition (i == 4) we don't actually
4418 * decrement partitions.
4421 if (warn_geometry())
4422 return; /* C/H/S not set */
4425 #ifdef CONFIG_FEATURE_SUN_LABEL
4426 if (label_sun == current_label_type) {
4427 sun_delete_partition(i);
4431 #ifdef CONFIG_FEATURE_SGI_LABEL
4432 if (label_sgi == current_label_type) {
4433 sgi_delete_partition(i);
4439 if (IS_EXTENDED(p->sys_ind) && i == ext_index) {
4441 ptes[ext_index].ext_pointer = NULL;
4442 extended_offset = 0;
4448 if (!q->sys_ind && i > 4) {
4449 /* the last one in the chain - just delete */
4452 clear_partition(ptes[i].ext_pointer);
4453 ptes[i].changed = 1;
4455 /* not the last one - further ones will be moved down */
4457 /* delete this link in the chain */
4458 p = ptes[i-1].ext_pointer;
4460 set_start_sect(p, get_start_sect(q));
4461 set_nr_sects(p, get_nr_sects(q));
4462 ptes[i-1].changed = 1;
4463 } else if (partitions > 5) { /* 5 will be moved to 4 */
4464 /* the first logical in a longer chain */
4467 if (pe->part_table) /* prevent SEGFAULT */
4468 set_start_sect(pe->part_table,
4469 get_partition_start(pe) -
4471 pe->offset = extended_offset;
4475 if (partitions > 5) {
4477 while (i < partitions) {
4478 ptes[i] = ptes[i+1];
4482 /* the only logical: clear only */
4483 clear_partition(ptes[i].part_table);
4490 int i, sys, origsys;
4491 struct partition *p;
4493 #ifdef CONFIG_FEATURE_SGI_LABEL
4494 /* If sgi_label then don't use get_existing_partition,
4495 let the user select a partition, since get_existing_partition()
4496 only works for Linux like partition tables. */
4497 if (label_sgi != current_label_type) {
4498 i = get_existing_partition(0, partitions);
4500 i = get_partition(0, partitions);
4503 i = get_existing_partition(0, partitions);
4507 p = ptes[i].part_table;
4508 origsys = sys = get_sysid(i);
4510 /* if changing types T to 0 is allowed, then
4511 the reverse change must be allowed, too */
4512 if (!sys && label_sgi != current_label_type &&
4513 label_sun != current_label_type && !get_nr_sects(p))
4515 printf(_("Partition %d does not exist yet!\n"), i + 1);
4518 sys = read_hex (get_sys_types());
4520 if (!sys && label_sgi != current_label_type &&
4521 label_sun != current_label_type)
4523 printf(_("Type 0 means free space to many systems\n"
4524 "(but not to Linux). Having partitions of\n"
4525 "type 0 is probably unwise. You can delete\n"
4526 "a partition using the `d' command.\n"));
4530 if (label_sun != current_label_type && label_sgi != current_label_type) {
4531 if (IS_EXTENDED(sys) != IS_EXTENDED(p->sys_ind)) {
4532 printf(_("You cannot change a partition into"
4533 " an extended one or vice versa\n"
4534 "Delete it first.\n"));
4540 #ifdef CONFIG_FEATURE_SUN_LABEL
4541 if (label_sun == current_label_type && i == 2 && sys != WHOLE_DISK)
4542 printf(_("Consider leaving partition 3 "
4543 "as Whole disk (5),\n"
4544 "as SunOS/Solaris expects it and "
4545 "even Linux likes it.\n\n"));
4547 #ifdef CONFIG_FEATURE_SGI_LABEL
4548 if (label_sgi == current_label_type &&
4550 (i == 10 && sys != ENTIRE_DISK) ||
4551 (i == 8 && sys != 0)
4554 printf(_("Consider leaving partition 9 "
4555 "as volume header (0),\nand "
4556 "partition 11 as entire volume (6)"
4557 "as IRIX expects it.\n\n"));
4562 #ifdef CONFIG_FEATURE_SUN_LABEL
4563 if (label_sun == current_label_type) {
4564 sun_change_sysid(i, sys);
4567 #ifdef CONFIG_FEATURE_SGI_LABEL
4568 if (label_sgi == current_label_type) {
4569 sgi_change_sysid(i, sys);
4574 printf(_("Changed system type of partition %d "
4575 "to %x (%s)\n"), i + 1, sys,
4576 partition_type(sys));
4577 ptes[i].changed = 1;
4578 if (is_dos_partition(origsys) ||
4579 is_dos_partition(sys))
4586 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
4589 /* check_consistency() and long2chs() added Sat Mar 6 12:28:16 1993,
4590 * faith@cs.unc.edu, based on code fragments from pfdisk by Gordon W. Ross,
4591 * Jan. 1990 (version 1.2.1 by Gordon W. Ross Aug. 1990; Modified by S.
4592 * Lubkin Oct. 1991). */
4595 long2chs(ulong ls, uint *c, uint *h, uint *s)
4597 int spc = heads * sectors;
4602 *s = ls % sectors + 1; /* sectors count from 1 */
4606 check_consistency(const struct partition *p, int partition)
4608 uint pbc, pbh, pbs; /* physical beginning c, h, s */
4609 uint pec, peh, pes; /* physical ending c, h, s */
4610 uint lbc, lbh, lbs; /* logical beginning c, h, s */
4611 uint lec, leh, les; /* logical ending c, h, s */
4613 if (!heads || !sectors || (partition >= 4))
4614 return; /* do not check extended partitions */
4616 /* physical beginning c, h, s */
4617 pbc = (p->cyl & 0xff) | ((p->sector << 2) & 0x300);
4619 pbs = p->sector & 0x3f;
4621 /* physical ending c, h, s */
4622 pec = (p->end_cyl & 0xff) | ((p->end_sector << 2) & 0x300);
4624 pes = p->end_sector & 0x3f;
4626 /* compute logical beginning (c, h, s) */
4627 long2chs(get_start_sect(p), &lbc, &lbh, &lbs);
4629 /* compute logical ending (c, h, s) */
4630 long2chs(get_start_sect(p) + get_nr_sects(p) - 1, &lec, &leh, &les);
4632 /* Same physical / logical beginning? */
4633 if (cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) {
4634 printf(_("Partition %d has different physical/logical "
4635 "beginnings (non-Linux?):\n"), partition + 1);
4636 printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs);
4637 printf(_("logical=(%d, %d, %d)\n"),lbc, lbh, lbs);
4640 /* Same physical / logical ending? */
4641 if (cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) {
4642 printf(_("Partition %d has different physical/logical "
4643 "endings:\n"), partition + 1);
4644 printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
4645 printf(_("logical=(%d, %d, %d)\n"),lec, leh, les);
4649 /* Beginning on cylinder boundary? */
4650 if (pbh != !pbc || pbs != 1) {
4651 printf(_("Partition %i does not start on cylinder "
4652 "boundary:\n"), partition + 1);
4653 printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs);
4654 printf(_("should be (%d, %d, 1)\n"), pbc, !pbc);
4658 /* Ending on cylinder boundary? */
4659 if (peh != (heads - 1) || pes != sectors) {
4660 printf(_("Partition %i does not end on cylinder boundary.\n"),
4663 printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
4664 printf(_("should be (%d, %d, %d)\n"),
4665 pec, heads - 1, sectors);
4671 list_disk_geometry(void)
4673 long long bytes = (total_number_of_sectors << 9);
4674 long megabytes = bytes/1000000;
4676 if (megabytes < 10000)
4677 printf(_("\nDisk %s: %ld MB, %lld bytes\n"),
4678 disk_device, megabytes, bytes);
4680 printf(_("\nDisk %s: %ld.%ld GB, %lld bytes\n"),
4681 disk_device, megabytes/1000, (megabytes/100)%10, bytes);
4682 printf(_("%d heads, %d sectors/track, %d cylinders"),
4683 heads, sectors, cylinders);
4684 if (units_per_sector == 1)
4685 printf(_(", total %llu sectors"),
4686 total_number_of_sectors / (sector_size/512));
4687 printf(_("\nUnits = %s of %d * %d = %d bytes\n\n"),
4689 units_per_sector, sector_size, units_per_sector * sector_size);
4693 * Check whether partition entries are ordered by their starting positions.
4694 * Return 0 if OK. Return i if partition i should have been earlier.
4695 * Two separate checks: primary and logical partitions.
4698 wrong_p_order(int *prev)
4700 const struct pte *pe;
4701 const struct partition *p;
4702 off_t last_p_start_pos = 0, p_start_pos;
4705 for (i = 0 ; i < partitions; i++) {
4708 last_p_start_pos = 0;
4711 if ((p = pe->part_table)->sys_ind) {
4712 p_start_pos = get_partition_start(pe);
4714 if (last_p_start_pos > p_start_pos) {
4720 last_p_start_pos = p_start_pos;
4727 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
4729 * Fix the chain of logicals.
4730 * extended_offset is unchanged, the set of sectors used is unchanged
4731 * The chain is sorted so that sectors increase, and so that
4732 * starting sectors increase.
4734 * After this it may still be that cfdisk doesnt like the table.
4735 * (This is because cfdisk considers expanded parts, from link to
4736 * end of partition, and these may still overlap.)
4738 * sfdisk /dev/hda > ohda; sfdisk /dev/hda < ohda
4742 fix_chain_of_logicals(void)
4744 int j, oj, ojj, sj, sjj;
4745 struct partition *pj,*pjj,tmp;
4747 /* Stage 1: sort sectors but leave sector of part 4 */
4748 /* (Its sector is the global extended_offset.) */
4750 for (j = 5; j < partitions-1; j++) {
4751 oj = ptes[j].offset;
4752 ojj = ptes[j+1].offset;
4754 ptes[j].offset = ojj;
4755 ptes[j+1].offset = oj;
4756 pj = ptes[j].part_table;
4757 set_start_sect(pj, get_start_sect(pj)+oj-ojj);
4758 pjj = ptes[j+1].part_table;
4759 set_start_sect(pjj, get_start_sect(pjj)+ojj-oj);
4760 set_start_sect(ptes[j-1].ext_pointer,
4761 ojj-extended_offset);
4762 set_start_sect(ptes[j].ext_pointer,
4763 oj-extended_offset);
4768 /* Stage 2: sort starting sectors */
4770 for (j = 4; j < partitions-1; j++) {
4771 pj = ptes[j].part_table;
4772 pjj = ptes[j+1].part_table;
4773 sj = get_start_sect(pj);
4774 sjj = get_start_sect(pjj);
4775 oj = ptes[j].offset;
4776 ojj = ptes[j+1].offset;
4777 if (oj+sj > ojj+sjj) {
4781 set_start_sect(pj, ojj+sjj-oj);
4782 set_start_sect(pjj, oj+sj-ojj);
4787 /* Probably something was changed */
4788 for (j = 4; j < partitions; j++)
4789 ptes[j].changed = 1;
4794 fix_partition_table_order(void)
4796 struct pte *pei, *pek;
4799 if (!wrong_p_order(NULL)) {
4800 printf(_("Nothing to do. Ordering is correct already.\n\n"));
4804 while ((i = wrong_p_order(&k)) != 0 && i < 4) {
4805 /* partition i should have come earlier, move it */
4806 /* We have to move data in the MBR */
4807 struct partition *pi, *pk, *pe, pbuf;
4811 pe = pei->ext_pointer;
4812 pei->ext_pointer = pek->ext_pointer;
4813 pek->ext_pointer = pe;
4815 pi = pei->part_table;
4816 pk = pek->part_table;
4818 memmove(&pbuf, pi, sizeof(struct partition));
4819 memmove(pi, pk, sizeof(struct partition));
4820 memmove(pk, &pbuf, sizeof(struct partition));
4822 pei->changed = pek->changed = 1;
4826 fix_chain_of_logicals();
4834 list_table(int xtra)
4836 const struct partition *p;
4839 #ifdef CONFIG_FEATURE_SUN_LABEL
4840 if (label_sun == current_label_type) {
4841 sun_list_table(xtra);
4846 #ifdef CONFIG_FEATURE_SGI_LABEL
4847 if (label_sgi == current_label_type) {
4848 sgi_list_table(xtra);
4853 list_disk_geometry();
4855 #ifdef CONFIG_FEATURE_OSF_LABEL
4856 if (label_osf == current_label_type) {
4857 xbsd_print_disklabel(xtra);
4862 /* Heuristic: we list partition 3 of /dev/foo as /dev/foo3,
4863 but if the device name ends in a digit, say /dev/foo1,
4864 then the partition is called /dev/foo1p3. */
4865 w = strlen(disk_device);
4866 if (w && isdigit(disk_device[w-1]))
4871 printf(_("%*s Boot Start End Blocks Id System\n"),
4874 for (i = 0; i < partitions; i++) {
4875 const struct pte *pe = &ptes[i];
4878 if (p && !is_cleared_partition(p)) {
4879 off_t psects = get_nr_sects(p);
4880 off_t pblocks = psects;
4881 unsigned int podd = 0;
4883 if (sector_size < 1024) {
4884 pblocks /= (1024 / sector_size);
4885 podd = psects % (1024 / sector_size);
4887 if (sector_size > 1024)
4888 pblocks *= (sector_size / 1024);
4890 "%s %c %11llu %11llu %11llu%c %2x %s\n",
4891 partname(disk_device, i+1, w+2),
4892 /* boot flag */ !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG
4894 /* start */ (unsigned long long) cround(get_partition_start(pe)),
4895 /* end */ (unsigned long long) cround(get_partition_start(pe) + psects
4896 - (psects ? 1 : 0)),
4897 /* odd flag on end */ (unsigned long long) pblocks, podd ? '+' : ' ',
4898 /* type id */ p->sys_ind,
4899 /* type name */ partition_type(p->sys_ind));
4900 check_consistency(p, i);
4904 /* Is partition table in disk order? It need not be, but... */
4905 /* partition table entries are not checked for correct order if this
4906 is a sgi, sun or aix labeled disk... */
4907 if (label_dos == current_label_type && wrong_p_order(NULL)) {
4909 printf(_("\nPartition table entries are not in disk order\n"));
4913 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
4915 x_list_table(int extend)
4917 const struct pte *pe;
4918 const struct partition *p;
4921 printf(_("\nDisk %s: %d heads, %d sectors, %d cylinders\n\n"),
4922 disk_device, heads, sectors, cylinders);
4923 printf(_("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n"));
4924 for (i = 0 ; i < partitions; i++) {
4926 p = (extend ? pe->ext_pointer : pe->part_table);
4928 printf("%2d %02x%4d%4d%5d%4d%4d%5d%11u%11u %02x\n",
4929 i + 1, p->boot_ind, p->head,
4931 cylinder(p->sector, p->cyl), p->end_head,
4932 sector(p->end_sector),
4933 cylinder(p->end_sector, p->end_cyl),
4934 get_start_sect(p), get_nr_sects(p), p->sys_ind);
4936 check_consistency(p, i);
4942 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4944 fill_bounds(off_t *first, off_t *last)
4947 const struct pte *pe = &ptes[0];
4948 const struct partition *p;
4950 for (i = 0; i < partitions; pe++,i++) {
4952 if (!p->sys_ind || IS_EXTENDED(p->sys_ind)) {
4953 first[i] = 0xffffffff;
4956 first[i] = get_partition_start(pe);
4957 last[i] = first[i] + get_nr_sects(p) - 1;
4963 check(int n, uint h, uint s, uint c, off_t start)
4965 off_t total, real_s, real_c;
4967 real_s = sector(s) - 1;
4968 real_c = cylinder(s, c);
4969 total = (real_c * sectors + real_s) * heads + h;
4971 fprintf(stderr, _("Warning: partition %d contains sector 0\n"), n);
4974 _("Partition %d: head %d greater than maximum %d\n"),
4976 if (real_s >= sectors)
4977 fprintf(stderr, _("Partition %d: sector %d greater than "
4978 "maximum %d\n"), n, s, sectors);
4979 if (real_c >= cylinders)
4980 fprintf(stderr, _("Partitions %d: cylinder %llu greater than "
4981 "maximum %d\n"), n, (unsigned long long)real_c + 1, cylinders);
4982 if (cylinders <= 1024 && start != total)
4984 _("Partition %d: previous sectors %llu disagrees with "
4985 "total %llu\n"), n, (unsigned long long)start, (unsigned long long)total);
4993 off_t first[partitions], last[partitions];
4994 struct partition *p;
4996 if (warn_geometry())
4999 #ifdef CONFIG_FEATURE_SUN_LABEL
5000 if (label_sun == current_label_type) {
5005 #ifdef CONFIG_FEATURE_SGI_LABEL
5006 if (label_sgi == current_label_type) {
5012 fill_bounds(first, last);
5013 for (i = 0; i < partitions; i++) {
5014 struct pte *pe = &ptes[i];
5017 if (p->sys_ind && !IS_EXTENDED(p->sys_ind)) {
5018 check_consistency(p, i);
5019 if (get_partition_start(pe) < first[i])
5020 printf(_("Warning: bad start-of-data in "
5021 "partition %d\n"), i + 1);
5022 check(i + 1, p->end_head, p->end_sector, p->end_cyl,
5024 total += last[i] + 1 - first[i];
5025 for (j = 0; j < i; j++)
5026 if ((first[i] >= first[j] && first[i] <= last[j])
5027 || ((last[i] <= last[j] && last[i] >= first[j]))) {
5028 printf(_("Warning: partition %d overlaps "
5029 "partition %d.\n"), j + 1, i + 1);
5030 total += first[i] >= first[j] ?
5031 first[i] : first[j];
5032 total -= last[i] <= last[j] ?
5038 if (extended_offset) {
5039 struct pte *pex = &ptes[ext_index];
5040 off_t e_last = get_start_sect(pex->part_table) +
5041 get_nr_sects(pex->part_table) - 1;
5043 for (i = 4; i < partitions; i++) {
5045 p = ptes[i].part_table;
5047 if (i != 4 || i + 1 < partitions)
5048 printf(_("Warning: partition %d "
5049 "is empty\n"), i + 1);
5051 else if (first[i] < extended_offset ||
5053 printf(_("Logical partition %d not entirely in "
5054 "partition %d\n"), i + 1, ext_index + 1);
5058 if (total > heads * sectors * cylinders)
5059 printf(_("Total allocated sectors %d greater than the maximum "
5060 "%d\n"), total, heads * sectors * cylinders);
5061 else if ((total = heads * sectors * cylinders - total) != 0)
5062 printf(_("%d unallocated sectors\n"), total);
5066 add_partition(int n, int sys)
5068 char mesg[256]; /* 48 does not suffice in Japanese */
5069 int i, num_read = 0;
5070 struct partition *p = ptes[n].part_table;
5071 struct partition *q = ptes[ext_index].part_table;
5073 off_t start, stop = 0, limit, temp,
5074 first[partitions], last[partitions];
5076 if (p && p->sys_ind) {
5077 printf(_("Partition %d is already defined. Delete "
5078 "it before re-adding it.\n"), n + 1);
5081 fill_bounds(first, last);
5083 start = sector_offset;
5084 if (display_in_cyl_units || !total_number_of_sectors)
5085 llimit = heads * sectors * cylinders - 1;
5087 llimit = total_number_of_sectors - 1;
5089 if (limit != llimit)
5091 if (extended_offset) {
5092 first[ext_index] = extended_offset;
5093 last[ext_index] = get_start_sect(q) +
5094 get_nr_sects(q) - 1;
5097 start = extended_offset + sector_offset;
5098 limit = get_start_sect(q) + get_nr_sects(q) - 1;
5100 if (display_in_cyl_units)
5101 for (i = 0; i < partitions; i++)
5102 first[i] = (cround(first[i]) - 1) * units_per_sector;
5104 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
5107 for (i = 0; i < partitions; i++) {
5110 if (start == ptes[i].offset)
5111 start += sector_offset;
5112 lastplusoff = last[i] + ((n < 4) ? 0 : sector_offset);
5113 if (start >= first[i] && start <= lastplusoff)
5114 start = lastplusoff + 1;
5118 if (start >= temp+units_per_sector && num_read) {
5119 printf(_("Sector %llu is already allocated\n"), (unsigned long long)temp);
5123 if (!num_read && start == temp) {
5126 saved_start = start;
5127 start = read_int(cround(saved_start), cround(saved_start), cround(limit),
5129 if (display_in_cyl_units) {
5130 start = (start - 1) * units_per_sector;
5131 if (start < saved_start) start = saved_start;
5135 } while (start != temp || !num_read);
5136 if (n > 4) { /* NOT for fifth partition */
5137 struct pte *pe = &ptes[n];
5139 pe->offset = start - sector_offset;
5140 if (pe->offset == extended_offset) { /* must be corrected */
5142 if (sector_offset == 1)
5147 for (i = 0; i < partitions; i++) {
5148 struct pte *pe = &ptes[i];
5150 if (start < pe->offset && limit >= pe->offset)
5151 limit = pe->offset - 1;
5152 if (start < first[i] && limit >= first[i])
5153 limit = first[i] - 1;
5155 if (start > limit) {
5156 printf(_("No free sectors available\n"));
5161 if (cround(start) == cround(limit)) {
5164 snprintf(mesg, sizeof(mesg),
5165 _("Last %s or +size or +sizeM or +sizeK"),
5166 str_units(SINGULAR));
5167 stop = read_int(cround(start), cround(limit), cround(limit),
5168 cround(start), mesg);
5169 if (display_in_cyl_units) {
5170 stop = stop * units_per_sector - 1;
5176 set_partition(n, 0, start, stop, sys);
5178 set_partition(n - 1, 1, ptes[n].offset, stop, EXTENDED);
5180 if (IS_EXTENDED(sys)) {
5181 struct pte *pe4 = &ptes[4];
5182 struct pte *pen = &ptes[n];
5185 pen->ext_pointer = p;
5186 pe4->offset = extended_offset = start;
5187 pe4->sectorbuffer = xcalloc(1, sector_size);
5188 pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
5189 pe4->ext_pointer = pe4->part_table + 1;
5198 if (partitions > 5 || ptes[4].part_table->sys_ind) {
5199 struct pte *pe = &ptes[partitions];
5201 pe->sectorbuffer = xcalloc(1, sector_size);
5202 pe->part_table = pt_offset(pe->sectorbuffer, 0);
5203 pe->ext_pointer = pe->part_table + 1;
5208 add_partition(partitions - 1, LINUX_NATIVE);
5214 int i, free_primary = 0;
5216 if (warn_geometry())
5219 #ifdef CONFIG_FEATURE_SUN_LABEL
5220 if (label_sun == current_label_type) {
5221 add_sun_partition(get_partition(0, partitions), LINUX_NATIVE);
5225 #ifdef CONFIG_FEATURE_SGI_LABEL
5226 if (label_sgi == current_label_type) {
5227 sgi_add_partition(get_partition(0, partitions), LINUX_NATIVE);
5231 #ifdef CONFIG_FEATURE_AIX_LABEL
5232 if (label_aix == current_label_type) {
5233 printf(_("\tSorry - this fdisk cannot handle AIX disk labels."
5234 "\n\tIf you want to add DOS-type partitions, create"
5235 "\n\ta new empty DOS partition table first. (Use o.)"
5237 "This will destroy the present disk contents.\n"));
5242 for (i = 0; i < 4; i++)
5243 free_primary += !ptes[i].part_table->sys_ind;
5245 if (!free_primary && partitions >= MAXIMUM_PARTS) {
5246 printf(_("The maximum number of partitions has been created\n"));
5250 if (!free_primary) {
5251 if (extended_offset)
5254 printf(_("You must delete some partition and add "
5255 "an extended partition first\n"));
5257 char c, line[LINE_LENGTH];
5258 snprintf(line, sizeof(line), "%s\n %s\n p primary "
5259 "partition (1-4)\n",
5260 "Command action", (extended_offset ?
5261 "l logical (5 or over)" : "e extended"));
5263 if ((c = read_char(line)) == 'p' || c == 'P') {
5264 i = get_nonexisting_partition(0, 4);
5266 add_partition(i, LINUX_NATIVE);
5269 else if (c == 'l' && extended_offset) {
5273 else if (c == 'e' && !extended_offset) {
5274 i = get_nonexisting_partition(0, 4);
5276 add_partition(i, EXTENDED);
5280 printf(_("Invalid partition number "
5281 "for type `%c'\n"), c);
5291 if (label_dos == current_label_type) {
5292 for (i = 0; i < 3; i++)
5293 if (ptes[i].changed)
5294 ptes[3].changed = 1;
5295 for (i = 3; i < partitions; i++) {
5296 struct pte *pe = &ptes[i];
5299 write_part_table_flag(pe->sectorbuffer);
5300 write_sector(pe->offset, pe->sectorbuffer);
5304 #ifdef CONFIG_FEATURE_SGI_LABEL
5305 else if (label_sgi == current_label_type) {
5306 /* no test on change? the printf below might be mistaken */
5310 #ifdef CONFIG_FEATURE_SUN_LABEL
5311 else if (label_sun == current_label_type) {
5314 for (i = 0; i < 8; i++)
5315 if (ptes[i].changed)
5322 printf(_("The partition table has been altered!\n\n"));
5323 reread_partition_table(1);
5327 reread_partition_table(int leave)
5332 printf(_("Calling ioctl() to re-read partition table.\n"));
5335 if ((i = ioctl(fd, BLKRRPART)) != 0) {
5338 /* some kernel versions (1.2.x) seem to have trouble
5339 rereading the partition table, but if asked to do it
5340 twice, the second time works. - biro@yggdrasil.com */
5343 if ((i = ioctl(fd, BLKRRPART)) != 0)
5348 printf(_("\nWARNING: Re-reading the partition table "
5349 "failed with error %d: %s.\n"
5350 "The kernel still uses the old table.\n"
5351 "The new table will be used "
5352 "at the next reboot.\n"),
5353 error, strerror(error));
5358 _("\nWARNING: If you have created or modified any DOS 6.x\n"
5359 "partitions, please see the fdisk manual page for additional\n"
5365 printf(_("Syncing disks.\n"));
5367 sleep(4); /* for sync() */
5371 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
5373 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
5374 #define MAX_PER_LINE 16
5376 print_buffer(char *pbuffer)
5380 for (i = 0, l = 0; i < sector_size; i++, l++) {
5382 printf("0x%03X:", i);
5383 printf(" %02X", (unsigned char) pbuffer[i]);
5384 if (l == MAX_PER_LINE - 1) {
5400 printf(_("Device: %s\n"), disk_device);
5401 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
5402 if (label_sun == current_label_type || label_sgi == current_label_type)
5403 print_buffer(MBRbuffer);
5406 for (i = 3; i < partitions; i++)
5407 print_buffer(ptes[i].sectorbuffer);
5413 struct pte *pe = &ptes[i];
5414 struct partition *p = pe->part_table;
5417 if (warn_geometry())
5419 if (!p->sys_ind || !get_nr_sects(p) || IS_EXTENDED(p->sys_ind)) {
5420 printf(_("Partition %d has no data area\n"), i + 1);
5423 first = get_partition_start(pe);
5424 new = read_int(first, first, first + get_nr_sects(p) - 1, first,
5425 _("New beginning of data")) - pe->offset;
5427 if (new != get_nr_sects(p)) {
5428 first = get_nr_sects(p) + get_start_sect(p) - new;
5429 set_nr_sects(p, first);
5430 set_start_sect(p, new);
5442 c = tolower(read_char(_("Expert command (m for help): ")));
5445 #ifdef CONFIG_FEATURE_SUN_LABEL
5446 if (label_sun == current_label_type)
5451 if (label_dos == current_label_type)
5452 move_begin(get_partition(0, partitions));
5455 user_cylinders = cylinders =
5456 read_int(1, cylinders, 1048576, 0,
5457 _("Number of cylinders"));
5458 #ifdef CONFIG_FEATURE_SUN_LABEL
5459 if (label_sun == current_label_type)
5460 sun_set_ncyl(cylinders);
5462 if (label_dos == current_label_type)
5469 #ifdef CONFIG_FEATURE_SGI_LABEL
5470 if (label_sgi == current_label_type)
5474 #ifdef CONFIG_FEATURE_SUN_LABEL
5475 if (label_sun == current_label_type)
5479 if (label_dos == current_label_type)
5483 if (label_dos == current_label_type)
5484 fix_partition_table_order();
5487 #ifdef CONFIG_FEATURE_SGI_LABEL
5492 user_heads = heads = read_int(1, heads, 256, 0,
5493 _("Number of heads"));
5497 #ifdef CONFIG_FEATURE_SUN_LABEL
5498 if (label_sun == current_label_type)
5503 #ifdef CONFIG_FEATURE_SUN_LABEL
5504 if (label_sun == current_label_type)
5509 #ifdef CONFIG_FEATURE_SUN_LABEL
5510 if (label_sun == current_label_type)
5523 user_sectors = sectors = read_int(1, sectors, 63, 0,
5524 _("Number of sectors"));
5525 if (dos_compatible_flag) {
5526 sector_offset = sectors;
5527 fprintf(stderr, _("Warning: setting "
5528 "sector offset for DOS "
5537 write_table(); /* does not return */
5540 #ifdef CONFIG_FEATURE_SUN_LABEL
5541 if (label_sun == current_label_type)
5542 sun_set_pcylcount();
5550 #endif /* ADVANCED mode */
5553 is_ide_cdrom_or_tape(const char *device)
5557 struct stat statbuf;
5560 /* No device was given explicitly, and we are trying some
5561 likely things. But opening /dev/hdc may produce errors like
5562 "hdc: tray open or drive not ready"
5563 if it happens to be a CD-ROM drive. It even happens that
5564 the process hangs on the attempt to read a music CD.
5565 So try to be careful. This only works since 2.1.73. */
5567 if (strncmp("/dev/hd", device, 7))
5570 snprintf(buf, sizeof(buf), "/proc/ide/%s/media", device+5);
5571 procf = fopen(buf, "r");
5572 if (procf != NULL && fgets(buf, sizeof(buf), procf))
5573 is_ide = (!strncmp(buf, "cdrom", 5) ||
5574 !strncmp(buf, "tape", 4));
5576 /* Now when this proc file does not exist, skip the
5577 device when it is read-only. */
5578 if (stat(device, &statbuf) == 0)
5579 is_ide = ((statbuf.st_mode & 0222) == 0);
5588 try(const char *device, int user_specified)
5592 disk_device = device;
5593 if (setjmp(listingbuf))
5595 if (!user_specified)
5596 if (is_ide_cdrom_or_tape(device))
5598 if ((fd = open(disk_device, type_open)) >= 0) {
5599 gb = get_boot(try_only);
5600 if (gb > 0) { /* I/O error */
5602 } else if (gb < 0) { /* no DOS signature */
5603 list_disk_geometry();
5604 if (label_aix == current_label_type){
5607 #ifdef CONFIG_FEATURE_OSF_LABEL
5608 if (btrydev(device) < 0)
5611 _("Disk %s doesn't contain a valid "
5612 "partition table\n"), device);
5617 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5618 if (label_sun != current_label_type && partitions > 4){
5619 delete_partition(ext_index);
5624 /* Ignore other errors, since we try IDE
5625 and SCSI hard disks which may not be
5626 installed on the system. */
5627 if (errno == EACCES) {
5628 fprintf(stderr, _("Cannot open %s\n"), device);
5634 /* for fdisk -l: try all things in /proc/partitions
5635 that look like a partition name (do not end in a digit) */
5640 char line[100], ptname[100], devname[120], *s;
5643 procpt = bb_wfopen(PROC_PARTITIONS, "r");
5645 while (fgets(line, sizeof(line), procpt)) {
5646 if (sscanf(line, " %d %d %d %[^\n ]",
5647 &ma, &mi, &sz, ptname) != 4)
5649 for (s = ptname; *s; s++);
5652 sprintf(devname, "/dev/%s", ptname);
5655 #ifdef CONFIG_FEATURE_CLEAN_UP
5660 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5662 unknown_command(int c)
5664 printf(_("%c: unknown command\n"), c);
5668 int fdisk_main(int argc, char **argv)
5671 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5674 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5680 * fdisk -l [-b sectorsize] [-u] device ...
5681 * fdisk -s [partition] ...
5682 * fdisk [-b sectorsize] [-u] device
5684 * Options -C, -H, -S set the geometry.
5687 while ((c = getopt(argc, argv, "b:C:H:lS:uvV"
5688 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5694 /* Ugly: this sector size is really per device,
5695 so cannot be combined with multiple disks,
5696 and te same goes for the C/H/S options.
5698 sector_size = atoi(optarg);
5699 if (sector_size != 512 && sector_size != 1024 &&
5700 sector_size != 2048)
5703 user_set_sector_size = 1;
5706 user_cylinders = atoi(optarg);
5709 user_heads = atoi(optarg);
5710 if (user_heads <= 0 || user_heads >= 256)
5714 user_sectors = atoi(optarg);
5715 if (user_sectors <= 0 || user_sectors >= 64)
5719 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5723 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5729 display_in_cyl_units = 0;
5733 printf("fdisk v" UTIL_LINUX_VERSION "\n");
5741 printf(_("This kernel finds the sector size itself - "
5742 "-b option ignored\n"));
5744 if (user_set_sector_size && argc-optind != 1)
5745 printf(_("Warning: the -b (set sector size) option should"
5746 " be used with one specified device\n"));
5749 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5753 type_open = O_RDONLY;
5754 if (argc > optind) {
5757 /* avoid gcc warning:
5758 variable `k' might be clobbered by `longjmp' */
5762 for (k = optind; k < argc; k++)
5765 /* we no longer have default device names */
5766 /* but, we can use /proc/partitions instead */
5770 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5774 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5780 type_open = O_RDONLY;
5782 opts = argc - optind;
5786 for (j = optind; j < argc; j++) {
5787 disk_device = argv[j];
5788 if ((fd = open(disk_device, type_open)) < 0)
5789 fdisk_fatal(unable_to_open);
5790 if (ioctl(fd, BLKGETSIZE, &size))
5791 fdisk_fatal(ioctl_error);
5794 printf("%ld\n", size/2);
5796 printf("%s: %ld\n", argv[j], size/2);
5802 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5803 if (argc-optind == 1)
5804 disk_device = argv[optind];
5810 #ifdef CONFIG_FEATURE_OSF_LABEL
5811 if (label_osf == current_label_type) {
5812 /* OSF label, and no DOS label */
5813 printf(_("Detected an OSF/1 disklabel on %s, entering "
5814 "disklabel mode.\n"),
5817 /*Why do we do this? It seems to be counter-intuitive*/
5818 current_label_type = label_dos;
5819 /* If we return we may want to make an empty DOS label? */
5825 c = tolower(read_char(_("Command (m for help): ")));
5828 if (label_dos == current_label_type)
5829 toggle_active(get_partition(1, partitions));
5830 #ifdef CONFIG_FEATURE_SUN_LABEL
5831 else if (label_sun == current_label_type)
5832 toggle_sunflags(get_partition(1, partitions),
5835 #ifdef CONFIG_FEATURE_SGI_LABEL
5836 else if (label_sgi == current_label_type)
5837 sgi_set_bootpartition(
5838 get_partition(1, partitions));
5844 #ifdef CONFIG_FEATURE_SGI_LABEL
5845 if (label_sgi == current_label_type) {
5846 printf(_("\nThe current boot file is: %s\n"),
5847 sgi_get_bootfile());
5848 if (read_chars(_("Please enter the name of the "
5849 "new boot file: ")) == '\n')
5850 printf(_("Boot file unchanged\n"));
5852 sgi_set_bootfile(line_ptr);
5855 #ifdef CONFIG_FEATURE_OSF_LABEL
5860 if (label_dos == current_label_type)
5861 toggle_dos_compatibility_flag();
5862 #ifdef CONFIG_FEATURE_SUN_LABEL
5863 else if (label_sun == current_label_type)
5864 toggle_sunflags(get_partition(1, partitions),
5867 #ifdef CONFIG_FEATURE_SGI_LABEL
5868 else if (label_sgi == current_label_type)
5869 sgi_set_swappartition(
5870 get_partition(1, partitions));
5878 #ifdef CONFIG_FEATURE_SGI_LABEL
5879 /* If sgi_label then don't use get_existing_partition,
5880 let the user select a partition, since
5881 get_existing_partition() only works for Linux-like
5883 if (label_sgi != current_label_type) {
5884 j = get_existing_partition(1, partitions);
5886 j = get_partition(1, partitions);
5889 j = get_existing_partition(1, partitions);
5892 delete_partition(j);
5896 #ifdef CONFIG_FEATURE_SGI_LABEL
5897 if (label_sgi == current_label_type)
5903 list_types(get_sys_types());
5922 #ifdef CONFIG_FEATURE_SUN_LABEL
5936 write_table(); /* does not return */
5938 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
5940 #ifdef CONFIG_FEATURE_SGI_LABEL
5941 if (label_sgi == current_label_type) {
5943 _("\n\tSorry, no experts menu for SGI "
5944 "partition tables available.\n\n"));
5957 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */