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);
871 static int xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d);
872 static int xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d);
874 #if defined (__alpha__)
875 static void alpha_bootblock_checksum (char *boot);
878 #if !defined (__alpha__)
879 static int xbsd_translate_fstype (int linux_type);
880 static void xbsd_link_part (void);
881 static struct partition *xbsd_part;
882 static int xbsd_part_index;
885 #if defined (__alpha__)
886 /* We access this through a uint64_t * when checksumming */
887 static char disklabelbuffer[BSD_BBSIZE] ATTRIBUTE_ALIGNED(8);
889 static char disklabelbuffer[BSD_BBSIZE];
892 static struct xbsd_disklabel xbsd_dlabel;
894 #define bsd_cround(n) \
895 (display_in_cyl_units ? ((n)/xbsd_dlabel.d_secpercyl) + 1 : (n))
898 * Test whether the whole disk has BSD disk label magic.
900 * Note: often reformatting with DOS-type label leaves the BSD magic,
901 * so this does not mean that there is a BSD disk label.
904 check_osf_label(void) {
905 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
910 static void xbsd_print_disklabel(int);
913 btrydev (const char * dev) {
914 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
916 printf(_("\nBSD label for device: %s\n"), dev);
917 xbsd_print_disklabel (0);
923 puts (_("Command action"));
924 puts (_("\td\tdelete a BSD partition"));
925 puts (_("\te\tedit drive data"));
926 puts (_("\ti\tinstall bootstrap"));
927 puts (_("\tl\tlist known filesystem types"));
928 puts (_("\tm\tprint this menu"));
929 puts (_("\tn\tadd a new BSD partition"));
930 puts (_("\tp\tprint BSD partition table"));
931 puts (_("\tq\tquit without saving changes"));
932 puts (_("\tr\treturn to main menu"));
933 puts (_("\ts\tshow complete disklabel"));
934 puts (_("\tt\tchange a partition's filesystem id"));
935 puts (_("\tu\tchange units (cylinders/sectors)"));
936 puts (_("\tw\twrite disklabel to disk"));
937 #if !defined (__alpha__)
938 puts (_("\tx\tlink BSD partition to non-BSD partition"));
942 #if !defined (__alpha__)
949 is_bsd_partition_type(int type) {
950 return (type == FREEBSD_PARTITION ||
951 type == hidden(FREEBSD_PARTITION) ||
952 type == NETBSD_PARTITION ||
953 type == hidden(NETBSD_PARTITION));
959 #if !defined (__alpha__)
963 for (t=0; t<4; t++) {
964 p = get_part_table(t);
965 if (p && is_bsd_partition_type(p->sys_ind)) {
968 ss = get_start_sect(xbsd_part);
970 fprintf (stderr, _("Partition %s has invalid starting sector 0.\n"),
971 partname(disk_device, t+1, 0));
974 printf (_("Reading disklabel of %s at sector %d.\n"),
975 partname(disk_device, t+1, 0), ss + BSD_LABELSECTOR);
976 if (xbsd_readlabel (xbsd_part, &xbsd_dlabel) == 0)
977 if (xbsd_create_disklabel () == 0)
984 printf (_("There is no *BSD partition on %s.\n"), disk_device);
988 #elif defined (__alpha__)
990 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
991 if (xbsd_create_disklabel () == 0)
992 exit ( EXIT_SUCCESS );
998 switch (tolower (read_char (_("BSD disklabel command (m for help): ")))) {
1000 xbsd_delete_part ();
1003 xbsd_edit_disklabel ();
1006 xbsd_write_bootstrap ();
1015 xbsd_print_disklabel (0);
1019 exit ( EXIT_SUCCESS );
1023 xbsd_print_disklabel (1);
1026 xbsd_change_fstype ();
1032 xbsd_write_disklabel ();
1034 #if !defined (__alpha__)
1047 xbsd_delete_part (void)
1051 i = xbsd_get_part_index (xbsd_dlabel.d_npartitions);
1052 xbsd_dlabel.d_partitions[i].p_size = 0;
1053 xbsd_dlabel.d_partitions[i].p_offset = 0;
1054 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
1055 if (xbsd_dlabel.d_npartitions == i + 1)
1056 while (xbsd_dlabel.d_partitions[xbsd_dlabel.d_npartitions-1].p_size == 0)
1057 xbsd_dlabel.d_npartitions--;
1061 xbsd_new_part (void)
1067 if (!xbsd_check_new_partition (&i))
1070 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
1071 begin = get_start_sect(xbsd_part);
1072 end = begin + get_nr_sects(xbsd_part) - 1;
1075 end = xbsd_dlabel.d_secperunit - 1;
1078 snprintf (mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
1079 begin = read_int (bsd_cround (begin), bsd_cround (begin), bsd_cround (end),
1082 if (display_in_cyl_units)
1083 begin = (begin - 1) * xbsd_dlabel.d_secpercyl;
1085 snprintf (mesg, sizeof(mesg), _("Last %s or +size or +sizeM or +sizeK"),
1086 str_units(SINGULAR));
1087 end = read_int (bsd_cround (begin), bsd_cround (end), bsd_cround (end),
1088 bsd_cround (begin), mesg);
1090 if (display_in_cyl_units)
1091 end = end * xbsd_dlabel.d_secpercyl - 1;
1093 xbsd_dlabel.d_partitions[i].p_size = end - begin + 1;
1094 xbsd_dlabel.d_partitions[i].p_offset = begin;
1095 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
1099 xbsd_print_disklabel (int show_all) {
1100 struct xbsd_disklabel *lp = &xbsd_dlabel;
1101 struct xbsd_partition *pp;
1105 #if defined (__alpha__)
1106 printf("# %s:\n", disk_device);
1108 printf("# %s:\n", partname(disk_device, xbsd_part_index+1, 0));
1110 if ((unsigned) lp->d_type < BSD_DKMAXTYPES)
1111 printf(_("type: %s\n"), xbsd_dktypenames[lp->d_type]);
1113 printf(_("type: %d\n"), lp->d_type);
1114 printf(_("disk: %.*s\n"), (int) sizeof(lp->d_typename), lp->d_typename);
1115 printf(_("label: %.*s\n"), (int) sizeof(lp->d_packname), lp->d_packname);
1116 printf(_("flags:"));
1117 if (lp->d_flags & BSD_D_REMOVABLE)
1118 printf(_(" removable"));
1119 if (lp->d_flags & BSD_D_ECC)
1121 if (lp->d_flags & BSD_D_BADSECT)
1122 printf(_(" badsect"));
1124 /* On various machines the fields of *lp are short/int/long */
1125 /* In order to avoid problems, we cast them all to long. */
1126 printf(_("bytes/sector: %ld\n"), (long) lp->d_secsize);
1127 printf(_("sectors/track: %ld\n"), (long) lp->d_nsectors);
1128 printf(_("tracks/cylinder: %ld\n"), (long) lp->d_ntracks);
1129 printf(_("sectors/cylinder: %ld\n"), (long) lp->d_secpercyl);
1130 printf(_("cylinders: %ld\n"), (long) lp->d_ncylinders);
1131 printf(_("rpm: %d\n"), lp->d_rpm);
1132 printf(_("interleave: %d\n"), lp->d_interleave);
1133 printf(_("trackskew: %d\n"), lp->d_trackskew);
1134 printf(_("cylinderskew: %d\n"), lp->d_cylskew);
1135 printf(_("headswitch: %ld\t\t# milliseconds\n"),
1136 (long) lp->d_headswitch);
1137 printf(_("track-to-track seek: %ld\t# milliseconds\n"),
1138 (long) lp->d_trkseek);
1139 printf(_("drivedata: "));
1140 for (i = NDDATA - 1; i >= 0; i--)
1141 if (lp->d_drivedata[i])
1145 for (j = 0; j <= i; j++)
1146 printf("%ld ", (long) lp->d_drivedata[j]);
1148 printf(_("\n%d partitions:\n"), lp->d_npartitions);
1149 printf(_("# start end size fstype [fsize bsize cpg]\n"));
1150 pp = lp->d_partitions;
1151 for (i = 0; i < lp->d_npartitions; i++, pp++) {
1153 if (display_in_cyl_units && lp->d_secpercyl) {
1154 printf(" %c: %8ld%c %8ld%c %8ld%c ",
1156 (long) pp->p_offset / lp->d_secpercyl + 1,
1157 (pp->p_offset % lp->d_secpercyl) ? '*' : ' ',
1158 (long) (pp->p_offset + pp->p_size + lp->d_secpercyl - 1)
1160 ((pp->p_offset + pp->p_size) % lp->d_secpercyl) ? '*' : ' ',
1161 (long) pp->p_size / lp->d_secpercyl,
1162 (pp->p_size % lp->d_secpercyl) ? '*' : ' ');
1164 printf(" %c: %8ld %8ld %8ld ",
1166 (long) pp->p_offset,
1167 (long) pp->p_offset + pp->p_size - 1,
1170 if ((unsigned) pp->p_fstype < BSD_FSMAXTYPES)
1171 printf("%8.8s", xbsd_fstypes[pp->p_fstype].name);
1173 printf("%8x", pp->p_fstype);
1174 switch (pp->p_fstype) {
1176 printf(" %5ld %5ld %5.5s ",
1177 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, "");
1181 printf(" %5ld %5ld %5d ",
1182 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag,
1187 printf("%22.22s", "");
1196 xbsd_write_disklabel (void) {
1197 #if defined (__alpha__)
1198 printf (_("Writing disklabel to %s.\n"), disk_device);
1199 xbsd_writelabel (NULL, &xbsd_dlabel);
1201 printf (_("Writing disklabel to %s.\n"),
1202 partname(disk_device, xbsd_part_index+1, 0));
1203 xbsd_writelabel (xbsd_part, &xbsd_dlabel);
1205 reread_partition_table(0); /* no exit yet */
1209 xbsd_create_disklabel (void) {
1212 #if defined (__alpha__)
1213 fprintf (stderr, _("%s contains no disklabel.\n"), disk_device);
1215 fprintf (stderr, _("%s contains no disklabel.\n"),
1216 partname(disk_device, xbsd_part_index+1, 0));
1220 c = read_char (_("Do you want to create a disklabel? (y/n) "));
1221 if (c == 'y' || c == 'Y') {
1222 if (xbsd_initlabel (
1223 #if defined (__alpha__) || defined (__powerpc__) || defined (__hppa__) || \
1224 defined (__s390__) || defined (__s390x__)
1227 xbsd_part, &xbsd_dlabel/* not used, xbsd_part_index*/
1230 xbsd_print_disklabel (1);
1234 } else if (c == 'n')
1240 edit_int (int def, char *mesg)
1243 fputs (mesg, stdout);
1244 printf (" (%d): ", def);
1248 while (!isdigit (*line_ptr));
1249 return atoi (line_ptr);
1253 xbsd_edit_disklabel (void)
1255 struct xbsd_disklabel *d;
1259 #if defined (__alpha__) || defined (__ia64__)
1260 d -> d_secsize = (u_long) edit_int ((u_long) d -> d_secsize ,_("bytes/sector"));
1261 d -> d_nsectors = (u_long) edit_int ((u_long) d -> d_nsectors ,_("sectors/track"));
1262 d -> d_ntracks = (u_long) edit_int ((u_long) d -> d_ntracks ,_("tracks/cylinder"));
1263 d -> d_ncylinders = (u_long) edit_int ((u_long) d -> d_ncylinders ,_("cylinders"));
1266 /* d -> d_secpercyl can be != d -> d_nsectors * d -> d_ntracks */
1269 d -> d_secpercyl = (u_long) edit_int ((u_long) d -> d_nsectors * d -> d_ntracks,
1270 _("sectors/cylinder"));
1271 if (d -> d_secpercyl <= d -> d_nsectors * d -> d_ntracks)
1274 printf (_("Must be <= sectors/track * tracks/cylinder (default).\n"));
1276 d -> d_rpm = (u_short) edit_int ((u_short) d -> d_rpm ,_("rpm"));
1277 d -> d_interleave = (u_short) edit_int ((u_short) d -> d_interleave,_("interleave"));
1278 d -> d_trackskew = (u_short) edit_int ((u_short) d -> d_trackskew ,_("trackskew"));
1279 d -> d_cylskew = (u_short) edit_int ((u_short) d -> d_cylskew ,_("cylinderskew"));
1280 d -> d_headswitch = (u_long) edit_int ((u_long) d -> d_headswitch ,_("headswitch"));
1281 d -> d_trkseek = (u_long) edit_int ((u_long) d -> d_trkseek ,_("track-to-track seek"));
1283 d -> d_secperunit = d -> d_secpercyl * d -> d_ncylinders;
1287 xbsd_get_bootstrap (char *path, void *ptr, int size)
1291 if ((fdb = open (path, O_RDONLY)) < 0)
1296 if (read (fdb, ptr, size) < 0)
1302 printf (" ... %s\n", path);
1310 printf (_("\nSyncing disks.\n"));
1316 xbsd_write_bootstrap (void)
1318 char *bootdir = BSD_LINUX_BOOTDIR;
1319 char path[MAXPATHLEN];
1321 struct xbsd_disklabel dl;
1325 if (xbsd_dlabel.d_type == BSD_DTYPE_SCSI)
1330 printf (_("Bootstrap: %sboot -> boot%s (%s): "),
1331 dkbasename, dkbasename, dkbasename);
1333 line_ptr[strlen (line_ptr)-1] = '\0';
1334 dkbasename = line_ptr;
1336 snprintf (path, sizeof(path), "%s/%sboot", bootdir, dkbasename);
1337 if (!xbsd_get_bootstrap (path, disklabelbuffer, (int) xbsd_dlabel.d_secsize))
1340 /* We need a backup of the disklabel (xbsd_dlabel might have changed). */
1341 d = &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE];
1342 bcopy (d, &dl, sizeof (struct xbsd_disklabel));
1344 /* The disklabel will be overwritten by 0's from bootxx anyway */
1345 memset (d, 0, sizeof (struct xbsd_disklabel));
1347 snprintf (path, sizeof(path), "%s/boot%s", bootdir, dkbasename);
1348 if (!xbsd_get_bootstrap (path, &disklabelbuffer[xbsd_dlabel.d_secsize],
1349 (int) xbsd_dlabel.d_bbsize - xbsd_dlabel.d_secsize))
1352 e = d + sizeof (struct xbsd_disklabel);
1353 for (p=d; p < e; p++)
1355 fprintf (stderr, _("Bootstrap overlaps with disk label!\n"));
1356 exit ( EXIT_FAILURE );
1359 bcopy (&dl, d, sizeof (struct xbsd_disklabel));
1361 #if defined (__powerpc__) || defined (__hppa__)
1363 #elif defined (__alpha__)
1365 alpha_bootblock_checksum (disklabelbuffer);
1367 sector = get_start_sect(xbsd_part);
1370 if (lseek (fd, sector * SECTOR_SIZE, SEEK_SET) == -1)
1371 fdisk_fatal (unable_to_seek);
1372 if (BSD_BBSIZE != write (fd, disklabelbuffer, BSD_BBSIZE))
1373 fdisk_fatal (unable_to_write);
1375 #if defined (__alpha__)
1376 printf (_("Bootstrap installed on %s.\n"), disk_device);
1378 printf (_("Bootstrap installed on %s.\n"),
1379 partname (disk_device, xbsd_part_index+1, 0));
1386 xbsd_change_fstype (void)
1390 i = xbsd_get_part_index (xbsd_dlabel.d_npartitions);
1391 xbsd_dlabel.d_partitions[i].p_fstype = read_hex (xbsd_fstypes);
1395 xbsd_get_part_index (int max)
1400 snprintf (prompt, sizeof(prompt), _("Partition (a-%c): "), 'a' + max - 1);
1402 l = tolower (read_char (prompt));
1403 while (l < 'a' || l > 'a' + max - 1);
1408 xbsd_check_new_partition (int *i) {
1410 /* room for more? various BSD flavours have different maxima */
1411 if (xbsd_dlabel.d_npartitions == BSD_MAXPARTITIONS) {
1414 for (t = 0; t < BSD_MAXPARTITIONS; t++)
1415 if (xbsd_dlabel.d_partitions[t].p_size == 0)
1418 if (t == BSD_MAXPARTITIONS) {
1419 fprintf (stderr, _("The maximum number of partitions "
1420 "has been created\n"));
1425 *i = xbsd_get_part_index (BSD_MAXPARTITIONS);
1427 if (*i >= xbsd_dlabel.d_npartitions)
1428 xbsd_dlabel.d_npartitions = (*i) + 1;
1430 if (xbsd_dlabel.d_partitions[*i].p_size != 0) {
1431 fprintf (stderr, _("This partition already exists.\n"));
1439 xbsd_list_types (void) {
1440 list_types (xbsd_fstypes);
1444 xbsd_dkcksum (struct xbsd_disklabel *lp) {
1445 u_short *start, *end;
1448 start = (u_short *) lp;
1449 end = (u_short *) &lp->d_partitions[lp->d_npartitions];
1456 xbsd_initlabel (struct partition *p, struct xbsd_disklabel *d) {
1457 struct xbsd_partition *pp;
1460 memset (d, 0, sizeof (struct xbsd_disklabel));
1462 d -> d_magic = BSD_DISKMAGIC;
1464 if (strncmp (disk_device, "/dev/sd", 7) == 0)
1465 d -> d_type = BSD_DTYPE_SCSI;
1467 d -> d_type = BSD_DTYPE_ST506;
1469 #if 0 /* not used (at least not written to disk) by NetBSD/i386 1.0 */
1470 d -> d_subtype = BSD_DSTYPE_INDOSPART & pindex;
1473 #if !defined (__alpha__)
1474 d -> d_flags = BSD_D_DOSPART;
1478 d -> d_secsize = SECTOR_SIZE; /* bytes/sector */
1479 d -> d_nsectors = sectors; /* sectors/track */
1480 d -> d_ntracks = heads; /* tracks/cylinder (heads) */
1481 d -> d_ncylinders = cylinders;
1482 d -> d_secpercyl = sectors * heads;/* sectors/cylinder */
1483 if (d -> d_secpercyl == 0)
1484 d -> d_secpercyl = 1; /* avoid segfaults */
1485 d -> d_secperunit = d -> d_secpercyl * d -> d_ncylinders;
1488 d -> d_interleave = 1;
1489 d -> d_trackskew = 0;
1491 d -> d_headswitch = 0;
1494 d -> d_magic2 = BSD_DISKMAGIC;
1495 d -> d_bbsize = BSD_BBSIZE;
1496 d -> d_sbsize = BSD_SBSIZE;
1498 #if !defined (__alpha__)
1499 d -> d_npartitions = 4;
1500 pp = &d -> d_partitions[2]; /* Partition C should be
1501 the NetBSD partition */
1502 pp -> p_offset = get_start_sect(p);
1503 pp -> p_size = get_nr_sects(p);
1504 pp -> p_fstype = BSD_FS_UNUSED;
1505 pp = &d -> d_partitions[3]; /* Partition D should be
1508 pp -> p_size = d -> d_secperunit;
1509 pp -> p_fstype = BSD_FS_UNUSED;
1510 #elif defined (__alpha__)
1511 d -> d_npartitions = 3;
1512 pp = &d -> d_partitions[2]; /* Partition C should be
1515 pp -> p_size = d -> d_secperunit;
1516 pp -> p_fstype = BSD_FS_UNUSED;
1523 * Read a xbsd_disklabel from sector 0 or from the starting sector of p.
1524 * If it has the right magic, return 1.
1527 xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d)
1531 /* p is used only to get the starting sector */
1532 #if !defined (__alpha__)
1533 sector = (p ? get_start_sect(p) : 0);
1534 #elif defined (__alpha__)
1538 if (lseek (fd, sector * SECTOR_SIZE, SEEK_SET) == -1)
1539 fdisk_fatal (unable_to_seek);
1540 if (BSD_BBSIZE != read (fd, disklabelbuffer, BSD_BBSIZE))
1541 fdisk_fatal (unable_to_read);
1543 bcopy (&disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
1544 d, sizeof (struct xbsd_disklabel));
1546 if (d -> d_magic != BSD_DISKMAGIC || d -> d_magic2 != BSD_DISKMAGIC)
1549 for (t = d -> d_npartitions; t < BSD_MAXPARTITIONS; t++) {
1550 d -> d_partitions[t].p_size = 0;
1551 d -> d_partitions[t].p_offset = 0;
1552 d -> d_partitions[t].p_fstype = BSD_FS_UNUSED;
1555 if (d -> d_npartitions > BSD_MAXPARTITIONS)
1556 fprintf (stderr, _("Warning: too many partitions "
1557 "(%d, maximum is %d).\n"),
1558 d -> d_npartitions, BSD_MAXPARTITIONS);
1563 xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d)
1565 unsigned int sector;
1567 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
1568 sector = get_start_sect(p) + BSD_LABELSECTOR;
1570 sector = BSD_LABELSECTOR;
1573 d -> d_checksum = 0;
1574 d -> d_checksum = xbsd_dkcksum (d);
1576 /* This is necessary if we want to write the bootstrap later,
1577 otherwise we'd write the old disklabel with the bootstrap.
1579 bcopy (d, &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
1580 sizeof (struct xbsd_disklabel));
1582 #if defined (__alpha__) && BSD_LABELSECTOR == 0
1583 alpha_bootblock_checksum (disklabelbuffer);
1584 if (lseek (fd, 0, SEEK_SET) == -1)
1585 fdisk_fatal (unable_to_seek);
1586 if (BSD_BBSIZE != write (fd, disklabelbuffer, BSD_BBSIZE))
1587 fdisk_fatal (unable_to_write);
1589 if (lseek (fd, sector * SECTOR_SIZE + BSD_LABELOFFSET,
1591 fdisk_fatal (unable_to_seek);
1592 if (sizeof (struct xbsd_disklabel) != write (fd, d, sizeof (struct xbsd_disklabel)))
1593 fdisk_fatal (unable_to_write);
1602 #if !defined (__alpha__)
1604 xbsd_translate_fstype (int linux_type)
1608 case 0x01: /* DOS 12-bit FAT */
1609 case 0x04: /* DOS 16-bit <32M */
1610 case 0x06: /* DOS 16-bit >=32M */
1611 case 0xe1: /* DOS access */
1612 case 0xe3: /* DOS R/O */
1613 case 0xf2: /* DOS secondary */
1614 return BSD_FS_MSDOS;
1615 case 0x07: /* OS/2 HPFS */
1618 return BSD_FS_OTHER;
1623 xbsd_link_part (void)
1626 struct partition *p;
1628 k = get_partition (1, partitions);
1630 if (!xbsd_check_new_partition (&i))
1633 p = get_part_table(k);
1635 xbsd_dlabel.d_partitions[i].p_size = get_nr_sects(p);
1636 xbsd_dlabel.d_partitions[i].p_offset = get_start_sect(p);
1637 xbsd_dlabel.d_partitions[i].p_fstype = xbsd_translate_fstype(p->sys_ind);
1641 #if defined (__alpha__)
1643 #if !defined(__GLIBC__)
1644 typedef unsigned long long uint64_t;
1648 alpha_bootblock_checksum (char *boot)
1653 dp = (uint64_t *)boot;
1655 for (i = 0; i < 63; i++)
1659 #endif /* __alpha__ */
1661 #endif /* OSF_LABEL */
1663 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
1664 static inline unsigned short
1665 __swap16(unsigned short x) {
1666 return (((uint16_t)(x) & 0xFF) << 8) | (((uint16_t)(x) & 0xFF00) >> 8);
1669 static inline uint32_t
1670 __swap32(uint32_t x) {
1671 return (((x & 0xFF) << 24) |
1672 ((x & 0xFF00) << 8) |
1673 ((x & 0xFF0000) >> 8) |
1674 ((x & 0xFF000000) >> 24));
1678 #ifdef CONFIG_FEATURE_SGI_LABEL
1683 * Copyright (C) Andreas Neuper, Sep 1998.
1684 * This file may be modified and redistributed under
1685 * the terms of the GNU Public License.
1687 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
1688 * Internationalization
1692 static int sgi_other_endian;
1694 static short sgi_volumes=1;
1697 * only dealing with free blocks here
1700 typedef struct { unsigned int first; unsigned int last; } freeblocks;
1701 static freeblocks freelist[17]; /* 16 partitions can produce 17 vacant slots */
1704 setfreelist(int i, unsigned int f, unsigned int l) {
1705 freelist[i].first = f;
1706 freelist[i].last = l;
1710 add2freelist(unsigned int f, unsigned int l) {
1712 for ( ; i < 17 ; i++)
1713 if (freelist[i].last == 0)
1715 setfreelist(i, f, l);
1719 clearfreelist(void) {
1722 for (i = 0; i < 17 ; i++)
1723 setfreelist(i, 0, 0);
1727 isinfreelist(unsigned int b) {
1730 for (i = 0; i < 17 ; i++)
1731 if (freelist[i].first <= b && freelist[i].last >= b)
1732 return freelist[i].last;
1735 /* return last vacant block of this stride (never 0). */
1736 /* the '>=' is not quite correct, but simplifies the code */
1738 * end of free blocks section
1741 static const struct systypes sgi_sys_types[] = {
1742 /* SGI_VOLHDR */ {"\x00" "SGI volhdr" },
1743 /* 0x01 */ {"\x01" "SGI trkrepl" },
1744 /* 0x02 */ {"\x02" "SGI secrepl" },
1745 /* SGI_SWAP */ {"\x03" "SGI raw" },
1746 /* 0x04 */ {"\x04" "SGI bsd" },
1747 /* 0x05 */ {"\x05" "SGI sysv" },
1748 /* ENTIRE_DISK */ {"\x06" "SGI volume" },
1749 /* SGI_EFS */ {"\x07" "SGI efs" },
1750 /* 0x08 */ {"\x08" "SGI lvol" },
1751 /* 0x09 */ {"\x09" "SGI rlvol" },
1752 /* SGI_XFS */ {"\x0a" "SGI xfs" },
1753 /* SGI_XFSLOG */ {"\x0b" "SGI xfslog" },
1754 /* SGI_XLV */ {"\x0c" "SGI xlv" },
1755 /* SGI_XVM */ {"\x0d" "SGI xvm" },
1756 /* LINUX_SWAP */ {"\x82" "Linux swap" },
1757 /* LINUX_NATIVE */ {"\x83" "Linux native" },
1758 /* LINUX_LVM */ {"\x8d" "Linux LVM" },
1759 /* LINUX_RAID */ {"\xfd" "Linux RAID" },
1765 sgi_get_nsect(void) {
1766 return SGI_SSWAP16(sgilabel->devparam.nsect);
1770 sgi_get_ntrks(void) {
1771 return SGI_SSWAP16(sgilabel->devparam.ntrks);
1776 sgilabel->magic = 0;
1782 two_s_complement_32bit_sum(unsigned int* base, int size /* in bytes */) {
1786 size /= sizeof(unsigned int);
1787 for (i = 0; i < size; i++)
1788 sum -= SGI_SSWAP32(base[i]);
1793 check_sgi_label(void) {
1794 if (sizeof(sgilabel) > 512) {
1796 _("According to MIPS Computer Systems, Inc the "
1797 "Label must not contain more than 512 bytes\n"));
1801 if (sgilabel->magic != SGI_LABEL_MAGIC &&
1802 sgilabel->magic != SGI_LABEL_MAGIC_SWAPPED) {
1804 sgi_other_endian = 0;
1808 sgi_other_endian = (sgilabel->magic == SGI_LABEL_MAGIC_SWAPPED);
1810 * test for correct checksum
1812 if (two_s_complement_32bit_sum((unsigned int*)sgilabel,
1813 sizeof(*sgilabel))) {
1815 _("Detected sgi disklabel with wrong checksum.\n"));
1825 sgi_get_start_sector(int i) {
1826 return SGI_SSWAP32(sgilabel->partitions[i].start_sector);
1830 sgi_get_num_sectors(int i) {
1831 return SGI_SSWAP32(sgilabel->partitions[i].num_sectors);
1835 sgi_get_sysid(int i)
1837 return SGI_SSWAP32(sgilabel->partitions[i].id);
1841 sgi_get_bootpartition(void)
1843 return SGI_SSWAP16(sgilabel->boot_part);
1847 sgi_get_swappartition(void)
1849 return SGI_SSWAP16(sgilabel->swap_part);
1853 sgi_list_table(int xtra) {
1855 int kpi = 0; /* kernel partition ID */
1858 printf(_("\nDisk %s (SGI disk label): %d heads, %d sectors\n"
1859 "%d cylinders, %d physical cylinders\n"
1860 "%d extra sects/cyl, interleave %d:1\n"
1862 "Units = %s of %d * 512 bytes\n\n"),
1863 disk_device, heads, sectors, cylinders,
1864 SGI_SSWAP16(sgiparam.pcylcount),
1865 SGI_SSWAP16(sgiparam.sparecyl),
1866 SGI_SSWAP16(sgiparam.ilfact),
1868 str_units(PLURAL), units_per_sector);
1870 printf( _("\nDisk %s (SGI disk label): "
1871 "%d heads, %d sectors, %d cylinders\n"
1872 "Units = %s of %d * 512 bytes\n\n"),
1873 disk_device, heads, sectors, cylinders,
1874 str_units(PLURAL), units_per_sector );
1877 w = strlen(disk_device);
1878 wd = strlen(_("Device"));
1882 printf(_("----- partitions -----\n"
1883 "Pt# %*s Info Start End Sectors Id System\n"),
1884 w + 2, _("Device"));
1885 for (i = 0 ; i < partitions; i++) {
1886 if( sgi_get_num_sectors(i) || debug ) {
1887 uint32_t start = sgi_get_start_sector(i);
1888 uint32_t len = sgi_get_num_sectors(i);
1889 kpi++; /* only count nonempty partitions */
1891 "%2d: %s %4s %9ld %9ld %9ld %2x %s\n",
1892 /* fdisk part number */ i+1,
1893 /* device */ partname(disk_device, kpi, w+3),
1894 /* flags */ (sgi_get_swappartition() == i) ? "swap" :
1895 /* flags */ (sgi_get_bootpartition() == i) ? "boot" : " ",
1896 /* start */ (long) scround(start),
1897 /* end */ (long) scround(start+len)-1,
1898 /* no odd flag on end */ (long) len,
1899 /* type id */ sgi_get_sysid(i),
1900 /* type name */ partition_type(sgi_get_sysid(i)));
1903 printf(_("----- Bootinfo -----\nBootfile: %s\n"
1904 "----- Directory Entries -----\n"),
1905 sgilabel->boot_file);
1906 for (i = 0 ; i < sgi_volumes; i++) {
1907 if (sgilabel->directory[i].vol_file_size) {
1908 uint32_t start = SGI_SSWAP32(sgilabel->directory[i].vol_file_start);
1909 uint32_t len = SGI_SSWAP32(sgilabel->directory[i].vol_file_size);
1910 unsigned char*name = sgilabel->directory[i].vol_file_name;
1912 printf(_("%2d: %-10s sector%5u size%8u\n"),
1913 i, (char*)name, (unsigned int) start, (unsigned int) len);
1919 sgi_set_bootpartition( int i )
1921 sgilabel->boot_part = SGI_SSWAP16(((short)i));
1925 sgi_get_lastblock(void) {
1926 return heads * sectors * cylinders;
1930 sgi_set_swappartition( int i ) {
1931 sgilabel->swap_part = SGI_SSWAP16(((short)i));
1935 sgi_check_bootfile(const char* aFile) {
1937 if (strlen(aFile) < 3) /* "/a\n" is minimum */ {
1938 printf(_("\nInvalid Bootfile!\n"
1939 "\tThe bootfile must be an absolute non-zero pathname,\n"
1940 "\te.g. \"/unix\" or \"/unix.save\".\n"));
1943 if (strlen(aFile) > 16) {
1944 printf(_("\n\tName of Bootfile too long: "
1945 "16 bytes maximum.\n"));
1948 if (aFile[0] != '/') {
1949 printf(_("\n\tBootfile must have a "
1950 "fully qualified pathname.\n"));
1955 if (strncmp(aFile, (char*)sgilabel->boot_file, 16)) {
1956 printf(_("\n\tBe aware, that the bootfile is not checked for existence.\n\t"
1957 "SGI's default is \"/unix\" and for backup \"/unix.save\".\n"));
1958 /* filename is correct and did change */
1961 return 0; /* filename did not change */
1965 sgi_get_bootfile(void) {
1966 return (char*)sgilabel->boot_file;
1970 sgi_set_bootfile(const char* aFile) {
1973 if (sgi_check_bootfile(aFile)) {
1975 if ((aFile[i] != '\n') /* in principle caught again by next line */
1976 && (strlen(aFile) > i))
1977 sgilabel->boot_file[i] = aFile[i];
1979 sgilabel->boot_file[i] = 0;
1982 printf(_("\n\tBootfile is changed to \"%s\".\n"), sgilabel->boot_file);
1987 create_sgiinfo(void)
1989 /* I keep SGI's habit to write the sgilabel to the second block */
1990 sgilabel->directory[0].vol_file_start = SGI_SSWAP32(2);
1991 sgilabel->directory[0].vol_file_size = SGI_SSWAP32(sizeof(sgiinfo));
1992 strncpy((char*)sgilabel->directory[0].vol_file_name, "sgilabel", 8);
1995 static sgiinfo *fill_sgiinfo(void);
1998 sgi_write_table(void) {
2000 sgilabel->csum = SGI_SSWAP32(two_s_complement_32bit_sum(
2001 (unsigned int*)sgilabel,
2002 sizeof(*sgilabel)));
2003 assert(two_s_complement_32bit_sum(
2004 (unsigned int*)sgilabel, sizeof(*sgilabel)) == 0);
2005 if (lseek(fd, 0, SEEK_SET) < 0)
2006 fdisk_fatal(unable_to_seek);
2007 if (write(fd, sgilabel, SECTOR_SIZE) != SECTOR_SIZE)
2008 fdisk_fatal(unable_to_write);
2009 if (! strncmp((char*)sgilabel->directory[0].vol_file_name, "sgilabel", 8)) {
2011 * keep this habit of first writing the "sgilabel".
2012 * I never tested whether it works without (AN 981002).
2014 sgiinfo *info = fill_sgiinfo();
2015 int infostartblock = SGI_SSWAP32(sgilabel->directory[0].vol_file_start);
2016 if (lseek(fd, infostartblock*SECTOR_SIZE, SEEK_SET) < 0)
2017 fdisk_fatal(unable_to_seek);
2018 if (write(fd, info, SECTOR_SIZE) != SECTOR_SIZE)
2019 fdisk_fatal(unable_to_write);
2025 compare_start(int *x, int *y) {
2027 * sort according to start sectors
2028 * and prefers largest partition:
2029 * entry zero is entire disk entry
2031 unsigned int i = *x;
2032 unsigned int j = *y;
2033 unsigned int a = sgi_get_start_sector(i);
2034 unsigned int b = sgi_get_start_sector(j);
2035 unsigned int c = sgi_get_num_sectors(i);
2036 unsigned int d = sgi_get_num_sectors(j);
2039 return (d > c) ? 1 : (d == c) ? 0 : -1;
2040 return (a > b) ? 1 : -1;
2045 verify_sgi(int verbose)
2047 int Index[16]; /* list of valid partitions */
2048 int sortcount = 0; /* number of used partitions, i.e. non-zero lengths */
2049 int entire = 0, i = 0;
2050 unsigned int start = 0;
2051 long long gap = 0; /* count unused blocks */
2052 unsigned int lastblock = sgi_get_lastblock();
2055 for (i=0; i<16; i++) {
2056 if (sgi_get_num_sectors(i) != 0) {
2057 Index[sortcount++]=i;
2058 if (sgi_get_sysid(i) == ENTIRE_DISK) {
2059 if (entire++ == 1) {
2061 printf(_("More than one entire disk entry present.\n"));
2066 if (sortcount == 0) {
2068 printf(_("No partitions defined\n"));
2069 return (lastblock > 0) ? 1 : (lastblock == 0) ? 0 : -1;
2071 qsort(Index, sortcount, sizeof(Index[0]), (void*)compare_start);
2072 if (sgi_get_sysid(Index[0]) == ENTIRE_DISK) {
2073 if ((Index[0] != 10) && verbose)
2074 printf(_("IRIX likes when Partition 11 covers the entire disk.\n"));
2075 if ((sgi_get_start_sector(Index[0]) != 0) && verbose)
2076 printf(_("The entire disk partition should start "
2078 "not at diskblock %d.\n"),
2079 sgi_get_start_sector(Index[0]));
2080 if (debug) /* I do not understand how some disks fulfil it */
2081 if ((sgi_get_num_sectors(Index[0]) != lastblock) && verbose)
2082 printf(_("The entire disk partition is only %d diskblock large,\n"
2083 "but the disk is %d diskblocks long.\n"),
2084 sgi_get_num_sectors(Index[0]), lastblock);
2085 lastblock = sgi_get_num_sectors(Index[0]);
2088 printf(_("One Partition (#11) should cover the entire disk.\n"));
2090 printf("sysid=%d\tpartition=%d\n",
2091 sgi_get_sysid(Index[0]), Index[0]+1);
2093 for (i=1, start=0; i<sortcount; i++) {
2094 int cylsize = sgi_get_nsect() * sgi_get_ntrks();
2096 if ((sgi_get_start_sector(Index[i]) % cylsize) != 0) {
2097 if (debug) /* I do not understand how some disks fulfil it */
2099 printf(_("Partition %d does not start on cylinder boundary.\n"),
2102 if (sgi_get_num_sectors(Index[i]) % cylsize != 0) {
2103 if (debug) /* I do not understand how some disks fulfil it */
2105 printf(_("Partition %d does not end on cylinder boundary.\n"),
2108 /* We cannot handle several "entire disk" entries. */
2109 if (sgi_get_sysid(Index[i]) == ENTIRE_DISK) continue;
2110 if (start > sgi_get_start_sector(Index[i])) {
2112 printf(_("The Partition %d and %d overlap by %d sectors.\n"),
2113 Index[i-1]+1, Index[i]+1,
2114 start - sgi_get_start_sector(Index[i]));
2115 if (gap > 0) gap = -gap;
2116 if (gap == 0) gap = -1;
2118 if (start < sgi_get_start_sector(Index[i])) {
2120 printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"),
2121 sgi_get_start_sector(Index[i]) - start,
2122 start, sgi_get_start_sector(Index[i])-1);
2123 gap += sgi_get_start_sector(Index[i]) - start;
2124 add2freelist(start, sgi_get_start_sector(Index[i]));
2126 start = sgi_get_start_sector(Index[i])
2127 + sgi_get_num_sectors(Index[i]);
2130 printf("%2d:%12d\t%12d\t%12d\n", Index[i],
2131 sgi_get_start_sector(Index[i]),
2132 sgi_get_num_sectors(Index[i]),
2133 sgi_get_sysid(Index[i]));
2136 if (start < lastblock) {
2138 printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"),
2139 lastblock - start, start, lastblock-1);
2140 gap += lastblock - start;
2141 add2freelist(start, lastblock);
2144 * Done with arithmetics
2145 * Go for details now
2148 if (!sgi_get_num_sectors(sgi_get_bootpartition())) {
2149 printf(_("\nThe boot partition does not exist.\n"));
2151 if (!sgi_get_num_sectors(sgi_get_swappartition())) {
2152 printf(_("\nThe swap partition does not exist.\n"));
2154 if ((sgi_get_sysid(sgi_get_swappartition()) != SGI_SWAP)
2155 && (sgi_get_sysid(sgi_get_swappartition()) != LINUX_SWAP))
2156 printf(_("\nThe swap partition has no swap type.\n"));
2158 if (sgi_check_bootfile("/unix"))
2159 printf(_("\tYou have chosen an unusual boot file name.\n"));
2161 return (gap > 0) ? 1 : (gap == 0) ? 0 : -1;
2167 * returned value is:
2168 * = 0 : disk is properly filled to the rim
2169 * < 0 : there is an overlap
2170 * > 0 : there is still some vacant space
2172 return verify_sgi(0);
2176 sgi_change_sysid( int i, int sys )
2178 if( sgi_get_num_sectors(i) == 0 ) /* caught already before, ... */
2180 printf(_("Sorry You may change the Tag of non-empty partitions.\n"));
2183 if( ((sys != ENTIRE_DISK ) && (sys != SGI_VOLHDR))
2184 && (sgi_get_start_sector(i)<1) )
2187 _("It is highly recommended that the partition at offset 0\n"
2188 "is of type \"SGI volhdr\", the IRIX system will rely on it to\n"
2189 "retrieve from its directory standalone tools like sash and fx.\n"
2190 "Only the \"SGI volume\" entire disk section may violate this.\n"
2191 "Type YES if you are sure about tagging this partition differently.\n"));
2192 if (strcmp (line_ptr, _("YES\n")))
2195 sgilabel->partitions[i].id = SGI_SSWAP32(sys);
2198 /* returns partition index of first entry marked as entire disk */
2204 if(sgi_get_sysid(i) == SGI_VOLUME)
2210 sgi_set_partition(int i, unsigned int start, unsigned int length, int sys) {
2212 sgilabel->partitions[i].id = SGI_SSWAP32(sys);
2213 sgilabel->partitions[i].num_sectors = SGI_SSWAP32(length);
2214 sgilabel->partitions[i].start_sector = SGI_SSWAP32(start);
2216 if (sgi_gaps() < 0) /* rebuild freelist */
2217 printf(_("Do You know, You got a partition overlap on the disk?\n"));
2221 sgi_set_entire(void) {
2224 for(n=10; n < partitions; n++) {
2225 if(!sgi_get_num_sectors(n) ) {
2226 sgi_set_partition(n, 0, sgi_get_lastblock(), SGI_VOLUME);
2233 sgi_set_volhdr(void)
2236 for( n=8; n<partitions; n++ )
2238 if(!sgi_get_num_sectors( n ) )
2241 * 5 cylinders is an arbitrary value I like
2242 * IRIX 5.3 stored files in the volume header
2243 * (like sash, symmon, fx, ide) with ca. 3200
2246 if( heads * sectors * 5 < sgi_get_lastblock() )
2247 sgi_set_partition( n, 0, heads * sectors * 5, SGI_VOLHDR );
2254 sgi_delete_partition( int i )
2256 sgi_set_partition( i, 0, 0, 0 );
2260 sgi_add_partition( int n, int sys )
2263 unsigned int first=0, last=0;
2267 } else if ( n == 8 ) {
2270 if(sgi_get_num_sectors(n)) {
2271 printf(_("Partition %d is already defined. Delete "
2272 "it before re-adding it.\n"), n + 1);
2275 if( (sgi_entire() == -1) && (sys != SGI_VOLUME) ) {
2276 printf(_("Attempting to generate entire disk entry automatically.\n"));
2280 if( (sgi_gaps() == 0) && (sys != SGI_VOLUME) ) {
2281 printf(_("The entire disk is already covered with partitions.\n"));
2284 if(sgi_gaps() < 0) {
2285 printf(_("You got a partition overlap on the disk. Fix it first!\n"));
2288 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
2290 if(sys == SGI_VOLUME) {
2291 last = sgi_get_lastblock();
2292 first = read_int(0, 0, last-1, 0, mesg);
2294 printf(_("It is highly recommended that eleventh partition\n"
2295 "covers the entire disk and is of type `SGI volume'\n"));
2298 first = freelist[0].first;
2299 last = freelist[0].last;
2300 first = read_int(scround(first), scround(first), scround(last)-1,
2303 if (display_in_cyl_units)
2304 first *= units_per_sector;
2306 first = first; /* align to cylinder if you know how ... */
2308 last = isinfreelist(first);
2310 printf(_("You will get a partition overlap on the disk. "
2311 "Fix it first!\n"));
2315 snprintf(mesg, sizeof(mesg), _(" Last %s"), str_units(SINGULAR));
2316 last = read_int(scround(first), scround(last)-1, scround(last)-1,
2317 scround(first), mesg)+1;
2318 if (display_in_cyl_units)
2319 last *= units_per_sector;
2321 last = last; /* align to cylinder if You know how ... */
2322 if( (sys == SGI_VOLUME) && ( first != 0 || last != sgi_get_lastblock() ) )
2323 printf(_("It is highly recommended that eleventh partition\n"
2324 "covers the entire disk and is of type `SGI volume'\n"));
2325 sgi_set_partition( n, first, last-first, sys );
2328 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
2330 create_sgilabel(void)
2332 struct hd_geometry geometry;
2339 long longsectors; /* the number of sectors on the device */
2340 int res; /* the result from the ioctl */
2341 int sec_fac; /* the sector factor */
2343 sec_fac = sector_size / 512; /* determine the sector factor */
2346 _("Building a new SGI disklabel. Changes will remain in memory only,\n"
2347 "until you decide to write them. After that, of course, the previous\n"
2348 "content will be unrecoverably lost.\n\n"));
2350 sgi_other_endian = (BYTE_ORDER == LITTLE_ENDIAN);
2351 res = ioctl(fd, BLKGETSIZE, &longsectors);
2352 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
2353 heads = geometry.heads;
2354 sectors = geometry.sectors;
2356 /* the get device size ioctl was successful */
2357 cylinders = longsectors / (heads * sectors);
2358 cylinders /= sec_fac;
2360 /* otherwise print error and use truncated version */
2361 cylinders = geometry.cylinders;
2363 _("Warning: BLKGETSIZE ioctl failed on %s. "
2364 "Using geometry cylinder value of %d.\n"
2365 "This value may be truncated for devices"
2366 " > 33.8 GB.\n"), disk_device, cylinders);
2369 for (i = 0; i < 4; i++) {
2371 if(valid_part_table_flag(MBRbuffer)) {
2372 if(get_part_table(i)->sys_ind) {
2373 old[i].sysid = get_part_table(i)->sys_ind;
2374 old[i].start = get_start_sect(get_part_table(i));
2375 old[i].nsect = get_nr_sects(get_part_table(i));
2376 printf(_("Trying to keep parameters of partition %d.\n"), i);
2378 printf(_("ID=%02x\tSTART=%d\tLENGTH=%d\n"),
2379 old[i].sysid, old[i].start, old[i].nsect);
2384 memset(MBRbuffer, 0, sizeof(MBRbuffer));
2385 sgilabel->magic = SGI_SSWAP32(SGI_LABEL_MAGIC);
2386 sgilabel->boot_part = SGI_SSWAP16(0);
2387 sgilabel->swap_part = SGI_SSWAP16(1);
2389 /* sizeof(sgilabel->boot_file) = 16 > 6 */
2390 memset(sgilabel->boot_file, 0, 16);
2391 strcpy((char*)sgilabel->boot_file, "/unix");
2393 sgilabel->devparam.skew = (0);
2394 sgilabel->devparam.gap1 = (0);
2395 sgilabel->devparam.gap2 = (0);
2396 sgilabel->devparam.sparecyl = (0);
2397 sgilabel->devparam.pcylcount = SGI_SSWAP16(geometry.cylinders);
2398 sgilabel->devparam.head_vol0 = SGI_SSWAP16(0);
2399 sgilabel->devparam.ntrks = SGI_SSWAP16(geometry.heads);
2400 /* tracks/cylinder (heads) */
2401 sgilabel->devparam.cmd_tag_queue_depth = (0);
2402 sgilabel->devparam.unused0 = (0);
2403 sgilabel->devparam.unused1 = SGI_SSWAP16(0);
2404 sgilabel->devparam.nsect = SGI_SSWAP16(geometry.sectors);
2406 sgilabel->devparam.bytes = SGI_SSWAP16(512);
2407 sgilabel->devparam.ilfact = SGI_SSWAP16(1);
2408 sgilabel->devparam.flags = SGI_SSWAP32(TRACK_FWD|
2409 IGNORE_ERRORS|RESEEK);
2410 sgilabel->devparam.datarate = SGI_SSWAP32(0);
2411 sgilabel->devparam.retries_on_error = SGI_SSWAP32(1);
2412 sgilabel->devparam.ms_per_word = SGI_SSWAP32(0);
2413 sgilabel->devparam.xylogics_gap1 = SGI_SSWAP16(0);
2414 sgilabel->devparam.xylogics_syncdelay = SGI_SSWAP16(0);
2415 sgilabel->devparam.xylogics_readdelay = SGI_SSWAP16(0);
2416 sgilabel->devparam.xylogics_gap2 = SGI_SSWAP16(0);
2417 sgilabel->devparam.xylogics_readgate = SGI_SSWAP16(0);
2418 sgilabel->devparam.xylogics_writecont = SGI_SSWAP16(0);
2419 memset( &(sgilabel->directory), 0, sizeof(struct volume_directory)*15 );
2420 memset( &(sgilabel->partitions), 0, sizeof(struct sgi_partition)*16 );
2426 for (i = 0; i < 4; i++) {
2428 sgi_set_partition(i, old[i].start, old[i].nsect, old[i].sysid);
2436 /* do nothing in the beginning */
2438 #endif /* CONFIG_FEATURE_FDISK_ADVANCED */
2440 /* _____________________________________________________________
2446 sgiinfo *info = calloc(1, sizeof(sgiinfo));
2448 info->magic=SGI_SSWAP32(SGI_INFO_MAGIC);
2449 info->b1=SGI_SSWAP32(-1);
2450 info->b2=SGI_SSWAP16(-1);
2451 info->b3=SGI_SSWAP16(1);
2452 /* You may want to replace this string !!!!!!! */
2453 strcpy( (char*)info->scsi_string, "IBM OEM 0662S12 3 30" );
2454 strcpy( (char*)info->serial, "0000" );
2455 info->check1816 = SGI_SSWAP16(18*256 +16 );
2456 strcpy( (char*)info->installer, "Sfx version 5.3, Oct 18, 1994" );
2459 #endif /* SGI_LABEL */
2462 #ifdef CONFIG_FEATURE_SUN_LABEL
2466 * I think this is mostly, or entirely, due to
2467 * Jakub Jelinek (jj@sunsite.mff.cuni.cz), July 1996
2469 * Merged with fdisk for other architectures, aeb, June 1998.
2471 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
2472 * Internationalization
2476 static int sun_other_endian;
2477 static int scsi_disk;
2481 #define IDE0_MAJOR 3
2484 #define IDE1_MAJOR 22
2487 static void guess_device_type(void) {
2488 struct stat bootstat;
2490 if (fstat (fd, &bootstat) < 0) {
2493 } else if (S_ISBLK(bootstat.st_mode)
2494 && (major(bootstat.st_rdev) == IDE0_MAJOR ||
2495 major(bootstat.st_rdev) == IDE1_MAJOR)) {
2498 } else if (S_ISBLK(bootstat.st_mode)
2499 && major(bootstat.st_rdev) == FLOPPY_MAJOR) {
2508 static const struct systypes sun_sys_types[] = {
2509 /* 0 */ {"\x00" "Empty" },
2510 /* 1 */ {"\x01" "Boot" },
2511 /* 2 */ {"\x02" "SunOS root" },
2512 /* SUNOS_SWAP */ {"\x03" "SunOS swap" },
2513 /* 4 */ {"\x04" "SunOS usr" },
2514 /* WHOLE_DISK */ {"\x05" "Whole disk" },
2515 /* 6 */ {"\x06" "SunOS stand" },
2516 /* 7 */ {"\x07" "SunOS var" },
2517 /* 8 */ {"\x08" "SunOS home" },
2518 /* LINUX_SWAP */ {"\x82" "Linux swap" },
2519 /* LINUX_NATIVE */ {"\x83" "Linux native" },
2520 /* 0x8e */ {"\x8e" "Linux LVM" },
2521 /* New (2.2.x) raid partition with autodetect using persistent superblock */
2522 /* 0xfd */ {"\xfd" "Linux raid autodetect" },
2528 set_sun_partition(int i, uint start, uint stop, int sysid) {
2529 sunlabel->infos[i].id = sysid;
2530 sunlabel->partitions[i].start_cylinder =
2531 SUN_SSWAP32(start / (heads * sectors));
2532 sunlabel->partitions[i].num_sectors =
2533 SUN_SSWAP32(stop - start);
2540 sunlabel->magic = 0;
2545 check_sun_label(void) {
2546 unsigned short *ush;
2549 if (sunlabel->magic != SUN_LABEL_MAGIC &&
2550 sunlabel->magic != SUN_LABEL_MAGIC_SWAPPED) {
2552 sun_other_endian = 0;
2555 sun_other_endian = (sunlabel->magic == SUN_LABEL_MAGIC_SWAPPED);
2556 ush = ((unsigned short *) (sunlabel + 1)) - 1;
2557 for (csum = 0; ush >= (unsigned short *)sunlabel;) csum ^= *ush--;
2559 fprintf(stderr,_("Detected sun disklabel with wrong checksum.\n"
2560 "Probably you'll have to set all the values,\n"
2561 "e.g. heads, sectors, cylinders and partitions\n"
2562 "or force a fresh label (s command in main menu)\n"));
2564 heads = SUN_SSWAP16(sunlabel->ntrks);
2565 cylinders = SUN_SSWAP16(sunlabel->ncyl);
2566 sectors = SUN_SSWAP16(sunlabel->nsect);
2574 static const struct sun_predefined_drives {
2577 unsigned short sparecyl;
2578 unsigned short ncyl;
2579 unsigned short nacyl;
2580 unsigned short pcylcount;
2581 unsigned short ntrks;
2582 unsigned short nsect;
2583 unsigned short rspeed;
2585 {"Quantum","ProDrive 80S",1,832,2,834,6,34,3662},
2586 {"Quantum","ProDrive 105S",1,974,2,1019,6,35,3662},
2587 {"CDC","Wren IV 94171-344",3,1545,2,1549,9,46,3600},
2588 {"IBM","DPES-31080",0,4901,2,4903,4,108,5400},
2589 {"IBM","DORS-32160",0,1015,2,1017,67,62,5400},
2590 {"IBM","DNES-318350",0,11199,2,11474,10,320,7200},
2591 {"SEAGATE","ST34371",0,3880,2,3882,16,135,7228},
2592 {"","SUN0104",1,974,2,1019,6,35,3662},
2593 {"","SUN0207",4,1254,2,1272,9,36,3600},
2594 {"","SUN0327",3,1545,2,1549,9,46,3600},
2595 {"","SUN0340",0,1538,2,1544,6,72,4200},
2596 {"","SUN0424",2,1151,2,2500,9,80,4400},
2597 {"","SUN0535",0,1866,2,2500,7,80,5400},
2598 {"","SUN0669",5,1614,2,1632,15,54,3600},
2599 {"","SUN1.0G",5,1703,2,1931,15,80,3597},
2600 {"","SUN1.05",0,2036,2,2038,14,72,5400},
2601 {"","SUN1.3G",6,1965,2,3500,17,80,5400},
2602 {"","SUN2.1G",0,2733,2,3500,19,80,5400},
2603 {"IOMEGA","Jaz",0,1019,2,1021,64,32,5394},
2606 static const struct sun_predefined_drives *
2607 sun_autoconfigure_scsi(void) {
2608 const struct sun_predefined_drives *p = NULL;
2610 #ifdef SCSI_IOCTL_GET_IDLUN
2620 if (!ioctl(fd, SCSI_IOCTL_GET_IDLUN, &id)) {
2622 "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n",
2624 ((id[0]>>24)&0xff)-/*PROC_SCSI_SCSI+PROC_SCSI_FILE*/33,
2626 /* This is very wrong (works only if you have one HBA),
2627 but I haven't found a way how to get hostno
2628 from the current kernel */
2634 pfd = fopen("/proc/scsi/scsi","r");
2636 while (fgets(buffer2,2048,pfd)) {
2637 if (!strcmp(buffer, buffer2)) {
2638 if (fgets(buffer2,2048,pfd)) {
2639 q = strstr(buffer2,"Vendor: ");
2644 *q++ = 0; /* truncate vendor name */
2645 q = strstr(q,"Model: ");
2650 q = strstr(q," Rev: ");
2653 for (i = 0; i < SIZE(sun_drives); i++) {
2654 if (*sun_drives[i].vendor && strcasecmp(sun_drives[i].vendor, vendor))
2656 if (!strstr(model, sun_drives[i].model))
2658 printf(_("Autoconfigure found a %s%s%s\n"),sun_drives[i].vendor,(*sun_drives[i].vendor) ? " " : "",sun_drives[i].model);
2676 static void create_sunlabel(void)
2678 struct hd_geometry geometry;
2682 const struct sun_predefined_drives *p = NULL;
2685 _("Building a new sun disklabel. Changes will remain in memory only,\n"
2686 "until you decide to write them. After that, of course, the previous\n"
2687 "content won't be recoverable.\n\n"));
2688 #if BYTE_ORDER == LITTLE_ENDIAN
2689 sun_other_endian = 1;
2691 sun_other_endian = 0;
2693 memset(MBRbuffer, 0, sizeof(MBRbuffer));
2694 sunlabel->magic = SUN_SSWAP16(SUN_LABEL_MAGIC);
2696 puts(_("Drive type\n"
2697 " ? auto configure\n"
2698 " 0 custom (with hardware detected defaults)"));
2699 for (i = 0; i < SIZE(sun_drives); i++) {
2700 printf(" %c %s%s%s\n",
2701 i + 'a', sun_drives[i].vendor,
2702 (*sun_drives[i].vendor) ? " " : "",
2703 sun_drives[i].model);
2706 c = read_char(_("Select type (? for auto, 0 for custom): "));
2707 if (c >= 'a' && c < 'a' + SIZE(sun_drives)) {
2708 p = sun_drives + c - 'a';
2710 } else if (c >= 'A' && c < 'A' + SIZE(sun_drives)) {
2711 p = sun_drives + c - 'A';
2713 } else if (c == '0') {
2715 } else if (c == '?' && scsi_disk) {
2716 p = sun_autoconfigure_scsi();
2718 printf(_("Autoconfigure failed.\n"));
2725 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
2726 heads = geometry.heads;
2727 sectors = geometry.sectors;
2728 cylinders = geometry.cylinders;
2735 sunlabel->nacyl = 0;
2736 sunlabel->pcylcount = SUN_SSWAP16(cylinders);
2737 sunlabel->rspeed = SUN_SSWAP16(300);
2738 sunlabel->ilfact = SUN_SSWAP16(1);
2739 sunlabel->sparecyl = 0;
2741 heads = read_int(1,heads,1024,0,_("Heads"));
2742 sectors = read_int(1,sectors,1024,0,_("Sectors/track"));
2744 cylinders = read_int(1,cylinders-2,65535,0,_("Cylinders"));
2746 cylinders = read_int(1,0,65535,0,_("Cylinders"));
2748 SUN_SSWAP16(read_int(0,2,65535,0,
2749 _("Alternate cylinders")));
2750 sunlabel->pcylcount =
2751 SUN_SSWAP16(read_int(0,cylinders+SUN_SSWAP16(sunlabel->nacyl),
2752 65535,0,_("Physical cylinders")));
2754 SUN_SSWAP16(read_int(1,5400,100000,0,
2755 _("Rotation speed (rpm)")));
2757 SUN_SSWAP16(read_int(1,1,32,0,_("Interleave factor")));
2758 sunlabel->sparecyl =
2759 SUN_SSWAP16(read_int(0,0,sectors,0,
2760 _("Extra sectors per cylinder")));
2763 sunlabel->sparecyl = SUN_SSWAP16(p->sparecyl);
2764 sunlabel->ncyl = SUN_SSWAP16(p->ncyl);
2765 sunlabel->nacyl = SUN_SSWAP16(p->nacyl);
2766 sunlabel->pcylcount = SUN_SSWAP16(p->pcylcount);
2767 sunlabel->ntrks = SUN_SSWAP16(p->ntrks);
2768 sunlabel->nsect = SUN_SSWAP16(p->nsect);
2769 sunlabel->rspeed = SUN_SSWAP16(p->rspeed);
2770 sunlabel->ilfact = SUN_SSWAP16(1);
2771 cylinders = p->ncyl;
2774 puts(_("You may change all the disk params from the x menu"));
2777 snprintf((char *)(sunlabel->info), sizeof(sunlabel->info),
2778 "%s%s%s cyl %d alt %d hd %d sec %d",
2779 p ? p->vendor : "", (p && *p->vendor) ? " " : "",
2781 : (floppy ? _("3,5\" floppy") : _("Linux custom")),
2782 cylinders, SUN_SSWAP16(sunlabel->nacyl), heads, sectors);
2784 sunlabel->ntrks = SUN_SSWAP16(heads);
2785 sunlabel->nsect = SUN_SSWAP16(sectors);
2786 sunlabel->ncyl = SUN_SSWAP16(cylinders);
2788 set_sun_partition(0, 0, cylinders * heads * sectors, LINUX_NATIVE);
2790 if (cylinders * heads * sectors >= 150 * 2048) {
2791 ndiv = cylinders - (50 * 2048 / (heads * sectors)); /* 50M swap */
2793 ndiv = cylinders * 2 / 3;
2794 set_sun_partition(0, 0, ndiv * heads * sectors, LINUX_NATIVE);
2795 set_sun_partition(1, ndiv * heads * sectors, cylinders * heads * sectors, LINUX_SWAP);
2796 sunlabel->infos[1].flags |= 0x01; /* Not mountable */
2798 set_sun_partition(2, 0, cylinders * heads * sectors, WHOLE_DISK);
2800 unsigned short *ush = (unsigned short *)sunlabel;
2801 unsigned short csum = 0;
2802 while(ush < (unsigned short *)(&sunlabel->csum))
2804 sunlabel->csum = csum;
2807 set_all_unchanged();
2809 get_boot(create_empty_sun);
2813 toggle_sunflags(int i, unsigned char mask) {
2814 if (sunlabel->infos[i].flags & mask)
2815 sunlabel->infos[i].flags &= ~mask;
2816 else sunlabel->infos[i].flags |= mask;
2821 fetch_sun(uint *starts, uint *lens, uint *start, uint *stop) {
2822 int i, continuous = 1;
2823 *start = 0; *stop = cylinders * heads * sectors;
2824 for (i = 0; i < partitions; i++) {
2825 if (sunlabel->partitions[i].num_sectors
2826 && sunlabel->infos[i].id
2827 && sunlabel->infos[i].id != WHOLE_DISK) {
2828 starts[i] = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
2829 lens[i] = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
2831 if (starts[i] == *start)
2833 else if (starts[i] + lens[i] >= *stop)
2837 /* There will be probably more gaps
2838 than one, so lets check afterwards */
2847 static uint *verify_sun_starts;
2850 verify_sun_cmp(int *a, int *b) {
2851 if (*a == -1) return 1;
2852 if (*b == -1) return -1;
2853 if (verify_sun_starts[*a] > verify_sun_starts[*b]) return 1;
2859 uint starts[8], lens[8], start, stop;
2860 int i,j,k,starto,endo;
2863 verify_sun_starts = starts;
2864 fetch_sun(starts,lens,&start,&stop);
2865 for (k = 0; k < 7; k++) {
2866 for (i = 0; i < 8; i++) {
2867 if (k && (lens[i] % (heads * sectors))) {
2868 printf(_("Partition %d doesn't end on cylinder boundary\n"), i+1);
2871 for (j = 0; j < i; j++)
2873 if (starts[j] == starts[i]+lens[i]) {
2874 starts[j] = starts[i]; lens[j] += lens[i];
2876 } else if (starts[i] == starts[j]+lens[j]){
2880 if (starts[i] < starts[j]+lens[j] &&
2881 starts[j] < starts[i]+lens[i]) {
2883 if (starts[j] > starto)
2885 endo = starts[i]+lens[i];
2886 if (starts[j]+lens[j] < endo)
2887 endo = starts[j]+lens[j];
2888 printf(_("Partition %d overlaps with others in "
2889 "sectors %d-%d\n"), i+1, starto, endo);
2896 for (i = 0; i < 8; i++) {
2902 qsort(array,SIZE(array),sizeof(array[0]),
2903 (int (*)(const void *,const void *)) verify_sun_cmp);
2904 if (array[0] == -1) {
2905 printf(_("No partitions defined\n"));
2908 stop = cylinders * heads * sectors;
2909 if (starts[array[0]])
2910 printf(_("Unused gap - sectors 0-%d\n"),starts[array[0]]);
2911 for (i = 0; i < 7 && array[i+1] != -1; i++) {
2912 printf(_("Unused gap - sectors %d-%d\n"),starts[array[i]]+lens[array[i]],starts[array[i+1]]);
2914 start = starts[array[i]]+lens[array[i]];
2916 printf(_("Unused gap - sectors %d-%d\n"),start,stop);
2920 add_sun_partition(int n, int sys) {
2921 uint start, stop, stop2;
2922 uint starts[8], lens[8];
2928 if (sunlabel->partitions[n].num_sectors && sunlabel->infos[n].id) {
2929 printf(_("Partition %d is already defined. Delete "
2930 "it before re-adding it.\n"), n + 1);
2934 fetch_sun(starts,lens,&start,&stop);
2935 if (stop <= start) {
2939 printf(_("Other partitions already cover the whole disk.\nDelete "
2940 "some/shrink them before retry.\n"));
2944 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
2947 first = read_int(0, 0, 0, 0, mesg);
2949 first = read_int(scround(start), scround(stop)+1,
2950 scround(stop), 0, mesg);
2951 if (display_in_cyl_units)
2952 first *= units_per_sector;
2954 /* Starting sector has to be properly aligned */
2955 first = (first + heads * sectors - 1) / (heads * sectors);
2956 if (n == 2 && first != 0)
2958 It is highly recommended that the third partition covers the whole disk\n\
2959 and is of type `Whole disk'\n");
2960 /* ewt asks to add: "don't start a partition at cyl 0"
2961 However, edmundo@rano.demon.co.uk writes:
2962 "In addition to having a Sun partition table, to be able to
2963 boot from the disc, the first partition, /dev/sdX1, must
2964 start at cylinder 0. This means that /dev/sdX1 contains
2965 the partition table and the boot block, as these are the
2966 first two sectors of the disc. Therefore you must be
2967 careful what you use /dev/sdX1 for. In particular, you must
2968 not use a partition starting at cylinder 0 for Linux swap,
2969 as that would overwrite the partition table and the boot
2970 block. You may, however, use such a partition for a UFS
2971 or EXT2 file system, as these file systems leave the first
2972 1024 bytes undisturbed. */
2973 /* On the other hand, one should not use partitions
2974 starting at block 0 in an md, or the label will
2976 for (i = 0; i < partitions; i++)
2977 if (lens[i] && starts[i] <= first
2978 && starts[i] + lens[i] > first)
2980 if (i < partitions && !whole_disk) {
2981 if (n == 2 && !first) {
2985 printf(_("Sector %d is already allocated\n"), first);
2989 stop = cylinders * heads * sectors;
2991 for (i = 0; i < partitions; i++) {
2992 if (starts[i] > first && starts[i] < stop)
2995 snprintf(mesg, sizeof(mesg),
2996 _("Last %s or +size or +sizeM or +sizeK"),
2997 str_units(SINGULAR));
2999 last = read_int(scround(stop2), scround(stop2), scround(stop2),
3001 else if (n == 2 && !first)
3002 last = read_int(scround(first), scround(stop2), scround(stop2),
3003 scround(first), mesg);
3005 last = read_int(scround(first), scround(stop), scround(stop),
3006 scround(first), mesg);
3007 if (display_in_cyl_units)
3008 last *= units_per_sector;
3009 if (n == 2 && !first) {
3010 if (last >= stop2) {
3013 } else if (last > stop) {
3015 _("You haven't covered the whole disk with the 3rd partition, but your value\n"
3016 "%d %s covers some other partition. Your entry has been changed\n"
3018 scround(last), str_units(SINGULAR),
3019 scround(stop), str_units(SINGULAR));
3022 } else if (!whole_disk && last > stop)
3025 if (whole_disk) sys = WHOLE_DISK;
3026 set_sun_partition(n, first, last, sys);
3030 sun_delete_partition(int i) {
3033 if (i == 2 && sunlabel->infos[i].id == WHOLE_DISK &&
3034 !sunlabel->partitions[i].start_cylinder &&
3035 (nsec = SUN_SSWAP32(sunlabel->partitions[i].num_sectors))
3036 == heads * sectors * cylinders)
3037 printf(_("If you want to maintain SunOS/Solaris compatibility, "
3038 "consider leaving this\n"
3039 "partition as Whole disk (5), starting at 0, with %u "
3040 "sectors\n"), nsec);
3041 sunlabel->infos[i].id = 0;
3042 sunlabel->partitions[i].num_sectors = 0;
3046 sun_change_sysid(int i, int sys) {
3047 if (sys == LINUX_SWAP && !sunlabel->partitions[i].start_cylinder) {
3049 _("It is highly recommended that the partition at offset 0\n"
3050 "is UFS, EXT2FS filesystem or SunOS swap. Putting Linux swap\n"
3051 "there may destroy your partition table and bootblock.\n"
3052 "Type YES if you're very sure you would like that partition\n"
3053 "tagged with 82 (Linux swap): "));
3054 if (strcmp (line_ptr, _("YES\n")))
3060 /* swaps are not mountable by default */
3061 sunlabel->infos[i].flags |= 0x01;
3064 /* assume other types are mountable;
3065 user can change it anyway */
3066 sunlabel->infos[i].flags &= ~0x01;
3069 sunlabel->infos[i].id = sys;
3073 sun_list_table(int xtra) {
3076 w = strlen(disk_device);
3079 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d rpm\n"
3080 "%d cylinders, %d alternate cylinders, %d physical cylinders\n"
3081 "%d extra sects/cyl, interleave %d:1\n"
3083 "Units = %s of %d * 512 bytes\n\n"),
3084 disk_device, heads, sectors, SUN_SSWAP16(sunlabel->rspeed),
3085 cylinders, SUN_SSWAP16(sunlabel->nacyl),
3086 SUN_SSWAP16(sunlabel->pcylcount),
3087 SUN_SSWAP16(sunlabel->sparecyl),
3088 SUN_SSWAP16(sunlabel->ilfact),
3090 str_units(PLURAL), units_per_sector);
3093 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d cylinders\n"
3094 "Units = %s of %d * 512 bytes\n\n"),
3095 disk_device, heads, sectors, cylinders,
3096 str_units(PLURAL), units_per_sector);
3098 printf(_("%*s Flag Start End Blocks Id System\n"),
3099 w + 1, _("Device"));
3100 for (i = 0 ; i < partitions; i++) {
3101 if (sunlabel->partitions[i].num_sectors) {
3102 uint32_t start = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
3103 uint32_t len = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
3105 "%s %c%c %9ld %9ld %9ld%c %2x %s\n",
3106 /* device */ partname(disk_device, i+1, w),
3107 /* flags */ (sunlabel->infos[i].flags & 0x01) ? 'u' : ' ',
3108 (sunlabel->infos[i].flags & 0x10) ? 'r' : ' ',
3109 /* start */ (long) scround(start),
3110 /* end */ (long) scround(start+len),
3111 /* odd flag on end */ (long) len / 2, len & 1 ? '+' : ' ',
3112 /* type id */ sunlabel->infos[i].id,
3113 /* type name */ partition_type(sunlabel->infos[i].id));
3118 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3121 sun_set_alt_cyl(void) {
3123 SUN_SSWAP16(read_int(0,SUN_SSWAP16(sunlabel->nacyl), 65535, 0,
3124 _("Number of alternate cylinders")));
3128 sun_set_ncyl(int cyl) {
3129 sunlabel->ncyl = SUN_SSWAP16(cyl);
3133 sun_set_xcyl(void) {
3134 sunlabel->sparecyl =
3135 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->sparecyl), sectors, 0,
3136 _("Extra sectors per cylinder")));
3140 sun_set_ilfact(void) {
3142 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->ilfact), 32, 0,
3143 _("Interleave factor")));
3147 sun_set_rspeed(void) {
3149 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->rspeed), 100000, 0,
3150 _("Rotation speed (rpm)")));
3154 sun_set_pcylcount(void) {
3155 sunlabel->pcylcount =
3156 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->pcylcount), 65535, 0,
3157 _("Number of physical cylinders")));
3159 #endif /* CONFIG_FEATURE_FDISK_ADVANCED */
3162 sun_write_table(void) {
3163 unsigned short *ush = (unsigned short *)sunlabel;
3164 unsigned short csum = 0;
3166 while(ush < (unsigned short *)(&sunlabel->csum))
3168 sunlabel->csum = csum;
3169 if (lseek(fd, 0, SEEK_SET) < 0)
3170 fdisk_fatal(unable_to_seek);
3171 if (write(fd, sunlabel, SECTOR_SIZE) != SECTOR_SIZE)
3172 fdisk_fatal(unable_to_write);
3174 #endif /* SUN_LABEL */
3176 /* DOS partition types */
3178 static const struct systypes i386_sys_types[] = {
3181 {"\x04" "FAT16 <32M"},
3182 {"\x05" "Extended"}, /* DOS 3.3+ extended partition */
3183 {"\x06" "FAT16"}, /* DOS 16-bit >=32M */
3184 {"\x07" "HPFS/NTFS"}, /* OS/2 IFS, eg, HPFS or NTFS or QNX */
3185 {"\x0a" "OS/2 Boot Manager"},/* OS/2 Boot Manager */
3186 {"\x0b" "Win95 FAT32"},
3187 {"\x0c" "Win95 FAT32 (LBA)"},/* LBA really is `Extended Int 13h' */
3188 {"\x0e" "Win95 FAT16 (LBA)"},
3189 {"\x0f" "Win95 Ext'd (LBA)"},
3190 {"\x11" "Hidden FAT12"},
3191 {"\x12" "Compaq diagnostics"},
3192 {"\x14" "Hidden FAT16 <32M"},
3193 {"\x16" "Hidden FAT16"},
3194 {"\x17" "Hidden HPFS/NTFS"},
3195 {"\x1b" "Hidden Win95 FAT32"},
3196 {"\x1c" "Hidden Win95 FAT32 (LBA)"},
3197 {"\x1e" "Hidden Win95 FAT16 (LBA)"},
3198 {"\x3c" "PartitionMagic recovery"},
3199 {"\x41" "PPC PReP Boot"},
3201 {"\x63" "GNU HURD or SysV"}, /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */
3202 {"\x80" "Old Minix"}, /* Minix 1.4a and earlier */
3203 {"\x81" "Minix / old Linux"},/* Minix 1.4b and later */
3204 {"\x82" "Linux swap"}, /* also Solaris */
3206 {"\x84" "OS/2 hidden C: drive"},
3207 {"\x85" "Linux extended"},
3208 {"\x86" "NTFS volume set"},
3209 {"\x87" "NTFS volume set"},
3210 {"\x8e" "Linux LVM"},
3211 {"\x9f" "BSD/OS"}, /* BSDI */
3212 {"\xa0" "IBM Thinkpad hibernation"},
3213 {"\xa5" "FreeBSD"}, /* various BSD flavours */
3215 {"\xa8" "Darwin UFS"},
3217 {"\xab" "Darwin boot"},
3219 {"\xb8" "BSDI swap"},
3220 {"\xbe" "Solaris boot"},
3222 {"\xee" "EFI GPT"}, /* Intel EFI GUID Partition Table */
3223 {"\xef" "EFI (FAT-12/16/32)"},/* Intel EFI System Partition */
3224 {"\xf0" "Linux/PA-RISC boot"},/* Linux/PA-RISC boot loader */
3225 {"\xf2" "DOS secondary"}, /* DOS 3.3+ secondary */
3226 {"\xfd" "Linux raid autodetect"},/* New (2.2.x) raid partition with
3227 autodetect using persistent
3229 #ifdef CONFIG_WEIRD_PARTITION_TYPES
3230 {"\x02" "XENIX root"},
3231 {"\x03" "XENIX usr"},
3232 {"\x08" "AIX"}, /* AIX boot (AIX -- PS/2 port) or SplitDrive */
3233 {"\x09" "AIX bootable"}, /* AIX data or Coherent */
3235 {"\x18" "AST SmartSleep"},
3238 {"\x40" "Venix 80286"},
3240 {"\x4e" "QNX4.x 2nd part"},
3241 {"\x4f" "QNX4.x 3rd part"},
3242 {"\x50" "OnTrack DM"},
3243 {"\x51" "OnTrack DM6 Aux1"}, /* (or Novell) */
3244 {"\x52" "CP/M"}, /* CP/M or Microport SysV/AT */
3245 {"\x53" "OnTrack DM6 Aux3"},
3246 {"\x54" "OnTrackDM6"},
3247 {"\x55" "EZ-Drive"},
3248 {"\x56" "Golden Bow"},
3249 {"\x5c" "Priam Edisk"},
3250 {"\x61" "SpeedStor"},
3251 {"\x64" "Novell Netware 286"},
3252 {"\x65" "Novell Netware 386"},
3253 {"\x70" "DiskSecure Multi-Boot"},
3256 {"\x94" "Amoeba BBT"}, /* (bad block table) */
3257 {"\xa7" "NeXTSTEP"},
3258 {"\xbb" "Boot Wizard hidden"},
3259 {"\xc1" "DRDOS/sec (FAT-12)"},
3260 {"\xc4" "DRDOS/sec (FAT-16 < 32M)"},
3261 {"\xc6" "DRDOS/sec (FAT-16)"},
3263 {"\xda" "Non-FS data"},
3264 {"\xdb" "CP/M / CTOS / ..."},/* CP/M or Concurrent CP/M or
3265 Concurrent DOS or CTOS */
3266 {"\xde" "Dell Utility"}, /* Dell PowerEdge Server utilities */
3267 {"\xdf" "BootIt"}, /* BootIt EMBRM */
3268 {"\xe1" "DOS access"}, /* DOS access or SpeedStor 12-bit FAT
3269 extended partition */
3270 {"\xe3" "DOS R/O"}, /* DOS R/O or SpeedStor */
3271 {"\xe4" "SpeedStor"}, /* SpeedStor 16-bit FAT extended
3272 partition < 1024 cyl. */
3273 {"\xf1" "SpeedStor"},
3274 {"\xf4" "SpeedStor"}, /* SpeedStor large partition */
3275 {"\xfe" "LANstep"}, /* SpeedStor >1024 cyl. or LANstep */
3276 {"\xff" "BBT"}, /* Xenix Bad Block Table */
3283 /* A valid partition table sector ends in 0x55 0xaa */
3285 part_table_flag(const char *b) {
3286 return ((uint) b[510]) + (((uint) b[511]) << 8);
3290 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3292 write_part_table_flag(char *b) {
3297 /* start_sect and nr_sects are stored little endian on all machines */
3298 /* moreover, they are not aligned correctly */
3300 store4_little_endian(unsigned char *cp, unsigned int val) {
3301 cp[0] = (val & 0xff);
3302 cp[1] = ((val >> 8) & 0xff);
3303 cp[2] = ((val >> 16) & 0xff);
3304 cp[3] = ((val >> 24) & 0xff);
3306 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3309 read4_little_endian(const unsigned char *cp) {
3310 return (uint)(cp[0]) + ((uint)(cp[1]) << 8)
3311 + ((uint)(cp[2]) << 16) + ((uint)(cp[3]) << 24);
3314 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3316 set_start_sect(struct partition *p, unsigned int start_sect) {
3317 store4_little_endian(p->start4, start_sect);
3322 get_start_sect(const struct partition *p) {
3323 return read4_little_endian(p->start4);
3326 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3328 set_nr_sects(struct partition *p, int32_t nr_sects) {
3329 store4_little_endian(p->size4, nr_sects);
3334 get_nr_sects(const struct partition *p) {
3335 return read4_little_endian(p->size4);
3338 /* normally O_RDWR, -l option gives O_RDONLY */
3339 static int type_open = O_RDWR;
3342 static int ext_index, /* the prime extended partition */
3343 listing, /* no aborts for fdisk -l */
3344 dos_compatible_flag = ~0;
3345 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3346 static int dos_changed;
3347 static int nowarn; /* no warnings for fdisk -l/-s */
3352 static uint user_cylinders, user_heads, user_sectors;
3353 static uint pt_heads, pt_sectors;
3354 static uint kern_heads, kern_sectors;
3356 static off_t extended_offset; /* offset of link pointers */
3358 static unsigned long long total_number_of_sectors;
3361 static jmp_buf listingbuf;
3363 static void fdisk_fatal(enum failure why) {
3364 const char *message;
3368 longjmp(listingbuf, 1);
3372 case unable_to_open:
3373 message = "Unable to open %s\n";
3375 case unable_to_read:
3376 message = "Unable to read %s\n";
3378 case unable_to_seek:
3379 message = "Unable to seek on %s\n";
3381 case unable_to_write:
3382 message = "Unable to write %s\n";
3385 message = "BLKGETSIZE ioctl failed on %s\n";
3388 message = "Fatal error\n";
3391 fputc('\n', stderr);
3392 fprintf(stderr, message, disk_device);
3397 seek_sector(off_t secno) {
3398 off_t offset = secno * sector_size;
3399 if (lseek(fd, offset, SEEK_SET) == (off_t) -1)
3400 fdisk_fatal(unable_to_seek);
3403 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3405 write_sector(off_t secno, char *buf) {
3407 if (write(fd, buf, sector_size) != sector_size)
3408 fdisk_fatal(unable_to_write);
3412 /* Allocate a buffer and read a partition table sector */
3414 read_pte(struct pte *pe, off_t offset) {
3416 pe->offset = offset;
3417 pe->sectorbuffer = (char *) xmalloc(sector_size);
3418 seek_sector(offset);
3419 if (read(fd, pe->sectorbuffer, sector_size) != sector_size)
3420 fdisk_fatal(unable_to_read);
3421 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3424 pe->part_table = pe->ext_pointer = NULL;
3428 get_partition_start(const struct pte *pe) {
3429 return pe->offset + get_start_sect(pe->part_table);
3432 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3434 * Avoid warning about DOS partitions when no DOS partition was changed.
3435 * Here a heuristic "is probably dos partition".
3436 * We might also do the opposite and warn in all cases except
3437 * for "is probably nondos partition".
3440 is_dos_partition(int t) {
3441 return (t == 1 || t == 4 || t == 6 ||
3442 t == 0x0b || t == 0x0c || t == 0x0e ||
3443 t == 0x11 || t == 0x12 || t == 0x14 || t == 0x16 ||
3444 t == 0x1b || t == 0x1c || t == 0x1e || t == 0x24 ||
3445 t == 0xc1 || t == 0xc4 || t == 0xc6);
3450 #ifdef CONFIG_FEATURE_SUN_LABEL
3452 puts(_("Command action"));
3453 puts(_("\ta\ttoggle a read only flag")); /* sun */
3454 puts(_("\tb\tedit bsd disklabel"));
3455 puts(_("\tc\ttoggle the mountable flag")); /* sun */
3456 puts(_("\td\tdelete a partition"));
3457 puts(_("\tl\tlist known partition types"));
3458 puts(_("\tm\tprint this menu"));
3459 puts(_("\tn\tadd a new partition"));
3460 puts(_("\to\tcreate a new empty DOS partition table"));
3461 puts(_("\tp\tprint the partition table"));
3462 puts(_("\tq\tquit without saving changes"));
3463 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3464 puts(_("\tt\tchange a partition's system id"));
3465 puts(_("\tu\tchange display/entry units"));
3466 puts(_("\tv\tverify the partition table"));
3467 puts(_("\tw\twrite table to disk and exit"));
3468 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3469 puts(_("\tx\textra functionality (experts only)"));
3473 #ifdef CONFIG_FEATURE_SGI_LABEL
3475 puts(_("Command action"));
3476 puts(_("\ta\tselect bootable partition")); /* sgi flavour */
3477 puts(_("\tb\tedit bootfile entry")); /* sgi */
3478 puts(_("\tc\tselect sgi swap partition")); /* sgi flavour */
3479 puts(_("\td\tdelete a partition"));
3480 puts(_("\tl\tlist known partition types"));
3481 puts(_("\tm\tprint this menu"));
3482 puts(_("\tn\tadd a new partition"));
3483 puts(_("\to\tcreate a new empty DOS partition table"));
3484 puts(_("\tp\tprint the partition table"));
3485 puts(_("\tq\tquit without saving changes"));
3486 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3487 puts(_("\tt\tchange a partition's system id"));
3488 puts(_("\tu\tchange display/entry units"));
3489 puts(_("\tv\tverify the partition table"));
3490 puts(_("\tw\twrite table to disk and exit"));
3493 #ifdef CONFIG_FEATURE_AIX_LABEL
3495 puts(_("Command action"));
3496 puts(_("\tm\tprint this menu"));
3497 puts(_("\to\tcreate a new empty DOS partition table"));
3498 puts(_("\tq\tquit without saving changes"));
3499 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3503 puts(_("Command action"));
3504 puts(_("\ta\ttoggle a bootable flag"));
3505 puts(_("\tb\tedit bsd disklabel"));
3506 puts(_("\tc\ttoggle the dos compatibility flag"));
3507 puts(_("\td\tdelete a partition"));
3508 puts(_("\tl\tlist known partition types"));
3509 puts(_("\tm\tprint this menu"));
3510 puts(_("\tn\tadd a new partition"));
3511 puts(_("\to\tcreate a new empty DOS partition table"));
3512 puts(_("\tp\tprint the partition table"));
3513 puts(_("\tq\tquit without saving changes"));
3514 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3515 puts(_("\tt\tchange a partition's system id"));
3516 puts(_("\tu\tchange display/entry units"));
3517 puts(_("\tv\tverify the partition table"));
3518 puts(_("\tw\twrite table to disk and exit"));
3519 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3520 puts(_("\tx\textra functionality (experts only)"));
3524 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3527 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3530 #ifdef CONFIG_FEATURE_SUN_LABEL
3532 puts(_("Command action"));
3533 puts(_("\ta\tchange number of alternate cylinders")); /*sun*/
3534 puts(_("\tc\tchange number of cylinders"));
3535 puts(_("\td\tprint the raw data in the partition table"));
3536 puts(_("\te\tchange number of extra sectors per cylinder"));/*sun*/
3537 puts(_("\th\tchange number of heads"));
3538 puts(_("\ti\tchange interleave factor")); /*sun*/
3539 puts(_("\to\tchange rotation speed (rpm)")); /*sun*/
3540 puts(_("\tm\tprint this menu"));
3541 puts(_("\tp\tprint the partition table"));
3542 puts(_("\tq\tquit without saving changes"));
3543 puts(_("\tr\treturn to main menu"));
3544 puts(_("\ts\tchange number of sectors/track"));
3545 puts(_("\tv\tverify the partition table"));
3546 puts(_("\tw\twrite table to disk and exit"));
3547 puts(_("\ty\tchange number of physical cylinders")); /*sun*/
3550 #ifdef CONFIG_FEATURE_SGI_LABEL
3552 puts(_("Command action"));
3553 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3554 puts(_("\tc\tchange number of cylinders"));
3555 puts(_("\td\tprint the raw data in the partition table"));
3556 puts(_("\te\tlist extended partitions")); /* !sun */
3557 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3558 puts(_("\th\tchange number of heads"));
3559 puts(_("\tm\tprint this menu"));
3560 puts(_("\tp\tprint the partition table"));
3561 puts(_("\tq\tquit without saving changes"));
3562 puts(_("\tr\treturn to main menu"));
3563 puts(_("\ts\tchange number of sectors/track"));
3564 puts(_("\tv\tverify the partition table"));
3565 puts(_("\tw\twrite table to disk and exit"));
3568 #ifdef CONFIG_FEATURE_AIX_LABEL
3570 puts(_("Command action"));
3571 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3572 puts(_("\tc\tchange number of cylinders"));
3573 puts(_("\td\tprint the raw data in the partition table"));
3574 puts(_("\te\tlist extended partitions")); /* !sun */
3575 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3576 puts(_("\th\tchange number of heads"));
3577 puts(_("\tm\tprint this menu"));
3578 puts(_("\tp\tprint the partition table"));
3579 puts(_("\tq\tquit without saving changes"));
3580 puts(_("\tr\treturn to main menu"));
3581 puts(_("\ts\tchange number of sectors/track"));
3582 puts(_("\tv\tverify the partition table"));
3583 puts(_("\tw\twrite table to disk and exit"));
3587 puts(_("Command action"));
3588 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3589 puts(_("\tc\tchange number of cylinders"));
3590 puts(_("\td\tprint the raw data in the partition table"));
3591 puts(_("\te\tlist extended partitions")); /* !sun */
3592 puts(_("\tf\tfix partition order")); /* !sun, !aix, !sgi */
3593 #ifdef CONFIG_FEATURE_SGI_LABEL
3594 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3596 puts(_("\th\tchange number of heads"));
3597 puts(_("\tm\tprint this menu"));
3598 puts(_("\tp\tprint the partition table"));
3599 puts(_("\tq\tquit without saving changes"));
3600 puts(_("\tr\treturn to main menu"));
3601 puts(_("\ts\tchange number of sectors/track"));
3602 puts(_("\tv\tverify the partition table"));
3603 puts(_("\tw\twrite table to disk and exit"));
3606 #endif /* ADVANCED mode */
3608 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3609 static const struct systypes *
3610 get_sys_types(void) {
3612 #ifdef CONFIG_FEATURE_SUN_LABEL
3613 sun_label ? sun_sys_types :
3615 #ifdef CONFIG_FEATURE_SGI_LABEL
3616 sgi_label ? sgi_sys_types :
3621 #define get_sys_types() i386_sys_types
3622 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3624 static const char *partition_type(unsigned char type)
3627 const struct systypes *types = get_sys_types();
3629 for (i=0; types[i].name; i++)
3630 if ((unsigned char )types[i].name[0] == type)
3631 return types[i].name + 1;
3633 return _("Unknown");
3637 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3641 #ifdef CONFIG_FEATURE_SUN_LABEL
3642 sun_label ? sunlabel->infos[i].id :
3644 #ifdef CONFIG_FEATURE_SGI_LABEL
3645 sgi_label ? sgi_get_sysid(i) :
3647 ptes[i].part_table->sys_ind);
3650 void list_types(const struct systypes *sys)
3652 uint last[4], done = 0, next = 0, size;
3655 for (i = 0; sys[i].name; i++);
3658 for (i = 3; i >= 0; i--)
3659 last[3 - i] = done += (size + i - done) / (i + 1);
3663 printf("%c%2x %-15.15s", i ? ' ' : '\n',
3664 (unsigned char)sys[next].name[0],
3665 partition_type((unsigned char)sys[next].name[0]));
3666 next = last[i++] + done;
3667 if (i > 3 || next >= last[i]) {
3671 } while (done < last[0]);
3674 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3677 is_cleared_partition(const struct partition *p) {
3678 return !(!p || p->boot_ind || p->head || p->sector || p->cyl ||
3679 p->sys_ind || p->end_head || p->end_sector || p->end_cyl ||
3680 get_start_sect(p) || get_nr_sects(p));
3684 clear_partition(struct partition *p) {
3687 memset(p, 0, sizeof(struct partition));
3690 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3692 set_partition(int i, int doext, off_t start, off_t stop, int sysid) {
3693 struct partition *p;
3697 p = ptes[i].ext_pointer;
3698 offset = extended_offset;
3700 p = ptes[i].part_table;
3701 offset = ptes[i].offset;
3705 set_start_sect(p, start - offset);
3706 set_nr_sects(p, stop - start + 1);
3707 if (dos_compatible_flag && (start/(sectors*heads) > 1023))
3708 start = heads*sectors*1024 - 1;
3709 set_hsc(p->head, p->sector, p->cyl, start);
3710 if (dos_compatible_flag && (stop/(sectors*heads) > 1023))
3711 stop = heads*sectors*1024 - 1;
3712 set_hsc(p->end_head, p->end_sector, p->end_cyl, stop);
3713 ptes[i].changed = 1;
3718 test_c(const char **m, const char *mesg) {
3721 fprintf(stderr, _("You must set"));
3723 fprintf(stderr, " %s", *m);
3731 warn_geometry(void) {
3732 const char *m = NULL;
3736 prev = test_c(&m, _("heads"));
3738 prev = test_c(&m, _("sectors"));
3740 prev = test_c(&m, _("cylinders"));
3744 fprintf(stderr, "%s%s.\n"
3745 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3746 "You can do this from the extra functions menu.\n"
3748 , prev ? _(" and ") : " ", m);
3753 static void update_units(void)
3755 int cyl_units = heads * sectors;
3757 if (display_in_cyl_units && cyl_units)
3758 units_per_sector = cyl_units;
3760 units_per_sector = 1; /* in sectors */
3763 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3765 warn_cylinders(void) {
3766 if (dos_label && cylinders > 1024 && !nowarn)
3767 fprintf(stderr, _("\n"
3768 "The number of cylinders for this disk is set to %d.\n"
3769 "There is nothing wrong with that, but this is larger than 1024,\n"
3770 "and could in certain setups cause problems with:\n"
3771 "1) software that runs at boot time (e.g., old versions of LILO)\n"
3772 "2) booting and partitioning software from other OSs\n"
3773 " (e.g., DOS FDISK, OS/2 FDISK)\n"),
3779 read_extended(int ext) {
3782 struct partition *p, *q;
3786 pex->ext_pointer = pex->part_table;
3788 p = pex->part_table;
3789 if (!get_start_sect(p)) {
3791 _("Bad offset in primary extended partition\n"));
3795 while (IS_EXTENDED (p->sys_ind)) {
3796 struct pte *pe = &ptes[partitions];
3798 if (partitions >= MAXIMUM_PARTS) {
3799 /* This is not a Linux restriction, but
3800 this program uses arrays of size MAXIMUM_PARTS.
3801 Do not try to `improve' this test. */
3802 struct pte *pre = &ptes[partitions-1];
3803 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3805 _("Warning: deleting partitions after %d\n"),
3809 clear_partition(pre->ext_pointer);
3813 read_pte(pe, extended_offset + get_start_sect(p));
3815 if (!extended_offset)
3816 extended_offset = get_start_sect(p);
3818 q = p = pt_offset(pe->sectorbuffer, 0);
3819 for (i = 0; i < 4; i++, p++) if (get_nr_sects(p)) {
3820 if (IS_EXTENDED (p->sys_ind)) {
3821 if (pe->ext_pointer)
3823 _("Warning: extra link "
3824 "pointer in partition table"
3825 " %d\n"), partitions + 1);
3827 pe->ext_pointer = p;
3828 } else if (p->sys_ind) {
3831 _("Warning: ignoring extra "
3832 "data in partition table"
3833 " %d\n"), partitions + 1);
3839 /* very strange code here... */
3840 if (!pe->part_table) {
3841 if (q != pe->ext_pointer)
3844 pe->part_table = q + 1;
3846 if (!pe->ext_pointer) {
3847 if (q != pe->part_table)
3848 pe->ext_pointer = q;
3850 pe->ext_pointer = q + 1;
3853 p = pe->ext_pointer;
3857 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3858 /* remove empty links */
3860 for (i = 4; i < partitions; i++) {
3861 struct pte *pe = &ptes[i];
3863 if (!get_nr_sects(pe->part_table) &&
3864 (partitions > 5 || ptes[4].part_table->sys_ind)) {
3865 printf("omitting empty partition (%d)\n", i+1);
3866 delete_partition(i);
3867 goto remove; /* numbering changed */
3873 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3875 create_doslabel(void) {
3879 _("Building a new DOS disklabel. Changes will remain in memory only,\n"
3880 "until you decide to write them. After that, of course, the previous\n"
3881 "content won't be recoverable.\n\n"));
3882 #ifdef CONFIG_FEATURE_SUN_LABEL
3883 sun_nolabel(); /* otherwise always recognised as sun */
3885 #ifdef CONFIG_FEATURE_SGI_LABEL
3886 sgi_nolabel(); /* otherwise always recognised as sgi */
3888 #ifdef CONFIG_FEATURE_AIX_LABEL
3891 #ifdef CONFIG_FEATURE_OSF_LABEL
3893 possibly_osf_label = 0;
3897 for (i = 510-64; i < 510; i++)
3899 write_part_table_flag(MBRbuffer);
3900 extended_offset = 0;
3901 set_all_unchanged();
3903 get_boot(create_empty_dos);
3905 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3908 get_sectorsize(void) {
3909 if (!user_set_sector_size &&
3910 get_kernel_revision() >= MAKE_VERSION(2,3,3)) {
3912 if (ioctl(fd, BLKSSZGET, &arg) == 0)
3914 if (sector_size != DEFAULT_SECTOR_SIZE)
3915 printf(_("Note: sector size is %d (not %d)\n"),
3916 sector_size, DEFAULT_SECTOR_SIZE);
3921 get_kernel_geometry(void) {
3922 struct hd_geometry geometry;
3924 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
3925 kern_heads = geometry.heads;
3926 kern_sectors = geometry.sectors;
3927 /* never use geometry.cylinders - it is truncated */
3932 get_partition_table_geometry(void) {
3933 const unsigned char *bufp = (const unsigned char *)MBRbuffer;
3934 struct partition *p;
3935 int i, h, s, hh, ss;
3939 if (!(valid_part_table_flag((char*)bufp)))
3943 for (i=0; i<4; i++) {
3944 p = pt_offset(bufp, i);
3945 if (p->sys_ind != 0) {
3946 h = p->end_head + 1;
3947 s = (p->end_sector & 077);
3952 } else if (hh != h || ss != s)
3957 if (!first && !bad) {
3964 get_geometry(void) {
3966 unsigned long long bytes; /* really u64 */
3969 sec_fac = sector_size / 512;
3970 #ifdef CONFIG_FEATURE_SUN_LABEL
3971 guess_device_type();
3973 heads = cylinders = sectors = 0;
3974 kern_heads = kern_sectors = 0;
3975 pt_heads = pt_sectors = 0;
3977 get_kernel_geometry();
3978 get_partition_table_geometry();
3980 heads = user_heads ? user_heads :
3981 pt_heads ? pt_heads :
3982 kern_heads ? kern_heads : 255;
3983 sectors = user_sectors ? user_sectors :
3984 pt_sectors ? pt_sectors :
3985 kern_sectors ? kern_sectors : 63;
3986 if (ioctl(fd, BLKGETSIZE64, &bytes) == 0) {
3989 unsigned long longsectors;
3991 if (ioctl(fd, BLKGETSIZE, &longsectors))
3993 bytes = ((unsigned long long) longsectors) << 9;
3996 total_number_of_sectors = (bytes >> 9);
3999 if (dos_compatible_flag)
4000 sector_offset = sectors;
4002 cylinders = total_number_of_sectors / (heads * sectors * sec_fac);
4004 cylinders = user_cylinders;
4008 * Read MBR. Returns:
4009 * -1: no 0xaa55 flag present (possibly entire disk BSD)
4010 * 0: found or created label
4014 get_boot(enum action what) {
4019 for (i = 0; i < 4; i++) {
4020 struct pte *pe = &ptes[i];
4022 pe->part_table = pt_offset(MBRbuffer, i);
4023 pe->ext_pointer = NULL;
4025 pe->sectorbuffer = MBRbuffer;
4026 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4027 pe->changed = (what == create_empty_dos);
4031 #ifdef CONFIG_FEATURE_SUN_LABEL
4032 if (what == create_empty_sun && check_sun_label())
4036 memset(MBRbuffer, 0, 512);
4038 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4039 if (what == create_empty_dos)
4040 goto got_dos_table; /* skip reading disk */
4042 if ((fd = open(disk_device, type_open)) < 0) {
4043 if ((fd = open(disk_device, O_RDONLY)) < 0) {
4044 if (what == try_only)
4046 fdisk_fatal(unable_to_open);
4048 printf(_("You will not be able to write "
4049 "the partition table.\n"));
4052 if (512 != read(fd, MBRbuffer, 512)) {
4053 if (what == try_only)
4055 fdisk_fatal(unable_to_read);
4058 if ((fd = open(disk_device, O_RDONLY)) < 0)
4060 if (512 != read(fd, MBRbuffer, 512))
4068 #ifdef CONFIG_FEATURE_SUN_LABEL
4069 if (check_sun_label())
4073 #ifdef CONFIG_FEATURE_SGI_LABEL
4074 if (check_sgi_label())
4078 #ifdef CONFIG_FEATURE_AIX_LABEL
4079 if (check_aix_label())
4083 #ifdef CONFIG_FEATURE_OSF_LABEL
4084 if (check_osf_label()) {
4085 possibly_osf_label = 1;
4086 if (!valid_part_table_flag(MBRbuffer)) {
4090 printf(_("This disk has both DOS and BSD magic.\n"
4091 "Give the 'b' command to go to BSD mode.\n"));
4095 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4099 if (!valid_part_table_flag(MBRbuffer)) {
4100 #ifndef CONFIG_FEATURE_FDISK_WRITABLE
4106 _("Device contains neither a valid DOS "
4107 "partition table, nor Sun, SGI or OSF "
4110 #ifdef CONFIG_FEATURE_SUN_LABEL
4119 case create_empty_dos:
4120 #ifdef CONFIG_FEATURE_SUN_LABEL
4121 case create_empty_sun:
4125 fprintf(stderr, _("Internal error\n"));
4128 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
4131 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4136 for (i = 0; i < 4; i++) {
4137 struct pte *pe = &ptes[i];
4139 if (IS_EXTENDED (pe->part_table->sys_ind)) {
4140 if (partitions != 4)
4141 fprintf(stderr, _("Ignoring extra extended "
4142 "partition %d\n"), i + 1);
4148 for (i = 3; i < partitions; i++) {
4149 struct pte *pe = &ptes[i];
4151 if (!valid_part_table_flag(pe->sectorbuffer)) {
4153 _("Warning: invalid flag 0x%04x of partition "
4154 "table %d will be corrected by w(rite)\n"),
4155 part_table_flag(pe->sectorbuffer), i + 1);
4156 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4165 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4167 * Print the message MESG, then read an integer between LOW and HIGH (inclusive).
4168 * If the user hits Enter, DFLT is returned.
4169 * Answers like +10 are interpreted as offsets from BASE.
4171 * There is no default if DFLT is not between LOW and HIGH.
4174 read_int(uint low, uint dflt, uint high, uint base, char *mesg)
4178 static char *ms = NULL;
4179 static int mslen = 0;
4181 if (!ms || strlen(mesg)+100 > mslen) {
4182 mslen = strlen(mesg)+200;
4183 ms = xrealloc(ms,mslen);
4186 if (dflt < low || dflt > high)
4190 snprintf(ms, mslen, _("%s (%u-%u, default %u): "),
4191 mesg, low, high, dflt);
4193 snprintf(ms, mslen, "%s (%u-%u): ",
4197 int use_default = default_ok;
4199 /* ask question and read answer */
4200 while (read_chars(ms) != '\n' && !isdigit(*line_ptr)
4201 && *line_ptr != '-' && *line_ptr != '+')
4204 if (*line_ptr == '+' || *line_ptr == '-') {
4205 int minus = (*line_ptr == '-');
4208 i = atoi(line_ptr+1);
4210 while (isdigit(*++line_ptr))
4213 switch (*line_ptr) {
4216 if (!display_in_cyl_units)
4217 i *= heads * sectors;
4231 absolute = 1000000000;
4237 unsigned long long bytes;
4240 bytes = (unsigned long long) i * absolute;
4241 unit = sector_size * units_per_sector;
4242 bytes += unit/2; /* round */
4251 while (isdigit(*line_ptr)) {
4257 printf(_("Using default value %u\n"), i = dflt);
4258 if (i >= low && i <= high)
4261 printf(_("Value out of range.\n"));
4267 get_partition(int warn, int max) {
4271 i = read_int(1, 0, max, 0, _("Partition number")) - 1;
4275 if ((!sun_label && !sgi_label && !pe->part_table->sys_ind)
4276 #ifdef CONFIG_FEATURE_SUN_LABEL
4278 (!sunlabel->partitions[i].num_sectors ||
4279 !sunlabel->infos[i].id))
4281 #ifdef CONFIG_FEATURE_SGI_LABEL
4282 || (sgi_label && (!sgi_get_num_sectors(i)))
4286 _("Warning: partition %d has empty type\n"),
4293 get_existing_partition(int warn, int max) {
4297 for (i = 0; i < max; i++) {
4298 struct pte *pe = &ptes[i];
4299 struct partition *p = pe->part_table;
4301 if (p && !is_cleared_partition(p)) {
4308 printf(_("Selected partition %d\n"), pno+1);
4311 printf(_("No partition is defined yet!\n"));
4315 return get_partition(warn, max);
4319 get_nonexisting_partition(int warn, int max) {
4323 for (i = 0; i < max; i++) {
4324 struct pte *pe = &ptes[i];
4325 struct partition *p = pe->part_table;
4327 if (p && is_cleared_partition(p)) {
4334 printf(_("Selected partition %d\n"), pno+1);
4337 printf(_("All primary partitions have been defined already!\n"));
4341 return get_partition(warn, max);
4345 void change_units(void)
4347 display_in_cyl_units = !display_in_cyl_units;
4349 printf(_("Changing display/entry units to %s\n"),
4354 toggle_active(int i) {
4355 struct pte *pe = &ptes[i];
4356 struct partition *p = pe->part_table;
4358 if (IS_EXTENDED (p->sys_ind) && !p->boot_ind)
4360 _("WARNING: Partition %d is an extended partition\n"),
4362 p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG);
4367 toggle_dos_compatibility_flag(void) {
4368 dos_compatible_flag = ~dos_compatible_flag;
4369 if (dos_compatible_flag) {
4370 sector_offset = sectors;
4371 printf(_("DOS Compatibility flag is set\n"));
4375 printf(_("DOS Compatibility flag is not set\n"));
4380 delete_partition(int i) {
4381 struct pte *pe = &ptes[i];
4382 struct partition *p = pe->part_table;
4383 struct partition *q = pe->ext_pointer;
4385 /* Note that for the fifth partition (i == 4) we don't actually
4386 * decrement partitions.
4389 if (warn_geometry())
4390 return; /* C/H/S not set */
4393 #ifdef CONFIG_FEATURE_SUN_LABEL
4395 sun_delete_partition(i);
4399 #ifdef CONFIG_FEATURE_SGI_LABEL
4401 sgi_delete_partition(i);
4407 if (IS_EXTENDED (p->sys_ind) && i == ext_index) {
4409 ptes[ext_index].ext_pointer = NULL;
4410 extended_offset = 0;
4416 if (!q->sys_ind && i > 4) {
4417 /* the last one in the chain - just delete */
4420 clear_partition(ptes[i].ext_pointer);
4421 ptes[i].changed = 1;
4423 /* not the last one - further ones will be moved down */
4425 /* delete this link in the chain */
4426 p = ptes[i-1].ext_pointer;
4428 set_start_sect(p, get_start_sect(q));
4429 set_nr_sects(p, get_nr_sects(q));
4430 ptes[i-1].changed = 1;
4431 } else if (partitions > 5) { /* 5 will be moved to 4 */
4432 /* the first logical in a longer chain */
4435 if (pe->part_table) /* prevent SEGFAULT */
4436 set_start_sect(pe->part_table,
4437 get_partition_start(pe) -
4439 pe->offset = extended_offset;
4443 if (partitions > 5) {
4445 while (i < partitions) {
4446 ptes[i] = ptes[i+1];
4450 /* the only logical: clear only */
4451 clear_partition(ptes[i].part_table);
4456 change_sysid(void) {
4457 int i, sys, origsys;
4458 struct partition *p;
4460 #ifdef CONFIG_FEATURE_SGI_LABEL
4461 /* If sgi_label then don't use get_existing_partition,
4462 let the user select a partition, since get_existing_partition()
4463 only works for Linux like partition tables. */
4465 i = get_existing_partition(0, partitions);
4467 i = get_partition(0, partitions);
4470 i = get_existing_partition(0, partitions);
4474 p = ptes[i].part_table;
4475 origsys = sys = get_sysid(i);
4477 /* if changing types T to 0 is allowed, then
4478 the reverse change must be allowed, too */
4479 if (!sys && !sgi_label && !sun_label && !get_nr_sects(p))
4480 printf(_("Partition %d does not exist yet!\n"), i + 1);
4482 sys = read_hex (get_sys_types());
4484 if (!sys && !sgi_label && !sun_label) {
4485 printf(_("Type 0 means free space to many systems\n"
4486 "(but not to Linux). Having partitions of\n"
4487 "type 0 is probably unwise. You can delete\n"
4488 "a partition using the `d' command.\n"));
4492 if (!sun_label && !sgi_label) {
4493 if (IS_EXTENDED (sys) != IS_EXTENDED (p->sys_ind)) {
4494 printf(_("You cannot change a partition into"
4495 " an extended one or vice versa\n"
4496 "Delete it first.\n"));
4502 #ifdef CONFIG_FEATURE_SUN_LABEL
4503 if (sun_label && i == 2 && sys != WHOLE_DISK)
4504 printf(_("Consider leaving partition 3 "
4505 "as Whole disk (5),\n"
4506 "as SunOS/Solaris expects it and "
4507 "even Linux likes it.\n\n"));
4509 #ifdef CONFIG_FEATURE_SGI_LABEL
4510 if (sgi_label && ((i == 10 && sys != ENTIRE_DISK)
4511 || (i == 8 && sys != 0)))
4512 printf(_("Consider leaving partition 9 "
4513 "as volume header (0),\nand "
4514 "partition 11 as entire volume (6)"
4515 "as IRIX expects it.\n\n"));
4519 #ifdef CONFIG_FEATURE_SUN_LABEL
4521 sun_change_sysid(i, sys);
4524 #ifdef CONFIG_FEATURE_SGI_LABEL
4526 sgi_change_sysid(i, sys);
4530 printf (_("Changed system type of partition %d "
4531 "to %x (%s)\n"), i + 1, sys,
4532 partition_type(sys));
4533 ptes[i].changed = 1;
4534 if (is_dos_partition(origsys) ||
4535 is_dos_partition(sys))
4541 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
4544 /* check_consistency() and long2chs() added Sat Mar 6 12:28:16 1993,
4545 * faith@cs.unc.edu, based on code fragments from pfdisk by Gordon W. Ross,
4546 * Jan. 1990 (version 1.2.1 by Gordon W. Ross Aug. 1990; Modified by S.
4547 * Lubkin Oct. 1991). */
4549 static void long2chs(ulong ls, uint *c, uint *h, uint *s) {
4550 int spc = heads * sectors;
4555 *s = ls % sectors + 1; /* sectors count from 1 */
4558 static void check_consistency(const struct partition *p, int partition) {
4559 uint pbc, pbh, pbs; /* physical beginning c, h, s */
4560 uint pec, peh, pes; /* physical ending c, h, s */
4561 uint lbc, lbh, lbs; /* logical beginning c, h, s */
4562 uint lec, leh, les; /* logical ending c, h, s */
4564 if (!heads || !sectors || (partition >= 4))
4565 return; /* do not check extended partitions */
4567 /* physical beginning c, h, s */
4568 pbc = (p->cyl & 0xff) | ((p->sector << 2) & 0x300);
4570 pbs = p->sector & 0x3f;
4572 /* physical ending c, h, s */
4573 pec = (p->end_cyl & 0xff) | ((p->end_sector << 2) & 0x300);
4575 pes = p->end_sector & 0x3f;
4577 /* compute logical beginning (c, h, s) */
4578 long2chs(get_start_sect(p), &lbc, &lbh, &lbs);
4580 /* compute logical ending (c, h, s) */
4581 long2chs(get_start_sect(p) + get_nr_sects(p) - 1, &lec, &leh, &les);
4583 /* Same physical / logical beginning? */
4584 if (cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) {
4585 printf(_("Partition %d has different physical/logical "
4586 "beginnings (non-Linux?):\n"), partition + 1);
4587 printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs);
4588 printf(_("logical=(%d, %d, %d)\n"),lbc, lbh, lbs);
4591 /* Same physical / logical ending? */
4592 if (cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) {
4593 printf(_("Partition %d has different physical/logical "
4594 "endings:\n"), partition + 1);
4595 printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
4596 printf(_("logical=(%d, %d, %d)\n"),lec, leh, les);
4600 /* Beginning on cylinder boundary? */
4601 if (pbh != !pbc || pbs != 1) {
4602 printf(_("Partition %i does not start on cylinder "
4603 "boundary:\n"), partition + 1);
4604 printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs);
4605 printf(_("should be (%d, %d, 1)\n"), pbc, !pbc);
4609 /* Ending on cylinder boundary? */
4610 if (peh != (heads - 1) || pes != sectors) {
4611 printf(_("Partition %i does not end on cylinder boundary.\n"),
4614 printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
4615 printf(_("should be (%d, %d, %d)\n"),
4616 pec, heads - 1, sectors);
4622 list_disk_geometry(void) {
4623 long long bytes = (total_number_of_sectors << 9);
4624 long megabytes = bytes/1000000;
4626 if (megabytes < 10000)
4627 printf(_("\nDisk %s: %ld MB, %lld bytes\n"),
4628 disk_device, megabytes, bytes);
4630 printf(_("\nDisk %s: %ld.%ld GB, %lld bytes\n"),
4631 disk_device, megabytes/1000, (megabytes/100)%10, bytes);
4632 printf(_("%d heads, %d sectors/track, %d cylinders"),
4633 heads, sectors, cylinders);
4634 if (units_per_sector == 1)
4635 printf(_(", total %llu sectors"),
4636 total_number_of_sectors / (sector_size/512));
4637 printf(_("\nUnits = %s of %d * %d = %d bytes\n\n"),
4639 units_per_sector, sector_size, units_per_sector * sector_size);
4643 * Check whether partition entries are ordered by their starting positions.
4644 * Return 0 if OK. Return i if partition i should have been earlier.
4645 * Two separate checks: primary and logical partitions.
4648 wrong_p_order(int *prev) {
4649 const struct pte *pe;
4650 const struct partition *p;
4651 off_t last_p_start_pos = 0, p_start_pos;
4654 for (i = 0 ; i < partitions; i++) {
4657 last_p_start_pos = 0;
4660 if ((p = pe->part_table)->sys_ind) {
4661 p_start_pos = get_partition_start(pe);
4663 if (last_p_start_pos > p_start_pos) {
4669 last_p_start_pos = p_start_pos;
4676 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
4678 * Fix the chain of logicals.
4679 * extended_offset is unchanged, the set of sectors used is unchanged
4680 * The chain is sorted so that sectors increase, and so that
4681 * starting sectors increase.
4683 * After this it may still be that cfdisk doesnt like the table.
4684 * (This is because cfdisk considers expanded parts, from link to
4685 * end of partition, and these may still overlap.)
4687 * sfdisk /dev/hda > ohda; sfdisk /dev/hda < ohda
4691 fix_chain_of_logicals(void) {
4692 int j, oj, ojj, sj, sjj;
4693 struct partition *pj,*pjj,tmp;
4695 /* Stage 1: sort sectors but leave sector of part 4 */
4696 /* (Its sector is the global extended_offset.) */
4698 for (j = 5; j < partitions-1; j++) {
4699 oj = ptes[j].offset;
4700 ojj = ptes[j+1].offset;
4702 ptes[j].offset = ojj;
4703 ptes[j+1].offset = oj;
4704 pj = ptes[j].part_table;
4705 set_start_sect(pj, get_start_sect(pj)+oj-ojj);
4706 pjj = ptes[j+1].part_table;
4707 set_start_sect(pjj, get_start_sect(pjj)+ojj-oj);
4708 set_start_sect(ptes[j-1].ext_pointer,
4709 ojj-extended_offset);
4710 set_start_sect(ptes[j].ext_pointer,
4711 oj-extended_offset);
4716 /* Stage 2: sort starting sectors */
4718 for (j = 4; j < partitions-1; j++) {
4719 pj = ptes[j].part_table;
4720 pjj = ptes[j+1].part_table;
4721 sj = get_start_sect(pj);
4722 sjj = get_start_sect(pjj);
4723 oj = ptes[j].offset;
4724 ojj = ptes[j+1].offset;
4725 if (oj+sj > ojj+sjj) {
4729 set_start_sect(pj, ojj+sjj-oj);
4730 set_start_sect(pjj, oj+sj-ojj);
4735 /* Probably something was changed */
4736 for (j = 4; j < partitions; j++)
4737 ptes[j].changed = 1;
4742 fix_partition_table_order(void) {
4743 struct pte *pei, *pek;
4746 if (!wrong_p_order(NULL)) {
4747 printf(_("Nothing to do. Ordering is correct already.\n\n"));
4751 while ((i = wrong_p_order(&k)) != 0 && i < 4) {
4752 /* partition i should have come earlier, move it */
4753 /* We have to move data in the MBR */
4754 struct partition *pi, *pk, *pe, pbuf;
4758 pe = pei->ext_pointer;
4759 pei->ext_pointer = pek->ext_pointer;
4760 pek->ext_pointer = pe;
4762 pi = pei->part_table;
4763 pk = pek->part_table;
4765 memmove(&pbuf, pi, sizeof(struct partition));
4766 memmove(pi, pk, sizeof(struct partition));
4767 memmove(pk, &pbuf, sizeof(struct partition));
4769 pei->changed = pek->changed = 1;
4773 fix_chain_of_logicals();
4781 list_table(int xtra) {
4782 const struct partition *p;
4785 #ifdef CONFIG_FEATURE_SUN_LABEL
4787 sun_list_table(xtra);
4792 #ifdef CONFIG_FEATURE_SGI_LABEL
4794 sgi_list_table(xtra);
4799 list_disk_geometry();
4801 #ifdef CONFIG_FEATURE_OSF_LABEL
4803 xbsd_print_disklabel(xtra);
4808 /* Heuristic: we list partition 3 of /dev/foo as /dev/foo3,
4809 but if the device name ends in a digit, say /dev/foo1,
4810 then the partition is called /dev/foo1p3. */
4811 w = strlen(disk_device);
4812 if (w && isdigit(disk_device[w-1]))
4817 printf(_("%*s Boot Start End Blocks Id System\n"),
4820 for (i = 0; i < partitions; i++) {
4821 const struct pte *pe = &ptes[i];
4824 if (p && !is_cleared_partition(p)) {
4825 off_t psects = get_nr_sects(p);
4826 off_t pblocks = psects;
4827 unsigned int podd = 0;
4829 if (sector_size < 1024) {
4830 pblocks /= (1024 / sector_size);
4831 podd = psects % (1024 / sector_size);
4833 if (sector_size > 1024)
4834 pblocks *= (sector_size / 1024);
4836 "%s %c %11llu %11llu %11llu%c %2x %s\n",
4837 partname(disk_device, i+1, w+2),
4838 /* boot flag */ !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG
4840 /* start */ (unsigned long long) cround(get_partition_start(pe)),
4841 /* end */ (unsigned long long) cround(get_partition_start(pe) + psects
4842 - (psects ? 1 : 0)),
4843 /* odd flag on end */ (unsigned long long) pblocks, podd ? '+' : ' ',
4844 /* type id */ p->sys_ind,
4845 /* type name */ partition_type(p->sys_ind));
4846 check_consistency(p, i);
4850 /* Is partition table in disk order? It need not be, but... */
4851 /* partition table entries are not checked for correct order if this
4852 is a sgi, sun or aix labeled disk... */
4853 if (dos_label && wrong_p_order(NULL)) {
4854 printf(_("\nPartition table entries are not in disk order\n"));
4858 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
4860 x_list_table(int extend) {
4861 const struct pte *pe;
4862 const struct partition *p;
4865 printf(_("\nDisk %s: %d heads, %d sectors, %d cylinders\n\n"),
4866 disk_device, heads, sectors, cylinders);
4867 printf(_("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n"));
4868 for (i = 0 ; i < partitions; i++) {
4870 p = (extend ? pe->ext_pointer : pe->part_table);
4872 printf("%2d %02x%4d%4d%5d%4d%4d%5d%11u%11u %02x\n",
4873 i + 1, p->boot_ind, p->head,
4875 cylinder(p->sector, p->cyl), p->end_head,
4876 sector(p->end_sector),
4877 cylinder(p->end_sector, p->end_cyl),
4878 get_start_sect(p), get_nr_sects(p), p->sys_ind);
4880 check_consistency(p, i);
4886 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4888 fill_bounds(off_t *first, off_t *last) {
4890 const struct pte *pe = &ptes[0];
4891 const struct partition *p;
4893 for (i = 0; i < partitions; pe++,i++) {
4895 if (!p->sys_ind || IS_EXTENDED (p->sys_ind)) {
4896 first[i] = 0xffffffff;
4899 first[i] = get_partition_start(pe);
4900 last[i] = first[i] + get_nr_sects(p) - 1;
4906 check(int n, uint h, uint s, uint c, off_t start) {
4907 off_t total, real_s, real_c;
4909 real_s = sector(s) - 1;
4910 real_c = cylinder(s, c);
4911 total = (real_c * sectors + real_s) * heads + h;
4913 fprintf(stderr, _("Warning: partition %d contains sector 0\n"), n);
4916 _("Partition %d: head %d greater than maximum %d\n"),
4918 if (real_s >= sectors)
4919 fprintf(stderr, _("Partition %d: sector %d greater than "
4920 "maximum %d\n"), n, s, sectors);
4921 if (real_c >= cylinders)
4922 fprintf(stderr, _("Partitions %d: cylinder %llu greater than "
4923 "maximum %d\n"), n, (unsigned long long)real_c + 1, cylinders);
4924 if (cylinders <= 1024 && start != total)
4926 _("Partition %d: previous sectors %llu disagrees with "
4927 "total %llu\n"), n, (unsigned long long)start, (unsigned long long)total);
4934 off_t first[partitions], last[partitions];
4935 struct partition *p;
4937 if (warn_geometry())
4940 #ifdef CONFIG_FEATURE_SUN_LABEL
4946 #ifdef CONFIG_FEATURE_SGI_LABEL
4953 fill_bounds(first, last);
4954 for (i = 0; i < partitions; i++) {
4955 struct pte *pe = &ptes[i];
4958 if (p->sys_ind && !IS_EXTENDED (p->sys_ind)) {
4959 check_consistency(p, i);
4960 if (get_partition_start(pe) < first[i])
4961 printf(_("Warning: bad start-of-data in "
4962 "partition %d\n"), i + 1);
4963 check(i + 1, p->end_head, p->end_sector, p->end_cyl,
4965 total += last[i] + 1 - first[i];
4966 for (j = 0; j < i; j++)
4967 if ((first[i] >= first[j] && first[i] <= last[j])
4968 || ((last[i] <= last[j] && last[i] >= first[j]))) {
4969 printf(_("Warning: partition %d overlaps "
4970 "partition %d.\n"), j + 1, i + 1);
4971 total += first[i] >= first[j] ?
4972 first[i] : first[j];
4973 total -= last[i] <= last[j] ?
4979 if (extended_offset) {
4980 struct pte *pex = &ptes[ext_index];
4981 off_t e_last = get_start_sect(pex->part_table) +
4982 get_nr_sects(pex->part_table) - 1;
4984 for (i = 4; i < partitions; i++) {
4986 p = ptes[i].part_table;
4988 if (i != 4 || i + 1 < partitions)
4989 printf(_("Warning: partition %d "
4990 "is empty\n"), i + 1);
4992 else if (first[i] < extended_offset ||
4994 printf(_("Logical partition %d not entirely in "
4995 "partition %d\n"), i + 1, ext_index + 1);
4999 if (total > heads * sectors * cylinders)
5000 printf(_("Total allocated sectors %d greater than the maximum "
5001 "%d\n"), total, heads * sectors * cylinders);
5002 else if ((total = heads * sectors * cylinders - total) != 0)
5003 printf(_("%d unallocated sectors\n"), total);
5007 add_partition(int n, int sys) {
5008 char mesg[256]; /* 48 does not suffice in Japanese */
5010 struct partition *p = ptes[n].part_table;
5011 struct partition *q = ptes[ext_index].part_table;
5013 off_t start, stop = 0, limit, temp,
5014 first[partitions], last[partitions];
5016 if (p && p->sys_ind) {
5017 printf(_("Partition %d is already defined. Delete "
5018 "it before re-adding it.\n"), n + 1);
5021 fill_bounds(first, last);
5023 start = sector_offset;
5024 if (display_in_cyl_units || !total_number_of_sectors)
5025 llimit = heads * sectors * cylinders - 1;
5027 llimit = total_number_of_sectors - 1;
5029 if (limit != llimit)
5031 if (extended_offset) {
5032 first[ext_index] = extended_offset;
5033 last[ext_index] = get_start_sect(q) +
5034 get_nr_sects(q) - 1;
5037 start = extended_offset + sector_offset;
5038 limit = get_start_sect(q) + get_nr_sects(q) - 1;
5040 if (display_in_cyl_units)
5041 for (i = 0; i < partitions; i++)
5042 first[i] = (cround(first[i]) - 1) * units_per_sector;
5044 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
5047 for (i = 0; i < partitions; i++) {
5050 if (start == ptes[i].offset)
5051 start += sector_offset;
5052 lastplusoff = last[i] + ((n<4) ? 0 : sector_offset);
5053 if (start >= first[i] && start <= lastplusoff)
5054 start = lastplusoff + 1;
5058 if (start >= temp+units_per_sector && readed) {
5059 printf(_("Sector %llu is already allocated\n"), (unsigned long long)temp);
5063 if (!readed && start == temp) {
5066 saved_start = start;
5067 start = read_int(cround(saved_start), cround(saved_start), cround(limit),
5069 if (display_in_cyl_units) {
5070 start = (start - 1) * units_per_sector;
5071 if (start < saved_start) start = saved_start;
5075 } while (start != temp || !readed);
5076 if (n > 4) { /* NOT for fifth partition */
5077 struct pte *pe = &ptes[n];
5079 pe->offset = start - sector_offset;
5080 if (pe->offset == extended_offset) { /* must be corrected */
5082 if (sector_offset == 1)
5087 for (i = 0; i < partitions; i++) {
5088 struct pte *pe = &ptes[i];
5090 if (start < pe->offset && limit >= pe->offset)
5091 limit = pe->offset - 1;
5092 if (start < first[i] && limit >= first[i])
5093 limit = first[i] - 1;
5095 if (start > limit) {
5096 printf(_("No free sectors available\n"));
5101 if (cround(start) == cround(limit)) {
5104 snprintf(mesg, sizeof(mesg),
5105 _("Last %s or +size or +sizeM or +sizeK"),
5106 str_units(SINGULAR));
5107 stop = read_int(cround(start), cround(limit), cround(limit),
5108 cround(start), mesg);
5109 if (display_in_cyl_units) {
5110 stop = stop * units_per_sector - 1;
5116 set_partition(n, 0, start, stop, sys);
5118 set_partition(n - 1, 1, ptes[n].offset, stop, EXTENDED);
5120 if (IS_EXTENDED (sys)) {
5121 struct pte *pe4 = &ptes[4];
5122 struct pte *pen = &ptes[n];
5125 pen->ext_pointer = p;
5126 pe4->offset = extended_offset = start;
5127 pe4->sectorbuffer = xcalloc(1, sector_size);
5128 pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
5129 pe4->ext_pointer = pe4->part_table + 1;
5137 if (partitions > 5 || ptes[4].part_table->sys_ind) {
5138 struct pte *pe = &ptes[partitions];
5140 pe->sectorbuffer = xcalloc(1, sector_size);
5141 pe->part_table = pt_offset(pe->sectorbuffer, 0);
5142 pe->ext_pointer = pe->part_table + 1;
5147 add_partition(partitions - 1, LINUX_NATIVE);
5151 new_partition(void) {
5152 int i, free_primary = 0;
5154 if (warn_geometry())
5157 #ifdef CONFIG_FEATURE_SUN_LABEL
5159 add_sun_partition(get_partition(0, partitions), LINUX_NATIVE);
5163 #ifdef CONFIG_FEATURE_SGI_LABEL
5165 sgi_add_partition(get_partition(0, partitions), LINUX_NATIVE);
5169 #ifdef CONFIG_FEATURE_AIX_LABEL
5171 printf(_("\tSorry - this fdisk cannot handle AIX disk labels."
5172 "\n\tIf you want to add DOS-type partitions, create"
5173 "\n\ta new empty DOS partition table first. (Use o.)"
5175 "This will destroy the present disk contents.\n"));
5180 for (i = 0; i < 4; i++)
5181 free_primary += !ptes[i].part_table->sys_ind;
5183 if (!free_primary && partitions >= MAXIMUM_PARTS) {
5184 printf(_("The maximum number of partitions has been created\n"));
5188 if (!free_primary) {
5189 if (extended_offset)
5192 printf(_("You must delete some partition and add "
5193 "an extended partition first\n"));
5195 char c, line[LINE_LENGTH];
5196 snprintf(line, sizeof(line), "%s\n %s\n p primary "
5197 "partition (1-4)\n",
5198 "Command action", (extended_offset ?
5199 "l logical (5 or over)" : "e extended"));
5201 if ((c = read_char(line)) == 'p' || c == 'P') {
5202 i = get_nonexisting_partition(0, 4);
5204 add_partition(i, LINUX_NATIVE);
5207 else if (c == 'l' && extended_offset) {
5211 else if (c == 'e' && !extended_offset) {
5212 i = get_nonexisting_partition(0, 4);
5214 add_partition(i, EXTENDED);
5218 printf(_("Invalid partition number "
5219 "for type `%c'\n"), c);
5230 if (ptes[i].changed)
5231 ptes[3].changed = 1;
5232 for (i = 3; i < partitions; i++) {
5233 struct pte *pe = &ptes[i];
5236 write_part_table_flag(pe->sectorbuffer);
5237 write_sector(pe->offset, pe->sectorbuffer);
5241 #ifdef CONFIG_FEATURE_SGI_LABEL
5242 else if (sgi_label) {
5243 /* no test on change? the printf below might be mistaken */
5247 #ifdef CONFIG_FEATURE_SUN_LABEL
5248 else if (sun_label) {
5252 if (ptes[i].changed)
5259 printf(_("The partition table has been altered!\n\n"));
5260 reread_partition_table(1);
5264 reread_partition_table(int leave) {
5268 printf(_("Calling ioctl() to re-read partition table.\n"));
5271 if ((i = ioctl(fd, BLKRRPART)) != 0) {
5274 /* some kernel versions (1.2.x) seem to have trouble
5275 rereading the partition table, but if asked to do it
5276 twice, the second time works. - biro@yggdrasil.com */
5279 if ((i = ioctl(fd, BLKRRPART)) != 0)
5284 printf(_("\nWARNING: Re-reading the partition table "
5285 "failed with error %d: %s.\n"
5286 "The kernel still uses the old table.\n"
5287 "The new table will be used "
5288 "at the next reboot.\n"),
5289 error, strerror(error));
5294 _("\nWARNING: If you have created or modified any DOS 6.x\n"
5295 "partitions, please see the fdisk manual page for additional\n"
5301 printf(_("Syncing disks.\n"));
5303 sleep(4); /* for sync() */
5307 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
5309 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
5310 #define MAX_PER_LINE 16
5312 print_buffer(char pbuffer[]) {
5316 for (i = 0, l = 0; i < sector_size; i++, l++) {
5318 printf("0x%03X:", i);
5319 printf(" %02X", (unsigned char) pbuffer[i]);
5320 if (l == MAX_PER_LINE - 1) {
5335 printf(_("Device: %s\n"), disk_device);
5336 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
5337 if (sun_label || sgi_label)
5338 print_buffer(MBRbuffer);
5341 for (i = 3; i < partitions; i++)
5342 print_buffer(ptes[i].sectorbuffer);
5347 struct pte *pe = &ptes[i];
5348 struct partition *p = pe->part_table;
5351 if (warn_geometry())
5353 if (!p->sys_ind || !get_nr_sects(p) || IS_EXTENDED (p->sys_ind)) {
5354 printf(_("Partition %d has no data area\n"), i + 1);
5357 first = get_partition_start(pe);
5358 new = read_int(first, first, first + get_nr_sects(p) - 1, first,
5359 _("New beginning of data")) - pe->offset;
5361 if (new != get_nr_sects(p)) {
5362 first = get_nr_sects(p) + get_start_sect(p) - new;
5363 set_nr_sects(p, first);
5364 set_start_sect(p, new);
5375 c = tolower(read_char(_("Expert command (m for help): ")));
5378 #ifdef CONFIG_FEATURE_SUN_LABEL
5385 move_begin(get_partition(0, partitions));
5388 user_cylinders = cylinders =
5389 read_int(1, cylinders, 1048576, 0,
5390 _("Number of cylinders"));
5391 #ifdef CONFIG_FEATURE_SUN_LABEL
5393 sun_set_ncyl(cylinders);
5402 #ifdef CONFIG_FEATURE_SGI_LABEL
5407 #ifdef CONFIG_FEATURE_SUN_LABEL
5417 fix_partition_table_order();
5420 #ifdef CONFIG_FEATURE_SGI_LABEL
5425 user_heads = heads = read_int(1, heads, 256, 0,
5426 _("Number of heads"));
5430 #ifdef CONFIG_FEATURE_SUN_LABEL
5436 #ifdef CONFIG_FEATURE_SUN_LABEL
5442 #ifdef CONFIG_FEATURE_SUN_LABEL
5456 user_sectors = sectors = read_int(1, sectors, 63, 0,
5457 _("Number of sectors"));
5458 if (dos_compatible_flag) {
5459 sector_offset = sectors;
5460 fprintf(stderr, _("Warning: setting "
5461 "sector offset for DOS "
5470 write_table(); /* does not return */
5473 #ifdef CONFIG_FEATURE_SUN_LABEL
5475 sun_set_pcylcount();
5483 #endif /* ADVANCED mode */
5486 is_ide_cdrom_or_tape(const char *device) {
5489 struct stat statbuf;
5492 /* No device was given explicitly, and we are trying some
5493 likely things. But opening /dev/hdc may produce errors like
5494 "hdc: tray open or drive not ready"
5495 if it happens to be a CD-ROM drive. It even happens that
5496 the process hangs on the attempt to read a music CD.
5497 So try to be careful. This only works since 2.1.73. */
5499 if (strncmp("/dev/hd", device, 7))
5502 snprintf(buf, sizeof(buf), "/proc/ide/%s/media", device+5);
5503 procf = fopen(buf, "r");
5504 if (procf != NULL && fgets(buf, sizeof(buf), procf))
5505 is_ide = (!strncmp(buf, "cdrom", 5) ||
5506 !strncmp(buf, "tape", 4));
5508 /* Now when this proc file does not exist, skip the
5509 device when it is read-only. */
5510 if (stat(device, &statbuf) == 0)
5511 is_ide = ((statbuf.st_mode & 0222) == 0);
5519 try(const char *device, int user_specified) {
5522 disk_device = device;
5523 if (setjmp(listingbuf))
5525 if (!user_specified)
5526 if (is_ide_cdrom_or_tape(device))
5528 if ((fd = open(disk_device, type_open)) >= 0) {
5529 gb = get_boot(try_only);
5530 if (gb > 0) { /* I/O error */
5532 } else if (gb < 0) { /* no DOS signature */
5533 list_disk_geometry();
5536 #ifdef CONFIG_FEATURE_OSF_LABEL
5537 if (btrydev(device) < 0)
5540 _("Disk %s doesn't contain a valid "
5541 "partition table\n"), device);
5546 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5547 if (!sun_label && partitions > 4)
5548 delete_partition(ext_index);
5552 /* Ignore other errors, since we try IDE
5553 and SCSI hard disks which may not be
5554 installed on the system. */
5555 if (errno == EACCES) {
5556 fprintf(stderr, _("Cannot open %s\n"), device);
5562 /* for fdisk -l: try all things in /proc/partitions
5563 that look like a partition name (do not end in a digit) */
5567 char line[100], ptname[100], devname[120], *s;
5570 procpt = bb_wfopen(PROC_PARTITIONS, "r");
5572 while (fgets(line, sizeof(line), procpt)) {
5573 if (sscanf (line, " %d %d %d %[^\n ]",
5574 &ma, &mi, &sz, ptname) != 4)
5576 for (s = ptname; *s; s++);
5579 sprintf(devname, "/dev/%s", ptname);
5582 #ifdef CONFIG_FEATURE_CLEAN_UP
5587 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5589 unknown_command(int c) {
5590 printf(_("%c: unknown command\n"), c);
5594 int fdisk_main(int argc, char **argv) {
5596 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5599 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5605 * fdisk -l [-b sectorsize] [-u] device ...
5606 * fdisk -s [partition] ...
5607 * fdisk [-b sectorsize] [-u] device
5609 * Options -C, -H, -S set the geometry.
5612 while ((c = getopt(argc, argv, "b:C:H:lS:uvV"
5613 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5619 /* Ugly: this sector size is really per device,
5620 so cannot be combined with multiple disks,
5621 and te same goes for the C/H/S options.
5623 sector_size = atoi(optarg);
5624 if (sector_size != 512 && sector_size != 1024 &&
5625 sector_size != 2048)
5628 user_set_sector_size = 1;
5631 user_cylinders = atoi(optarg);
5634 user_heads = atoi(optarg);
5635 if (user_heads <= 0 || user_heads >= 256)
5639 user_sectors = atoi(optarg);
5640 if (user_sectors <= 0 || user_sectors >= 64)
5644 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5648 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5654 display_in_cyl_units = 0;
5658 printf("fdisk v" UTIL_LINUX_VERSION "\n");
5666 printf(_("This kernel finds the sector size itself - "
5667 "-b option ignored\n"));
5669 if (user_set_sector_size && argc-optind != 1)
5670 printf(_("Warning: the -b (set sector size) option should"
5671 " be used with one specified device\n"));
5674 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5678 type_open = O_RDONLY;
5679 if (argc > optind) {
5682 /* avoid gcc warning:
5683 variable `k' might be clobbered by `longjmp' */
5687 for (k=optind; k<argc; k++)
5690 /* we no longer have default device names */
5691 /* but, we can use /proc/partitions instead */
5695 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5699 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5705 type_open = O_RDONLY;
5707 opts = argc - optind;
5711 for (j = optind; j < argc; j++) {
5712 disk_device = argv[j];
5713 if ((fd = open(disk_device, type_open)) < 0)
5714 fdisk_fatal(unable_to_open);
5715 if (ioctl(fd, BLKGETSIZE, &size))
5716 fdisk_fatal(ioctl_error);
5719 printf("%ld\n", size/2);
5721 printf("%s: %ld\n", argv[j], size/2);
5727 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5728 if (argc-optind == 1)
5729 disk_device = argv[optind];
5735 #ifdef CONFIG_FEATURE_OSF_LABEL
5737 /* OSF label, and no DOS label */
5738 printf(_("Detected an OSF/1 disklabel on %s, entering "
5739 "disklabel mode.\n"),
5743 /* If we return we may want to make an empty DOS label? */
5749 c = tolower(read_char(_("Command (m for help): ")));
5753 toggle_active(get_partition(1, partitions));
5754 #ifdef CONFIG_FEATURE_SUN_LABEL
5756 toggle_sunflags(get_partition(1, partitions),
5759 #ifdef CONFIG_FEATURE_SGI_LABEL
5761 sgi_set_bootpartition(
5762 get_partition(1, partitions));
5768 #ifdef CONFIG_FEATURE_SGI_LABEL
5770 printf(_("\nThe current boot file is: %s\n"),
5771 sgi_get_bootfile());
5772 if (read_chars(_("Please enter the name of the "
5773 "new boot file: ")) == '\n')
5774 printf(_("Boot file unchanged\n"));
5776 sgi_set_bootfile(line_ptr);
5779 #ifdef CONFIG_FEATURE_OSF_LABEL
5785 toggle_dos_compatibility_flag();
5786 #ifdef CONFIG_FEATURE_SUN_LABEL
5788 toggle_sunflags(get_partition(1, partitions),
5791 #ifdef CONFIG_FEATURE_SGI_LABEL
5793 sgi_set_swappartition(
5794 get_partition(1, partitions));
5802 #ifdef CONFIG_FEATURE_SGI_LABEL
5803 /* If sgi_label then don't use get_existing_partition,
5804 let the user select a partition, since
5805 get_existing_partition() only works for Linux-like
5808 j = get_existing_partition(1, partitions);
5810 j = get_partition(1, partitions);
5813 j = get_existing_partition(1, partitions);
5816 delete_partition(j);
5820 #ifdef CONFIG_FEATURE_SGI_LABEL
5827 list_types(get_sys_types());
5846 #ifdef CONFIG_FEATURE_SUN_LABEL
5860 write_table(); /* does not return */
5862 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
5864 #ifdef CONFIG_FEATURE_SGI_LABEL
5867 _("\n\tSorry, no experts menu for SGI "
5868 "partition tables available.\n\n"));
5881 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */