1 /* fdisk.c -- Partition table manipulator for Linux.
3 * Copyright (C) 1992 A. V. Le Blanc (LeBlanc@mcc.ac.uk)
5 * Licensed under the GPL v1 or later, see the file LICENSE in this tarball.
7 * Vladimir Oleynik <dzo@simtreas.ru> 2001,2002 Busybox port
10 #define UTIL_LINUX_VERSION "2.12"
12 #define PROC_PARTITIONS "/proc/partitions"
15 #include <sys/types.h>
16 #include <sys/stat.h> /* stat */
25 #include <assert.h> /* assert */
28 #include <sys/ioctl.h>
29 #include <sys/param.h>
30 #include <sys/sysmacros.h> /* major */
32 #include <stdint.h> /* for uint32_t, uint16_t, uint8_t, int16_t, etc */
34 /* Copied from linux/major.h */
35 #define FLOPPY_MAJOR 2
37 #include <sys/utsname.h>
41 #define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r))
47 #define BLKRRPART _IO(0x12,95) /* re-read partition table */
48 #define BLKGETSIZE _IO(0x12,96) /* return device size */
49 #define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */
50 #define BLKSSZGET _IO(0x12,104) /* get block device sector size */
52 /* Avoid conflicts with the 2.6 kernel headers, which define
53 * _IOR rather differently */
55 #define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size))
56 #define BLKGETSIZE64 _IOR(0x12,114,uint64_t)
62 #define DEFAULT_SECTOR_SIZE 512
63 #define MAX_SECTOR_SIZE 2048
64 #define SECTOR_SIZE 512 /* still used in BSD code */
65 #define MAXIMUM_PARTS 60
67 #define ACTIVE_FLAG 0x80
70 #define WIN98_EXTENDED 0x0f
71 #define LINUX_PARTITION 0x81
72 #define LINUX_SWAP 0x82
73 #define LINUX_NATIVE 0x83
74 #define LINUX_EXTENDED 0x85
75 #define LINUX_LVM 0x8e
76 #define LINUX_RAID 0xfd
81 #define IS_EXTENDED(i) \
82 ((i) == EXTENDED || (i) == WIN98_EXTENDED || (i) == LINUX_EXTENDED)
84 #define SIZE(a) (sizeof(a)/sizeof((a)[0]))
86 #define cround(n) (display_in_cyl_units ? ((n)/units_per_sector)+1 : (n))
87 #define scround(x) (((x)+units_per_sector-1)/units_per_sector)
89 #ifdef CONFIG_FEATURE_SUN_LABEL
90 #define SCSI_IOCTL_GET_IDLUN 0x5382
94 /* including <linux/hdreg.h> also fails */
97 unsigned char sectors;
98 unsigned short cylinders;
102 #define HDIO_GETGEO 0x0301 /* get device geometry */
109 static uint sector_size = DEFAULT_SECTOR_SIZE,
110 user_set_sector_size,
114 * Raw disk label. For DOS-type partition tables the MBR,
115 * with descriptions of the primary partitions.
117 #if (MAX_SECTOR_SIZE) > (BUFSIZ+1)
118 static char MBRbuffer[MAX_SECTOR_SIZE];
120 # define MBRbuffer bb_common_bufsiz1
123 #ifdef CONFIG_FEATURE_SUN_LABEL
124 static int sun_label; /* looking at sun disklabel */
128 #ifdef CONFIG_FEATURE_SGI_LABEL
129 static int sgi_label; /* looking at sgi disklabel */
133 #ifdef CONFIG_FEATURE_AIX_LABEL
134 static int aix_label; /* looking at aix disklabel */
138 #ifdef CONFIG_FEATURE_OSF_LABEL
139 static int osf_label; /* looking at OSF/1 disklabel */
140 static int possibly_osf_label;
145 #define dos_label (!sun_label && !sgi_label && !aix_label && !osf_label)
147 static uint heads, sectors, cylinders;
148 static void update_units(void);
152 * return partition name - uses static storage unless buf is supplied
155 partname(const char *dev, int pno, int lth) {
156 static char buffer[80];
163 bufsiz = sizeof(buffer);
168 if (isdigit(dev[w-1]))
171 /* devfs kludge - note: fdisk partition names are not supposed
172 to equal kernel names, so there is no reason to do this */
173 if (strcmp (dev + w - 4, "disc") == 0) {
181 snprintf(bufp, bufsiz, "%*.*s%s%-2u",
182 lth-wp-2, w, dev, p, pno);
184 snprintf(bufp, bufsiz, "%.*s%s%-2u", w, dev, p, pno);
190 unsigned char boot_ind; /* 0x80 - active */
191 unsigned char head; /* starting head */
192 unsigned char sector; /* starting sector */
193 unsigned char cyl; /* starting cylinder */
194 unsigned char sys_ind; /* What partition type */
195 unsigned char end_head; /* end head */
196 unsigned char end_sector; /* end sector */
197 unsigned char end_cyl; /* end cylinder */
198 unsigned char start4[4]; /* starting sector counting from 0 */
199 unsigned char size4[4]; /* nr of sectors in partition */
203 ioctl_error, unable_to_open, unable_to_read, unable_to_seek,
207 enum action {fdisk, require, try_only, create_empty_dos, create_empty_sun};
209 static const char *disk_device;
210 static int fd; /* the disk */
211 static int partitions = 4; /* maximum partition + 1 */
212 static uint display_in_cyl_units = 1;
213 static uint units_per_sector = 1;
214 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
215 static char *line_ptr;
216 static void change_units(void);
217 static void reread_partition_table(int leave);
218 static void delete_partition(int i);
219 static int get_partition(int warn, int max);
220 static void list_types(const struct systypes *sys);
221 static uint read_int(uint low, uint dflt, uint high, uint base, char *mesg);
223 static const char *partition_type(unsigned char type);
224 static void fdisk_fatal(enum failure why) ATTRIBUTE_NORETURN;
225 static void get_geometry(void);
226 static int get_boot(enum action what);
231 #define hex_val(c) ({ \
233 isdigit(_c) ? _c - '0' : \
234 tolower(_c) + 10 - 'a'; \
238 #define LINE_LENGTH 800
239 #define pt_offset(b, n) ((struct partition *)((b) + 0x1be + \
240 (n) * sizeof(struct partition)))
241 #define sector(s) ((s) & 0x3f)
242 #define cylinder(s, c) ((c) | (((s) & 0xc0) << 2))
244 #define hsc2sector(h,s,c) (sector(s) - 1 + sectors * \
245 ((h) + heads * cylinder(s,c)))
246 #define set_hsc(h,s,c,sector) { \
247 s = sector % sectors + 1; \
249 h = sector % heads; \
252 s |= (sector >> 2) & 0xc0; \
256 static int32_t get_start_sect(const struct partition *p);
257 static int32_t get_nr_sects(const struct partition *p);
260 * per partition table entry data
262 * The four primary partitions have the same sectorbuffer (MBRbuffer)
263 * and have NULL ext_pointer.
264 * Each logical partition table entry has two pointers, one for the
265 * partition and one link to the next one.
268 struct partition *part_table; /* points into sectorbuffer */
269 struct partition *ext_pointer; /* points into sectorbuffer */
270 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
271 char changed; /* boolean */
273 off_t offset; /* disk sector number */
274 char *sectorbuffer; /* disk sector contents */
275 } ptes[MAXIMUM_PARTS];
278 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
280 set_all_unchanged(void) {
283 for (i = 0; i < MAXIMUM_PARTS; i++)
291 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
293 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_OSF_LABEL)
294 static struct partition *
295 get_part_table(int i) {
296 return ptes[i].part_table;
301 str_units(int n) { /* n==1: use singular */
303 return display_in_cyl_units ? _("cylinder") : _("sector");
305 return display_in_cyl_units ? _("cylinders") : _("sectors");
309 valid_part_table_flag(const char *mbuffer) {
310 const unsigned char *b = (const unsigned char *)mbuffer;
311 return (b[510] == 0x55 && b[511] == 0xaa);
314 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
315 static char line_buffer[LINE_LENGTH];
317 /* read line; return 0 or first char */
321 static int got_eof = 0;
323 fflush (stdout); /* requested by niles@scyld.com */
324 line_ptr = line_buffer;
325 if (!fgets(line_buffer, LINE_LENGTH, stdin)) {
327 got_eof++; /* user typed ^D ? */
329 fprintf(stderr, _("\ngot EOF thrice - exiting..\n"));
334 while (*line_ptr && !isgraph(*line_ptr))
340 read_char(const char *mesg)
344 } while (!read_line());
349 read_chars(const char *mesg)
360 read_hex(const struct systypes *sys)
366 read_char(_("Hex code (type L to list codes): "));
367 if (*line_ptr == 'l' || *line_ptr == 'L')
369 else if (isxdigit (*line_ptr))
373 hex = hex << 4 | hex_val(*line_ptr++);
374 while (isxdigit(*line_ptr));
379 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
381 #ifdef CONFIG_FEATURE_AIX_LABEL
383 * Copyright (C) Andreas Neuper, Sep 1998.
384 * This file may be redistributed under
385 * the terms of the GNU Public License.
389 unsigned int magic; /* expect AIX_LABEL_MAGIC */
390 unsigned int fillbytes1[124];
391 unsigned int physical_volume_id;
392 unsigned int fillbytes2[124];
395 #define AIX_LABEL_MAGIC 0xc9c2d4c1
396 #define AIX_LABEL_MAGIC_SWAPPED 0xc1d4c2c9
397 #define AIX_INFO_MAGIC 0x00072959
398 #define AIX_INFO_MAGIC_SWAPPED 0x59290700
400 #define aixlabel ((aix_partition *)MBRbuffer)
405 * 1999-03-20 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
406 * Internationalization
408 * 2003-03-20 Phillip Kesling <pkesling@sgi.com>
412 static int aix_other_endian;
413 static short aix_volumes=1;
416 * only dealing with free blocks here
422 _("\n\tThere is a valid AIX label on this disk.\n"
423 "\tUnfortunately Linux cannot handle these\n"
424 "\tdisks at the moment. Nevertheless some\n"
426 "\t1. fdisk will destroy its contents on write.\n"
427 "\t2. Be sure that this disk is NOT a still vital\n"
428 "\t part of a volume group. (Otherwise you may\n"
429 "\t erase the other disks as well, if unmirrored.)\n"
430 "\t3. Before deleting this physical volume be sure\n"
431 "\t to remove the disk logically from your AIX\n"
432 "\t machine. (Otherwise you become an AIXpert).")
442 memset( MBRbuffer, 0, sizeof(MBRbuffer) ); /* avoid fdisk cores */
447 check_aix_label( void )
449 if (aixlabel->magic != AIX_LABEL_MAGIC &&
450 aixlabel->magic != AIX_LABEL_MAGIC_SWAPPED) {
452 aix_other_endian = 0;
455 aix_other_endian = (aixlabel->magic == AIX_LABEL_MAGIC_SWAPPED);
461 aix_nolabel(); /* %% */
462 aix_label = 1; /* %% */
465 #endif /* AIX_LABEL */
467 #ifdef CONFIG_FEATURE_OSF_LABEL
469 * Copyright (c) 1987, 1988 Regents of the University of California.
470 * All rights reserved.
472 * Redistribution and use in source and binary forms, with or without
473 * modification, are permitted provided that the following conditions
475 * 1. Redistributions of source code must retain the above copyright
476 * notice, this list of conditions and the following disclaimer.
477 * 2. Redistributions in binary form must reproduce the above copyright
478 * notice, this list of conditions and the following disclaimer in the
479 * documentation and/or other materials provided with the distribution.
480 * 3. All advertising materials mentioning features or use of this software
481 * must display the following acknowledgment:
482 * This product includes software developed by the University of
483 * California, Berkeley and its contributors.
484 * 4. Neither the name of the University nor the names of its contributors
485 * may be used to endorse or promote products derived from this software
486 * without specific prior written permission.
488 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
489 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
490 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
491 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
492 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
493 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
494 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
495 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
496 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
497 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
502 #ifndef BSD_DISKMAGIC
503 #define BSD_DISKMAGIC ((uint32_t) 0x82564557)
506 #ifndef BSD_MAXPARTITIONS
507 #define BSD_MAXPARTITIONS 16
510 #define BSD_LINUX_BOOTDIR "/usr/ucb/mdec"
512 #if defined (i386) || defined (__sparc__) || defined (__arm__) || defined (__mips__) || defined (__s390__) || defined (__sh__) || defined(__x86_64__)
513 #define BSD_LABELSECTOR 1
514 #define BSD_LABELOFFSET 0
515 #elif defined (__alpha__) || defined (__powerpc__) || defined (__ia64__) || defined (__hppa__)
516 #define BSD_LABELSECTOR 0
517 #define BSD_LABELOFFSET 64
518 #elif defined (__s390__) || defined (__s390x__)
519 #define BSD_LABELSECTOR 1
520 #define BSD_LABELOFFSET 0
522 #error unknown architecture
525 #define BSD_BBSIZE 8192 /* size of boot area, with label */
526 #define BSD_SBSIZE 8192 /* max size of fs superblock */
528 struct xbsd_disklabel {
529 uint32_t d_magic; /* the magic number */
530 int16_t d_type; /* drive type */
531 int16_t d_subtype; /* controller/d_type specific */
532 char d_typename[16]; /* type name, e.g. "eagle" */
533 char d_packname[16]; /* pack identifier */
535 uint32_t d_secsize; /* # of bytes per sector */
536 uint32_t d_nsectors; /* # of data sectors per track */
537 uint32_t d_ntracks; /* # of tracks per cylinder */
538 uint32_t d_ncylinders; /* # of data cylinders per unit */
539 uint32_t d_secpercyl; /* # of data sectors per cylinder */
540 uint32_t d_secperunit; /* # of data sectors per unit */
542 * Spares (bad sector replacements) below
543 * are not counted in d_nsectors or d_secpercyl.
544 * Spare sectors are assumed to be physical sectors
545 * which occupy space at the end of each track and/or cylinder.
547 uint16_t d_sparespertrack; /* # of spare sectors per track */
548 uint16_t d_sparespercyl; /* # of spare sectors per cylinder */
550 * Alternate cylinders include maintenance, replacement,
551 * configuration description areas, etc.
553 uint32_t d_acylinders; /* # of alt. cylinders per unit */
555 /* hardware characteristics: */
557 * d_interleave, d_trackskew and d_cylskew describe perturbations
558 * in the media format used to compensate for a slow controller.
559 * Interleave is physical sector interleave, set up by the formatter
560 * or controller when formatting. When interleaving is in use,
561 * logically adjacent sectors are not physically contiguous,
562 * but instead are separated by some number of sectors.
563 * It is specified as the ratio of physical sectors traversed
564 * per logical sector. Thus an interleave of 1:1 implies contiguous
565 * layout, while 2:1 implies that logical sector 0 is separated
566 * by one sector from logical sector 1.
567 * d_trackskew is the offset of sector 0 on track N
568 * relative to sector 0 on track N-1 on the same cylinder.
569 * Finally, d_cylskew is the offset of sector 0 on cylinder N
570 * relative to sector 0 on cylinder N-1.
572 uint16_t d_rpm; /* rotational speed */
573 uint16_t d_interleave; /* hardware sector interleave */
574 uint16_t d_trackskew; /* sector 0 skew, per track */
575 uint16_t d_cylskew; /* sector 0 skew, per cylinder */
576 uint32_t d_headswitch; /* head switch time, usec */
577 uint32_t d_trkseek; /* track-to-track seek, usec */
578 uint32_t d_flags; /* generic flags */
580 uint32_t d_drivedata[NDDATA]; /* drive-type specific information */
582 uint32_t d_spare[NSPARE]; /* reserved for future use */
583 uint32_t d_magic2; /* the magic number (again) */
584 uint16_t d_checksum; /* xor of data incl. partitions */
585 /* filesystem and partition information: */
586 uint16_t d_npartitions; /* number of partitions in following */
587 uint32_t d_bbsize; /* size of boot area at sn0, bytes */
588 uint32_t d_sbsize; /* max size of fs superblock, bytes */
589 struct xbsd_partition { /* the partition table */
590 uint32_t p_size; /* number of sectors in partition */
591 uint32_t p_offset; /* starting sector */
592 uint32_t p_fsize; /* filesystem basic fragment size */
593 uint8_t p_fstype; /* filesystem type, see below */
594 uint8_t p_frag; /* filesystem fragments per block */
595 uint16_t p_cpg; /* filesystem cylinders per group */
596 } d_partitions[BSD_MAXPARTITIONS]; /* actually may be more */
600 #define BSD_DTYPE_SMD 1 /* SMD, XSMD; VAX hp/up */
601 #define BSD_DTYPE_MSCP 2 /* MSCP */
602 #define BSD_DTYPE_DEC 3 /* other DEC (rk, rl) */
603 #define BSD_DTYPE_SCSI 4 /* SCSI */
604 #define BSD_DTYPE_ESDI 5 /* ESDI interface */
605 #define BSD_DTYPE_ST506 6 /* ST506 etc. */
606 #define BSD_DTYPE_HPIB 7 /* CS/80 on HP-IB */
607 #define BSD_DTYPE_HPFL 8 /* HP Fiber-link */
608 #define BSD_DTYPE_FLOPPY 10 /* floppy */
610 /* d_subtype values: */
611 #define BSD_DSTYPE_INDOSPART 0x8 /* is inside dos partition */
612 #define BSD_DSTYPE_DOSPART(s) ((s) & 3) /* dos partition number */
613 #define BSD_DSTYPE_GEOMETRY 0x10 /* drive params in label */
616 static const char * const xbsd_dktypenames[] = {
630 #define BSD_DKMAXTYPES (sizeof(xbsd_dktypenames) / sizeof(xbsd_dktypenames[0]) - 1)
634 * Filesystem type and version.
635 * Used to interpret other filesystem-specific
636 * per-partition information.
638 #define BSD_FS_UNUSED 0 /* unused */
639 #define BSD_FS_SWAP 1 /* swap */
640 #define BSD_FS_V6 2 /* Sixth Edition */
641 #define BSD_FS_V7 3 /* Seventh Edition */
642 #define BSD_FS_SYSV 4 /* System V */
643 #define BSD_FS_V71K 5 /* V7 with 1K blocks (4.1, 2.9) */
644 #define BSD_FS_V8 6 /* Eighth Edition, 4K blocks */
645 #define BSD_FS_BSDFFS 7 /* 4.2BSD fast file system */
646 #define BSD_FS_BSDLFS 9 /* 4.4BSD log-structured file system */
647 #define BSD_FS_OTHER 10 /* in use, but unknown/unsupported */
648 #define BSD_FS_HPFS 11 /* OS/2 high-performance file system */
649 #define BSD_FS_ISO9660 12 /* ISO-9660 filesystem (cdrom) */
650 #define BSD_FS_ISOFS BSD_FS_ISO9660
651 #define BSD_FS_BOOT 13 /* partition contains bootstrap */
652 #define BSD_FS_ADOS 14 /* AmigaDOS fast file system */
653 #define BSD_FS_HFS 15 /* Macintosh HFS */
654 #define BSD_FS_ADVFS 16 /* Digital Unix AdvFS */
656 /* this is annoying, but it's also the way it is :-( */
658 #define BSD_FS_EXT2 8 /* ext2 file system */
660 #define BSD_FS_MSDOS 8 /* MS-DOS file system */
664 static const struct systypes xbsd_fstypes[] = {
665 /* BSD_FS_UNUSED */ {"\x00" "unused"},
666 /* BSD_FS_SWAP */ {"\x01" "swap"},
667 /* BSD_FS_V6 */ {"\x02" "Version 6"},
668 /* BSD_FS_V7 */ {"\x03" "Version 7"},
669 /* BSD_FS_SYSV */ {"\x04" "System V"},
670 /* BSD_FS_V71K */ {"\x05" "4.1BSD"},
671 /* BSD_FS_V8 */ {"\x06" "Eighth Edition"},
672 /* BSD_FS_BSDFFS */ {"\x07" "4.2BSD"},
674 /* BSD_FS_EXT2 */ {"\x08" "ext2"},
676 /* BSD_FS_MSDOS */ {"\x08" "MS-DOS"},
678 /* BSD_FS_BSDLFS */ {"\x09" "4.4LFS"},
679 /* BSD_FS_OTHER */ {"\x0a" "unknown"},
680 /* BSD_FS_HPFS */ {"\x0b" "HPFS"},
681 /* BSD_FS_ISO9660 */ {"\x0c" "ISO-9660"},
682 /* BSD_FS_BOOT */ {"\x0d" "boot"},
683 /* BSD_FS_ADOS */ {"\x0e" "ADOS"},
684 /* BSD_FS_HFS */ {"\x0f" "HFS"},
685 /* BSD_FS_ADVFS */ {"\x10" "AdvFS"},
688 #define BSD_FSMAXTYPES (SIZE(xbsd_fstypes)-1)
693 * flags shared by various drives:
695 #define BSD_D_REMOVABLE 0x01 /* removable media */
696 #define BSD_D_ECC 0x02 /* supports ECC */
697 #define BSD_D_BADSECT 0x04 /* supports bad sector forw. */
698 #define BSD_D_RAMDISK 0x08 /* disk emulator */
699 #define BSD_D_CHAIN 0x10 /* can do back-back transfers */
700 #define BSD_D_DOSPART 0x20 /* within MSDOS partition */
702 #endif /* OSF_LABEL */
705 * Copyright (C) Andreas Neuper, Sep 1998.
706 * This file may be modified and redistributed under
707 * the terms of the GNU Public License.
710 struct device_parameter { /* 48 bytes */
714 unsigned char sparecyl;
715 unsigned short pcylcount;
716 unsigned short head_vol0;
717 unsigned short ntrks; /* tracks in cyl 0 or vol 0 */
718 unsigned char cmd_tag_queue_depth;
719 unsigned char unused0;
720 unsigned short unused1;
721 unsigned short nsect; /* sectors/tracks in cyl 0 or vol 0 */
722 unsigned short bytes;
723 unsigned short ilfact;
724 unsigned int flags; /* controller flags */
725 unsigned int datarate;
726 unsigned int retries_on_error;
727 unsigned int ms_per_word;
728 unsigned short xylogics_gap1;
729 unsigned short xylogics_syncdelay;
730 unsigned short xylogics_readdelay;
731 unsigned short xylogics_gap2;
732 unsigned short xylogics_readgate;
733 unsigned short xylogics_writecont;
736 #define SGI_VOLHDR 0x00
737 /* 1 and 2 were used for drive types no longer supported by SGI */
738 #define SGI_SWAP 0x03
739 /* 4 and 5 were for filesystem types SGI haven't ever supported on MIPS CPUs */
740 #define SGI_VOLUME 0x06
742 #define SGI_LVOL 0x08
743 #define SGI_RLVOL 0x09
745 #define SGI_XFSLOG 0x0b
748 #define ENTIRE_DISK SGI_VOLUME
752 #define SECTOR_SLIP 0x01
753 #define SECTOR_FWD 0x02
754 #define TRACK_FWD 0x04
755 #define TRACK_MULTIVOL 0x08
756 #define IGNORE_ERRORS 0x10
758 #define ENABLE_CMDTAGQ 0x40
761 unsigned int magic; /* expect SGI_LABEL_MAGIC */
762 unsigned short boot_part; /* active boot partition */
763 unsigned short swap_part; /* active swap partition */
764 unsigned char boot_file[16]; /* name of the bootfile */
765 struct device_parameter devparam; /* 1 * 48 bytes */
766 struct volume_directory { /* 15 * 16 bytes */
767 unsigned char vol_file_name[8]; /* a character array */
768 unsigned int vol_file_start; /* number of logical block */
769 unsigned int vol_file_size; /* number of bytes */
771 struct sgi_partition { /* 16 * 12 bytes */
772 unsigned int num_sectors; /* number of blocks */
773 unsigned int start_sector; /* must be cylinder aligned */
777 unsigned int fillbytes;
781 unsigned int magic; /* looks like a magic number */
790 unsigned char scsi_string[50];
791 unsigned char serial[137];
792 unsigned short check1816;
793 unsigned char installer[225];
796 #define SGI_LABEL_MAGIC 0x0be5a941
797 #define SGI_LABEL_MAGIC_SWAPPED 0x41a9e50b
798 #define SGI_INFO_MAGIC 0x00072959
799 #define SGI_INFO_MAGIC_SWAPPED 0x59290700
800 #define SGI_SSWAP16(x) (sgi_other_endian ? __swap16(x) \
802 #define SGI_SSWAP32(x) (sgi_other_endian ? __swap32(x) \
805 #define sgilabel ((sgi_partition *)MBRbuffer)
806 #define sgiparam (sgilabel->devparam)
809 unsigned char info[128]; /* Informative text string */
810 unsigned char spare0[14];
812 unsigned char spare1;
814 unsigned char spare2;
817 unsigned char spare1[246]; /* Boot information etc. */
818 unsigned short rspeed; /* Disk rotational speed */
819 unsigned short pcylcount; /* Physical cylinder count */
820 unsigned short sparecyl; /* extra sects per cylinder */
821 unsigned char spare2[4]; /* More magic... */
822 unsigned short ilfact; /* Interleave factor */
823 unsigned short ncyl; /* Data cylinder count */
824 unsigned short nacyl; /* Alt. cylinder count */
825 unsigned short ntrks; /* Tracks per cylinder */
826 unsigned short nsect; /* Sectors per track */
827 unsigned char spare3[4]; /* Even more magic... */
828 struct sun_partition {
829 uint32_t start_cylinder;
830 uint32_t num_sectors;
832 unsigned short magic; /* Magic number */
833 unsigned short csum; /* Label xor'd checksum */
837 #define SUN_LABEL_MAGIC 0xDABE
838 #define SUN_LABEL_MAGIC_SWAPPED 0xBEDA
839 #define sunlabel ((sun_partition *)MBRbuffer)
840 #define SUN_SSWAP16(x) (sun_other_endian ? __swap16(x) \
842 #define SUN_SSWAP32(x) (sun_other_endian ? __swap32(x) \
846 #ifdef CONFIG_FEATURE_OSF_LABEL
849 19990319 - Arnaldo Carvalho de Melo <acme@conectiva.com.br> - i18n/nls
851 20000101 - David Huggins-Daines <dhuggins@linuxcare.com> - Better
852 support for OSF/1 disklabels on Alpha.
853 Also fixed unaligned accesses in alpha_bootblock_checksum()
856 #define FREEBSD_PARTITION 0xa5
857 #define NETBSD_PARTITION 0xa9
859 static void xbsd_delete_part (void);
860 static void xbsd_new_part (void);
861 static void xbsd_write_disklabel (void);
862 static int xbsd_create_disklabel (void);
863 static void xbsd_edit_disklabel (void);
864 static void xbsd_write_bootstrap (void);
865 static void xbsd_change_fstype (void);
866 static int xbsd_get_part_index (int max);
867 static int xbsd_check_new_partition (int *i);
868 static void xbsd_list_types (void);
869 static u_short xbsd_dkcksum (struct xbsd_disklabel *lp);
870 static int xbsd_initlabel (struct partition *p, struct xbsd_disklabel *d,
872 static int xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d);
873 static int xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d);
875 #if defined (__alpha__)
876 static void alpha_bootblock_checksum (char *boot);
879 #if !defined (__alpha__)
880 static int xbsd_translate_fstype (int linux_type);
881 static void xbsd_link_part (void);
882 static struct partition *xbsd_part;
883 static int xbsd_part_index;
886 #if defined (__alpha__)
887 /* We access this through a uint64_t * when checksumming */
888 static char disklabelbuffer[BSD_BBSIZE] __attribute__((aligned(8)));
890 static char disklabelbuffer[BSD_BBSIZE];
893 static struct xbsd_disklabel xbsd_dlabel;
895 #define bsd_cround(n) \
896 (display_in_cyl_units ? ((n)/xbsd_dlabel.d_secpercyl) + 1 : (n))
899 * Test whether the whole disk has BSD disk label magic.
901 * Note: often reformatting with DOS-type label leaves the BSD magic,
902 * so this does not mean that there is a BSD disk label.
905 check_osf_label(void) {
906 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
911 static void xbsd_print_disklabel(int);
914 btrydev (const char * dev) {
915 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
917 printf(_("\nBSD label for device: %s\n"), dev);
918 xbsd_print_disklabel (0);
924 puts (_("Command action"));
925 puts (_("\td\tdelete a BSD partition"));
926 puts (_("\te\tedit drive data"));
927 puts (_("\ti\tinstall bootstrap"));
928 puts (_("\tl\tlist known filesystem types"));
929 puts (_("\tm\tprint this menu"));
930 puts (_("\tn\tadd a new BSD partition"));
931 puts (_("\tp\tprint BSD partition table"));
932 puts (_("\tq\tquit without saving changes"));
933 puts (_("\tr\treturn to main menu"));
934 puts (_("\ts\tshow complete disklabel"));
935 puts (_("\tt\tchange a partition's filesystem id"));
936 puts (_("\tu\tchange units (cylinders/sectors)"));
937 puts (_("\tw\twrite disklabel to disk"));
938 #if !defined (__alpha__)
939 puts (_("\tx\tlink BSD partition to non-BSD partition"));
943 #if !defined (__alpha__)
950 is_bsd_partition_type(int type) {
951 return (type == FREEBSD_PARTITION ||
952 type == hidden(FREEBSD_PARTITION) ||
953 type == NETBSD_PARTITION ||
954 type == hidden(NETBSD_PARTITION));
960 #if !defined (__alpha__)
964 for (t=0; t<4; t++) {
965 p = get_part_table(t);
966 if (p && is_bsd_partition_type(p->sys_ind)) {
969 ss = get_start_sect(xbsd_part);
971 fprintf (stderr, _("Partition %s has invalid starting sector 0.\n"),
972 partname(disk_device, t+1, 0));
975 printf (_("Reading disklabel of %s at sector %d.\n"),
976 partname(disk_device, t+1, 0), ss + BSD_LABELSECTOR);
977 if (xbsd_readlabel (xbsd_part, &xbsd_dlabel) == 0)
978 if (xbsd_create_disklabel () == 0)
985 printf (_("There is no *BSD partition on %s.\n"), disk_device);
989 #elif defined (__alpha__)
991 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
992 if (xbsd_create_disklabel () == 0)
993 exit ( EXIT_SUCCESS );
999 switch (tolower (read_char (_("BSD disklabel command (m for help): ")))) {
1001 xbsd_delete_part ();
1004 xbsd_edit_disklabel ();
1007 xbsd_write_bootstrap ();
1016 xbsd_print_disklabel (0);
1020 exit ( EXIT_SUCCESS );
1024 xbsd_print_disklabel (1);
1027 xbsd_change_fstype ();
1033 xbsd_write_disklabel ();
1035 #if !defined (__alpha__)
1048 xbsd_delete_part (void)
1052 i = xbsd_get_part_index (xbsd_dlabel.d_npartitions);
1053 xbsd_dlabel.d_partitions[i].p_size = 0;
1054 xbsd_dlabel.d_partitions[i].p_offset = 0;
1055 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
1056 if (xbsd_dlabel.d_npartitions == i + 1)
1057 while (xbsd_dlabel.d_partitions[xbsd_dlabel.d_npartitions-1].p_size == 0)
1058 xbsd_dlabel.d_npartitions--;
1062 xbsd_new_part (void)
1068 if (!xbsd_check_new_partition (&i))
1071 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
1072 begin = get_start_sect(xbsd_part);
1073 end = begin + get_nr_sects(xbsd_part) - 1;
1076 end = xbsd_dlabel.d_secperunit - 1;
1079 snprintf (mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
1080 begin = read_int (bsd_cround (begin), bsd_cround (begin), bsd_cround (end),
1083 if (display_in_cyl_units)
1084 begin = (begin - 1) * xbsd_dlabel.d_secpercyl;
1086 snprintf (mesg, sizeof(mesg), _("Last %s or +size or +sizeM or +sizeK"),
1087 str_units(SINGULAR));
1088 end = read_int (bsd_cround (begin), bsd_cround (end), bsd_cround (end),
1089 bsd_cround (begin), mesg);
1091 if (display_in_cyl_units)
1092 end = end * xbsd_dlabel.d_secpercyl - 1;
1094 xbsd_dlabel.d_partitions[i].p_size = end - begin + 1;
1095 xbsd_dlabel.d_partitions[i].p_offset = begin;
1096 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
1100 xbsd_print_disklabel (int show_all) {
1101 struct xbsd_disklabel *lp = &xbsd_dlabel;
1102 struct xbsd_partition *pp;
1106 #if defined (__alpha__)
1107 printf("# %s:\n", disk_device);
1109 printf("# %s:\n", partname(disk_device, xbsd_part_index+1, 0));
1111 if ((unsigned) lp->d_type < BSD_DKMAXTYPES)
1112 printf(_("type: %s\n"), xbsd_dktypenames[lp->d_type]);
1114 printf(_("type: %d\n"), lp->d_type);
1115 printf(_("disk: %.*s\n"), (int) sizeof(lp->d_typename), lp->d_typename);
1116 printf(_("label: %.*s\n"), (int) sizeof(lp->d_packname), lp->d_packname);
1117 printf(_("flags:"));
1118 if (lp->d_flags & BSD_D_REMOVABLE)
1119 printf(_(" removable"));
1120 if (lp->d_flags & BSD_D_ECC)
1122 if (lp->d_flags & BSD_D_BADSECT)
1123 printf(_(" badsect"));
1125 /* On various machines the fields of *lp are short/int/long */
1126 /* In order to avoid problems, we cast them all to long. */
1127 printf(_("bytes/sector: %ld\n"), (long) lp->d_secsize);
1128 printf(_("sectors/track: %ld\n"), (long) lp->d_nsectors);
1129 printf(_("tracks/cylinder: %ld\n"), (long) lp->d_ntracks);
1130 printf(_("sectors/cylinder: %ld\n"), (long) lp->d_secpercyl);
1131 printf(_("cylinders: %ld\n"), (long) lp->d_ncylinders);
1132 printf(_("rpm: %d\n"), lp->d_rpm);
1133 printf(_("interleave: %d\n"), lp->d_interleave);
1134 printf(_("trackskew: %d\n"), lp->d_trackskew);
1135 printf(_("cylinderskew: %d\n"), lp->d_cylskew);
1136 printf(_("headswitch: %ld\t\t# milliseconds\n"),
1137 (long) lp->d_headswitch);
1138 printf(_("track-to-track seek: %ld\t# milliseconds\n"),
1139 (long) lp->d_trkseek);
1140 printf(_("drivedata: "));
1141 for (i = NDDATA - 1; i >= 0; i--)
1142 if (lp->d_drivedata[i])
1146 for (j = 0; j <= i; j++)
1147 printf("%ld ", (long) lp->d_drivedata[j]);
1149 printf(_("\n%d partitions:\n"), lp->d_npartitions);
1150 printf(_("# start end size fstype [fsize bsize cpg]\n"));
1151 pp = lp->d_partitions;
1152 for (i = 0; i < lp->d_npartitions; i++, pp++) {
1154 if (display_in_cyl_units && lp->d_secpercyl) {
1155 printf(" %c: %8ld%c %8ld%c %8ld%c ",
1157 (long) pp->p_offset / lp->d_secpercyl + 1,
1158 (pp->p_offset % lp->d_secpercyl) ? '*' : ' ',
1159 (long) (pp->p_offset + pp->p_size + lp->d_secpercyl - 1)
1161 ((pp->p_offset + pp->p_size) % lp->d_secpercyl) ? '*' : ' ',
1162 (long) pp->p_size / lp->d_secpercyl,
1163 (pp->p_size % lp->d_secpercyl) ? '*' : ' ');
1165 printf(" %c: %8ld %8ld %8ld ",
1167 (long) pp->p_offset,
1168 (long) pp->p_offset + pp->p_size - 1,
1171 if ((unsigned) pp->p_fstype < BSD_FSMAXTYPES)
1172 printf("%8.8s", xbsd_fstypes[pp->p_fstype].name);
1174 printf("%8x", pp->p_fstype);
1175 switch (pp->p_fstype) {
1177 printf(" %5ld %5ld %5.5s ",
1178 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, "");
1182 printf(" %5ld %5ld %5d ",
1183 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag,
1188 printf("%22.22s", "");
1197 xbsd_write_disklabel (void) {
1198 #if defined (__alpha__)
1199 printf (_("Writing disklabel to %s.\n"), disk_device);
1200 xbsd_writelabel (NULL, &xbsd_dlabel);
1202 printf (_("Writing disklabel to %s.\n"),
1203 partname(disk_device, xbsd_part_index+1, 0));
1204 xbsd_writelabel (xbsd_part, &xbsd_dlabel);
1206 reread_partition_table(0); /* no exit yet */
1210 xbsd_create_disklabel (void) {
1213 #if defined (__alpha__)
1214 fprintf (stderr, _("%s contains no disklabel.\n"), disk_device);
1216 fprintf (stderr, _("%s contains no disklabel.\n"),
1217 partname(disk_device, xbsd_part_index+1, 0));
1221 c = read_char (_("Do you want to create a disklabel? (y/n) "));
1222 if (c == 'y' || c == 'Y') {
1223 if (xbsd_initlabel (
1224 #if defined (__alpha__) || defined (__powerpc__) || defined (__hppa__) || \
1225 defined (__s390__) || defined (__s390x__)
1226 NULL, &xbsd_dlabel, 0
1228 xbsd_part, &xbsd_dlabel, xbsd_part_index
1231 xbsd_print_disklabel (1);
1235 } else if (c == 'n')
1241 edit_int (int def, char *mesg)
1244 fputs (mesg, stdout);
1245 printf (" (%d): ", def);
1249 while (!isdigit (*line_ptr));
1250 return atoi (line_ptr);
1254 xbsd_edit_disklabel (void)
1256 struct xbsd_disklabel *d;
1260 #if defined (__alpha__) || defined (__ia64__)
1261 d -> d_secsize = (u_long) edit_int ((u_long) d -> d_secsize ,_("bytes/sector"));
1262 d -> d_nsectors = (u_long) edit_int ((u_long) d -> d_nsectors ,_("sectors/track"));
1263 d -> d_ntracks = (u_long) edit_int ((u_long) d -> d_ntracks ,_("tracks/cylinder"));
1264 d -> d_ncylinders = (u_long) edit_int ((u_long) d -> d_ncylinders ,_("cylinders"));
1267 /* d -> d_secpercyl can be != d -> d_nsectors * d -> d_ntracks */
1270 d -> d_secpercyl = (u_long) edit_int ((u_long) d -> d_nsectors * d -> d_ntracks,
1271 _("sectors/cylinder"));
1272 if (d -> d_secpercyl <= d -> d_nsectors * d -> d_ntracks)
1275 printf (_("Must be <= sectors/track * tracks/cylinder (default).\n"));
1277 d -> d_rpm = (u_short) edit_int ((u_short) d -> d_rpm ,_("rpm"));
1278 d -> d_interleave = (u_short) edit_int ((u_short) d -> d_interleave,_("interleave"));
1279 d -> d_trackskew = (u_short) edit_int ((u_short) d -> d_trackskew ,_("trackskew"));
1280 d -> d_cylskew = (u_short) edit_int ((u_short) d -> d_cylskew ,_("cylinderskew"));
1281 d -> d_headswitch = (u_long) edit_int ((u_long) d -> d_headswitch ,_("headswitch"));
1282 d -> d_trkseek = (u_long) edit_int ((u_long) d -> d_trkseek ,_("track-to-track seek"));
1284 d -> d_secperunit = d -> d_secpercyl * d -> d_ncylinders;
1288 xbsd_get_bootstrap (char *path, void *ptr, int size)
1292 if ((fdb = open (path, O_RDONLY)) < 0)
1297 if (read (fdb, ptr, size) < 0)
1303 printf (" ... %s\n", path);
1311 printf (_("\nSyncing disks.\n"));
1317 xbsd_write_bootstrap (void)
1319 char *bootdir = BSD_LINUX_BOOTDIR;
1320 char path[MAXPATHLEN];
1322 struct xbsd_disklabel dl;
1326 if (xbsd_dlabel.d_type == BSD_DTYPE_SCSI)
1331 printf (_("Bootstrap: %sboot -> boot%s (%s): "),
1332 dkbasename, dkbasename, dkbasename);
1334 line_ptr[strlen (line_ptr)-1] = '\0';
1335 dkbasename = line_ptr;
1337 snprintf (path, sizeof(path), "%s/%sboot", bootdir, dkbasename);
1338 if (!xbsd_get_bootstrap (path, disklabelbuffer, (int) xbsd_dlabel.d_secsize))
1341 /* We need a backup of the disklabel (xbsd_dlabel might have changed). */
1342 d = &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE];
1343 bcopy (d, &dl, sizeof (struct xbsd_disklabel));
1345 /* The disklabel will be overwritten by 0's from bootxx anyway */
1346 bzero (d, sizeof (struct xbsd_disklabel));
1348 snprintf (path, sizeof(path), "%s/boot%s", bootdir, dkbasename);
1349 if (!xbsd_get_bootstrap (path, &disklabelbuffer[xbsd_dlabel.d_secsize],
1350 (int) xbsd_dlabel.d_bbsize - xbsd_dlabel.d_secsize))
1353 e = d + sizeof (struct xbsd_disklabel);
1354 for (p=d; p < e; p++)
1356 fprintf (stderr, _("Bootstrap overlaps with disk label!\n"));
1357 exit ( EXIT_FAILURE );
1360 bcopy (&dl, d, sizeof (struct xbsd_disklabel));
1362 #if defined (__powerpc__) || defined (__hppa__)
1364 #elif defined (__alpha__)
1366 alpha_bootblock_checksum (disklabelbuffer);
1368 sector = get_start_sect(xbsd_part);
1371 if (lseek (fd, sector * SECTOR_SIZE, SEEK_SET) == -1)
1372 fdisk_fatal (unable_to_seek);
1373 if (BSD_BBSIZE != write (fd, disklabelbuffer, BSD_BBSIZE))
1374 fdisk_fatal (unable_to_write);
1376 #if defined (__alpha__)
1377 printf (_("Bootstrap installed on %s.\n"), disk_device);
1379 printf (_("Bootstrap installed on %s.\n"),
1380 partname (disk_device, xbsd_part_index+1, 0));
1387 xbsd_change_fstype (void)
1391 i = xbsd_get_part_index (xbsd_dlabel.d_npartitions);
1392 xbsd_dlabel.d_partitions[i].p_fstype = read_hex (xbsd_fstypes);
1396 xbsd_get_part_index (int max)
1401 snprintf (prompt, sizeof(prompt), _("Partition (a-%c): "), 'a' + max - 1);
1403 l = tolower (read_char (prompt));
1404 while (l < 'a' || l > 'a' + max - 1);
1409 xbsd_check_new_partition (int *i) {
1411 /* room for more? various BSD flavours have different maxima */
1412 if (xbsd_dlabel.d_npartitions == BSD_MAXPARTITIONS) {
1415 for (t = 0; t < BSD_MAXPARTITIONS; t++)
1416 if (xbsd_dlabel.d_partitions[t].p_size == 0)
1419 if (t == BSD_MAXPARTITIONS) {
1420 fprintf (stderr, _("The maximum number of partitions "
1421 "has been created\n"));
1426 *i = xbsd_get_part_index (BSD_MAXPARTITIONS);
1428 if (*i >= xbsd_dlabel.d_npartitions)
1429 xbsd_dlabel.d_npartitions = (*i) + 1;
1431 if (xbsd_dlabel.d_partitions[*i].p_size != 0) {
1432 fprintf (stderr, _("This partition already exists.\n"));
1440 xbsd_list_types (void) {
1441 list_types (xbsd_fstypes);
1445 xbsd_dkcksum (struct xbsd_disklabel *lp) {
1446 u_short *start, *end;
1449 start = (u_short *) lp;
1450 end = (u_short *) &lp->d_partitions[lp->d_npartitions];
1457 xbsd_initlabel (struct partition *p, struct xbsd_disklabel *d, int pindex) {
1458 struct xbsd_partition *pp;
1461 bzero (d, sizeof (struct xbsd_disklabel));
1463 d -> d_magic = BSD_DISKMAGIC;
1465 if (strncmp (disk_device, "/dev/sd", 7) == 0)
1466 d -> d_type = BSD_DTYPE_SCSI;
1468 d -> d_type = BSD_DTYPE_ST506;
1470 #if 0 /* not used (at least not written to disk) by NetBSD/i386 1.0 */
1471 d -> d_subtype = BSD_DSTYPE_INDOSPART & pindex;
1474 #if !defined (__alpha__)
1475 d -> d_flags = BSD_D_DOSPART;
1479 d -> d_secsize = SECTOR_SIZE; /* bytes/sector */
1480 d -> d_nsectors = sectors; /* sectors/track */
1481 d -> d_ntracks = heads; /* tracks/cylinder (heads) */
1482 d -> d_ncylinders = cylinders;
1483 d -> d_secpercyl = sectors * heads;/* sectors/cylinder */
1484 if (d -> d_secpercyl == 0)
1485 d -> d_secpercyl = 1; /* avoid segfaults */
1486 d -> d_secperunit = d -> d_secpercyl * d -> d_ncylinders;
1489 d -> d_interleave = 1;
1490 d -> d_trackskew = 0;
1492 d -> d_headswitch = 0;
1495 d -> d_magic2 = BSD_DISKMAGIC;
1496 d -> d_bbsize = BSD_BBSIZE;
1497 d -> d_sbsize = BSD_SBSIZE;
1499 #if !defined (__alpha__)
1500 d -> d_npartitions = 4;
1501 pp = &d -> d_partitions[2]; /* Partition C should be
1502 the NetBSD partition */
1503 pp -> p_offset = get_start_sect(p);
1504 pp -> p_size = get_nr_sects(p);
1505 pp -> p_fstype = BSD_FS_UNUSED;
1506 pp = &d -> d_partitions[3]; /* Partition D should be
1509 pp -> p_size = d -> d_secperunit;
1510 pp -> p_fstype = BSD_FS_UNUSED;
1511 #elif defined (__alpha__)
1512 d -> d_npartitions = 3;
1513 pp = &d -> d_partitions[2]; /* Partition C should be
1516 pp -> p_size = d -> d_secperunit;
1517 pp -> p_fstype = BSD_FS_UNUSED;
1524 * Read a xbsd_disklabel from sector 0 or from the starting sector of p.
1525 * If it has the right magic, return 1.
1528 xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d)
1532 /* p is used only to get the starting sector */
1533 #if !defined (__alpha__)
1534 sector = (p ? get_start_sect(p) : 0);
1535 #elif defined (__alpha__)
1539 if (lseek (fd, sector * SECTOR_SIZE, SEEK_SET) == -1)
1540 fdisk_fatal (unable_to_seek);
1541 if (BSD_BBSIZE != read (fd, disklabelbuffer, BSD_BBSIZE))
1542 fdisk_fatal (unable_to_read);
1544 bcopy (&disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
1545 d, sizeof (struct xbsd_disklabel));
1547 if (d -> d_magic != BSD_DISKMAGIC || d -> d_magic2 != BSD_DISKMAGIC)
1550 for (t = d -> d_npartitions; t < BSD_MAXPARTITIONS; t++) {
1551 d -> d_partitions[t].p_size = 0;
1552 d -> d_partitions[t].p_offset = 0;
1553 d -> d_partitions[t].p_fstype = BSD_FS_UNUSED;
1556 if (d -> d_npartitions > BSD_MAXPARTITIONS)
1557 fprintf (stderr, _("Warning: too many partitions "
1558 "(%d, maximum is %d).\n"),
1559 d -> d_npartitions, BSD_MAXPARTITIONS);
1564 xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d)
1566 unsigned int sector;
1568 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
1569 sector = get_start_sect(p) + BSD_LABELSECTOR;
1571 sector = BSD_LABELSECTOR;
1574 d -> d_checksum = 0;
1575 d -> d_checksum = xbsd_dkcksum (d);
1577 /* This is necessary if we want to write the bootstrap later,
1578 otherwise we'd write the old disklabel with the bootstrap.
1580 bcopy (d, &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
1581 sizeof (struct xbsd_disklabel));
1583 #if defined (__alpha__) && BSD_LABELSECTOR == 0
1584 alpha_bootblock_checksum (disklabelbuffer);
1585 if (lseek (fd, 0, SEEK_SET) == -1)
1586 fdisk_fatal (unable_to_seek);
1587 if (BSD_BBSIZE != write (fd, disklabelbuffer, BSD_BBSIZE))
1588 fdisk_fatal (unable_to_write);
1590 if (lseek (fd, sector * SECTOR_SIZE + BSD_LABELOFFSET,
1592 fdisk_fatal (unable_to_seek);
1593 if (sizeof (struct xbsd_disklabel) != write (fd, d, sizeof (struct xbsd_disklabel)))
1594 fdisk_fatal (unable_to_write);
1603 #if !defined (__alpha__)
1605 xbsd_translate_fstype (int linux_type)
1609 case 0x01: /* DOS 12-bit FAT */
1610 case 0x04: /* DOS 16-bit <32M */
1611 case 0x06: /* DOS 16-bit >=32M */
1612 case 0xe1: /* DOS access */
1613 case 0xe3: /* DOS R/O */
1614 case 0xf2: /* DOS secondary */
1615 return BSD_FS_MSDOS;
1616 case 0x07: /* OS/2 HPFS */
1619 return BSD_FS_OTHER;
1624 xbsd_link_part (void)
1627 struct partition *p;
1629 k = get_partition (1, partitions);
1631 if (!xbsd_check_new_partition (&i))
1634 p = get_part_table(k);
1636 xbsd_dlabel.d_partitions[i].p_size = get_nr_sects(p);
1637 xbsd_dlabel.d_partitions[i].p_offset = get_start_sect(p);
1638 xbsd_dlabel.d_partitions[i].p_fstype = xbsd_translate_fstype(p->sys_ind);
1642 #if defined (__alpha__)
1644 #if !defined(__GLIBC__)
1645 typedef unsigned long long uint64_t;
1649 alpha_bootblock_checksum (char *boot)
1654 dp = (uint64_t *)boot;
1656 for (i = 0; i < 63; i++)
1660 #endif /* __alpha__ */
1662 #endif /* OSF_LABEL */
1664 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
1665 static inline unsigned short
1666 __swap16(unsigned short x) {
1667 return (((uint16_t)(x) & 0xFF) << 8) | (((uint16_t)(x) & 0xFF00) >> 8);
1670 static inline uint32_t
1671 __swap32(uint32_t x) {
1672 return (((x & 0xFF) << 24) |
1673 ((x & 0xFF00) << 8) |
1674 ((x & 0xFF0000) >> 8) |
1675 ((x & 0xFF000000) >> 24));
1679 #ifdef CONFIG_FEATURE_SGI_LABEL
1684 * Copyright (C) Andreas Neuper, Sep 1998.
1685 * This file may be modified and redistributed under
1686 * the terms of the GNU Public License.
1688 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
1689 * Internationalization
1693 static int sgi_other_endian;
1695 static short sgi_volumes=1;
1698 * only dealing with free blocks here
1701 typedef struct { unsigned int first; unsigned int last; } freeblocks;
1702 static freeblocks freelist[17]; /* 16 partitions can produce 17 vacant slots */
1705 setfreelist(int i, unsigned int f, unsigned int l) {
1706 freelist[i].first = f;
1707 freelist[i].last = l;
1711 add2freelist(unsigned int f, unsigned int l) {
1713 for ( ; i < 17 ; i++)
1714 if (freelist[i].last == 0)
1716 setfreelist(i, f, l);
1720 clearfreelist(void) {
1723 for (i = 0; i < 17 ; i++)
1724 setfreelist(i, 0, 0);
1728 isinfreelist(unsigned int b) {
1731 for (i = 0; i < 17 ; i++)
1732 if (freelist[i].first <= b && freelist[i].last >= b)
1733 return freelist[i].last;
1736 /* return last vacant block of this stride (never 0). */
1737 /* the '>=' is not quite correct, but simplifies the code */
1739 * end of free blocks section
1742 static const struct systypes sgi_sys_types[] = {
1743 /* SGI_VOLHDR */ {"\x00" "SGI volhdr" },
1744 /* 0x01 */ {"\x01" "SGI trkrepl" },
1745 /* 0x02 */ {"\x02" "SGI secrepl" },
1746 /* SGI_SWAP */ {"\x03" "SGI raw" },
1747 /* 0x04 */ {"\x04" "SGI bsd" },
1748 /* 0x05 */ {"\x05" "SGI sysv" },
1749 /* ENTIRE_DISK */ {"\x06" "SGI volume" },
1750 /* SGI_EFS */ {"\x07" "SGI efs" },
1751 /* 0x08 */ {"\x08" "SGI lvol" },
1752 /* 0x09 */ {"\x09" "SGI rlvol" },
1753 /* SGI_XFS */ {"\x0a" "SGI xfs" },
1754 /* SGI_XFSLOG */ {"\x0b" "SGI xfslog" },
1755 /* SGI_XLV */ {"\x0c" "SGI xlv" },
1756 /* SGI_XVM */ {"\x0d" "SGI xvm" },
1757 /* LINUX_SWAP */ {"\x82" "Linux swap" },
1758 /* LINUX_NATIVE */ {"\x83" "Linux native" },
1759 /* LINUX_LVM */ {"\x8d" "Linux LVM" },
1760 /* LINUX_RAID */ {"\xfd" "Linux RAID" },
1766 sgi_get_nsect(void) {
1767 return SGI_SSWAP16(sgilabel->devparam.nsect);
1771 sgi_get_ntrks(void) {
1772 return SGI_SSWAP16(sgilabel->devparam.ntrks);
1777 sgilabel->magic = 0;
1783 two_s_complement_32bit_sum(unsigned int* base, int size /* in bytes */) {
1787 size /= sizeof(unsigned int);
1788 for (i = 0; i < size; i++)
1789 sum -= SGI_SSWAP32(base[i]);
1794 check_sgi_label(void) {
1795 if (sizeof(sgilabel) > 512) {
1797 _("According to MIPS Computer Systems, Inc the "
1798 "Label must not contain more than 512 bytes\n"));
1802 if (sgilabel->magic != SGI_LABEL_MAGIC &&
1803 sgilabel->magic != SGI_LABEL_MAGIC_SWAPPED) {
1805 sgi_other_endian = 0;
1809 sgi_other_endian = (sgilabel->magic == SGI_LABEL_MAGIC_SWAPPED);
1811 * test for correct checksum
1813 if (two_s_complement_32bit_sum((unsigned int*)sgilabel,
1814 sizeof(*sgilabel))) {
1816 _("Detected sgi disklabel with wrong checksum.\n"));
1826 sgi_get_start_sector(int i) {
1827 return SGI_SSWAP32(sgilabel->partitions[i].start_sector);
1831 sgi_get_num_sectors(int i) {
1832 return SGI_SSWAP32(sgilabel->partitions[i].num_sectors);
1836 sgi_get_sysid(int i)
1838 return SGI_SSWAP32(sgilabel->partitions[i].id);
1842 sgi_get_bootpartition(void)
1844 return SGI_SSWAP16(sgilabel->boot_part);
1848 sgi_get_swappartition(void)
1850 return SGI_SSWAP16(sgilabel->swap_part);
1854 sgi_list_table(int xtra) {
1856 int kpi = 0; /* kernel partition ID */
1859 printf(_("\nDisk %s (SGI disk label): %d heads, %d sectors\n"
1860 "%d cylinders, %d physical cylinders\n"
1861 "%d extra sects/cyl, interleave %d:1\n"
1863 "Units = %s of %d * 512 bytes\n\n"),
1864 disk_device, heads, sectors, cylinders,
1865 SGI_SSWAP16(sgiparam.pcylcount),
1866 SGI_SSWAP16(sgiparam.sparecyl),
1867 SGI_SSWAP16(sgiparam.ilfact),
1869 str_units(PLURAL), units_per_sector);
1871 printf( _("\nDisk %s (SGI disk label): "
1872 "%d heads, %d sectors, %d cylinders\n"
1873 "Units = %s of %d * 512 bytes\n\n"),
1874 disk_device, heads, sectors, cylinders,
1875 str_units(PLURAL), units_per_sector );
1878 w = strlen(disk_device);
1879 wd = strlen(_("Device"));
1883 printf(_("----- partitions -----\n"
1884 "Pt# %*s Info Start End Sectors Id System\n"),
1885 w + 2, _("Device"));
1886 for (i = 0 ; i < partitions; i++) {
1887 if( sgi_get_num_sectors(i) || debug ) {
1888 uint32_t start = sgi_get_start_sector(i);
1889 uint32_t len = sgi_get_num_sectors(i);
1890 kpi++; /* only count nonempty partitions */
1892 "%2d: %s %4s %9ld %9ld %9ld %2x %s\n",
1893 /* fdisk part number */ i+1,
1894 /* device */ partname(disk_device, kpi, w+3),
1895 /* flags */ (sgi_get_swappartition() == i) ? "swap" :
1896 /* flags */ (sgi_get_bootpartition() == i) ? "boot" : " ",
1897 /* start */ (long) scround(start),
1898 /* end */ (long) scround(start+len)-1,
1899 /* no odd flag on end */ (long) len,
1900 /* type id */ sgi_get_sysid(i),
1901 /* type name */ partition_type(sgi_get_sysid(i)));
1904 printf(_("----- Bootinfo -----\nBootfile: %s\n"
1905 "----- Directory Entries -----\n"),
1906 sgilabel->boot_file);
1907 for (i = 0 ; i < sgi_volumes; i++) {
1908 if (sgilabel->directory[i].vol_file_size) {
1909 uint32_t start = SGI_SSWAP32(sgilabel->directory[i].vol_file_start);
1910 uint32_t len = SGI_SSWAP32(sgilabel->directory[i].vol_file_size);
1911 char*name = sgilabel->directory[i].vol_file_name;
1913 printf(_("%2d: %-10s sector%5u size%8u\n"),
1914 i, name, (unsigned int) start, (unsigned int) len);
1920 sgi_set_bootpartition( int i )
1922 sgilabel->boot_part = SGI_SSWAP16(((short)i));
1926 sgi_get_lastblock(void) {
1927 return heads * sectors * cylinders;
1931 sgi_set_swappartition( int i ) {
1932 sgilabel->swap_part = SGI_SSWAP16(((short)i));
1936 sgi_check_bootfile(const char* aFile) {
1938 if (strlen(aFile) < 3) /* "/a\n" is minimum */ {
1939 printf(_("\nInvalid Bootfile!\n"
1940 "\tThe bootfile must be an absolute non-zero pathname,\n"
1941 "\te.g. \"/unix\" or \"/unix.save\".\n"));
1944 if (strlen(aFile) > 16) {
1945 printf(_("\n\tName of Bootfile too long: "
1946 "16 bytes maximum.\n"));
1949 if (aFile[0] != '/') {
1950 printf(_("\n\tBootfile must have a "
1951 "fully qualified pathname.\n"));
1956 if (strncmp(aFile, sgilabel->boot_file, 16)) {
1957 printf(_("\n\tBe aware, that the bootfile is not checked for existence.\n\t"
1958 "SGI's default is \"/unix\" and for backup \"/unix.save\".\n"));
1959 /* filename is correct and did change */
1962 return 0; /* filename did not change */
1966 sgi_get_bootfile(void) {
1967 return sgilabel->boot_file;
1971 sgi_set_bootfile(const char* aFile) {
1974 if (sgi_check_bootfile(aFile)) {
1976 if ((aFile[i] != '\n') /* in principle caught again by next line */
1977 && (strlen(aFile) > i))
1978 sgilabel->boot_file[i] = aFile[i];
1980 sgilabel->boot_file[i] = 0;
1983 printf(_("\n\tBootfile is changed to \"%s\".\n"), sgilabel->boot_file);
1988 create_sgiinfo(void)
1990 /* I keep SGI's habit to write the sgilabel to the second block */
1991 sgilabel->directory[0].vol_file_start = SGI_SSWAP32(2);
1992 sgilabel->directory[0].vol_file_size = SGI_SSWAP32(sizeof(sgiinfo));
1993 strncpy(sgilabel->directory[0].vol_file_name, "sgilabel", 8);
1996 static sgiinfo *fill_sgiinfo(void);
1999 sgi_write_table(void) {
2001 sgilabel->csum = SGI_SSWAP32(two_s_complement_32bit_sum(
2002 (unsigned int*)sgilabel,
2003 sizeof(*sgilabel)));
2004 assert(two_s_complement_32bit_sum(
2005 (unsigned int*)sgilabel, sizeof(*sgilabel)) == 0);
2006 if (lseek(fd, 0, SEEK_SET) < 0)
2007 fdisk_fatal(unable_to_seek);
2008 if (write(fd, sgilabel, SECTOR_SIZE) != SECTOR_SIZE)
2009 fdisk_fatal(unable_to_write);
2010 if (! strncmp(sgilabel->directory[0].vol_file_name, "sgilabel", 8)) {
2012 * keep this habit of first writing the "sgilabel".
2013 * I never tested whether it works without (AN 981002).
2015 sgiinfo *info = fill_sgiinfo();
2016 int infostartblock = SGI_SSWAP32(sgilabel->directory[0].vol_file_start);
2017 if (lseek(fd, infostartblock*SECTOR_SIZE, SEEK_SET) < 0)
2018 fdisk_fatal(unable_to_seek);
2019 if (write(fd, info, SECTOR_SIZE) != SECTOR_SIZE)
2020 fdisk_fatal(unable_to_write);
2026 compare_start(int *x, int *y) {
2028 * sort according to start sectors
2029 * and prefers largest partition:
2030 * entry zero is entire disk entry
2032 unsigned int i = *x;
2033 unsigned int j = *y;
2034 unsigned int a = sgi_get_start_sector(i);
2035 unsigned int b = sgi_get_start_sector(j);
2036 unsigned int c = sgi_get_num_sectors(i);
2037 unsigned int d = sgi_get_num_sectors(j);
2040 return (d > c) ? 1 : (d == c) ? 0 : -1;
2041 return (a > b) ? 1 : -1;
2046 verify_sgi(int verbose)
2048 int Index[16]; /* list of valid partitions */
2049 int sortcount = 0; /* number of used partitions, i.e. non-zero lengths */
2050 int entire = 0, i = 0;
2051 unsigned int start = 0;
2052 long long gap = 0; /* count unused blocks */
2053 unsigned int lastblock = sgi_get_lastblock();
2056 for (i=0; i<16; i++) {
2057 if (sgi_get_num_sectors(i) != 0) {
2058 Index[sortcount++]=i;
2059 if (sgi_get_sysid(i) == ENTIRE_DISK) {
2060 if (entire++ == 1) {
2062 printf(_("More than one entire disk entry present.\n"));
2067 if (sortcount == 0) {
2069 printf(_("No partitions defined\n"));
2070 return (lastblock > 0) ? 1 : (lastblock == 0) ? 0 : -1;
2072 qsort(Index, sortcount, sizeof(Index[0]), (void*)compare_start);
2073 if (sgi_get_sysid(Index[0]) == ENTIRE_DISK) {
2074 if ((Index[0] != 10) && verbose)
2075 printf(_("IRIX likes when Partition 11 covers the entire disk.\n"));
2076 if ((sgi_get_start_sector(Index[0]) != 0) && verbose)
2077 printf(_("The entire disk partition should start "
2079 "not at diskblock %d.\n"),
2080 sgi_get_start_sector(Index[0]));
2081 if (debug) /* I do not understand how some disks fulfil it */
2082 if ((sgi_get_num_sectors(Index[0]) != lastblock) && verbose)
2083 printf(_("The entire disk partition is only %d diskblock large,\n"
2084 "but the disk is %d diskblocks long.\n"),
2085 sgi_get_num_sectors(Index[0]), lastblock);
2086 lastblock = sgi_get_num_sectors(Index[0]);
2089 printf(_("One Partition (#11) should cover the entire disk.\n"));
2091 printf("sysid=%d\tpartition=%d\n",
2092 sgi_get_sysid(Index[0]), Index[0]+1);
2094 for (i=1, start=0; i<sortcount; i++) {
2095 int cylsize = sgi_get_nsect() * sgi_get_ntrks();
2097 if ((sgi_get_start_sector(Index[i]) % cylsize) != 0) {
2098 if (debug) /* I do not understand how some disks fulfil it */
2100 printf(_("Partition %d does not start on cylinder boundary.\n"),
2103 if (sgi_get_num_sectors(Index[i]) % cylsize != 0) {
2104 if (debug) /* I do not understand how some disks fulfil it */
2106 printf(_("Partition %d does not end on cylinder boundary.\n"),
2109 /* We cannot handle several "entire disk" entries. */
2110 if (sgi_get_sysid(Index[i]) == ENTIRE_DISK) continue;
2111 if (start > sgi_get_start_sector(Index[i])) {
2113 printf(_("The Partition %d and %d overlap by %d sectors.\n"),
2114 Index[i-1]+1, Index[i]+1,
2115 start - sgi_get_start_sector(Index[i]));
2116 if (gap > 0) gap = -gap;
2117 if (gap == 0) gap = -1;
2119 if (start < sgi_get_start_sector(Index[i])) {
2121 printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"),
2122 sgi_get_start_sector(Index[i]) - start,
2123 start, sgi_get_start_sector(Index[i])-1);
2124 gap += sgi_get_start_sector(Index[i]) - start;
2125 add2freelist(start, sgi_get_start_sector(Index[i]));
2127 start = sgi_get_start_sector(Index[i])
2128 + sgi_get_num_sectors(Index[i]);
2131 printf("%2d:%12d\t%12d\t%12d\n", Index[i],
2132 sgi_get_start_sector(Index[i]),
2133 sgi_get_num_sectors(Index[i]),
2134 sgi_get_sysid(Index[i]));
2137 if (start < lastblock) {
2139 printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"),
2140 lastblock - start, start, lastblock-1);
2141 gap += lastblock - start;
2142 add2freelist(start, lastblock);
2145 * Done with arithmetics
2146 * Go for details now
2149 if (!sgi_get_num_sectors(sgi_get_bootpartition())) {
2150 printf(_("\nThe boot partition does not exist.\n"));
2152 if (!sgi_get_num_sectors(sgi_get_swappartition())) {
2153 printf(_("\nThe swap partition does not exist.\n"));
2155 if ((sgi_get_sysid(sgi_get_swappartition()) != SGI_SWAP)
2156 && (sgi_get_sysid(sgi_get_swappartition()) != LINUX_SWAP))
2157 printf(_("\nThe swap partition has no swap type.\n"));
2159 if (sgi_check_bootfile("/unix"))
2160 printf(_("\tYou have chosen an unusual boot file name.\n"));
2162 return (gap > 0) ? 1 : (gap == 0) ? 0 : -1;
2168 * returned value is:
2169 * = 0 : disk is properly filled to the rim
2170 * < 0 : there is an overlap
2171 * > 0 : there is still some vacant space
2173 return verify_sgi(0);
2177 sgi_change_sysid( int i, int sys )
2179 if( sgi_get_num_sectors(i) == 0 ) /* caught already before, ... */
2181 printf(_("Sorry You may change the Tag of non-empty partitions.\n"));
2184 if( ((sys != ENTIRE_DISK ) && (sys != SGI_VOLHDR))
2185 && (sgi_get_start_sector(i)<1) )
2188 _("It is highly recommended that the partition at offset 0\n"
2189 "is of type \"SGI volhdr\", the IRIX system will rely on it to\n"
2190 "retrieve from its directory standalone tools like sash and fx.\n"
2191 "Only the \"SGI volume\" entire disk section may violate this.\n"
2192 "Type YES if you are sure about tagging this partition differently.\n"));
2193 if (strcmp (line_ptr, _("YES\n")))
2196 sgilabel->partitions[i].id = SGI_SSWAP32(sys);
2199 /* returns partition index of first entry marked as entire disk */
2205 if(sgi_get_sysid(i) == SGI_VOLUME)
2211 sgi_set_partition(int i, unsigned int start, unsigned int length, int sys) {
2213 sgilabel->partitions[i].id = SGI_SSWAP32(sys);
2214 sgilabel->partitions[i].num_sectors = SGI_SSWAP32(length);
2215 sgilabel->partitions[i].start_sector = SGI_SSWAP32(start);
2217 if (sgi_gaps() < 0) /* rebuild freelist */
2218 printf(_("Do You know, You got a partition overlap on the disk?\n"));
2222 sgi_set_entire(void) {
2225 for(n=10; n < partitions; n++) {
2226 if(!sgi_get_num_sectors(n) ) {
2227 sgi_set_partition(n, 0, sgi_get_lastblock(), SGI_VOLUME);
2234 sgi_set_volhdr(void)
2237 for( n=8; n<partitions; n++ )
2239 if(!sgi_get_num_sectors( n ) )
2242 * 5 cylinders is an arbitrary value I like
2243 * IRIX 5.3 stored files in the volume header
2244 * (like sash, symmon, fx, ide) with ca. 3200
2247 if( heads * sectors * 5 < sgi_get_lastblock() )
2248 sgi_set_partition( n, 0, heads * sectors * 5, SGI_VOLHDR );
2255 sgi_delete_partition( int i )
2257 sgi_set_partition( i, 0, 0, 0 );
2261 sgi_add_partition( int n, int sys )
2264 unsigned int first=0, last=0;
2268 } else if ( n == 8 ) {
2271 if(sgi_get_num_sectors(n)) {
2272 printf(_("Partition %d is already defined. Delete "
2273 "it before re-adding it.\n"), n + 1);
2276 if( (sgi_entire() == -1) && (sys != SGI_VOLUME) ) {
2277 printf(_("Attempting to generate entire disk entry automatically.\n"));
2281 if( (sgi_gaps() == 0) && (sys != SGI_VOLUME) ) {
2282 printf(_("The entire disk is already covered with partitions.\n"));
2285 if(sgi_gaps() < 0) {
2286 printf(_("You got a partition overlap on the disk. Fix it first!\n"));
2289 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
2291 if(sys == SGI_VOLUME) {
2292 last = sgi_get_lastblock();
2293 first = read_int(0, 0, last-1, 0, mesg);
2295 printf(_("It is highly recommended that eleventh partition\n"
2296 "covers the entire disk and is of type `SGI volume'\n"));
2299 first = freelist[0].first;
2300 last = freelist[0].last;
2301 first = read_int(scround(first), scround(first), scround(last)-1,
2304 if (display_in_cyl_units)
2305 first *= units_per_sector;
2307 first = first; /* align to cylinder if you know how ... */
2309 last = isinfreelist(first);
2311 printf(_("You will get a partition overlap on the disk. "
2312 "Fix it first!\n"));
2316 snprintf(mesg, sizeof(mesg), _(" Last %s"), str_units(SINGULAR));
2317 last = read_int(scround(first), scround(last)-1, scround(last)-1,
2318 scround(first), mesg)+1;
2319 if (display_in_cyl_units)
2320 last *= units_per_sector;
2322 last = last; /* align to cylinder if You know how ... */
2323 if( (sys == SGI_VOLUME) && ( first != 0 || last != sgi_get_lastblock() ) )
2324 printf(_("It is highly recommended that eleventh partition\n"
2325 "covers the entire disk and is of type `SGI volume'\n"));
2326 sgi_set_partition( n, first, last-first, sys );
2329 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
2331 create_sgilabel(void)
2333 struct hd_geometry geometry;
2340 long longsectors; /* the number of sectors on the device */
2341 int res; /* the result from the ioctl */
2342 int sec_fac; /* the sector factor */
2344 sec_fac = sector_size / 512; /* determine the sector factor */
2347 _("Building a new SGI disklabel. Changes will remain in memory only,\n"
2348 "until you decide to write them. After that, of course, the previous\n"
2349 "content will be unrecoverably lost.\n\n"));
2351 sgi_other_endian = (BYTE_ORDER == LITTLE_ENDIAN);
2352 res = ioctl(fd, BLKGETSIZE, &longsectors);
2353 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
2354 heads = geometry.heads;
2355 sectors = geometry.sectors;
2357 /* the get device size ioctl was successful */
2358 cylinders = longsectors / (heads * sectors);
2359 cylinders /= sec_fac;
2361 /* otherwise print error and use truncated version */
2362 cylinders = geometry.cylinders;
2364 _("Warning: BLKGETSIZE ioctl failed on %s. "
2365 "Using geometry cylinder value of %d.\n"
2366 "This value may be truncated for devices"
2367 " > 33.8 GB.\n"), disk_device, cylinders);
2370 for (i = 0; i < 4; i++) {
2372 if(valid_part_table_flag(MBRbuffer)) {
2373 if(get_part_table(i)->sys_ind) {
2374 old[i].sysid = get_part_table(i)->sys_ind;
2375 old[i].start = get_start_sect(get_part_table(i));
2376 old[i].nsect = get_nr_sects(get_part_table(i));
2377 printf(_("Trying to keep parameters of partition %d.\n"), i);
2379 printf(_("ID=%02x\tSTART=%d\tLENGTH=%d\n"),
2380 old[i].sysid, old[i].start, old[i].nsect);
2385 memset(MBRbuffer, 0, sizeof(MBRbuffer));
2386 sgilabel->magic = SGI_SSWAP32(SGI_LABEL_MAGIC);
2387 sgilabel->boot_part = SGI_SSWAP16(0);
2388 sgilabel->swap_part = SGI_SSWAP16(1);
2390 /* sizeof(sgilabel->boot_file) = 16 > 6 */
2391 memset(sgilabel->boot_file, 0, 16);
2392 strcpy(sgilabel->boot_file, "/unix");
2394 sgilabel->devparam.skew = (0);
2395 sgilabel->devparam.gap1 = (0);
2396 sgilabel->devparam.gap2 = (0);
2397 sgilabel->devparam.sparecyl = (0);
2398 sgilabel->devparam.pcylcount = SGI_SSWAP16(geometry.cylinders);
2399 sgilabel->devparam.head_vol0 = SGI_SSWAP16(0);
2400 sgilabel->devparam.ntrks = SGI_SSWAP16(geometry.heads);
2401 /* tracks/cylinder (heads) */
2402 sgilabel->devparam.cmd_tag_queue_depth = (0);
2403 sgilabel->devparam.unused0 = (0);
2404 sgilabel->devparam.unused1 = SGI_SSWAP16(0);
2405 sgilabel->devparam.nsect = SGI_SSWAP16(geometry.sectors);
2407 sgilabel->devparam.bytes = SGI_SSWAP16(512);
2408 sgilabel->devparam.ilfact = SGI_SSWAP16(1);
2409 sgilabel->devparam.flags = SGI_SSWAP32(TRACK_FWD|
2410 IGNORE_ERRORS|RESEEK);
2411 sgilabel->devparam.datarate = SGI_SSWAP32(0);
2412 sgilabel->devparam.retries_on_error = SGI_SSWAP32(1);
2413 sgilabel->devparam.ms_per_word = SGI_SSWAP32(0);
2414 sgilabel->devparam.xylogics_gap1 = SGI_SSWAP16(0);
2415 sgilabel->devparam.xylogics_syncdelay = SGI_SSWAP16(0);
2416 sgilabel->devparam.xylogics_readdelay = SGI_SSWAP16(0);
2417 sgilabel->devparam.xylogics_gap2 = SGI_SSWAP16(0);
2418 sgilabel->devparam.xylogics_readgate = SGI_SSWAP16(0);
2419 sgilabel->devparam.xylogics_writecont = SGI_SSWAP16(0);
2420 memset( &(sgilabel->directory), 0, sizeof(struct volume_directory)*15 );
2421 memset( &(sgilabel->partitions), 0, sizeof(struct sgi_partition)*16 );
2427 for (i = 0; i < 4; i++) {
2429 sgi_set_partition(i, old[i].start, old[i].nsect, old[i].sysid);
2437 /* do nothing in the beginning */
2439 #endif /* CONFIG_FEATURE_FDISK_ADVANCED */
2441 /* _____________________________________________________________
2447 sgiinfo *info = calloc(1, sizeof(sgiinfo));
2449 info->magic=SGI_SSWAP32(SGI_INFO_MAGIC);
2450 info->b1=SGI_SSWAP32(-1);
2451 info->b2=SGI_SSWAP16(-1);
2452 info->b3=SGI_SSWAP16(1);
2453 /* You may want to replace this string !!!!!!! */
2454 strcpy( info->scsi_string, "IBM OEM 0662S12 3 30" );
2455 strcpy( info->serial, "0000" );
2456 info->check1816 = SGI_SSWAP16(18*256 +16 );
2457 strcpy( info->installer, "Sfx version 5.3, Oct 18, 1994" );
2460 #endif /* SGI_LABEL */
2463 #ifdef CONFIG_FEATURE_SUN_LABEL
2467 * I think this is mostly, or entirely, due to
2468 * Jakub Jelinek (jj@sunsite.mff.cuni.cz), July 1996
2470 * Merged with fdisk for other architectures, aeb, June 1998.
2472 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
2473 * Internationalization
2477 static int sun_other_endian;
2478 static int scsi_disk;
2482 #define IDE0_MAJOR 3
2485 #define IDE1_MAJOR 22
2488 static void guess_device_type(void) {
2489 struct stat bootstat;
2491 if (fstat (fd, &bootstat) < 0) {
2494 } else if (S_ISBLK(bootstat.st_mode)
2495 && (major(bootstat.st_rdev) == IDE0_MAJOR ||
2496 major(bootstat.st_rdev) == IDE1_MAJOR)) {
2499 } else if (S_ISBLK(bootstat.st_mode)
2500 && major(bootstat.st_rdev) == FLOPPY_MAJOR) {
2509 static const struct systypes sun_sys_types[] = {
2510 /* 0 */ {"\x00" "Empty" },
2511 /* 1 */ {"\x01" "Boot" },
2512 /* 2 */ {"\x02" "SunOS root" },
2513 /* SUNOS_SWAP */ {"\x03" "SunOS swap" },
2514 /* 4 */ {"\x04" "SunOS usr" },
2515 /* WHOLE_DISK */ {"\x05" "Whole disk" },
2516 /* 6 */ {"\x06" "SunOS stand" },
2517 /* 7 */ {"\x07" "SunOS var" },
2518 /* 8 */ {"\x08" "SunOS home" },
2519 /* LINUX_SWAP */ {"\x82" "Linux swap" },
2520 /* LINUX_NATIVE */ {"\x83" "Linux native" },
2521 /* 0x8e */ {"\x8e" "Linux LVM" },
2522 /* New (2.2.x) raid partition with autodetect using persistent superblock */
2523 /* 0xfd */ {"\xfd" "Linux raid autodetect" },
2529 set_sun_partition(int i, uint start, uint stop, int sysid) {
2530 sunlabel->infos[i].id = sysid;
2531 sunlabel->partitions[i].start_cylinder =
2532 SUN_SSWAP32(start / (heads * sectors));
2533 sunlabel->partitions[i].num_sectors =
2534 SUN_SSWAP32(stop - start);
2541 sunlabel->magic = 0;
2546 check_sun_label(void) {
2547 unsigned short *ush;
2550 if (sunlabel->magic != SUN_LABEL_MAGIC &&
2551 sunlabel->magic != SUN_LABEL_MAGIC_SWAPPED) {
2553 sun_other_endian = 0;
2556 sun_other_endian = (sunlabel->magic == SUN_LABEL_MAGIC_SWAPPED);
2557 ush = ((unsigned short *) (sunlabel + 1)) - 1;
2558 for (csum = 0; ush >= (unsigned short *)sunlabel;) csum ^= *ush--;
2560 fprintf(stderr,_("Detected sun disklabel with wrong checksum.\n"
2561 "Probably you'll have to set all the values,\n"
2562 "e.g. heads, sectors, cylinders and partitions\n"
2563 "or force a fresh label (s command in main menu)\n"));
2565 heads = SUN_SSWAP16(sunlabel->ntrks);
2566 cylinders = SUN_SSWAP16(sunlabel->ncyl);
2567 sectors = SUN_SSWAP16(sunlabel->nsect);
2575 static const struct sun_predefined_drives {
2578 unsigned short sparecyl;
2579 unsigned short ncyl;
2580 unsigned short nacyl;
2581 unsigned short pcylcount;
2582 unsigned short ntrks;
2583 unsigned short nsect;
2584 unsigned short rspeed;
2586 {"Quantum","ProDrive 80S",1,832,2,834,6,34,3662},
2587 {"Quantum","ProDrive 105S",1,974,2,1019,6,35,3662},
2588 {"CDC","Wren IV 94171-344",3,1545,2,1549,9,46,3600},
2589 {"IBM","DPES-31080",0,4901,2,4903,4,108,5400},
2590 {"IBM","DORS-32160",0,1015,2,1017,67,62,5400},
2591 {"IBM","DNES-318350",0,11199,2,11474,10,320,7200},
2592 {"SEAGATE","ST34371",0,3880,2,3882,16,135,7228},
2593 {"","SUN0104",1,974,2,1019,6,35,3662},
2594 {"","SUN0207",4,1254,2,1272,9,36,3600},
2595 {"","SUN0327",3,1545,2,1549,9,46,3600},
2596 {"","SUN0340",0,1538,2,1544,6,72,4200},
2597 {"","SUN0424",2,1151,2,2500,9,80,4400},
2598 {"","SUN0535",0,1866,2,2500,7,80,5400},
2599 {"","SUN0669",5,1614,2,1632,15,54,3600},
2600 {"","SUN1.0G",5,1703,2,1931,15,80,3597},
2601 {"","SUN1.05",0,2036,2,2038,14,72,5400},
2602 {"","SUN1.3G",6,1965,2,3500,17,80,5400},
2603 {"","SUN2.1G",0,2733,2,3500,19,80,5400},
2604 {"IOMEGA","Jaz",0,1019,2,1021,64,32,5394},
2607 static const struct sun_predefined_drives *
2608 sun_autoconfigure_scsi(void) {
2609 const struct sun_predefined_drives *p = NULL;
2611 #ifdef SCSI_IOCTL_GET_IDLUN
2621 if (!ioctl(fd, SCSI_IOCTL_GET_IDLUN, &id)) {
2623 "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n",
2625 ((id[0]>>24)&0xff)-/*PROC_SCSI_SCSI+PROC_SCSI_FILE*/33,
2627 /* This is very wrong (works only if you have one HBA),
2628 but I haven't found a way how to get hostno
2629 from the current kernel */
2635 pfd = fopen("/proc/scsi/scsi","r");
2637 while (fgets(buffer2,2048,pfd)) {
2638 if (!strcmp(buffer, buffer2)) {
2639 if (fgets(buffer2,2048,pfd)) {
2640 q = strstr(buffer2,"Vendor: ");
2645 *q++ = 0; /* truncate vendor name */
2646 q = strstr(q,"Model: ");
2651 q = strstr(q," Rev: ");
2654 for (i = 0; i < SIZE(sun_drives); i++) {
2655 if (*sun_drives[i].vendor && strcasecmp(sun_drives[i].vendor, vendor))
2657 if (!strstr(model, sun_drives[i].model))
2659 printf(_("Autoconfigure found a %s%s%s\n"),sun_drives[i].vendor,(*sun_drives[i].vendor) ? " " : "",sun_drives[i].model);
2677 static void create_sunlabel(void)
2679 struct hd_geometry geometry;
2683 const struct sun_predefined_drives *p = NULL;
2686 _("Building a new sun disklabel. Changes will remain in memory only,\n"
2687 "until you decide to write them. After that, of course, the previous\n"
2688 "content won't be recoverable.\n\n"));
2689 #if BYTE_ORDER == LITTLE_ENDIAN
2690 sun_other_endian = 1;
2692 sun_other_endian = 0;
2694 memset(MBRbuffer, 0, sizeof(MBRbuffer));
2695 sunlabel->magic = SUN_SSWAP16(SUN_LABEL_MAGIC);
2697 puts(_("Drive type\n"
2698 " ? auto configure\n"
2699 " 0 custom (with hardware detected defaults)"));
2700 for (i = 0; i < SIZE(sun_drives); i++) {
2701 printf(" %c %s%s%s\n",
2702 i + 'a', sun_drives[i].vendor,
2703 (*sun_drives[i].vendor) ? " " : "",
2704 sun_drives[i].model);
2707 c = read_char(_("Select type (? for auto, 0 for custom): "));
2708 if (c >= 'a' && c < 'a' + SIZE(sun_drives)) {
2709 p = sun_drives + c - 'a';
2711 } else if (c >= 'A' && c < 'A' + SIZE(sun_drives)) {
2712 p = sun_drives + c - 'A';
2714 } else if (c == '0') {
2716 } else if (c == '?' && scsi_disk) {
2717 p = sun_autoconfigure_scsi();
2719 printf(_("Autoconfigure failed.\n"));
2726 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
2727 heads = geometry.heads;
2728 sectors = geometry.sectors;
2729 cylinders = geometry.cylinders;
2736 sunlabel->nacyl = 0;
2737 sunlabel->pcylcount = SUN_SSWAP16(cylinders);
2738 sunlabel->rspeed = SUN_SSWAP16(300);
2739 sunlabel->ilfact = SUN_SSWAP16(1);
2740 sunlabel->sparecyl = 0;
2742 heads = read_int(1,heads,1024,0,_("Heads"));
2743 sectors = read_int(1,sectors,1024,0,_("Sectors/track"));
2745 cylinders = read_int(1,cylinders-2,65535,0,_("Cylinders"));
2747 cylinders = read_int(1,0,65535,0,_("Cylinders"));
2749 SUN_SSWAP16(read_int(0,2,65535,0,
2750 _("Alternate cylinders")));
2751 sunlabel->pcylcount =
2752 SUN_SSWAP16(read_int(0,cylinders+SUN_SSWAP16(sunlabel->nacyl),
2753 65535,0,_("Physical cylinders")));
2755 SUN_SSWAP16(read_int(1,5400,100000,0,
2756 _("Rotation speed (rpm)")));
2758 SUN_SSWAP16(read_int(1,1,32,0,_("Interleave factor")));
2759 sunlabel->sparecyl =
2760 SUN_SSWAP16(read_int(0,0,sectors,0,
2761 _("Extra sectors per cylinder")));
2764 sunlabel->sparecyl = SUN_SSWAP16(p->sparecyl);
2765 sunlabel->ncyl = SUN_SSWAP16(p->ncyl);
2766 sunlabel->nacyl = SUN_SSWAP16(p->nacyl);
2767 sunlabel->pcylcount = SUN_SSWAP16(p->pcylcount);
2768 sunlabel->ntrks = SUN_SSWAP16(p->ntrks);
2769 sunlabel->nsect = SUN_SSWAP16(p->nsect);
2770 sunlabel->rspeed = SUN_SSWAP16(p->rspeed);
2771 sunlabel->ilfact = SUN_SSWAP16(1);
2772 cylinders = p->ncyl;
2775 puts(_("You may change all the disk params from the x menu"));
2778 snprintf((char *)(sunlabel->info), sizeof(sunlabel->info),
2779 "%s%s%s cyl %d alt %d hd %d sec %d",
2780 p ? p->vendor : "", (p && *p->vendor) ? " " : "",
2782 : (floppy ? _("3,5\" floppy") : _("Linux custom")),
2783 cylinders, SUN_SSWAP16(sunlabel->nacyl), heads, sectors);
2785 sunlabel->ntrks = SUN_SSWAP16(heads);
2786 sunlabel->nsect = SUN_SSWAP16(sectors);
2787 sunlabel->ncyl = SUN_SSWAP16(cylinders);
2789 set_sun_partition(0, 0, cylinders * heads * sectors, LINUX_NATIVE);
2791 if (cylinders * heads * sectors >= 150 * 2048) {
2792 ndiv = cylinders - (50 * 2048 / (heads * sectors)); /* 50M swap */
2794 ndiv = cylinders * 2 / 3;
2795 set_sun_partition(0, 0, ndiv * heads * sectors, LINUX_NATIVE);
2796 set_sun_partition(1, ndiv * heads * sectors, cylinders * heads * sectors, LINUX_SWAP);
2797 sunlabel->infos[1].flags |= 0x01; /* Not mountable */
2799 set_sun_partition(2, 0, cylinders * heads * sectors, WHOLE_DISK);
2801 unsigned short *ush = (unsigned short *)sunlabel;
2802 unsigned short csum = 0;
2803 while(ush < (unsigned short *)(&sunlabel->csum))
2805 sunlabel->csum = csum;
2808 set_all_unchanged();
2810 get_boot(create_empty_sun);
2814 toggle_sunflags(int i, unsigned char mask) {
2815 if (sunlabel->infos[i].flags & mask)
2816 sunlabel->infos[i].flags &= ~mask;
2817 else sunlabel->infos[i].flags |= mask;
2822 fetch_sun(uint *starts, uint *lens, uint *start, uint *stop) {
2823 int i, continuous = 1;
2824 *start = 0; *stop = cylinders * heads * sectors;
2825 for (i = 0; i < partitions; i++) {
2826 if (sunlabel->partitions[i].num_sectors
2827 && sunlabel->infos[i].id
2828 && sunlabel->infos[i].id != WHOLE_DISK) {
2829 starts[i] = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
2830 lens[i] = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
2832 if (starts[i] == *start)
2834 else if (starts[i] + lens[i] >= *stop)
2838 /* There will be probably more gaps
2839 than one, so lets check afterwards */
2848 static uint *verify_sun_starts;
2851 verify_sun_cmp(int *a, int *b) {
2852 if (*a == -1) return 1;
2853 if (*b == -1) return -1;
2854 if (verify_sun_starts[*a] > verify_sun_starts[*b]) return 1;
2860 uint starts[8], lens[8], start, stop;
2861 int i,j,k,starto,endo;
2864 verify_sun_starts = starts;
2865 fetch_sun(starts,lens,&start,&stop);
2866 for (k = 0; k < 7; k++) {
2867 for (i = 0; i < 8; i++) {
2868 if (k && (lens[i] % (heads * sectors))) {
2869 printf(_("Partition %d doesn't end on cylinder boundary\n"), i+1);
2872 for (j = 0; j < i; j++)
2874 if (starts[j] == starts[i]+lens[i]) {
2875 starts[j] = starts[i]; lens[j] += lens[i];
2877 } else if (starts[i] == starts[j]+lens[j]){
2881 if (starts[i] < starts[j]+lens[j] &&
2882 starts[j] < starts[i]+lens[i]) {
2884 if (starts[j] > starto)
2886 endo = starts[i]+lens[i];
2887 if (starts[j]+lens[j] < endo)
2888 endo = starts[j]+lens[j];
2889 printf(_("Partition %d overlaps with others in "
2890 "sectors %d-%d\n"), i+1, starto, endo);
2897 for (i = 0; i < 8; i++) {
2903 qsort(array,SIZE(array),sizeof(array[0]),
2904 (int (*)(const void *,const void *)) verify_sun_cmp);
2905 if (array[0] == -1) {
2906 printf(_("No partitions defined\n"));
2909 stop = cylinders * heads * sectors;
2910 if (starts[array[0]])
2911 printf(_("Unused gap - sectors 0-%d\n"),starts[array[0]]);
2912 for (i = 0; i < 7 && array[i+1] != -1; i++) {
2913 printf(_("Unused gap - sectors %d-%d\n"),starts[array[i]]+lens[array[i]],starts[array[i+1]]);
2915 start = starts[array[i]]+lens[array[i]];
2917 printf(_("Unused gap - sectors %d-%d\n"),start,stop);
2921 add_sun_partition(int n, int sys) {
2922 uint start, stop, stop2;
2923 uint starts[8], lens[8];
2929 if (sunlabel->partitions[n].num_sectors && sunlabel->infos[n].id) {
2930 printf(_("Partition %d is already defined. Delete "
2931 "it before re-adding it.\n"), n + 1);
2935 fetch_sun(starts,lens,&start,&stop);
2936 if (stop <= start) {
2940 printf(_("Other partitions already cover the whole disk.\nDelete "
2941 "some/shrink them before retry.\n"));
2945 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
2948 first = read_int(0, 0, 0, 0, mesg);
2950 first = read_int(scround(start), scround(stop)+1,
2951 scround(stop), 0, mesg);
2952 if (display_in_cyl_units)
2953 first *= units_per_sector;
2955 /* Starting sector has to be properly aligned */
2956 first = (first + heads * sectors - 1) / (heads * sectors);
2957 if (n == 2 && first != 0)
2959 It is highly recommended that the third partition covers the whole disk\n\
2960 and is of type `Whole disk'\n");
2961 /* ewt asks to add: "don't start a partition at cyl 0"
2962 However, edmundo@rano.demon.co.uk writes:
2963 "In addition to having a Sun partition table, to be able to
2964 boot from the disc, the first partition, /dev/sdX1, must
2965 start at cylinder 0. This means that /dev/sdX1 contains
2966 the partition table and the boot block, as these are the
2967 first two sectors of the disc. Therefore you must be
2968 careful what you use /dev/sdX1 for. In particular, you must
2969 not use a partition starting at cylinder 0 for Linux swap,
2970 as that would overwrite the partition table and the boot
2971 block. You may, however, use such a partition for a UFS
2972 or EXT2 file system, as these file systems leave the first
2973 1024 bytes undisturbed. */
2974 /* On the other hand, one should not use partitions
2975 starting at block 0 in an md, or the label will
2977 for (i = 0; i < partitions; i++)
2978 if (lens[i] && starts[i] <= first
2979 && starts[i] + lens[i] > first)
2981 if (i < partitions && !whole_disk) {
2982 if (n == 2 && !first) {
2986 printf(_("Sector %d is already allocated\n"), first);
2990 stop = cylinders * heads * sectors;
2992 for (i = 0; i < partitions; i++) {
2993 if (starts[i] > first && starts[i] < stop)
2996 snprintf(mesg, sizeof(mesg),
2997 _("Last %s or +size or +sizeM or +sizeK"),
2998 str_units(SINGULAR));
3000 last = read_int(scround(stop2), scround(stop2), scround(stop2),
3002 else if (n == 2 && !first)
3003 last = read_int(scround(first), scround(stop2), scround(stop2),
3004 scround(first), mesg);
3006 last = read_int(scround(first), scround(stop), scround(stop),
3007 scround(first), mesg);
3008 if (display_in_cyl_units)
3009 last *= units_per_sector;
3010 if (n == 2 && !first) {
3011 if (last >= stop2) {
3014 } else if (last > stop) {
3016 _("You haven't covered the whole disk with the 3rd partition, but your value\n"
3017 "%d %s covers some other partition. Your entry has been changed\n"
3019 scround(last), str_units(SINGULAR),
3020 scround(stop), str_units(SINGULAR));
3023 } else if (!whole_disk && last > stop)
3026 if (whole_disk) sys = WHOLE_DISK;
3027 set_sun_partition(n, first, last, sys);
3031 sun_delete_partition(int i) {
3034 if (i == 2 && sunlabel->infos[i].id == WHOLE_DISK &&
3035 !sunlabel->partitions[i].start_cylinder &&
3036 (nsec = SUN_SSWAP32(sunlabel->partitions[i].num_sectors))
3037 == heads * sectors * cylinders)
3038 printf(_("If you want to maintain SunOS/Solaris compatibility, "
3039 "consider leaving this\n"
3040 "partition as Whole disk (5), starting at 0, with %u "
3041 "sectors\n"), nsec);
3042 sunlabel->infos[i].id = 0;
3043 sunlabel->partitions[i].num_sectors = 0;
3047 sun_change_sysid(int i, int sys) {
3048 if (sys == LINUX_SWAP && !sunlabel->partitions[i].start_cylinder) {
3050 _("It is highly recommended that the partition at offset 0\n"
3051 "is UFS, EXT2FS filesystem or SunOS swap. Putting Linux swap\n"
3052 "there may destroy your partition table and bootblock.\n"
3053 "Type YES if you're very sure you would like that partition\n"
3054 "tagged with 82 (Linux swap): "));
3055 if (strcmp (line_ptr, _("YES\n")))
3061 /* swaps are not mountable by default */
3062 sunlabel->infos[i].flags |= 0x01;
3065 /* assume other types are mountable;
3066 user can change it anyway */
3067 sunlabel->infos[i].flags &= ~0x01;
3070 sunlabel->infos[i].id = sys;
3074 sun_list_table(int xtra) {
3077 w = strlen(disk_device);
3080 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d rpm\n"
3081 "%d cylinders, %d alternate cylinders, %d physical cylinders\n"
3082 "%d extra sects/cyl, interleave %d:1\n"
3084 "Units = %s of %d * 512 bytes\n\n"),
3085 disk_device, heads, sectors, SUN_SSWAP16(sunlabel->rspeed),
3086 cylinders, SUN_SSWAP16(sunlabel->nacyl),
3087 SUN_SSWAP16(sunlabel->pcylcount),
3088 SUN_SSWAP16(sunlabel->sparecyl),
3089 SUN_SSWAP16(sunlabel->ilfact),
3091 str_units(PLURAL), units_per_sector);
3094 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d cylinders\n"
3095 "Units = %s of %d * 512 bytes\n\n"),
3096 disk_device, heads, sectors, cylinders,
3097 str_units(PLURAL), units_per_sector);
3099 printf(_("%*s Flag Start End Blocks Id System\n"),
3100 w + 1, _("Device"));
3101 for (i = 0 ; i < partitions; i++) {
3102 if (sunlabel->partitions[i].num_sectors) {
3103 uint32_t start = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
3104 uint32_t len = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
3106 "%s %c%c %9ld %9ld %9ld%c %2x %s\n",
3107 /* device */ partname(disk_device, i+1, w),
3108 /* flags */ (sunlabel->infos[i].flags & 0x01) ? 'u' : ' ',
3109 (sunlabel->infos[i].flags & 0x10) ? 'r' : ' ',
3110 /* start */ (long) scround(start),
3111 /* end */ (long) scround(start+len),
3112 /* odd flag on end */ (long) len / 2, len & 1 ? '+' : ' ',
3113 /* type id */ sunlabel->infos[i].id,
3114 /* type name */ partition_type(sunlabel->infos[i].id));
3119 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3122 sun_set_alt_cyl(void) {
3124 SUN_SSWAP16(read_int(0,SUN_SSWAP16(sunlabel->nacyl), 65535, 0,
3125 _("Number of alternate cylinders")));
3129 sun_set_ncyl(int cyl) {
3130 sunlabel->ncyl = SUN_SSWAP16(cyl);
3134 sun_set_xcyl(void) {
3135 sunlabel->sparecyl =
3136 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->sparecyl), sectors, 0,
3137 _("Extra sectors per cylinder")));
3141 sun_set_ilfact(void) {
3143 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->ilfact), 32, 0,
3144 _("Interleave factor")));
3148 sun_set_rspeed(void) {
3150 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->rspeed), 100000, 0,
3151 _("Rotation speed (rpm)")));
3155 sun_set_pcylcount(void) {
3156 sunlabel->pcylcount =
3157 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->pcylcount), 65535, 0,
3158 _("Number of physical cylinders")));
3160 #endif /* CONFIG_FEATURE_FDISK_ADVANCED */
3163 sun_write_table(void) {
3164 unsigned short *ush = (unsigned short *)sunlabel;
3165 unsigned short csum = 0;
3167 while(ush < (unsigned short *)(&sunlabel->csum))
3169 sunlabel->csum = csum;
3170 if (lseek(fd, 0, SEEK_SET) < 0)
3171 fdisk_fatal(unable_to_seek);
3172 if (write(fd, sunlabel, SECTOR_SIZE) != SECTOR_SIZE)
3173 fdisk_fatal(unable_to_write);
3175 #endif /* SUN_LABEL */
3177 /* DOS partition types */
3179 static const struct systypes i386_sys_types[] = {
3182 {"\x04" "FAT16 <32M"},
3183 {"\x05" "Extended"}, /* DOS 3.3+ extended partition */
3184 {"\x06" "FAT16"}, /* DOS 16-bit >=32M */
3185 {"\x07" "HPFS/NTFS"}, /* OS/2 IFS, eg, HPFS or NTFS or QNX */
3186 {"\x0a" "OS/2 Boot Manager"},/* OS/2 Boot Manager */
3187 {"\x0b" "Win95 FAT32"},
3188 {"\x0c" "Win95 FAT32 (LBA)"},/* LBA really is `Extended Int 13h' */
3189 {"\x0e" "Win95 FAT16 (LBA)"},
3190 {"\x0f" "Win95 Ext'd (LBA)"},
3191 {"\x11" "Hidden FAT12"},
3192 {"\x12" "Compaq diagnostics"},
3193 {"\x14" "Hidden FAT16 <32M"},
3194 {"\x16" "Hidden FAT16"},
3195 {"\x17" "Hidden HPFS/NTFS"},
3196 {"\x1b" "Hidden Win95 FAT32"},
3197 {"\x1c" "Hidden Win95 FAT32 (LBA)"},
3198 {"\x1e" "Hidden Win95 FAT16 (LBA)"},
3199 {"\x3c" "PartitionMagic recovery"},
3200 {"\x41" "PPC PReP Boot"},
3202 {"\x63" "GNU HURD or SysV"}, /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */
3203 {"\x80" "Old Minix"}, /* Minix 1.4a and earlier */
3204 {"\x81" "Minix / old Linux"},/* Minix 1.4b and later */
3205 {"\x82" "Linux swap"}, /* also Solaris */
3207 {"\x84" "OS/2 hidden C: drive"},
3208 {"\x85" "Linux extended"},
3209 {"\x86" "NTFS volume set"},
3210 {"\x87" "NTFS volume set"},
3211 {"\x8e" "Linux LVM"},
3212 {"\x9f" "BSD/OS"}, /* BSDI */
3213 {"\xa0" "IBM Thinkpad hibernation"},
3214 {"\xa5" "FreeBSD"}, /* various BSD flavours */
3216 {"\xa8" "Darwin UFS"},
3218 {"\xab" "Darwin boot"},
3220 {"\xb8" "BSDI swap"},
3221 {"\xbe" "Solaris boot"},
3223 {"\xee" "EFI GPT"}, /* Intel EFI GUID Partition Table */
3224 {"\xef" "EFI (FAT-12/16/32)"},/* Intel EFI System Partition */
3225 {"\xf0" "Linux/PA-RISC boot"},/* Linux/PA-RISC boot loader */
3226 {"\xf2" "DOS secondary"}, /* DOS 3.3+ secondary */
3227 {"\xfd" "Linux raid autodetect"},/* New (2.2.x) raid partition with
3228 autodetect using persistent
3230 #ifdef CONFIG_WEIRD_PARTITION_TYPES
3231 {"\x02" "XENIX root"},
3232 {"\x03" "XENIX usr"},
3233 {"\x08" "AIX"}, /* AIX boot (AIX -- PS/2 port) or SplitDrive */
3234 {"\x09" "AIX bootable"}, /* AIX data or Coherent */
3236 {"\x18" "AST SmartSleep"},
3239 {"\x40" "Venix 80286"},
3241 {"\x4e" "QNX4.x 2nd part"},
3242 {"\x4f" "QNX4.x 3rd part"},
3243 {"\x50" "OnTrack DM"},
3244 {"\x51" "OnTrack DM6 Aux1"}, /* (or Novell) */
3245 {"\x52" "CP/M"}, /* CP/M or Microport SysV/AT */
3246 {"\x53" "OnTrack DM6 Aux3"},
3247 {"\x54" "OnTrackDM6"},
3248 {"\x55" "EZ-Drive"},
3249 {"\x56" "Golden Bow"},
3250 {"\x5c" "Priam Edisk"},
3251 {"\x61" "SpeedStor"},
3252 {"\x64" "Novell Netware 286"},
3253 {"\x65" "Novell Netware 386"},
3254 {"\x70" "DiskSecure Multi-Boot"},
3257 {"\x94" "Amoeba BBT"}, /* (bad block table) */
3258 {"\xa7" "NeXTSTEP"},
3259 {"\xbb" "Boot Wizard hidden"},
3260 {"\xc1" "DRDOS/sec (FAT-12)"},
3261 {"\xc4" "DRDOS/sec (FAT-16 < 32M)"},
3262 {"\xc6" "DRDOS/sec (FAT-16)"},
3264 {"\xda" "Non-FS data"},
3265 {"\xdb" "CP/M / CTOS / ..."},/* CP/M or Concurrent CP/M or
3266 Concurrent DOS or CTOS */
3267 {"\xde" "Dell Utility"}, /* Dell PowerEdge Server utilities */
3268 {"\xdf" "BootIt"}, /* BootIt EMBRM */
3269 {"\xe1" "DOS access"}, /* DOS access or SpeedStor 12-bit FAT
3270 extended partition */
3271 {"\xe3" "DOS R/O"}, /* DOS R/O or SpeedStor */
3272 {"\xe4" "SpeedStor"}, /* SpeedStor 16-bit FAT extended
3273 partition < 1024 cyl. */
3274 {"\xf1" "SpeedStor"},
3275 {"\xf4" "SpeedStor"}, /* SpeedStor large partition */
3276 {"\xfe" "LANstep"}, /* SpeedStor >1024 cyl. or LANstep */
3277 {"\xff" "BBT"}, /* Xenix Bad Block Table */
3284 /* A valid partition table sector ends in 0x55 0xaa */
3286 part_table_flag(const char *b) {
3287 return ((uint) b[510]) + (((uint) b[511]) << 8);
3291 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3293 write_part_table_flag(char *b) {
3298 /* start_sect and nr_sects are stored little endian on all machines */
3299 /* moreover, they are not aligned correctly */
3301 store4_little_endian(unsigned char *cp, unsigned int val) {
3302 cp[0] = (val & 0xff);
3303 cp[1] = ((val >> 8) & 0xff);
3304 cp[2] = ((val >> 16) & 0xff);
3305 cp[3] = ((val >> 24) & 0xff);
3307 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3310 read4_little_endian(const unsigned char *cp) {
3311 return (uint)(cp[0]) + ((uint)(cp[1]) << 8)
3312 + ((uint)(cp[2]) << 16) + ((uint)(cp[3]) << 24);
3315 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3317 set_start_sect(struct partition *p, unsigned int start_sect) {
3318 store4_little_endian(p->start4, start_sect);
3323 get_start_sect(const struct partition *p) {
3324 return read4_little_endian(p->start4);
3327 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3329 set_nr_sects(struct partition *p, int32_t nr_sects) {
3330 store4_little_endian(p->size4, nr_sects);
3335 get_nr_sects(const struct partition *p) {
3336 return read4_little_endian(p->size4);
3339 /* normally O_RDWR, -l option gives O_RDONLY */
3340 static int type_open = O_RDWR;
3343 static int ext_index, /* the prime extended partition */
3344 listing, /* no aborts for fdisk -l */
3345 dos_compatible_flag = ~0;
3346 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3347 static int dos_changed;
3348 static int nowarn; /* no warnings for fdisk -l/-s */
3353 static uint user_cylinders, user_heads, user_sectors;
3354 static uint pt_heads, pt_sectors;
3355 static uint kern_heads, kern_sectors;
3357 static off_t extended_offset; /* offset of link pointers */
3359 static unsigned long long total_number_of_sectors;
3362 static jmp_buf listingbuf;
3364 static void fdisk_fatal(enum failure why) {
3365 const char *message;
3369 longjmp(listingbuf, 1);
3373 case unable_to_open:
3374 message = "Unable to open %s\n";
3376 case unable_to_read:
3377 message = "Unable to read %s\n";
3379 case unable_to_seek:
3380 message = "Unable to seek on %s\n";
3382 case unable_to_write:
3383 message = "Unable to write %s\n";
3386 message = "BLKGETSIZE ioctl failed on %s\n";
3389 message = "Fatal error\n";
3392 fputc('\n', stderr);
3393 fprintf(stderr, message, disk_device);
3398 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) {
3408 if (write(fd, buf, sector_size) != sector_size)
3409 fdisk_fatal(unable_to_write);
3413 /* Allocate a buffer and read a partition table sector */
3415 read_pte(struct pte *pe, off_t offset) {
3417 pe->offset = offset;
3418 pe->sectorbuffer = (char *) xmalloc(sector_size);
3419 seek_sector(offset);
3420 if (read(fd, pe->sectorbuffer, sector_size) != sector_size)
3421 fdisk_fatal(unable_to_read);
3422 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3425 pe->part_table = pe->ext_pointer = NULL;
3429 get_partition_start(const struct pte *pe) {
3430 return pe->offset + get_start_sect(pe->part_table);
3433 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3435 * Avoid warning about DOS partitions when no DOS partition was changed.
3436 * Here a heuristic "is probably dos partition".
3437 * We might also do the opposite and warn in all cases except
3438 * for "is probably nondos partition".
3441 is_dos_partition(int t) {
3442 return (t == 1 || t == 4 || t == 6 ||
3443 t == 0x0b || t == 0x0c || t == 0x0e ||
3444 t == 0x11 || t == 0x12 || t == 0x14 || t == 0x16 ||
3445 t == 0x1b || t == 0x1c || t == 0x1e || t == 0x24 ||
3446 t == 0xc1 || t == 0xc4 || t == 0xc6);
3451 #ifdef CONFIG_FEATURE_SUN_LABEL
3453 puts(_("Command action"));
3454 puts(_("\ta\ttoggle a read only flag")); /* sun */
3455 puts(_("\tb\tedit bsd disklabel"));
3456 puts(_("\tc\ttoggle the mountable flag")); /* sun */
3457 puts(_("\td\tdelete a partition"));
3458 puts(_("\tl\tlist known partition types"));
3459 puts(_("\tm\tprint this menu"));
3460 puts(_("\tn\tadd a new partition"));
3461 puts(_("\to\tcreate a new empty DOS partition table"));
3462 puts(_("\tp\tprint the partition table"));
3463 puts(_("\tq\tquit without saving changes"));
3464 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3465 puts(_("\tt\tchange a partition's system id"));
3466 puts(_("\tu\tchange display/entry units"));
3467 puts(_("\tv\tverify the partition table"));
3468 puts(_("\tw\twrite table to disk and exit"));
3469 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3470 puts(_("\tx\textra functionality (experts only)"));
3474 #ifdef CONFIG_FEATURE_SGI_LABEL
3476 puts(_("Command action"));
3477 puts(_("\ta\tselect bootable partition")); /* sgi flavour */
3478 puts(_("\tb\tedit bootfile entry")); /* sgi */
3479 puts(_("\tc\tselect sgi swap partition")); /* sgi flavour */
3480 puts(_("\td\tdelete a partition"));
3481 puts(_("\tl\tlist known partition types"));
3482 puts(_("\tm\tprint this menu"));
3483 puts(_("\tn\tadd a new partition"));
3484 puts(_("\to\tcreate a new empty DOS partition table"));
3485 puts(_("\tp\tprint the partition table"));
3486 puts(_("\tq\tquit without saving changes"));
3487 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3488 puts(_("\tt\tchange a partition's system id"));
3489 puts(_("\tu\tchange display/entry units"));
3490 puts(_("\tv\tverify the partition table"));
3491 puts(_("\tw\twrite table to disk and exit"));
3494 #ifdef CONFIG_FEATURE_AIX_LABEL
3496 puts(_("Command action"));
3497 puts(_("\tm\tprint this menu"));
3498 puts(_("\to\tcreate a new empty DOS partition table"));
3499 puts(_("\tq\tquit without saving changes"));
3500 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3504 puts(_("Command action"));
3505 puts(_("\ta\ttoggle a bootable flag"));
3506 puts(_("\tb\tedit bsd disklabel"));
3507 puts(_("\tc\ttoggle the dos compatibility flag"));
3508 puts(_("\td\tdelete a partition"));
3509 puts(_("\tl\tlist known partition types"));
3510 puts(_("\tm\tprint this menu"));
3511 puts(_("\tn\tadd a new partition"));
3512 puts(_("\to\tcreate a new empty DOS partition table"));
3513 puts(_("\tp\tprint the partition table"));
3514 puts(_("\tq\tquit without saving changes"));
3515 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3516 puts(_("\tt\tchange a partition's system id"));
3517 puts(_("\tu\tchange display/entry units"));
3518 puts(_("\tv\tverify the partition table"));
3519 puts(_("\tw\twrite table to disk and exit"));
3520 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3521 puts(_("\tx\textra functionality (experts only)"));
3525 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3528 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3531 #ifdef CONFIG_FEATURE_SUN_LABEL
3533 puts(_("Command action"));
3534 puts(_("\ta\tchange number of alternate cylinders")); /*sun*/
3535 puts(_("\tc\tchange number of cylinders"));
3536 puts(_("\td\tprint the raw data in the partition table"));
3537 puts(_("\te\tchange number of extra sectors per cylinder"));/*sun*/
3538 puts(_("\th\tchange number of heads"));
3539 puts(_("\ti\tchange interleave factor")); /*sun*/
3540 puts(_("\to\tchange rotation speed (rpm)")); /*sun*/
3541 puts(_("\tm\tprint this menu"));
3542 puts(_("\tp\tprint the partition table"));
3543 puts(_("\tq\tquit without saving changes"));
3544 puts(_("\tr\treturn to main menu"));
3545 puts(_("\ts\tchange number of sectors/track"));
3546 puts(_("\tv\tverify the partition table"));
3547 puts(_("\tw\twrite table to disk and exit"));
3548 puts(_("\ty\tchange number of physical cylinders")); /*sun*/
3551 #ifdef CONFIG_FEATURE_SGI_LABEL
3553 puts(_("Command action"));
3554 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3555 puts(_("\tc\tchange number of cylinders"));
3556 puts(_("\td\tprint the raw data in the partition table"));
3557 puts(_("\te\tlist extended partitions")); /* !sun */
3558 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3559 puts(_("\th\tchange number of heads"));
3560 puts(_("\tm\tprint this menu"));
3561 puts(_("\tp\tprint the partition table"));
3562 puts(_("\tq\tquit without saving changes"));
3563 puts(_("\tr\treturn to main menu"));
3564 puts(_("\ts\tchange number of sectors/track"));
3565 puts(_("\tv\tverify the partition table"));
3566 puts(_("\tw\twrite table to disk and exit"));
3569 #ifdef CONFIG_FEATURE_AIX_LABEL
3571 puts(_("Command action"));
3572 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3573 puts(_("\tc\tchange number of cylinders"));
3574 puts(_("\td\tprint the raw data in the partition table"));
3575 puts(_("\te\tlist extended partitions")); /* !sun */
3576 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3577 puts(_("\th\tchange number of heads"));
3578 puts(_("\tm\tprint this menu"));
3579 puts(_("\tp\tprint the partition table"));
3580 puts(_("\tq\tquit without saving changes"));
3581 puts(_("\tr\treturn to main menu"));
3582 puts(_("\ts\tchange number of sectors/track"));
3583 puts(_("\tv\tverify the partition table"));
3584 puts(_("\tw\twrite table to disk and exit"));
3588 puts(_("Command action"));
3589 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3590 puts(_("\tc\tchange number of cylinders"));
3591 puts(_("\td\tprint the raw data in the partition table"));
3592 puts(_("\te\tlist extended partitions")); /* !sun */
3593 puts(_("\tf\tfix partition order")); /* !sun, !aix, !sgi */
3594 #ifdef CONFIG_FEATURE_SGI_LABEL
3595 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3597 puts(_("\th\tchange number of heads"));
3598 puts(_("\tm\tprint this menu"));
3599 puts(_("\tp\tprint the partition table"));
3600 puts(_("\tq\tquit without saving changes"));
3601 puts(_("\tr\treturn to main menu"));
3602 puts(_("\ts\tchange number of sectors/track"));
3603 puts(_("\tv\tverify the partition table"));
3604 puts(_("\tw\twrite table to disk and exit"));
3607 #endif /* ADVANCED mode */
3609 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3610 static const struct systypes *
3611 get_sys_types(void) {
3613 #ifdef CONFIG_FEATURE_SUN_LABEL
3614 sun_label ? sun_sys_types :
3616 #ifdef CONFIG_FEATURE_SGI_LABEL
3617 sgi_label ? sgi_sys_types :
3622 #define get_sys_types() i386_sys_types
3623 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3625 static const char *partition_type(unsigned char type)
3628 const struct systypes *types = get_sys_types();
3630 for (i=0; types[i].name; i++)
3631 if ((unsigned char )types[i].name[0] == type)
3632 return types[i].name + 1;
3634 return _("Unknown");
3638 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3642 #ifdef CONFIG_FEATURE_SUN_LABEL
3643 sun_label ? sunlabel->infos[i].id :
3645 #ifdef CONFIG_FEATURE_SGI_LABEL
3646 sgi_label ? sgi_get_sysid(i) :
3648 ptes[i].part_table->sys_ind);
3651 void list_types(const struct systypes *sys)
3653 uint last[4], done = 0, next = 0, size;
3656 for (i = 0; sys[i].name; i++);
3659 for (i = 3; i >= 0; i--)
3660 last[3 - i] = done += (size + i - done) / (i + 1);
3664 printf("%c%2x %-15.15s", i ? ' ' : '\n',
3665 (unsigned char)sys[next].name[0],
3666 partition_type((unsigned char)sys[next].name[0]));
3667 next = last[i++] + done;
3668 if (i > 3 || next >= last[i]) {
3672 } while (done < last[0]);
3675 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3678 is_cleared_partition(const struct partition *p) {
3679 return !(!p || p->boot_ind || p->head || p->sector || p->cyl ||
3680 p->sys_ind || p->end_head || p->end_sector || p->end_cyl ||
3681 get_start_sect(p) || get_nr_sects(p));
3685 clear_partition(struct partition *p) {
3688 memset(p, 0, sizeof(struct partition));
3691 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3693 set_partition(int i, int doext, off_t start, off_t stop, int sysid) {
3694 struct partition *p;
3698 p = ptes[i].ext_pointer;
3699 offset = extended_offset;
3701 p = ptes[i].part_table;
3702 offset = ptes[i].offset;
3706 set_start_sect(p, start - offset);
3707 set_nr_sects(p, stop - start + 1);
3708 if (dos_compatible_flag && (start/(sectors*heads) > 1023))
3709 start = heads*sectors*1024 - 1;
3710 set_hsc(p->head, p->sector, p->cyl, start);
3711 if (dos_compatible_flag && (stop/(sectors*heads) > 1023))
3712 stop = heads*sectors*1024 - 1;
3713 set_hsc(p->end_head, p->end_sector, p->end_cyl, stop);
3714 ptes[i].changed = 1;
3719 test_c(const char **m, const char *mesg) {
3722 fprintf(stderr, _("You must set"));
3724 fprintf(stderr, " %s", *m);
3732 warn_geometry(void) {
3733 const char *m = NULL;
3737 prev = test_c(&m, _("heads"));
3739 prev = test_c(&m, _("sectors"));
3741 prev = test_c(&m, _("cylinders"));
3745 fprintf(stderr, "%s%s.\n"
3746 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3747 "You can do this from the extra functions menu.\n"
3749 , prev ? _(" and ") : " ", m);
3754 static void update_units(void)
3756 int cyl_units = heads * sectors;
3758 if (display_in_cyl_units && cyl_units)
3759 units_per_sector = cyl_units;
3761 units_per_sector = 1; /* in sectors */
3764 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3766 warn_cylinders(void) {
3767 if (dos_label && cylinders > 1024 && !nowarn)
3768 fprintf(stderr, _("\n"
3769 "The number of cylinders for this disk is set to %d.\n"
3770 "There is nothing wrong with that, but this is larger than 1024,\n"
3771 "and could in certain setups cause problems with:\n"
3772 "1) software that runs at boot time (e.g., old versions of LILO)\n"
3773 "2) booting and partitioning software from other OSs\n"
3774 " (e.g., DOS FDISK, OS/2 FDISK)\n"),
3780 read_extended(int ext) {
3783 struct partition *p, *q;
3787 pex->ext_pointer = pex->part_table;
3789 p = pex->part_table;
3790 if (!get_start_sect(p)) {
3792 _("Bad offset in primary extended partition\n"));
3796 while (IS_EXTENDED (p->sys_ind)) {
3797 struct pte *pe = &ptes[partitions];
3799 if (partitions >= MAXIMUM_PARTS) {
3800 /* This is not a Linux restriction, but
3801 this program uses arrays of size MAXIMUM_PARTS.
3802 Do not try to `improve' this test. */
3803 struct pte *pre = &ptes[partitions-1];
3804 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3806 _("Warning: deleting partitions after %d\n"),
3810 clear_partition(pre->ext_pointer);
3814 read_pte(pe, extended_offset + get_start_sect(p));
3816 if (!extended_offset)
3817 extended_offset = get_start_sect(p);
3819 q = p = pt_offset(pe->sectorbuffer, 0);
3820 for (i = 0; i < 4; i++, p++) if (get_nr_sects(p)) {
3821 if (IS_EXTENDED (p->sys_ind)) {
3822 if (pe->ext_pointer)
3824 _("Warning: extra link "
3825 "pointer in partition table"
3826 " %d\n"), partitions + 1);
3828 pe->ext_pointer = p;
3829 } else if (p->sys_ind) {
3832 _("Warning: ignoring extra "
3833 "data in partition table"
3834 " %d\n"), partitions + 1);
3840 /* very strange code here... */
3841 if (!pe->part_table) {
3842 if (q != pe->ext_pointer)
3845 pe->part_table = q + 1;
3847 if (!pe->ext_pointer) {
3848 if (q != pe->part_table)
3849 pe->ext_pointer = q;
3851 pe->ext_pointer = q + 1;
3854 p = pe->ext_pointer;
3858 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3859 /* remove empty links */
3861 for (i = 4; i < partitions; i++) {
3862 struct pte *pe = &ptes[i];
3864 if (!get_nr_sects(pe->part_table) &&
3865 (partitions > 5 || ptes[4].part_table->sys_ind)) {
3866 printf("omitting empty partition (%d)\n", i+1);
3867 delete_partition(i);
3868 goto remove; /* numbering changed */
3874 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3876 create_doslabel(void) {
3880 _("Building a new DOS disklabel. Changes will remain in memory only,\n"
3881 "until you decide to write them. After that, of course, the previous\n"
3882 "content won't be recoverable.\n\n"));
3883 #ifdef CONFIG_FEATURE_SUN_LABEL
3884 sun_nolabel(); /* otherwise always recognised as sun */
3886 #ifdef CONFIG_FEATURE_SGI_LABEL
3887 sgi_nolabel(); /* otherwise always recognised as sgi */
3889 #ifdef CONFIG_FEATURE_AIX_LABEL
3892 #ifdef CONFIG_FEATURE_OSF_LABEL
3894 possibly_osf_label = 0;
3898 for (i = 510-64; i < 510; i++)
3900 write_part_table_flag(MBRbuffer);
3901 extended_offset = 0;
3902 set_all_unchanged();
3904 get_boot(create_empty_dos);
3906 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3909 get_sectorsize(void) {
3910 if (!user_set_sector_size &&
3911 get_kernel_revision() >= MAKE_VERSION(2,3,3)) {
3913 if (ioctl(fd, BLKSSZGET, &arg) == 0)
3915 if (sector_size != DEFAULT_SECTOR_SIZE)
3916 printf(_("Note: sector size is %d (not %d)\n"),
3917 sector_size, DEFAULT_SECTOR_SIZE);
3922 get_kernel_geometry(void) {
3923 struct hd_geometry geometry;
3925 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
3926 kern_heads = geometry.heads;
3927 kern_sectors = geometry.sectors;
3928 /* never use geometry.cylinders - it is truncated */
3933 get_partition_table_geometry(void) {
3934 const unsigned char *bufp = (const unsigned char *)MBRbuffer;
3935 struct partition *p;
3936 int i, h, s, hh, ss;
3940 if (!(valid_part_table_flag(bufp)))
3944 for (i=0; i<4; i++) {
3945 p = pt_offset(bufp, i);
3946 if (p->sys_ind != 0) {
3947 h = p->end_head + 1;
3948 s = (p->end_sector & 077);
3953 } else if (hh != h || ss != s)
3958 if (!first && !bad) {
3965 get_geometry(void) {
3967 unsigned long long bytes; /* really u64 */
3970 sec_fac = sector_size / 512;
3971 #ifdef CONFIG_FEATURE_SUN_LABEL
3972 guess_device_type();
3974 heads = cylinders = sectors = 0;
3975 kern_heads = kern_sectors = 0;
3976 pt_heads = pt_sectors = 0;
3978 get_kernel_geometry();
3979 get_partition_table_geometry();
3981 heads = user_heads ? user_heads :
3982 pt_heads ? pt_heads :
3983 kern_heads ? kern_heads : 255;
3984 sectors = user_sectors ? user_sectors :
3985 pt_sectors ? pt_sectors :
3986 kern_sectors ? kern_sectors : 63;
3987 if (ioctl(fd, BLKGETSIZE64, &bytes) == 0) {
3990 unsigned long longsectors;
3992 if (ioctl(fd, BLKGETSIZE, &longsectors))
3994 bytes = ((unsigned long long) longsectors) << 9;
3997 total_number_of_sectors = (bytes >> 9);
4000 if (dos_compatible_flag)
4001 sector_offset = sectors;
4003 cylinders = total_number_of_sectors / (heads * sectors * sec_fac);
4005 cylinders = user_cylinders;
4009 * Read MBR. Returns:
4010 * -1: no 0xaa55 flag present (possibly entire disk BSD)
4011 * 0: found or created label
4015 get_boot(enum action what) {
4020 for (i = 0; i < 4; i++) {
4021 struct pte *pe = &ptes[i];
4023 pe->part_table = pt_offset(MBRbuffer, i);
4024 pe->ext_pointer = NULL;
4026 pe->sectorbuffer = MBRbuffer;
4027 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4028 pe->changed = (what == create_empty_dos);
4032 #ifdef CONFIG_FEATURE_SUN_LABEL
4033 if (what == create_empty_sun && check_sun_label())
4037 memset(MBRbuffer, 0, 512);
4039 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4040 if (what == create_empty_dos)
4041 goto got_dos_table; /* skip reading disk */
4043 if ((fd = open(disk_device, type_open)) < 0) {
4044 if ((fd = open(disk_device, O_RDONLY)) < 0) {
4045 if (what == try_only)
4047 fdisk_fatal(unable_to_open);
4049 printf(_("You will not be able to write "
4050 "the partition table.\n"));
4053 if (512 != read(fd, MBRbuffer, 512)) {
4054 if (what == try_only)
4056 fdisk_fatal(unable_to_read);
4059 if ((fd = open(disk_device, O_RDONLY)) < 0)
4061 if (512 != read(fd, MBRbuffer, 512))
4069 #ifdef CONFIG_FEATURE_SUN_LABEL
4070 if (check_sun_label())
4074 #ifdef CONFIG_FEATURE_SGI_LABEL
4075 if (check_sgi_label())
4079 #ifdef CONFIG_FEATURE_AIX_LABEL
4080 if (check_aix_label())
4084 #ifdef CONFIG_FEATURE_OSF_LABEL
4085 if (check_osf_label()) {
4086 possibly_osf_label = 1;
4087 if (!valid_part_table_flag(MBRbuffer)) {
4091 printf(_("This disk has both DOS and BSD magic.\n"
4092 "Give the 'b' command to go to BSD mode.\n"));
4096 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4100 if (!valid_part_table_flag(MBRbuffer)) {
4101 #ifndef CONFIG_FEATURE_FDISK_WRITABLE
4107 _("Device contains neither a valid DOS "
4108 "partition table, nor Sun, SGI or OSF "
4111 #ifdef CONFIG_FEATURE_SUN_LABEL
4120 case create_empty_dos:
4121 #ifdef CONFIG_FEATURE_SUN_LABEL
4122 case create_empty_sun:
4126 fprintf(stderr, _("Internal error\n"));
4129 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
4132 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4137 for (i = 0; i < 4; i++) {
4138 struct pte *pe = &ptes[i];
4140 if (IS_EXTENDED (pe->part_table->sys_ind)) {
4141 if (partitions != 4)
4142 fprintf(stderr, _("Ignoring extra extended "
4143 "partition %d\n"), i + 1);
4149 for (i = 3; i < partitions; i++) {
4150 struct pte *pe = &ptes[i];
4152 if (!valid_part_table_flag(pe->sectorbuffer)) {
4154 _("Warning: invalid flag 0x%04x of partition "
4155 "table %d will be corrected by w(rite)\n"),
4156 part_table_flag(pe->sectorbuffer), i + 1);
4157 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4166 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4168 * Print the message MESG, then read an integer between LOW and HIGH (inclusive).
4169 * If the user hits Enter, DFLT is returned.
4170 * Answers like +10 are interpreted as offsets from BASE.
4172 * There is no default if DFLT is not between LOW and HIGH.
4175 read_int(uint low, uint dflt, uint high, uint base, char *mesg)
4179 static char *ms = NULL;
4180 static int mslen = 0;
4182 if (!ms || strlen(mesg)+100 > mslen) {
4183 mslen = strlen(mesg)+200;
4184 ms = xrealloc(ms,mslen);
4187 if (dflt < low || dflt > high)
4191 snprintf(ms, mslen, _("%s (%u-%u, default %u): "),
4192 mesg, low, high, dflt);
4194 snprintf(ms, mslen, "%s (%u-%u): ",
4198 int use_default = default_ok;
4200 /* ask question and read answer */
4201 while (read_chars(ms) != '\n' && !isdigit(*line_ptr)
4202 && *line_ptr != '-' && *line_ptr != '+')
4205 if (*line_ptr == '+' || *line_ptr == '-') {
4206 int minus = (*line_ptr == '-');
4209 i = atoi(line_ptr+1);
4211 while (isdigit(*++line_ptr))
4214 switch (*line_ptr) {
4217 if (!display_in_cyl_units)
4218 i *= heads * sectors;
4232 absolute = 1000000000;
4238 unsigned long long bytes;
4241 bytes = (unsigned long long) i * absolute;
4242 unit = sector_size * units_per_sector;
4243 bytes += unit/2; /* round */
4252 while (isdigit(*line_ptr)) {
4258 printf(_("Using default value %u\n"), i = dflt);
4259 if (i >= low && i <= high)
4262 printf(_("Value out of range.\n"));
4268 get_partition(int warn, int max) {
4272 i = read_int(1, 0, max, 0, _("Partition number")) - 1;
4276 if ((!sun_label && !sgi_label && !pe->part_table->sys_ind)
4277 #ifdef CONFIG_FEATURE_SUN_LABEL
4279 (!sunlabel->partitions[i].num_sectors ||
4280 !sunlabel->infos[i].id))
4282 #ifdef CONFIG_FEATURE_SGI_LABEL
4283 || (sgi_label && (!sgi_get_num_sectors(i)))
4287 _("Warning: partition %d has empty type\n"),
4294 get_existing_partition(int warn, int max) {
4298 for (i = 0; i < max; i++) {
4299 struct pte *pe = &ptes[i];
4300 struct partition *p = pe->part_table;
4302 if (p && !is_cleared_partition(p)) {
4309 printf(_("Selected partition %d\n"), pno+1);
4312 printf(_("No partition is defined yet!\n"));
4316 return get_partition(warn, max);
4320 get_nonexisting_partition(int warn, int max) {
4324 for (i = 0; i < max; i++) {
4325 struct pte *pe = &ptes[i];
4326 struct partition *p = pe->part_table;
4328 if (p && is_cleared_partition(p)) {
4335 printf(_("Selected partition %d\n"), pno+1);
4338 printf(_("All primary partitions have been defined already!\n"));
4342 return get_partition(warn, max);
4346 void change_units(void)
4348 display_in_cyl_units = !display_in_cyl_units;
4350 printf(_("Changing display/entry units to %s\n"),
4355 toggle_active(int i) {
4356 struct pte *pe = &ptes[i];
4357 struct partition *p = pe->part_table;
4359 if (IS_EXTENDED (p->sys_ind) && !p->boot_ind)
4361 _("WARNING: Partition %d is an extended partition\n"),
4363 p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG);
4368 toggle_dos_compatibility_flag(void) {
4369 dos_compatible_flag = ~dos_compatible_flag;
4370 if (dos_compatible_flag) {
4371 sector_offset = sectors;
4372 printf(_("DOS Compatibility flag is set\n"));
4376 printf(_("DOS Compatibility flag is not set\n"));
4381 delete_partition(int i) {
4382 struct pte *pe = &ptes[i];
4383 struct partition *p = pe->part_table;
4384 struct partition *q = pe->ext_pointer;
4386 /* Note that for the fifth partition (i == 4) we don't actually
4387 * decrement partitions.
4390 if (warn_geometry())
4391 return; /* C/H/S not set */
4394 #ifdef CONFIG_FEATURE_SUN_LABEL
4396 sun_delete_partition(i);
4400 #ifdef CONFIG_FEATURE_SGI_LABEL
4402 sgi_delete_partition(i);
4408 if (IS_EXTENDED (p->sys_ind) && i == ext_index) {
4410 ptes[ext_index].ext_pointer = NULL;
4411 extended_offset = 0;
4417 if (!q->sys_ind && i > 4) {
4418 /* the last one in the chain - just delete */
4421 clear_partition(ptes[i].ext_pointer);
4422 ptes[i].changed = 1;
4424 /* not the last one - further ones will be moved down */
4426 /* delete this link in the chain */
4427 p = ptes[i-1].ext_pointer;
4429 set_start_sect(p, get_start_sect(q));
4430 set_nr_sects(p, get_nr_sects(q));
4431 ptes[i-1].changed = 1;
4432 } else if (partitions > 5) { /* 5 will be moved to 4 */
4433 /* the first logical in a longer chain */
4436 if (pe->part_table) /* prevent SEGFAULT */
4437 set_start_sect(pe->part_table,
4438 get_partition_start(pe) -
4440 pe->offset = extended_offset;
4444 if (partitions > 5) {
4446 while (i < partitions) {
4447 ptes[i] = ptes[i+1];
4451 /* the only logical: clear only */
4452 clear_partition(ptes[i].part_table);
4457 change_sysid(void) {
4458 int i, sys, origsys;
4459 struct partition *p;
4461 #ifdef CONFIG_FEATURE_SGI_LABEL
4462 /* If sgi_label then don't use get_existing_partition,
4463 let the user select a partition, since get_existing_partition()
4464 only works for Linux like partition tables. */
4466 i = get_existing_partition(0, partitions);
4468 i = get_partition(0, partitions);
4471 i = get_existing_partition(0, partitions);
4475 p = ptes[i].part_table;
4476 origsys = sys = get_sysid(i);
4478 /* if changing types T to 0 is allowed, then
4479 the reverse change must be allowed, too */
4480 if (!sys && !sgi_label && !sun_label && !get_nr_sects(p))
4481 printf(_("Partition %d does not exist yet!\n"), i + 1);
4483 sys = read_hex (get_sys_types());
4485 if (!sys && !sgi_label && !sun_label) {
4486 printf(_("Type 0 means free space to many systems\n"
4487 "(but not to Linux). Having partitions of\n"
4488 "type 0 is probably unwise. You can delete\n"
4489 "a partition using the `d' command.\n"));
4493 if (!sun_label && !sgi_label) {
4494 if (IS_EXTENDED (sys) != IS_EXTENDED (p->sys_ind)) {
4495 printf(_("You cannot change a partition into"
4496 " an extended one or vice versa\n"
4497 "Delete it first.\n"));
4503 #ifdef CONFIG_FEATURE_SUN_LABEL
4504 if (sun_label && i == 2 && sys != WHOLE_DISK)
4505 printf(_("Consider leaving partition 3 "
4506 "as Whole disk (5),\n"
4507 "as SunOS/Solaris expects it and "
4508 "even Linux likes it.\n\n"));
4510 #ifdef CONFIG_FEATURE_SGI_LABEL
4511 if (sgi_label && ((i == 10 && sys != ENTIRE_DISK)
4512 || (i == 8 && sys != 0)))
4513 printf(_("Consider leaving partition 9 "
4514 "as volume header (0),\nand "
4515 "partition 11 as entire volume (6)"
4516 "as IRIX expects it.\n\n"));
4520 #ifdef CONFIG_FEATURE_SUN_LABEL
4522 sun_change_sysid(i, sys);
4525 #ifdef CONFIG_FEATURE_SGI_LABEL
4527 sgi_change_sysid(i, sys);
4531 printf (_("Changed system type of partition %d "
4532 "to %x (%s)\n"), i + 1, sys,
4533 partition_type(sys));
4534 ptes[i].changed = 1;
4535 if (is_dos_partition(origsys) ||
4536 is_dos_partition(sys))
4542 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
4545 /* check_consistency() and long2chs() added Sat Mar 6 12:28:16 1993,
4546 * faith@cs.unc.edu, based on code fragments from pfdisk by Gordon W. Ross,
4547 * Jan. 1990 (version 1.2.1 by Gordon W. Ross Aug. 1990; Modified by S.
4548 * Lubkin Oct. 1991). */
4550 static void long2chs(ulong ls, uint *c, uint *h, uint *s) {
4551 int spc = heads * sectors;
4556 *s = ls % sectors + 1; /* sectors count from 1 */
4559 static void check_consistency(const struct partition *p, int partition) {
4560 uint pbc, pbh, pbs; /* physical beginning c, h, s */
4561 uint pec, peh, pes; /* physical ending c, h, s */
4562 uint lbc, lbh, lbs; /* logical beginning c, h, s */
4563 uint lec, leh, les; /* logical ending c, h, s */
4565 if (!heads || !sectors || (partition >= 4))
4566 return; /* do not check extended partitions */
4568 /* physical beginning c, h, s */
4569 pbc = (p->cyl & 0xff) | ((p->sector << 2) & 0x300);
4571 pbs = p->sector & 0x3f;
4573 /* physical ending c, h, s */
4574 pec = (p->end_cyl & 0xff) | ((p->end_sector << 2) & 0x300);
4576 pes = p->end_sector & 0x3f;
4578 /* compute logical beginning (c, h, s) */
4579 long2chs(get_start_sect(p), &lbc, &lbh, &lbs);
4581 /* compute logical ending (c, h, s) */
4582 long2chs(get_start_sect(p) + get_nr_sects(p) - 1, &lec, &leh, &les);
4584 /* Same physical / logical beginning? */
4585 if (cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) {
4586 printf(_("Partition %d has different physical/logical "
4587 "beginnings (non-Linux?):\n"), partition + 1);
4588 printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs);
4589 printf(_("logical=(%d, %d, %d)\n"),lbc, lbh, lbs);
4592 /* Same physical / logical ending? */
4593 if (cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) {
4594 printf(_("Partition %d has different physical/logical "
4595 "endings:\n"), partition + 1);
4596 printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
4597 printf(_("logical=(%d, %d, %d)\n"),lec, leh, les);
4601 /* Beginning on cylinder boundary? */
4602 if (pbh != !pbc || pbs != 1) {
4603 printf(_("Partition %i does not start on cylinder "
4604 "boundary:\n"), partition + 1);
4605 printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs);
4606 printf(_("should be (%d, %d, 1)\n"), pbc, !pbc);
4610 /* Ending on cylinder boundary? */
4611 if (peh != (heads - 1) || pes != sectors) {
4612 printf(_("Partition %i does not end on cylinder boundary.\n"),
4615 printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
4616 printf(_("should be (%d, %d, %d)\n"),
4617 pec, heads - 1, sectors);
4623 list_disk_geometry(void) {
4624 long long bytes = (total_number_of_sectors << 9);
4625 long megabytes = bytes/1000000;
4627 if (megabytes < 10000)
4628 printf(_("\nDisk %s: %ld MB, %lld bytes\n"),
4629 disk_device, megabytes, bytes);
4631 printf(_("\nDisk %s: %ld.%ld GB, %lld bytes\n"),
4632 disk_device, megabytes/1000, (megabytes/100)%10, bytes);
4633 printf(_("%d heads, %d sectors/track, %d cylinders"),
4634 heads, sectors, cylinders);
4635 if (units_per_sector == 1)
4636 printf(_(", total %llu sectors"),
4637 total_number_of_sectors / (sector_size/512));
4638 printf(_("\nUnits = %s of %d * %d = %d bytes\n\n"),
4640 units_per_sector, sector_size, units_per_sector * sector_size);
4644 * Check whether partition entries are ordered by their starting positions.
4645 * Return 0 if OK. Return i if partition i should have been earlier.
4646 * Two separate checks: primary and logical partitions.
4649 wrong_p_order(int *prev) {
4650 const struct pte *pe;
4651 const struct partition *p;
4652 off_t last_p_start_pos = 0, p_start_pos;
4655 for (i = 0 ; i < partitions; i++) {
4658 last_p_start_pos = 0;
4661 if ((p = pe->part_table)->sys_ind) {
4662 p_start_pos = get_partition_start(pe);
4664 if (last_p_start_pos > p_start_pos) {
4670 last_p_start_pos = p_start_pos;
4677 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
4679 * Fix the chain of logicals.
4680 * extended_offset is unchanged, the set of sectors used is unchanged
4681 * The chain is sorted so that sectors increase, and so that
4682 * starting sectors increase.
4684 * After this it may still be that cfdisk doesnt like the table.
4685 * (This is because cfdisk considers expanded parts, from link to
4686 * end of partition, and these may still overlap.)
4688 * sfdisk /dev/hda > ohda; sfdisk /dev/hda < ohda
4692 fix_chain_of_logicals(void) {
4693 int j, oj, ojj, sj, sjj;
4694 struct partition *pj,*pjj,tmp;
4696 /* Stage 1: sort sectors but leave sector of part 4 */
4697 /* (Its sector is the global extended_offset.) */
4699 for (j = 5; j < partitions-1; j++) {
4700 oj = ptes[j].offset;
4701 ojj = ptes[j+1].offset;
4703 ptes[j].offset = ojj;
4704 ptes[j+1].offset = oj;
4705 pj = ptes[j].part_table;
4706 set_start_sect(pj, get_start_sect(pj)+oj-ojj);
4707 pjj = ptes[j+1].part_table;
4708 set_start_sect(pjj, get_start_sect(pjj)+ojj-oj);
4709 set_start_sect(ptes[j-1].ext_pointer,
4710 ojj-extended_offset);
4711 set_start_sect(ptes[j].ext_pointer,
4712 oj-extended_offset);
4717 /* Stage 2: sort starting sectors */
4719 for (j = 4; j < partitions-1; j++) {
4720 pj = ptes[j].part_table;
4721 pjj = ptes[j+1].part_table;
4722 sj = get_start_sect(pj);
4723 sjj = get_start_sect(pjj);
4724 oj = ptes[j].offset;
4725 ojj = ptes[j+1].offset;
4726 if (oj+sj > ojj+sjj) {
4730 set_start_sect(pj, ojj+sjj-oj);
4731 set_start_sect(pjj, oj+sj-ojj);
4736 /* Probably something was changed */
4737 for (j = 4; j < partitions; j++)
4738 ptes[j].changed = 1;
4743 fix_partition_table_order(void) {
4744 struct pte *pei, *pek;
4747 if (!wrong_p_order(NULL)) {
4748 printf(_("Nothing to do. Ordering is correct already.\n\n"));
4752 while ((i = wrong_p_order(&k)) != 0 && i < 4) {
4753 /* partition i should have come earlier, move it */
4754 /* We have to move data in the MBR */
4755 struct partition *pi, *pk, *pe, pbuf;
4759 pe = pei->ext_pointer;
4760 pei->ext_pointer = pek->ext_pointer;
4761 pek->ext_pointer = pe;
4763 pi = pei->part_table;
4764 pk = pek->part_table;
4766 memmove(&pbuf, pi, sizeof(struct partition));
4767 memmove(pi, pk, sizeof(struct partition));
4768 memmove(pk, &pbuf, sizeof(struct partition));
4770 pei->changed = pek->changed = 1;
4774 fix_chain_of_logicals();
4782 list_table(int xtra) {
4783 const struct partition *p;
4786 #ifdef CONFIG_FEATURE_SUN_LABEL
4788 sun_list_table(xtra);
4793 #ifdef CONFIG_FEATURE_SGI_LABEL
4795 sgi_list_table(xtra);
4800 list_disk_geometry();
4802 #ifdef CONFIG_FEATURE_OSF_LABEL
4804 xbsd_print_disklabel(xtra);
4809 /* Heuristic: we list partition 3 of /dev/foo as /dev/foo3,
4810 but if the device name ends in a digit, say /dev/foo1,
4811 then the partition is called /dev/foo1p3. */
4812 w = strlen(disk_device);
4813 if (w && isdigit(disk_device[w-1]))
4818 printf(_("%*s Boot Start End Blocks Id System\n"),
4821 for (i = 0; i < partitions; i++) {
4822 const struct pte *pe = &ptes[i];
4825 if (p && !is_cleared_partition(p)) {
4826 off_t psects = get_nr_sects(p);
4827 off_t pblocks = psects;
4828 unsigned int podd = 0;
4830 if (sector_size < 1024) {
4831 pblocks /= (1024 / sector_size);
4832 podd = psects % (1024 / sector_size);
4834 if (sector_size > 1024)
4835 pblocks *= (sector_size / 1024);
4837 "%s %c %11llu %11llu %11llu%c %2x %s\n",
4838 partname(disk_device, i+1, w+2),
4839 /* boot flag */ !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG
4841 /* start */ (unsigned long long) cround(get_partition_start(pe)),
4842 /* end */ (unsigned long long) cround(get_partition_start(pe) + psects
4843 - (psects ? 1 : 0)),
4844 /* odd flag on end */ (unsigned long long) pblocks, podd ? '+' : ' ',
4845 /* type id */ p->sys_ind,
4846 /* type name */ partition_type(p->sys_ind));
4847 check_consistency(p, i);
4851 /* Is partition table in disk order? It need not be, but... */
4852 /* partition table entries are not checked for correct order if this
4853 is a sgi, sun or aix labeled disk... */
4854 if (dos_label && wrong_p_order(NULL)) {
4855 printf(_("\nPartition table entries are not in disk order\n"));
4859 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
4861 x_list_table(int extend) {
4862 const struct pte *pe;
4863 const struct partition *p;
4866 printf(_("\nDisk %s: %d heads, %d sectors, %d cylinders\n\n"),
4867 disk_device, heads, sectors, cylinders);
4868 printf(_("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n"));
4869 for (i = 0 ; i < partitions; i++) {
4871 p = (extend ? pe->ext_pointer : pe->part_table);
4873 printf("%2d %02x%4d%4d%5d%4d%4d%5d%11u%11u %02x\n",
4874 i + 1, p->boot_ind, p->head,
4876 cylinder(p->sector, p->cyl), p->end_head,
4877 sector(p->end_sector),
4878 cylinder(p->end_sector, p->end_cyl),
4879 get_start_sect(p), get_nr_sects(p), p->sys_ind);
4881 check_consistency(p, i);
4887 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4889 fill_bounds(off_t *first, off_t *last) {
4891 const struct pte *pe = &ptes[0];
4892 const struct partition *p;
4894 for (i = 0; i < partitions; pe++,i++) {
4896 if (!p->sys_ind || IS_EXTENDED (p->sys_ind)) {
4897 first[i] = 0xffffffff;
4900 first[i] = get_partition_start(pe);
4901 last[i] = first[i] + get_nr_sects(p) - 1;
4907 check(int n, uint h, uint s, uint c, off_t start) {
4908 off_t total, real_s, real_c;
4910 real_s = sector(s) - 1;
4911 real_c = cylinder(s, c);
4912 total = (real_c * sectors + real_s) * heads + h;
4914 fprintf(stderr, _("Warning: partition %d contains sector 0\n"), n);
4917 _("Partition %d: head %d greater than maximum %d\n"),
4919 if (real_s >= sectors)
4920 fprintf(stderr, _("Partition %d: sector %d greater than "
4921 "maximum %d\n"), n, s, sectors);
4922 if (real_c >= cylinders)
4923 fprintf(stderr, _("Partitions %d: cylinder %llu greater than "
4924 "maximum %d\n"), n, (unsigned long long)real_c + 1, cylinders);
4925 if (cylinders <= 1024 && start != total)
4927 _("Partition %d: previous sectors %llu disagrees with "
4928 "total %llu\n"), n, (unsigned long long)start, (unsigned long long)total);
4935 off_t first[partitions], last[partitions];
4936 struct partition *p;
4938 if (warn_geometry())
4941 #ifdef CONFIG_FEATURE_SUN_LABEL
4947 #ifdef CONFIG_FEATURE_SGI_LABEL
4954 fill_bounds(first, last);
4955 for (i = 0; i < partitions; i++) {
4956 struct pte *pe = &ptes[i];
4959 if (p->sys_ind && !IS_EXTENDED (p->sys_ind)) {
4960 check_consistency(p, i);
4961 if (get_partition_start(pe) < first[i])
4962 printf(_("Warning: bad start-of-data in "
4963 "partition %d\n"), i + 1);
4964 check(i + 1, p->end_head, p->end_sector, p->end_cyl,
4966 total += last[i] + 1 - first[i];
4967 for (j = 0; j < i; j++)
4968 if ((first[i] >= first[j] && first[i] <= last[j])
4969 || ((last[i] <= last[j] && last[i] >= first[j]))) {
4970 printf(_("Warning: partition %d overlaps "
4971 "partition %d.\n"), j + 1, i + 1);
4972 total += first[i] >= first[j] ?
4973 first[i] : first[j];
4974 total -= last[i] <= last[j] ?
4980 if (extended_offset) {
4981 struct pte *pex = &ptes[ext_index];
4982 off_t e_last = get_start_sect(pex->part_table) +
4983 get_nr_sects(pex->part_table) - 1;
4985 for (i = 4; i < partitions; i++) {
4987 p = ptes[i].part_table;
4989 if (i != 4 || i + 1 < partitions)
4990 printf(_("Warning: partition %d "
4991 "is empty\n"), i + 1);
4993 else if (first[i] < extended_offset ||
4995 printf(_("Logical partition %d not entirely in "
4996 "partition %d\n"), i + 1, ext_index + 1);
5000 if (total > heads * sectors * cylinders)
5001 printf(_("Total allocated sectors %d greater than the maximum "
5002 "%d\n"), total, heads * sectors * cylinders);
5003 else if ((total = heads * sectors * cylinders - total) != 0)
5004 printf(_("%d unallocated sectors\n"), total);
5008 add_partition(int n, int sys) {
5009 char mesg[256]; /* 48 does not suffice in Japanese */
5011 struct partition *p = ptes[n].part_table;
5012 struct partition *q = ptes[ext_index].part_table;
5014 off_t start, stop = 0, limit, temp,
5015 first[partitions], last[partitions];
5017 if (p && p->sys_ind) {
5018 printf(_("Partition %d is already defined. Delete "
5019 "it before re-adding it.\n"), n + 1);
5022 fill_bounds(first, last);
5024 start = sector_offset;
5025 if (display_in_cyl_units || !total_number_of_sectors)
5026 llimit = heads * sectors * cylinders - 1;
5028 llimit = total_number_of_sectors - 1;
5030 if (limit != llimit)
5032 if (extended_offset) {
5033 first[ext_index] = extended_offset;
5034 last[ext_index] = get_start_sect(q) +
5035 get_nr_sects(q) - 1;
5038 start = extended_offset + sector_offset;
5039 limit = get_start_sect(q) + get_nr_sects(q) - 1;
5041 if (display_in_cyl_units)
5042 for (i = 0; i < partitions; i++)
5043 first[i] = (cround(first[i]) - 1) * units_per_sector;
5045 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
5048 for (i = 0; i < partitions; i++) {
5051 if (start == ptes[i].offset)
5052 start += sector_offset;
5053 lastplusoff = last[i] + ((n<4) ? 0 : sector_offset);
5054 if (start >= first[i] && start <= lastplusoff)
5055 start = lastplusoff + 1;
5059 if (start >= temp+units_per_sector && readed) {
5060 printf(_("Sector %llu is already allocated\n"), (unsigned long long)temp);
5064 if (!readed && start == temp) {
5067 saved_start = start;
5068 start = read_int(cround(saved_start), cround(saved_start), cround(limit),
5070 if (display_in_cyl_units) {
5071 start = (start - 1) * units_per_sector;
5072 if (start < saved_start) start = saved_start;
5076 } while (start != temp || !readed);
5077 if (n > 4) { /* NOT for fifth partition */
5078 struct pte *pe = &ptes[n];
5080 pe->offset = start - sector_offset;
5081 if (pe->offset == extended_offset) { /* must be corrected */
5083 if (sector_offset == 1)
5088 for (i = 0; i < partitions; i++) {
5089 struct pte *pe = &ptes[i];
5091 if (start < pe->offset && limit >= pe->offset)
5092 limit = pe->offset - 1;
5093 if (start < first[i] && limit >= first[i])
5094 limit = first[i] - 1;
5096 if (start > limit) {
5097 printf(_("No free sectors available\n"));
5102 if (cround(start) == cround(limit)) {
5105 snprintf(mesg, sizeof(mesg),
5106 _("Last %s or +size or +sizeM or +sizeK"),
5107 str_units(SINGULAR));
5108 stop = read_int(cround(start), cround(limit), cround(limit),
5109 cround(start), mesg);
5110 if (display_in_cyl_units) {
5111 stop = stop * units_per_sector - 1;
5117 set_partition(n, 0, start, stop, sys);
5119 set_partition(n - 1, 1, ptes[n].offset, stop, EXTENDED);
5121 if (IS_EXTENDED (sys)) {
5122 struct pte *pe4 = &ptes[4];
5123 struct pte *pen = &ptes[n];
5126 pen->ext_pointer = p;
5127 pe4->offset = extended_offset = start;
5128 pe4->sectorbuffer = xcalloc(1, sector_size);
5129 pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
5130 pe4->ext_pointer = pe4->part_table + 1;
5138 if (partitions > 5 || ptes[4].part_table->sys_ind) {
5139 struct pte *pe = &ptes[partitions];
5141 pe->sectorbuffer = xcalloc(1, sector_size);
5142 pe->part_table = pt_offset(pe->sectorbuffer, 0);
5143 pe->ext_pointer = pe->part_table + 1;
5148 add_partition(partitions - 1, LINUX_NATIVE);
5152 new_partition(void) {
5153 int i, free_primary = 0;
5155 if (warn_geometry())
5158 #ifdef CONFIG_FEATURE_SUN_LABEL
5160 add_sun_partition(get_partition(0, partitions), LINUX_NATIVE);
5164 #ifdef CONFIG_FEATURE_SGI_LABEL
5166 sgi_add_partition(get_partition(0, partitions), LINUX_NATIVE);
5170 #ifdef CONFIG_FEATURE_AIX_LABEL
5172 printf(_("\tSorry - this fdisk cannot handle AIX disk labels."
5173 "\n\tIf you want to add DOS-type partitions, create"
5174 "\n\ta new empty DOS partition table first. (Use o.)"
5176 "This will destroy the present disk contents.\n"));
5181 for (i = 0; i < 4; i++)
5182 free_primary += !ptes[i].part_table->sys_ind;
5184 if (!free_primary && partitions >= MAXIMUM_PARTS) {
5185 printf(_("The maximum number of partitions has been created\n"));
5189 if (!free_primary) {
5190 if (extended_offset)
5193 printf(_("You must delete some partition and add "
5194 "an extended partition first\n"));
5196 char c, line[LINE_LENGTH];
5197 snprintf(line, sizeof(line), "%s\n %s\n p primary "
5198 "partition (1-4)\n",
5199 "Command action", (extended_offset ?
5200 "l logical (5 or over)" : "e extended"));
5202 if ((c = read_char(line)) == 'p' || c == 'P') {
5203 i = get_nonexisting_partition(0, 4);
5205 add_partition(i, LINUX_NATIVE);
5208 else if (c == 'l' && extended_offset) {
5212 else if (c == 'e' && !extended_offset) {
5213 i = get_nonexisting_partition(0, 4);
5215 add_partition(i, EXTENDED);
5219 printf(_("Invalid partition number "
5220 "for type `%c'\n"), c);
5231 if (ptes[i].changed)
5232 ptes[3].changed = 1;
5233 for (i = 3; i < partitions; i++) {
5234 struct pte *pe = &ptes[i];
5237 write_part_table_flag(pe->sectorbuffer);
5238 write_sector(pe->offset, pe->sectorbuffer);
5242 #ifdef CONFIG_FEATURE_SGI_LABEL
5243 else if (sgi_label) {
5244 /* no test on change? the printf below might be mistaken */
5248 #ifdef CONFIG_FEATURE_SUN_LABEL
5249 else if (sun_label) {
5253 if (ptes[i].changed)
5260 printf(_("The partition table has been altered!\n\n"));
5261 reread_partition_table(1);
5265 reread_partition_table(int leave) {
5269 printf(_("Calling ioctl() to re-read partition table.\n"));
5272 if ((i = ioctl(fd, BLKRRPART)) != 0) {
5275 /* some kernel versions (1.2.x) seem to have trouble
5276 rereading the partition table, but if asked to do it
5277 twice, the second time works. - biro@yggdrasil.com */
5280 if ((i = ioctl(fd, BLKRRPART)) != 0)
5285 printf(_("\nWARNING: Re-reading the partition table "
5286 "failed with error %d: %s.\n"
5287 "The kernel still uses the old table.\n"
5288 "The new table will be used "
5289 "at the next reboot.\n"),
5290 error, strerror(error));
5295 _("\nWARNING: If you have created or modified any DOS 6.x\n"
5296 "partitions, please see the fdisk manual page for additional\n"
5302 printf(_("Syncing disks.\n"));
5304 sleep(4); /* for sync() */
5308 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
5310 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
5311 #define MAX_PER_LINE 16
5313 print_buffer(char pbuffer[]) {
5317 for (i = 0, l = 0; i < sector_size; i++, l++) {
5319 printf("0x%03X:", i);
5320 printf(" %02X", (unsigned char) pbuffer[i]);
5321 if (l == MAX_PER_LINE - 1) {
5336 printf(_("Device: %s\n"), disk_device);
5337 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
5338 if (sun_label || sgi_label)
5339 print_buffer(MBRbuffer);
5342 for (i = 3; i < partitions; i++)
5343 print_buffer(ptes[i].sectorbuffer);
5348 struct pte *pe = &ptes[i];
5349 struct partition *p = pe->part_table;
5352 if (warn_geometry())
5354 if (!p->sys_ind || !get_nr_sects(p) || IS_EXTENDED (p->sys_ind)) {
5355 printf(_("Partition %d has no data area\n"), i + 1);
5358 first = get_partition_start(pe);
5359 new = read_int(first, first, first + get_nr_sects(p) - 1, first,
5360 _("New beginning of data")) - pe->offset;
5362 if (new != get_nr_sects(p)) {
5363 first = get_nr_sects(p) + get_start_sect(p) - new;
5364 set_nr_sects(p, first);
5365 set_start_sect(p, new);
5376 c = tolower(read_char(_("Expert command (m for help): ")));
5379 #ifdef CONFIG_FEATURE_SUN_LABEL
5386 move_begin(get_partition(0, partitions));
5389 user_cylinders = cylinders =
5390 read_int(1, cylinders, 1048576, 0,
5391 _("Number of cylinders"));
5392 #ifdef CONFIG_FEATURE_SUN_LABEL
5394 sun_set_ncyl(cylinders);
5403 #ifdef CONFIG_FEATURE_SGI_LABEL
5408 #ifdef CONFIG_FEATURE_SUN_LABEL
5418 fix_partition_table_order();
5421 #ifdef CONFIG_FEATURE_SGI_LABEL
5426 user_heads = heads = read_int(1, heads, 256, 0,
5427 _("Number of heads"));
5431 #ifdef CONFIG_FEATURE_SUN_LABEL
5437 #ifdef CONFIG_FEATURE_SUN_LABEL
5443 #ifdef CONFIG_FEATURE_SUN_LABEL
5457 user_sectors = sectors = read_int(1, sectors, 63, 0,
5458 _("Number of sectors"));
5459 if (dos_compatible_flag) {
5460 sector_offset = sectors;
5461 fprintf(stderr, _("Warning: setting "
5462 "sector offset for DOS "
5471 write_table(); /* does not return */
5474 #ifdef CONFIG_FEATURE_SUN_LABEL
5476 sun_set_pcylcount();
5484 #endif /* ADVANCED mode */
5487 is_ide_cdrom_or_tape(const char *device) {
5490 struct stat statbuf;
5493 /* No device was given explicitly, and we are trying some
5494 likely things. But opening /dev/hdc may produce errors like
5495 "hdc: tray open or drive not ready"
5496 if it happens to be a CD-ROM drive. It even happens that
5497 the process hangs on the attempt to read a music CD.
5498 So try to be careful. This only works since 2.1.73. */
5500 if (strncmp("/dev/hd", device, 7))
5503 snprintf(buf, sizeof(buf), "/proc/ide/%s/media", device+5);
5504 procf = fopen(buf, "r");
5505 if (procf != NULL && fgets(buf, sizeof(buf), procf))
5506 is_ide = (!strncmp(buf, "cdrom", 5) ||
5507 !strncmp(buf, "tape", 4));
5509 /* Now when this proc file does not exist, skip the
5510 device when it is read-only. */
5511 if (stat(device, &statbuf) == 0)
5512 is_ide = ((statbuf.st_mode & 0222) == 0);
5520 try(const char *device, int user_specified) {
5523 disk_device = device;
5524 if (setjmp(listingbuf))
5526 if (!user_specified)
5527 if (is_ide_cdrom_or_tape(device))
5529 if ((fd = open(disk_device, type_open)) >= 0) {
5530 gb = get_boot(try_only);
5531 if (gb > 0) { /* I/O error */
5533 } else if (gb < 0) { /* no DOS signature */
5534 list_disk_geometry();
5537 #ifdef CONFIG_FEATURE_OSF_LABEL
5538 if (btrydev(device) < 0)
5541 _("Disk %s doesn't contain a valid "
5542 "partition table\n"), device);
5547 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5548 if (!sun_label && partitions > 4)
5549 delete_partition(ext_index);
5553 /* Ignore other errors, since we try IDE
5554 and SCSI hard disks which may not be
5555 installed on the system. */
5556 if (errno == EACCES) {
5557 fprintf(stderr, _("Cannot open %s\n"), device);
5563 /* for fdisk -l: try all things in /proc/partitions
5564 that look like a partition name (do not end in a digit) */
5568 char line[100], ptname[100], devname[120], *s;
5571 procpt = bb_wfopen(PROC_PARTITIONS, "r");
5573 while (fgets(line, sizeof(line), procpt)) {
5574 if (sscanf (line, " %d %d %d %[^\n ]",
5575 &ma, &mi, &sz, ptname) != 4)
5577 for (s = ptname; *s; s++);
5580 sprintf(devname, "/dev/%s", ptname);
5583 #ifdef CONFIG_FEATURE_CLEAN_UP
5588 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5590 unknown_command(int c) {
5591 printf(_("%c: unknown command\n"), c);
5595 int fdisk_main(int argc, char **argv) {
5597 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5600 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5606 * fdisk -l [-b sectorsize] [-u] device ...
5607 * fdisk -s [partition] ...
5608 * fdisk [-b sectorsize] [-u] device
5610 * Options -C, -H, -S set the geometry.
5613 while ((c = getopt(argc, argv, "b:C:H:lS:uvV"
5614 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5620 /* Ugly: this sector size is really per device,
5621 so cannot be combined with multiple disks,
5622 and te same goes for the C/H/S options.
5624 sector_size = atoi(optarg);
5625 if (sector_size != 512 && sector_size != 1024 &&
5626 sector_size != 2048)
5629 user_set_sector_size = 1;
5632 user_cylinders = atoi(optarg);
5635 user_heads = atoi(optarg);
5636 if (user_heads <= 0 || user_heads >= 256)
5640 user_sectors = atoi(optarg);
5641 if (user_sectors <= 0 || user_sectors >= 64)
5645 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5649 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5655 display_in_cyl_units = 0;
5659 printf("fdisk v" UTIL_LINUX_VERSION "\n");
5667 printf(_("This kernel finds the sector size itself - "
5668 "-b option ignored\n"));
5670 if (user_set_sector_size && argc-optind != 1)
5671 printf(_("Warning: the -b (set sector size) option should"
5672 " be used with one specified device\n"));
5675 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5679 type_open = O_RDONLY;
5680 if (argc > optind) {
5683 /* avoid gcc warning:
5684 variable `k' might be clobbered by `longjmp' */
5688 for (k=optind; k<argc; k++)
5691 /* we no longer have default device names */
5692 /* but, we can use /proc/partitions instead */
5696 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5700 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5706 type_open = O_RDONLY;
5708 opts = argc - optind;
5712 for (j = optind; j < argc; j++) {
5713 disk_device = argv[j];
5714 if ((fd = open(disk_device, type_open)) < 0)
5715 fdisk_fatal(unable_to_open);
5716 if (ioctl(fd, BLKGETSIZE, &size))
5717 fdisk_fatal(ioctl_error);
5720 printf("%ld\n", size/2);
5722 printf("%s: %ld\n", argv[j], size/2);
5728 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5729 if (argc-optind == 1)
5730 disk_device = argv[optind];
5736 #ifdef CONFIG_FEATURE_OSF_LABEL
5738 /* OSF label, and no DOS label */
5739 printf(_("Detected an OSF/1 disklabel on %s, entering "
5740 "disklabel mode.\n"),
5744 /* If we return we may want to make an empty DOS label? */
5750 c = tolower(read_char(_("Command (m for help): ")));
5754 toggle_active(get_partition(1, partitions));
5755 #ifdef CONFIG_FEATURE_SUN_LABEL
5757 toggle_sunflags(get_partition(1, partitions),
5760 #ifdef CONFIG_FEATURE_SGI_LABEL
5762 sgi_set_bootpartition(
5763 get_partition(1, partitions));
5769 #ifdef CONFIG_FEATURE_SGI_LABEL
5771 printf(_("\nThe current boot file is: %s\n"),
5772 sgi_get_bootfile());
5773 if (read_chars(_("Please enter the name of the "
5774 "new boot file: ")) == '\n')
5775 printf(_("Boot file unchanged\n"));
5777 sgi_set_bootfile(line_ptr);
5780 #ifdef CONFIG_FEATURE_OSF_LABEL
5786 toggle_dos_compatibility_flag();
5787 #ifdef CONFIG_FEATURE_SUN_LABEL
5789 toggle_sunflags(get_partition(1, partitions),
5792 #ifdef CONFIG_FEATURE_SGI_LABEL
5794 sgi_set_swappartition(
5795 get_partition(1, partitions));
5803 #ifdef CONFIG_FEATURE_SGI_LABEL
5804 /* If sgi_label then don't use get_existing_partition,
5805 let the user select a partition, since
5806 get_existing_partition() only works for Linux-like
5809 j = get_existing_partition(1, partitions);
5811 j = get_partition(1, partitions);
5814 j = get_existing_partition(1, partitions);
5817 delete_partition(j);
5821 #ifdef CONFIG_FEATURE_SGI_LABEL
5828 list_types(get_sys_types());
5847 #ifdef CONFIG_FEATURE_SUN_LABEL
5861 write_table(); /* does not return */
5863 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
5865 #ifdef CONFIG_FEATURE_SGI_LABEL
5868 _("\n\tSorry, no experts menu for SGI "
5869 "partition tables available.\n\n"));
5882 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */