1 /* fdisk.c -- Partition table manipulator for Linux.
3 * Copyright (C) 1992 A. V. Le Blanc (LeBlanc@mcc.ac.uk)
5 * This program is free software. You can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation: either version 1 or
8 * (at your option) any later version.
10 * Vladimir Oleynik <dzo@simtreas.ru> 2001,2002 Busybox port
13 #define UTIL_LINUX_VERSION "2.12pre"
15 #define PROC_PARTITIONS "/proc/partitions"
17 #include <sys/types.h>
18 #include <sys/stat.h> /* stat */
27 #include <assert.h> /* assert */
31 #define u_char unsigned char
32 #include <scsi/scsi.h> /* SCSI_IOCTL_GET_IDLUN */
35 #include <sys/ioctl.h>
36 #include <sys/param.h>
37 #include <sys/sysmacros.h> /* major */
39 #include <stdint.h> /* for uint32_t, uint16_t, uint8_t, int16_t, etc */
41 /* Copied from linux/major.h */
42 #define FLOPPY_MAJOR 2
44 #include <sys/utsname.h>
48 #define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r))
54 #define BLKRRPART _IO(0x12,95) /* re-read partition table */
55 #define BLKGETSIZE _IO(0x12,96) /* return device size */
56 #define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */
57 #define BLKSSZGET _IO(0x12,104) /* get block device sector size */
58 #define BLKGETSIZE64 _IOR(0x12,114,8) /* 8 = sizeof(u64) */
64 #define DEFAULT_SECTOR_SIZE 512
65 #define MAX_SECTOR_SIZE 2048
66 #define SECTOR_SIZE 512 /* still used in BSD code */
67 #define MAXIMUM_PARTS 60
69 #define ACTIVE_FLAG 0x80
72 #define WIN98_EXTENDED 0x0f
73 #define LINUX_PARTITION 0x81
74 #define LINUX_SWAP 0x82
75 #define LINUX_NATIVE 0x83
76 #define LINUX_EXTENDED 0x85
77 #define LINUX_LVM 0x8e
78 #define LINUX_RAID 0xfd
83 #define IS_EXTENDED(i) \
84 ((i) == EXTENDED || (i) == WIN98_EXTENDED || (i) == LINUX_EXTENDED)
86 #define SIZE(a) (sizeof(a)/sizeof((a)[0]))
88 #define cround(n) (display_in_cyl_units ? ((n)/units_per_sector)+1 : (n))
89 #define scround(x) (((x)+units_per_sector-1)/units_per_sector)
91 #if defined(__GNUC__) || defined(HAS_LONG_LONG)
92 typedef long long ext2_loff_t;
94 typedef long ext2_loff_t;
97 /* including <linux/hdreg.h> also fails */
100 unsigned char sectors;
101 unsigned short cylinders;
105 #define HDIO_GETGEO 0x0301 /* get device geometry */
109 const unsigned char *name;
112 static uint sector_size = DEFAULT_SECTOR_SIZE,
113 user_set_sector_size,
117 * Raw disk label. For DOS-type partition tables the MBR,
118 * with descriptions of the primary partitions.
120 static char MBRbuffer[MAX_SECTOR_SIZE];
122 #ifdef CONFIG_FEATURE_SUN_LABEL
123 static int sun_label; /* looking at sun disklabel */
127 #ifdef CONFIG_FEATURE_SGI_LABEL
128 static int sgi_label; /* looking at sgi disklabel */
132 #ifdef CONFIG_FEATURE_AIX_LABEL
133 static int aix_label; /* looking at aix disklabel */
137 #ifdef CONFIG_FEATURE_OSF_LABEL
138 static int osf_label; /* looking at OSF/1 disklabel */
139 static int possibly_osf_label;
144 #define dos_label (!sun_label && !sgi_label && !aix_label && !osf_label)
146 static uint heads, sectors, cylinders;
147 static void update_units(void);
151 * return partition name - uses static storage unless buf is supplied
154 partname(const char *dev, int pno, int lth) {
155 static char buffer[80];
162 bufsiz = sizeof(buffer);
167 if (isdigit(dev[w-1]))
170 /* devfs kludge - note: fdisk partition names are not supposed
171 to equal kernel names, so there is no reason to do this */
172 if (strcmp (dev + w - 4, "disc") == 0) {
180 snprintf(bufp, bufsiz, "%*.*s%s%-2u",
181 lth-wp-2, w, dev, p, pno);
183 snprintf(bufp, bufsiz, "%.*s%s%-2u", w, dev, p, pno);
189 unsigned char boot_ind; /* 0x80 - active */
190 unsigned char head; /* starting head */
191 unsigned char sector; /* starting sector */
192 unsigned char cyl; /* starting cylinder */
193 unsigned char sys_ind; /* What partition type */
194 unsigned char end_head; /* end head */
195 unsigned char end_sector; /* end sector */
196 unsigned char end_cyl; /* end cylinder */
197 unsigned char start4[4]; /* starting sector counting from 0 */
198 unsigned char size4[4]; /* nr of sectors in partition */
202 ioctl_error, unable_to_open, unable_to_read, unable_to_seek,
206 enum action {fdisk, require, try_only, create_empty_dos, create_empty_sun};
208 static const char *disk_device;
209 static int fd; /* the disk */
210 static int partitions = 4; /* maximum partition + 1 */
211 static uint display_in_cyl_units = 1;
212 static uint units_per_sector = 1;
213 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
214 static char *line_ptr;
215 static void change_units(void);
216 static void reread_partition_table(int leave);
217 static void delete_partition(int i);
218 static int get_partition(int warn, int max);
219 static void list_types(const struct systypes *sys);
220 static uint read_int(uint low, uint dflt, uint high, uint base, char *mesg);
222 static const char *partition_type(unsigned char type);
223 static void fdisk_fatal(enum failure why) __attribute__ ((noreturn));
224 static void get_geometry(void);
225 static int get_boot(enum action what);
230 #define hex_val(c) ({ \
232 isdigit(_c) ? _c - '0' : \
233 tolower(_c) + 10 - 'a'; \
237 #define LINE_LENGTH 800
238 #define pt_offset(b, n) ((struct partition *)((b) + 0x1be + \
239 (n) * sizeof(struct partition)))
240 #define sector(s) ((s) & 0x3f)
241 #define cylinder(s, c) ((c) | (((s) & 0xc0) << 2))
243 #define hsc2sector(h,s,c) (sector(s) - 1 + sectors * \
244 ((h) + heads * cylinder(s,c)))
245 #define set_hsc(h,s,c,sector) { \
246 s = sector % sectors + 1; \
248 h = sector % heads; \
251 s |= (sector >> 2) & 0xc0; \
255 static unsigned int get_start_sect(const struct partition *p);
256 static unsigned int get_nr_sects(const struct partition *p);
259 * per partition table entry data
261 * The four primary partitions have the same sectorbuffer (MBRbuffer)
262 * and have NULL ext_pointer.
263 * Each logical partition table entry has two pointers, one for the
264 * partition and one link to the next one.
267 struct partition *part_table; /* points into sectorbuffer */
268 struct partition *ext_pointer; /* points into sectorbuffer */
269 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
270 char changed; /* boolean */
272 uint offset; /* disk sector number */
273 char *sectorbuffer; /* disk sector contents */
274 } ptes[MAXIMUM_PARTS];
277 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
279 set_all_unchanged(void) {
282 for (i = 0; i < MAXIMUM_PARTS; i++)
290 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
292 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_OSF_LABEL)
293 static struct partition *
294 get_part_table(int i) {
295 return ptes[i].part_table;
300 str_units(int n) { /* n==1: use singular */
302 return display_in_cyl_units ? _("cylinder") : _("sector");
304 return display_in_cyl_units ? _("cylinders") : _("sectors");
308 valid_part_table_flag(const unsigned char *b) {
309 return (b[510] == 0x55 && b[511] == 0xaa);
312 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
313 static char line_buffer[LINE_LENGTH];
315 /* read line; return 0 or first char */
319 static int got_eof = 0;
321 fflush (stdout); /* requested by niles@scyld.com */
322 line_ptr = line_buffer;
323 if (!fgets(line_buffer, LINE_LENGTH, stdin)) {
325 got_eof++; /* user typed ^D ? */
327 fprintf(stderr, _("\ngot EOF thrice - exiting..\n"));
332 while (*line_ptr && !isgraph(*line_ptr))
338 read_char(const char *mesg)
342 } while (!read_line());
347 read_chars(const char *mesg)
358 read_hex(const struct systypes *sys)
364 read_char(_("Hex code (type L to list codes): "));
365 if (*line_ptr == 'l' || *line_ptr == 'L')
367 else if (isxdigit (*line_ptr))
371 hex = hex << 4 | hex_val(*line_ptr++);
372 while (isxdigit(*line_ptr));
377 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
379 #ifdef CONFIG_FEATURE_AIX_LABEL
381 * Copyright (C) Andreas Neuper, Sep 1998.
382 * This file may be redistributed under
383 * the terms of the GNU Public License.
387 unsigned int magic; /* expect AIX_LABEL_MAGIC */
388 unsigned int fillbytes1[124];
389 unsigned int physical_volume_id;
390 unsigned int fillbytes2[124];
393 #define AIX_LABEL_MAGIC 0xc9c2d4c1
394 #define AIX_LABEL_MAGIC_SWAPPED 0xc1d4c2c9
395 #define AIX_INFO_MAGIC 0x00072959
396 #define AIX_INFO_MAGIC_SWAPPED 0x59290700
398 #define aixlabel ((aix_partition *)MBRbuffer)
403 * 1999-03-20 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
404 * Internationalization
406 * 2003-03-20 Phillip Kesling <pkesling@sgi.com>
410 static int aix_other_endian;
411 static short aix_volumes=1;
414 * only dealing with free blocks here
420 _("\n\tThere is a valid AIX label on this disk.\n"
421 "\tUnfortunately Linux cannot handle these\n"
422 "\tdisks at the moment. Nevertheless some\n"
424 "\t1. fdisk will destroy its contents on write.\n"
425 "\t2. Be sure that this disk is NOT a still vital\n"
426 "\t part of a volume group. (Otherwise you may\n"
427 "\t erase the other disks as well, if unmirrored.)\n"
428 "\t3. Before deleting this physical volume be sure\n"
429 "\t to remove the disk logically from your AIX\n"
430 "\t machine. (Otherwise you become an AIXpert).")
440 memset( MBRbuffer, 0, sizeof(MBRbuffer) ); /* avoid fdisk cores */
445 check_aix_label( void )
447 if (aixlabel->magic != AIX_LABEL_MAGIC &&
448 aixlabel->magic != AIX_LABEL_MAGIC_SWAPPED) {
450 aix_other_endian = 0;
453 aix_other_endian = (aixlabel->magic == AIX_LABEL_MAGIC_SWAPPED);
459 aix_nolabel(); /* %% */
460 aix_label = 1; /* %% */
463 #endif /* AIX_LABEL */
465 #ifdef CONFIG_FEATURE_OSF_LABEL
467 * Copyright (c) 1987, 1988 Regents of the University of California.
468 * All rights reserved.
470 * Redistribution and use in source and binary forms, with or without
471 * modification, are permitted provided that the following conditions
473 * 1. Redistributions of source code must retain the above copyright
474 * notice, this list of conditions and the following disclaimer.
475 * 2. Redistributions in binary form must reproduce the above copyright
476 * notice, this list of conditions and the following disclaimer in the
477 * documentation and/or other materials provided with the distribution.
478 * 3. All advertising materials mentioning features or use of this software
479 * must display the following acknowledgement:
480 * This product includes software developed by the University of
481 * California, Berkeley and its contributors.
482 * 4. Neither the name of the University nor the names of its contributors
483 * may be used to endorse or promote products derived from this software
484 * without specific prior written permission.
486 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
487 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
488 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
489 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
490 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
491 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
492 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
493 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
494 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
495 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
500 #ifndef BSD_DISKMAGIC
501 #define BSD_DISKMAGIC ((uint32_t) 0x82564557)
504 #ifndef BSD_MAXPARTITIONS
505 #define BSD_MAXPARTITIONS 16
508 #define BSD_LINUX_BOOTDIR "/usr/ucb/mdec"
510 #if defined (i386) || defined (__sparc__) || defined (__arm__) || defined (__mips__) || defined (__s390__) || defined (__sh__) || defined(__x86_64__)
511 #define BSD_LABELSECTOR 1
512 #define BSD_LABELOFFSET 0
513 #elif defined (__alpha__) || defined (__powerpc__) || defined (__ia64__) || defined (__hppa__)
514 #define BSD_LABELSECTOR 0
515 #define BSD_LABELOFFSET 64
516 #elif defined (__s390__) || defined (__s390x__)
517 #define BSD_LABELSECTOR 1
518 #define BSD_LABELOFFSET 0
520 #error unknown architecture
523 #define BSD_BBSIZE 8192 /* size of boot area, with label */
524 #define BSD_SBSIZE 8192 /* max size of fs superblock */
526 struct xbsd_disklabel {
527 uint32_t d_magic; /* the magic number */
528 int16_t d_type; /* drive type */
529 int16_t d_subtype; /* controller/d_type specific */
530 char d_typename[16]; /* type name, e.g. "eagle" */
531 char d_packname[16]; /* pack identifier */
533 uint32_t d_secsize; /* # of bytes per sector */
534 uint32_t d_nsectors; /* # of data sectors per track */
535 uint32_t d_ntracks; /* # of tracks per cylinder */
536 uint32_t d_ncylinders; /* # of data cylinders per unit */
537 uint32_t d_secpercyl; /* # of data sectors per cylinder */
538 uint32_t d_secperunit; /* # of data sectors per unit */
540 * Spares (bad sector replacements) below
541 * are not counted in d_nsectors or d_secpercyl.
542 * Spare sectors are assumed to be physical sectors
543 * which occupy space at the end of each track and/or cylinder.
545 uint16_t d_sparespertrack; /* # of spare sectors per track */
546 uint16_t d_sparespercyl; /* # of spare sectors per cylinder */
548 * Alternate cylinders include maintenance, replacement,
549 * configuration description areas, etc.
551 uint32_t d_acylinders; /* # of alt. cylinders per unit */
553 /* hardware characteristics: */
555 * d_interleave, d_trackskew and d_cylskew describe perturbations
556 * in the media format used to compensate for a slow controller.
557 * Interleave is physical sector interleave, set up by the formatter
558 * or controller when formatting. When interleaving is in use,
559 * logically adjacent sectors are not physically contiguous,
560 * but instead are separated by some number of sectors.
561 * It is specified as the ratio of physical sectors traversed
562 * per logical sector. Thus an interleave of 1:1 implies contiguous
563 * layout, while 2:1 implies that logical sector 0 is separated
564 * by one sector from logical sector 1.
565 * d_trackskew is the offset of sector 0 on track N
566 * relative to sector 0 on track N-1 on the same cylinder.
567 * Finally, d_cylskew is the offset of sector 0 on cylinder N
568 * relative to sector 0 on cylinder N-1.
570 uint16_t d_rpm; /* rotational speed */
571 uint16_t d_interleave; /* hardware sector interleave */
572 uint16_t d_trackskew; /* sector 0 skew, per track */
573 uint16_t d_cylskew; /* sector 0 skew, per cylinder */
574 uint32_t d_headswitch; /* head switch time, usec */
575 uint32_t d_trkseek; /* track-to-track seek, usec */
576 uint32_t d_flags; /* generic flags */
578 uint32_t d_drivedata[NDDATA]; /* drive-type specific information */
580 uint32_t d_spare[NSPARE]; /* reserved for future use */
581 uint32_t d_magic2; /* the magic number (again) */
582 uint16_t d_checksum; /* xor of data incl. partitions */
583 /* filesystem and partition information: */
584 uint16_t d_npartitions; /* number of partitions in following */
585 uint32_t d_bbsize; /* size of boot area at sn0, bytes */
586 uint32_t d_sbsize; /* max size of fs superblock, bytes */
587 struct xbsd_partition { /* the partition table */
588 uint32_t p_size; /* number of sectors in partition */
589 uint32_t p_offset; /* starting sector */
590 uint32_t p_fsize; /* filesystem basic fragment size */
591 uint8_t p_fstype; /* filesystem type, see below */
592 uint8_t p_frag; /* filesystem fragments per block */
593 uint16_t p_cpg; /* filesystem cylinders per group */
594 } d_partitions[BSD_MAXPARTITIONS]; /* actually may be more */
598 #define BSD_DTYPE_SMD 1 /* SMD, XSMD; VAX hp/up */
599 #define BSD_DTYPE_MSCP 2 /* MSCP */
600 #define BSD_DTYPE_DEC 3 /* other DEC (rk, rl) */
601 #define BSD_DTYPE_SCSI 4 /* SCSI */
602 #define BSD_DTYPE_ESDI 5 /* ESDI interface */
603 #define BSD_DTYPE_ST506 6 /* ST506 etc. */
604 #define BSD_DTYPE_HPIB 7 /* CS/80 on HP-IB */
605 #define BSD_DTYPE_HPFL 8 /* HP Fiber-link */
606 #define BSD_DTYPE_FLOPPY 10 /* floppy */
608 /* d_subtype values: */
609 #define BSD_DSTYPE_INDOSPART 0x8 /* is inside dos partition */
610 #define BSD_DSTYPE_DOSPART(s) ((s) & 3) /* dos partition number */
611 #define BSD_DSTYPE_GEOMETRY 0x10 /* drive params in label */
614 static const char * const xbsd_dktypenames[] = {
628 #define BSD_DKMAXTYPES (sizeof(xbsd_dktypenames) / sizeof(xbsd_dktypenames[0]) - 1)
632 * Filesystem type and version.
633 * Used to interpret other filesystem-specific
634 * per-partition information.
636 #define BSD_FS_UNUSED 0 /* unused */
637 #define BSD_FS_SWAP 1 /* swap */
638 #define BSD_FS_V6 2 /* Sixth Edition */
639 #define BSD_FS_V7 3 /* Seventh Edition */
640 #define BSD_FS_SYSV 4 /* System V */
641 #define BSD_FS_V71K 5 /* V7 with 1K blocks (4.1, 2.9) */
642 #define BSD_FS_V8 6 /* Eighth Edition, 4K blocks */
643 #define BSD_FS_BSDFFS 7 /* 4.2BSD fast file system */
644 #define BSD_FS_BSDLFS 9 /* 4.4BSD log-structured file system */
645 #define BSD_FS_OTHER 10 /* in use, but unknown/unsupported */
646 #define BSD_FS_HPFS 11 /* OS/2 high-performance file system */
647 #define BSD_FS_ISO9660 12 /* ISO-9660 filesystem (cdrom) */
648 #define BSD_FS_ISOFS BSD_FS_ISO9660
649 #define BSD_FS_BOOT 13 /* partition contains bootstrap */
650 #define BSD_FS_ADOS 14 /* AmigaDOS fast file system */
651 #define BSD_FS_HFS 15 /* Macintosh HFS */
652 #define BSD_FS_ADVFS 16 /* Digital Unix AdvFS */
654 /* this is annoying, but it's also the way it is :-( */
656 #define BSD_FS_EXT2 8 /* ext2 file system */
658 #define BSD_FS_MSDOS 8 /* MS-DOS file system */
662 static const struct systypes xbsd_fstypes[] = {
663 /* BSD_FS_UNUSED */ {"\x00" "unused"},
664 /* BSD_FS_SWAP */ {"\x01" "swap"},
665 /* BSD_FS_V6 */ {"\x02" "Version 6"},
666 /* BSD_FS_V7 */ {"\x03" "Version 7"},
667 /* BSD_FS_SYSV */ {"\x04" "System V"},
668 /* BSD_FS_V71K */ {"\x05" "4.1BSD"},
669 /* BSD_FS_V8 */ {"\x06" "Eighth Edition"},
670 /* BSD_FS_BSDFFS */ {"\x07" "4.2BSD"},
672 /* BSD_FS_EXT2 */ {"\x08" "ext2"},
674 /* BSD_FS_MSDOS */ {"\x08" "MS-DOS"},
676 /* BSD_FS_BSDLFS */ {"\x09" "4.4LFS"},
677 /* BSD_FS_OTHER */ {"\x0a" "unknown"},
678 /* BSD_FS_HPFS */ {"\x0b" "HPFS"},
679 /* BSD_FS_ISO9660 */ {"\x0c" "ISO-9660"},
680 /* BSD_FS_BOOT */ {"\x0d" "boot"},
681 /* BSD_FS_ADOS */ {"\x0e" "ADOS"},
682 /* BSD_FS_HFS */ {"\x0f" "HFS"},
683 /* BSD_FS_ADVFS */ {"\x10" "AdvFS"},
686 #define BSD_FSMAXTYPES (SIZE(xbsd_fstypes)-1)
691 * flags shared by various drives:
693 #define BSD_D_REMOVABLE 0x01 /* removable media */
694 #define BSD_D_ECC 0x02 /* supports ECC */
695 #define BSD_D_BADSECT 0x04 /* supports bad sector forw. */
696 #define BSD_D_RAMDISK 0x08 /* disk emulator */
697 #define BSD_D_CHAIN 0x10 /* can do back-back transfers */
698 #define BSD_D_DOSPART 0x20 /* within MSDOS partition */
700 #endif /* OSF_LABEL */
703 * Copyright (C) Andreas Neuper, Sep 1998.
704 * This file may be modified and redistributed under
705 * the terms of the GNU Public License.
708 struct device_parameter { /* 48 bytes */
712 unsigned char sparecyl;
713 unsigned short pcylcount;
714 unsigned short head_vol0;
715 unsigned short ntrks; /* tracks in cyl 0 or vol 0 */
716 unsigned char cmd_tag_queue_depth;
717 unsigned char unused0;
718 unsigned short unused1;
719 unsigned short nsect; /* sectors/tracks in cyl 0 or vol 0 */
720 unsigned short bytes;
721 unsigned short ilfact;
722 unsigned int flags; /* controller flags */
723 unsigned int datarate;
724 unsigned int retries_on_error;
725 unsigned int ms_per_word;
726 unsigned short xylogics_gap1;
727 unsigned short xylogics_syncdelay;
728 unsigned short xylogics_readdelay;
729 unsigned short xylogics_gap2;
730 unsigned short xylogics_readgate;
731 unsigned short xylogics_writecont;
734 #define SGI_VOLHDR 0x00
735 /* 1 and 2 were used for drive types no longer supported by SGI */
736 #define SGI_SWAP 0x03
737 /* 4 and 5 were for filesystem types SGI haven't ever supported on MIPS CPUs */
738 #define SGI_VOLUME 0x06
740 #define SGI_LVOL 0x08
741 #define SGI_RLVOL 0x09
743 #define SGI_XFSLOG 0x0b
746 #define ENTIRE_DISK SGI_VOLUME
750 #define SECTOR_SLIP 0x01
751 #define SECTOR_FWD 0x02
752 #define TRACK_FWD 0x04
753 #define TRACK_MULTIVOL 0x08
754 #define IGNORE_ERRORS 0x10
756 #define ENABLE_CMDTAGQ 0x40
759 unsigned int magic; /* expect SGI_LABEL_MAGIC */
760 unsigned short boot_part; /* active boot partition */
761 unsigned short swap_part; /* active swap partition */
762 unsigned char boot_file[16]; /* name of the bootfile */
763 struct device_parameter devparam; /* 1 * 48 bytes */
764 struct volume_directory { /* 15 * 16 bytes */
765 unsigned char vol_file_name[8]; /* a character array */
766 unsigned int vol_file_start; /* number of logical block */
767 unsigned int vol_file_size; /* number of bytes */
769 struct sgi_partition { /* 16 * 12 bytes */
770 unsigned int num_sectors; /* number of blocks */
771 unsigned int start_sector; /* must be cylinder aligned */
775 unsigned int fillbytes;
779 unsigned int magic; /* looks like a magic number */
788 unsigned char scsi_string[50];
789 unsigned char serial[137];
790 unsigned short check1816;
791 unsigned char installer[225];
794 #define SGI_LABEL_MAGIC 0x0be5a941
795 #define SGI_LABEL_MAGIC_SWAPPED 0x41a9e50b
796 #define SGI_INFO_MAGIC 0x00072959
797 #define SGI_INFO_MAGIC_SWAPPED 0x59290700
798 #define SGI_SSWAP16(x) (sgi_other_endian ? __swap16(x) \
800 #define SGI_SSWAP32(x) (sgi_other_endian ? __swap32(x) \
803 #define sgilabel ((sgi_partition *)MBRbuffer)
804 #define sgiparam (sgilabel->devparam)
807 unsigned char info[128]; /* Informative text string */
808 unsigned char spare0[14];
810 unsigned char spare1;
812 unsigned char spare2;
815 unsigned char spare1[246]; /* Boot information etc. */
816 unsigned short rspeed; /* Disk rotational speed */
817 unsigned short pcylcount; /* Physical cylinder count */
818 unsigned short sparecyl; /* extra sects per cylinder */
819 unsigned char spare2[4]; /* More magic... */
820 unsigned short ilfact; /* Interleave factor */
821 unsigned short ncyl; /* Data cylinder count */
822 unsigned short nacyl; /* Alt. cylinder count */
823 unsigned short ntrks; /* Tracks per cylinder */
824 unsigned short nsect; /* Sectors per track */
825 unsigned char spare3[4]; /* Even more magic... */
826 struct sun_partition {
827 uint32_t start_cylinder;
828 uint32_t num_sectors;
830 unsigned short magic; /* Magic number */
831 unsigned short csum; /* Label xor'd checksum */
835 #define SUN_LABEL_MAGIC 0xDABE
836 #define SUN_LABEL_MAGIC_SWAPPED 0xBEDA
837 #define sunlabel ((sun_partition *)MBRbuffer)
838 #define SUN_SSWAP16(x) (sun_other_endian ? __swap16(x) \
840 #define SUN_SSWAP32(x) (sun_other_endian ? __swap32(x) \
843 #ifdef CONFIG_FEATURE_OSF_LABEL
846 19990319 - Arnaldo Carvalho de Melo <acme@conectiva.com.br> - i18n/nls
848 20000101 - David Huggins-Daines <dhuggins@linuxcare.com> - Better
849 support for OSF/1 disklabels on Alpha.
850 Also fixed unaligned accesses in alpha_bootblock_checksum()
853 #define FREEBSD_PARTITION 0xa5
854 #define NETBSD_PARTITION 0xa9
856 static void xbsd_delete_part (void);
857 static void xbsd_new_part (void);
858 static void xbsd_write_disklabel (void);
859 static int xbsd_create_disklabel (void);
860 static void xbsd_edit_disklabel (void);
861 static void xbsd_write_bootstrap (void);
862 static void xbsd_change_fstype (void);
863 static int xbsd_get_part_index (int max);
864 static int xbsd_check_new_partition (int *i);
865 static void xbsd_list_types (void);
866 static u_short xbsd_dkcksum (struct xbsd_disklabel *lp);
867 static int xbsd_initlabel (struct partition *p, struct xbsd_disklabel *d,
869 static int xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d);
870 static int xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d);
872 #if defined (__alpha__)
873 static void alpha_bootblock_checksum (char *boot);
876 #if !defined (__alpha__)
877 static int xbsd_translate_fstype (int linux_type);
878 static void xbsd_link_part (void);
879 static struct partition *xbsd_part;
880 static int xbsd_part_index;
883 #if defined (__alpha__)
884 /* We access this through a u_int64_t * when checksumming */
885 static char disklabelbuffer[BSD_BBSIZE] __attribute__((aligned(8)));
887 static char disklabelbuffer[BSD_BBSIZE];
890 static struct xbsd_disklabel xbsd_dlabel;
892 #define bsd_cround(n) \
893 (display_in_cyl_units ? ((n)/xbsd_dlabel.d_secpercyl) + 1 : (n))
896 * Test whether the whole disk has BSD disk label magic.
898 * Note: often reformatting with DOS-type label leaves the BSD magic,
899 * so this does not mean that there is a BSD disk label.
902 check_osf_label(void) {
903 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
908 static void xbsd_print_disklabel(int);
911 btrydev (const char * dev) {
912 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
914 printf(_("\nBSD label for device: %s\n"), dev);
915 xbsd_print_disklabel (0);
921 puts (_("Command action"));
922 puts (_("\td\tdelete a BSD partition"));
923 puts (_("\te\tedit drive data"));
924 puts (_("\ti\tinstall bootstrap"));
925 puts (_("\tl\tlist known filesystem types"));
926 puts (_("\tm\tprint this menu"));
927 puts (_("\tn\tadd a new BSD partition"));
928 puts (_("\tp\tprint BSD partition table"));
929 puts (_("\tq\tquit without saving changes"));
930 puts (_("\tr\treturn to main menu"));
931 puts (_("\ts\tshow complete disklabel"));
932 puts (_("\tt\tchange a partition's filesystem id"));
933 puts (_("\tu\tchange units (cylinders/sectors)"));
934 puts (_("\tw\twrite disklabel to disk"));
935 #if !defined (__alpha__)
936 puts (_("\tx\tlink BSD partition to non-BSD partition"));
940 #if !defined (__alpha__)
947 is_bsd_partition_type(int type) {
948 return (type == FREEBSD_PARTITION ||
949 type == hidden(FREEBSD_PARTITION) ||
950 type == NETBSD_PARTITION ||
951 type == hidden(NETBSD_PARTITION));
957 #if !defined (__alpha__)
961 for (t=0; t<4; t++) {
962 p = get_part_table(t);
963 if (p && is_bsd_partition_type(p->sys_ind)) {
966 ss = get_start_sect(xbsd_part);
968 fprintf (stderr, _("Partition %s has invalid starting sector 0.\n"),
969 partname(disk_device, t+1, 0));
972 printf (_("Reading disklabel of %s at sector %d.\n"),
973 partname(disk_device, t+1, 0), ss + BSD_LABELSECTOR);
974 if (xbsd_readlabel (xbsd_part, &xbsd_dlabel) == 0)
975 if (xbsd_create_disklabel () == 0)
982 printf (_("There is no *BSD partition on %s.\n"), disk_device);
986 #elif defined (__alpha__)
988 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
989 if (xbsd_create_disklabel () == 0)
990 exit ( EXIT_SUCCESS );
996 switch (tolower (read_char (_("BSD disklabel command (m for help): ")))) {
1001 xbsd_edit_disklabel ();
1004 xbsd_write_bootstrap ();
1013 xbsd_print_disklabel (0);
1017 exit ( EXIT_SUCCESS );
1021 xbsd_print_disklabel (1);
1024 xbsd_change_fstype ();
1030 xbsd_write_disklabel ();
1032 #if !defined (__alpha__)
1045 xbsd_delete_part (void)
1049 i = xbsd_get_part_index (xbsd_dlabel.d_npartitions);
1050 xbsd_dlabel.d_partitions[i].p_size = 0;
1051 xbsd_dlabel.d_partitions[i].p_offset = 0;
1052 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
1053 if (xbsd_dlabel.d_npartitions == i + 1)
1054 while (xbsd_dlabel.d_partitions[xbsd_dlabel.d_npartitions-1].p_size == 0)
1055 xbsd_dlabel.d_npartitions--;
1059 xbsd_new_part (void)
1065 if (!xbsd_check_new_partition (&i))
1068 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
1069 begin = get_start_sect(xbsd_part);
1070 end = begin + get_nr_sects(xbsd_part) - 1;
1073 end = xbsd_dlabel.d_secperunit - 1;
1076 snprintf (mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
1077 begin = read_int (bsd_cround (begin), bsd_cround (begin), bsd_cround (end),
1080 if (display_in_cyl_units)
1081 begin = (begin - 1) * xbsd_dlabel.d_secpercyl;
1083 snprintf (mesg, sizeof(mesg), _("Last %s or +size or +sizeM or +sizeK"),
1084 str_units(SINGULAR));
1085 end = read_int (bsd_cround (begin), bsd_cround (end), bsd_cround (end),
1086 bsd_cround (begin), mesg);
1088 if (display_in_cyl_units)
1089 end = end * xbsd_dlabel.d_secpercyl - 1;
1091 xbsd_dlabel.d_partitions[i].p_size = end - begin + 1;
1092 xbsd_dlabel.d_partitions[i].p_offset = begin;
1093 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
1097 xbsd_print_disklabel (int show_all) {
1098 struct xbsd_disklabel *lp = &xbsd_dlabel;
1099 struct xbsd_partition *pp;
1103 #if defined (__alpha__)
1104 printf("# %s:\n", disk_device);
1106 printf("# %s:\n", partname(disk_device, xbsd_part_index+1, 0));
1108 if ((unsigned) lp->d_type < BSD_DKMAXTYPES)
1109 printf(_("type: %s\n"), xbsd_dktypenames[lp->d_type]);
1111 printf(_("type: %d\n"), lp->d_type);
1112 printf(_("disk: %.*s\n"), (int) sizeof(lp->d_typename), lp->d_typename);
1113 printf(_("label: %.*s\n"), (int) sizeof(lp->d_packname), lp->d_packname);
1114 printf(_("flags:"));
1115 if (lp->d_flags & BSD_D_REMOVABLE)
1116 printf(_(" removable"));
1117 if (lp->d_flags & BSD_D_ECC)
1119 if (lp->d_flags & BSD_D_BADSECT)
1120 printf(_(" badsect"));
1122 /* On various machines the fields of *lp are short/int/long */
1123 /* In order to avoid problems, we cast them all to long. */
1124 printf(_("bytes/sector: %ld\n"), (long) lp->d_secsize);
1125 printf(_("sectors/track: %ld\n"), (long) lp->d_nsectors);
1126 printf(_("tracks/cylinder: %ld\n"), (long) lp->d_ntracks);
1127 printf(_("sectors/cylinder: %ld\n"), (long) lp->d_secpercyl);
1128 printf(_("cylinders: %ld\n"), (long) lp->d_ncylinders);
1129 printf(_("rpm: %d\n"), lp->d_rpm);
1130 printf(_("interleave: %d\n"), lp->d_interleave);
1131 printf(_("trackskew: %d\n"), lp->d_trackskew);
1132 printf(_("cylinderskew: %d\n"), lp->d_cylskew);
1133 printf(_("headswitch: %ld\t\t# milliseconds\n"),
1134 (long) lp->d_headswitch);
1135 printf(_("track-to-track seek: %ld\t# milliseconds\n"),
1136 (long) lp->d_trkseek);
1137 printf(_("drivedata: "));
1138 for (i = NDDATA - 1; i >= 0; i--)
1139 if (lp->d_drivedata[i])
1143 for (j = 0; j <= i; j++)
1144 printf("%ld ", (long) lp->d_drivedata[j]);
1146 printf(_("\n%d partitions:\n"), lp->d_npartitions);
1147 printf(_("# start end size fstype [fsize bsize cpg]\n"));
1148 pp = lp->d_partitions;
1149 for (i = 0; i < lp->d_npartitions; i++, pp++) {
1151 if (display_in_cyl_units && lp->d_secpercyl) {
1152 printf(" %c: %8ld%c %8ld%c %8ld%c ",
1154 (long) pp->p_offset / lp->d_secpercyl + 1,
1155 (pp->p_offset % lp->d_secpercyl) ? '*' : ' ',
1156 (long) (pp->p_offset + pp->p_size + lp->d_secpercyl - 1)
1158 ((pp->p_offset + pp->p_size) % lp->d_secpercyl) ? '*' : ' ',
1159 (long) pp->p_size / lp->d_secpercyl,
1160 (pp->p_size % lp->d_secpercyl) ? '*' : ' ');
1162 printf(" %c: %8ld %8ld %8ld ",
1164 (long) pp->p_offset,
1165 (long) pp->p_offset + pp->p_size - 1,
1168 if ((unsigned) pp->p_fstype < BSD_FSMAXTYPES)
1169 printf("%8.8s", xbsd_fstypes[pp->p_fstype].name);
1171 printf("%8x", pp->p_fstype);
1172 switch (pp->p_fstype) {
1174 printf(" %5ld %5ld %5.5s ",
1175 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, "");
1179 printf(" %5ld %5ld %5d ",
1180 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag,
1185 printf("%22.22s", "");
1194 xbsd_write_disklabel (void) {
1195 #if defined (__alpha__)
1196 printf (_("Writing disklabel to %s.\n"), disk_device);
1197 xbsd_writelabel (NULL, &xbsd_dlabel);
1199 printf (_("Writing disklabel to %s.\n"),
1200 partname(disk_device, xbsd_part_index+1, 0));
1201 xbsd_writelabel (xbsd_part, &xbsd_dlabel);
1203 reread_partition_table(0); /* no exit yet */
1207 xbsd_create_disklabel (void) {
1210 #if defined (__alpha__)
1211 fprintf (stderr, _("%s contains no disklabel.\n"), disk_device);
1213 fprintf (stderr, _("%s contains no disklabel.\n"),
1214 partname(disk_device, xbsd_part_index+1, 0));
1218 c = read_char (_("Do you want to create a disklabel? (y/n) "));
1219 if (c == 'y' || c == 'Y') {
1220 if (xbsd_initlabel (
1221 #if defined (__alpha__) || defined (__powerpc__) || defined (__hppa__) || \
1222 defined (__s390__) || defined (__s390x__)
1223 NULL, &xbsd_dlabel, 0
1225 xbsd_part, &xbsd_dlabel, xbsd_part_index
1228 xbsd_print_disklabel (1);
1232 } else if (c == 'n')
1238 edit_int (int def, char *mesg)
1241 fputs (mesg, stdout);
1242 printf (" (%d): ", def);
1246 while (!isdigit (*line_ptr));
1247 return atoi (line_ptr);
1251 xbsd_edit_disklabel (void)
1253 struct xbsd_disklabel *d;
1257 #if defined (__alpha__) || defined (__ia64__)
1258 d -> d_secsize = (u_long) edit_int ((u_long) d -> d_secsize ,_("bytes/sector"));
1259 d -> d_nsectors = (u_long) edit_int ((u_long) d -> d_nsectors ,_("sectors/track"));
1260 d -> d_ntracks = (u_long) edit_int ((u_long) d -> d_ntracks ,_("tracks/cylinder"));
1261 d -> d_ncylinders = (u_long) edit_int ((u_long) d -> d_ncylinders ,_("cylinders"));
1264 /* d -> d_secpercyl can be != d -> d_nsectors * d -> d_ntracks */
1267 d -> d_secpercyl = (u_long) edit_int ((u_long) d -> d_nsectors * d -> d_ntracks,
1268 _("sectors/cylinder"));
1269 if (d -> d_secpercyl <= d -> d_nsectors * d -> d_ntracks)
1272 printf (_("Must be <= sectors/track * tracks/cylinder (default).\n"));
1274 d -> d_rpm = (u_short) edit_int ((u_short) d -> d_rpm ,_("rpm"));
1275 d -> d_interleave = (u_short) edit_int ((u_short) d -> d_interleave,_("interleave"));
1276 d -> d_trackskew = (u_short) edit_int ((u_short) d -> d_trackskew ,_("trackskew"));
1277 d -> d_cylskew = (u_short) edit_int ((u_short) d -> d_cylskew ,_("cylinderskew"));
1278 d -> d_headswitch = (u_long) edit_int ((u_long) d -> d_headswitch ,_("headswitch"));
1279 d -> d_trkseek = (u_long) edit_int ((u_long) d -> d_trkseek ,_("track-to-track seek"));
1281 d -> d_secperunit = d -> d_secpercyl * d -> d_ncylinders;
1285 xbsd_get_bootstrap (char *path, void *ptr, int size)
1289 if ((fdb = open (path, O_RDONLY)) < 0)
1294 if (read (fdb, ptr, size) < 0)
1300 printf (" ... %s\n", path);
1308 printf (_("\nSyncing disks.\n"));
1314 xbsd_write_bootstrap (void)
1316 char *bootdir = BSD_LINUX_BOOTDIR;
1317 char path[MAXPATHLEN];
1319 struct xbsd_disklabel dl;
1323 if (xbsd_dlabel.d_type == BSD_DTYPE_SCSI)
1328 printf (_("Bootstrap: %sboot -> boot%s (%s): "),
1329 dkbasename, dkbasename, dkbasename);
1331 line_ptr[strlen (line_ptr)-1] = '\0';
1332 dkbasename = line_ptr;
1334 snprintf (path, sizeof(path), "%s/%sboot", bootdir, dkbasename);
1335 if (!xbsd_get_bootstrap (path, disklabelbuffer, (int) xbsd_dlabel.d_secsize))
1338 /* We need a backup of the disklabel (xbsd_dlabel might have changed). */
1339 d = &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE];
1340 bcopy (d, &dl, sizeof (struct xbsd_disklabel));
1342 /* The disklabel will be overwritten by 0's from bootxx anyway */
1343 bzero (d, sizeof (struct xbsd_disklabel));
1345 snprintf (path, sizeof(path), "%s/boot%s", bootdir, dkbasename);
1346 if (!xbsd_get_bootstrap (path, &disklabelbuffer[xbsd_dlabel.d_secsize],
1347 (int) xbsd_dlabel.d_bbsize - xbsd_dlabel.d_secsize))
1350 e = d + sizeof (struct xbsd_disklabel);
1351 for (p=d; p < e; p++)
1353 fprintf (stderr, _("Bootstrap overlaps with disk label!\n"));
1354 exit ( EXIT_FAILURE );
1357 bcopy (&dl, d, sizeof (struct xbsd_disklabel));
1359 #if defined (__powerpc__) || defined (__hppa__)
1361 #elif defined (__alpha__)
1363 alpha_bootblock_checksum (disklabelbuffer);
1365 sector = get_start_sect(xbsd_part);
1368 if (lseek (fd, (ext2_loff_t) sector * SECTOR_SIZE, SEEK_SET) == -1)
1369 fdisk_fatal (unable_to_seek);
1370 if (BSD_BBSIZE != write (fd, disklabelbuffer, BSD_BBSIZE))
1371 fdisk_fatal (unable_to_write);
1373 #if defined (__alpha__)
1374 printf (_("Bootstrap installed on %s.\n"), disk_device);
1376 printf (_("Bootstrap installed on %s.\n"),
1377 partname (disk_device, xbsd_part_index+1, 0));
1384 xbsd_change_fstype (void)
1388 i = xbsd_get_part_index (xbsd_dlabel.d_npartitions);
1389 xbsd_dlabel.d_partitions[i].p_fstype = read_hex (xbsd_fstypes);
1393 xbsd_get_part_index (int max)
1398 snprintf (prompt, sizeof(prompt), _("Partition (a-%c): "), 'a' + max - 1);
1400 l = tolower (read_char (prompt));
1401 while (l < 'a' || l > 'a' + max - 1);
1406 xbsd_check_new_partition (int *i) {
1408 /* room for more? various BSD flavours have different maxima */
1409 if (xbsd_dlabel.d_npartitions == BSD_MAXPARTITIONS) {
1412 for (t = 0; t < BSD_MAXPARTITIONS; t++)
1413 if (xbsd_dlabel.d_partitions[t].p_size == 0)
1416 if (t == BSD_MAXPARTITIONS) {
1417 fprintf (stderr, _("The maximum number of partitions "
1418 "has been created\n"));
1423 *i = xbsd_get_part_index (BSD_MAXPARTITIONS);
1425 if (*i >= xbsd_dlabel.d_npartitions)
1426 xbsd_dlabel.d_npartitions = (*i) + 1;
1428 if (xbsd_dlabel.d_partitions[*i].p_size != 0) {
1429 fprintf (stderr, _("This partition already exists.\n"));
1437 xbsd_list_types (void) {
1438 list_types (xbsd_fstypes);
1442 xbsd_dkcksum (struct xbsd_disklabel *lp) {
1443 u_short *start, *end;
1446 start = (u_short *) lp;
1447 end = (u_short *) &lp->d_partitions[lp->d_npartitions];
1454 xbsd_initlabel (struct partition *p, struct xbsd_disklabel *d, int pindex) {
1455 struct xbsd_partition *pp;
1458 bzero (d, sizeof (struct xbsd_disklabel));
1460 d -> d_magic = BSD_DISKMAGIC;
1462 if (strncmp (disk_device, "/dev/sd", 7) == 0)
1463 d -> d_type = BSD_DTYPE_SCSI;
1465 d -> d_type = BSD_DTYPE_ST506;
1467 #if 0 /* not used (at least not written to disk) by NetBSD/i386 1.0 */
1468 d -> d_subtype = BSD_DSTYPE_INDOSPART & pindex;
1471 #if !defined (__alpha__)
1472 d -> d_flags = BSD_D_DOSPART;
1476 d -> d_secsize = SECTOR_SIZE; /* bytes/sector */
1477 d -> d_nsectors = sectors; /* sectors/track */
1478 d -> d_ntracks = heads; /* tracks/cylinder (heads) */
1479 d -> d_ncylinders = cylinders;
1480 d -> d_secpercyl = sectors * heads;/* sectors/cylinder */
1481 if (d -> d_secpercyl == 0)
1482 d -> d_secpercyl = 1; /* avoid segfaults */
1483 d -> d_secperunit = d -> d_secpercyl * d -> d_ncylinders;
1486 d -> d_interleave = 1;
1487 d -> d_trackskew = 0;
1489 d -> d_headswitch = 0;
1492 d -> d_magic2 = BSD_DISKMAGIC;
1493 d -> d_bbsize = BSD_BBSIZE;
1494 d -> d_sbsize = BSD_SBSIZE;
1496 #if !defined (__alpha__)
1497 d -> d_npartitions = 4;
1498 pp = &d -> d_partitions[2]; /* Partition C should be
1499 the NetBSD partition */
1500 pp -> p_offset = get_start_sect(p);
1501 pp -> p_size = get_nr_sects(p);
1502 pp -> p_fstype = BSD_FS_UNUSED;
1503 pp = &d -> d_partitions[3]; /* Partition D should be
1506 pp -> p_size = d -> d_secperunit;
1507 pp -> p_fstype = BSD_FS_UNUSED;
1508 #elif defined (__alpha__)
1509 d -> d_npartitions = 3;
1510 pp = &d -> d_partitions[2]; /* Partition C should be
1513 pp -> p_size = d -> d_secperunit;
1514 pp -> p_fstype = BSD_FS_UNUSED;
1521 * Read a xbsd_disklabel from sector 0 or from the starting sector of p.
1522 * If it has the right magic, return 1.
1525 xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d)
1529 /* p is used only to get the starting sector */
1530 #if !defined (__alpha__)
1531 sector = (p ? get_start_sect(p) : 0);
1532 #elif defined (__alpha__)
1536 if (lseek (fd, (ext2_loff_t) sector * SECTOR_SIZE, SEEK_SET) == -1)
1537 fdisk_fatal (unable_to_seek);
1538 if (BSD_BBSIZE != read (fd, disklabelbuffer, BSD_BBSIZE))
1539 fdisk_fatal (unable_to_read);
1541 bcopy (&disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
1542 d, sizeof (struct xbsd_disklabel));
1544 if (d -> d_magic != BSD_DISKMAGIC || d -> d_magic2 != BSD_DISKMAGIC)
1547 for (t = d -> d_npartitions; t < BSD_MAXPARTITIONS; t++) {
1548 d -> d_partitions[t].p_size = 0;
1549 d -> d_partitions[t].p_offset = 0;
1550 d -> d_partitions[t].p_fstype = BSD_FS_UNUSED;
1553 if (d -> d_npartitions > BSD_MAXPARTITIONS)
1554 fprintf (stderr, _("Warning: too many partitions "
1555 "(%d, maximum is %d).\n"),
1556 d -> d_npartitions, BSD_MAXPARTITIONS);
1561 xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d)
1563 unsigned int sector;
1565 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
1566 sector = get_start_sect(p) + BSD_LABELSECTOR;
1568 sector = BSD_LABELSECTOR;
1571 d -> d_checksum = 0;
1572 d -> d_checksum = xbsd_dkcksum (d);
1574 /* This is necessary if we want to write the bootstrap later,
1575 otherwise we'd write the old disklabel with the bootstrap.
1577 bcopy (d, &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
1578 sizeof (struct xbsd_disklabel));
1580 #if defined (__alpha__) && BSD_LABELSECTOR == 0
1581 alpha_bootblock_checksum (disklabelbuffer);
1582 if (lseek (fd, (ext2_loff_t) 0, SEEK_SET) == -1)
1583 fdisk_fatal (unable_to_seek);
1584 if (BSD_BBSIZE != write (fd, disklabelbuffer, BSD_BBSIZE))
1585 fdisk_fatal (unable_to_write);
1587 if (lseek (fd, (ext2_loff_t) sector * SECTOR_SIZE + BSD_LABELOFFSET,
1589 fdisk_fatal (unable_to_seek);
1590 if (sizeof (struct xbsd_disklabel) != write (fd, d, sizeof (struct xbsd_disklabel)))
1591 fdisk_fatal (unable_to_write);
1600 #if !defined (__alpha__)
1602 xbsd_translate_fstype (int linux_type)
1606 case 0x01: /* DOS 12-bit FAT */
1607 case 0x04: /* DOS 16-bit <32M */
1608 case 0x06: /* DOS 16-bit >=32M */
1609 case 0xe1: /* DOS access */
1610 case 0xe3: /* DOS R/O */
1611 case 0xf2: /* DOS secondary */
1612 return BSD_FS_MSDOS;
1613 case 0x07: /* OS/2 HPFS */
1616 return BSD_FS_OTHER;
1621 xbsd_link_part (void)
1624 struct partition *p;
1626 k = get_partition (1, partitions);
1628 if (!xbsd_check_new_partition (&i))
1631 p = get_part_table(k);
1633 xbsd_dlabel.d_partitions[i].p_size = get_nr_sects(p);
1634 xbsd_dlabel.d_partitions[i].p_offset = get_start_sect(p);
1635 xbsd_dlabel.d_partitions[i].p_fstype = xbsd_translate_fstype(p->sys_ind);
1639 #if defined (__alpha__)
1641 #if !defined(__GLIBC__)
1642 typedef unsigned long long u_int64_t;
1646 alpha_bootblock_checksum (char *boot)
1651 dp = (u_int64_t *)boot;
1653 for (i = 0; i < 63; i++)
1657 #endif /* __alpha__ */
1659 #endif /* OSF_LABEL */
1661 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
1662 static inline unsigned short
1663 __swap16(unsigned short x) {
1664 return (((uint16_t)(x) & 0xFF) << 8) | (((uint16_t)(x) & 0xFF00) >> 8);
1667 static inline uint32_t
1668 __swap32(uint32_t x) {
1669 return (((x & 0xFF) << 24) |
1670 ((x & 0xFF00) << 8) |
1671 ((x & 0xFF0000) >> 8) |
1672 ((x & 0xFF000000) >> 24));
1676 #ifdef CONFIG_FEATURE_SGI_LABEL
1681 * Copyright (C) Andreas Neuper, Sep 1998.
1682 * This file may be modified and redistributed under
1683 * the terms of the GNU Public License.
1685 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
1686 * Internationalization
1690 static int sgi_other_endian;
1692 static short sgi_volumes=1;
1695 * only dealing with free blocks here
1698 typedef struct { unsigned int first; unsigned int last; } freeblocks;
1699 static freeblocks freelist[17]; /* 16 partitions can produce 17 vacant slots */
1702 setfreelist(int i, unsigned int f, unsigned int l) {
1703 freelist[i].first = f;
1704 freelist[i].last = l;
1708 add2freelist(unsigned int f, unsigned int l) {
1710 for ( ; i < 17 ; i++)
1711 if (freelist[i].last == 0)
1713 setfreelist(i, f, l);
1717 clearfreelist(void) {
1720 for (i = 0; i < 17 ; i++)
1721 setfreelist(i, 0, 0);
1725 isinfreelist(unsigned int b) {
1728 for (i = 0; i < 17 ; i++)
1729 if (freelist[i].first <= b && freelist[i].last >= b)
1730 return freelist[i].last;
1733 /* return last vacant block of this stride (never 0). */
1734 /* the '>=' is not quite correct, but simplifies the code */
1736 * end of free blocks section
1739 static const struct systypes sgi_sys_types[] = {
1740 /* SGI_VOLHDR */ {"\x00" "SGI volhdr" },
1741 /* 0x01 */ {"\x01" "SGI trkrepl" },
1742 /* 0x02 */ {"\x02" "SGI secrepl" },
1743 /* SGI_SWAP */ {"\x03" "SGI raw" },
1744 /* 0x04 */ {"\x04" "SGI bsd" },
1745 /* 0x05 */ {"\x05" "SGI sysv" },
1746 /* ENTIRE_DISK */ {"\x06" "SGI volume" },
1747 /* SGI_EFS */ {"\x07" "SGI efs" },
1748 /* 0x08 */ {"\x08" "SGI lvol" },
1749 /* 0x09 */ {"\x09" "SGI rlvol" },
1750 /* SGI_XFS */ {"\x0a" "SGI xfs" },
1751 /* SGI_XFSLOG */ {"\x0b" "SGI xfslog" },
1752 /* SGI_XLV */ {"\x0c" "SGI xlv" },
1753 /* SGI_XVM */ {"\x0d" "SGI xvm" },
1754 /* LINUX_SWAP */ {"\x82" "Linux swap" },
1755 /* LINUX_NATIVE */ {"\x83" "Linux native" },
1756 /* LINUX_LVM */ {"\x8d" "Linux LVM" },
1757 /* LINUX_RAID */ {"\xfd" "Linux RAID" },
1763 sgi_get_nsect(void) {
1764 return SGI_SSWAP16(sgilabel->devparam.nsect);
1768 sgi_get_ntrks(void) {
1769 return SGI_SSWAP16(sgilabel->devparam.ntrks);
1774 sgilabel->magic = 0;
1780 two_s_complement_32bit_sum(unsigned int* base, int size /* in bytes */) {
1784 size /= sizeof(unsigned int);
1785 for (i = 0; i < size; i++)
1786 sum -= SGI_SSWAP32(base[i]);
1791 check_sgi_label(void) {
1792 if (sizeof(sgilabel) > 512) {
1794 _("According to MIPS Computer Systems, Inc the "
1795 "Label must not contain more than 512 bytes\n"));
1799 if (sgilabel->magic != SGI_LABEL_MAGIC &&
1800 sgilabel->magic != SGI_LABEL_MAGIC_SWAPPED) {
1802 sgi_other_endian = 0;
1806 sgi_other_endian = (sgilabel->magic == SGI_LABEL_MAGIC_SWAPPED);
1808 * test for correct checksum
1810 if (two_s_complement_32bit_sum((unsigned int*)sgilabel,
1811 sizeof(*sgilabel))) {
1813 _("Detected sgi disklabel with wrong checksum.\n"));
1823 sgi_get_start_sector(int i) {
1824 return SGI_SSWAP32(sgilabel->partitions[i].start_sector);
1828 sgi_get_num_sectors(int i) {
1829 return SGI_SSWAP32(sgilabel->partitions[i].num_sectors);
1833 sgi_get_sysid(int i)
1835 return SGI_SSWAP32(sgilabel->partitions[i].id);
1839 sgi_get_bootpartition(void)
1841 return SGI_SSWAP16(sgilabel->boot_part);
1845 sgi_get_swappartition(void)
1847 return SGI_SSWAP16(sgilabel->swap_part);
1851 sgi_list_table(int xtra) {
1853 int kpi = 0; /* kernel partition ID */
1855 w = strlen(disk_device);
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 );
1876 printf(_("----- partitions -----\n"
1877 "Pt# %*s Info Start End Sectors Id System\n"),
1878 w + 1, _("Device"));
1879 for (i = 0 ; i < partitions; i++) {
1880 if( sgi_get_num_sectors(i) || debug ) {
1881 uint32_t start = sgi_get_start_sector(i);
1882 uint32_t len = sgi_get_num_sectors(i);
1883 kpi++; /* only count nonempty partitions */
1885 "%2d: %s %4s %9ld %9ld %9ld %2x %s\n",
1886 /* fdisk part number */ i+1,
1887 /* device */ partname(disk_device, kpi, w+2),
1888 /* flags */ (sgi_get_swappartition() == i) ? "swap" :
1889 /* flags */ (sgi_get_bootpartition() == i) ? "boot" : " ",
1890 /* start */ (long) scround(start),
1891 /* end */ (long) scround(start+len)-1,
1892 /* no odd flag on end */ (long) len,
1893 /* type id */ sgi_get_sysid(i),
1894 /* type name */ partition_type(sgi_get_sysid(i)));
1897 printf(_("----- Bootinfo -----\nBootfile: %s\n"
1898 "----- Directory Entries -----\n"),
1899 sgilabel->boot_file);
1900 for (i = 0 ; i < sgi_volumes; i++) {
1901 if (sgilabel->directory[i].vol_file_size) {
1902 uint32_t start = SGI_SSWAP32(sgilabel->directory[i].vol_file_start);
1903 uint32_t len = SGI_SSWAP32(sgilabel->directory[i].vol_file_size);
1904 char*name = sgilabel->directory[i].vol_file_name;
1906 printf(_("%2d: %-10s sector%5u size%8u\n"),
1907 i, name, (unsigned int) start, (unsigned int) len);
1913 sgi_set_bootpartition( int i )
1915 sgilabel->boot_part = SGI_SSWAP16(((short)i));
1919 sgi_get_lastblock(void) {
1920 return heads * sectors * cylinders;
1924 sgi_set_swappartition( int i ) {
1925 sgilabel->swap_part = SGI_SSWAP16(((short)i));
1929 sgi_check_bootfile(const char* aFile) {
1931 if (strlen(aFile) < 3) /* "/a\n" is minimum */ {
1932 printf(_("\nInvalid Bootfile!\n"
1933 "\tThe bootfile must be an absolute non-zero pathname,\n"
1934 "\te.g. \"/unix\" or \"/unix.save\".\n"));
1937 if (strlen(aFile) > 16) {
1938 printf(_("\n\tName of Bootfile too long: "
1939 "16 bytes maximum.\n"));
1942 if (aFile[0] != '/') {
1943 printf(_("\n\tBootfile must have a "
1944 "fully qualified pathname.\n"));
1949 if (strncmp(aFile, sgilabel->boot_file, 16)) {
1950 printf(_("\n\tBe aware, that the bootfile is not checked for existence.\n\t"
1951 "SGI's default is \"/unix\" and for backup \"/unix.save\".\n"));
1952 /* filename is correct and did change */
1955 return 0; /* filename did not change */
1959 sgi_get_bootfile(void) {
1960 return sgilabel->boot_file;
1964 sgi_set_bootfile(const char* aFile) {
1967 if (sgi_check_bootfile(aFile)) {
1969 if ((aFile[i] != '\n') /* in principle caught again by next line */
1970 && (strlen(aFile) > i))
1971 sgilabel->boot_file[i] = aFile[i];
1973 sgilabel->boot_file[i] = 0;
1976 printf(_("\n\tBootfile is changed to \"%s\".\n"), sgilabel->boot_file);
1981 create_sgiinfo(void)
1983 /* I keep SGI's habit to write the sgilabel to the second block */
1984 sgilabel->directory[0].vol_file_start = SGI_SSWAP32(2);
1985 sgilabel->directory[0].vol_file_size = SGI_SSWAP32(sizeof(sgiinfo));
1986 strncpy(sgilabel->directory[0].vol_file_name, "sgilabel", 8);
1989 static sgiinfo *fill_sgiinfo(void);
1992 sgi_write_table(void) {
1994 sgilabel->csum = SGI_SSWAP32(two_s_complement_32bit_sum(
1995 (unsigned int*)sgilabel,
1996 sizeof(*sgilabel)));
1997 assert(two_s_complement_32bit_sum(
1998 (unsigned int*)sgilabel, sizeof(*sgilabel)) == 0);
1999 if (lseek(fd, 0, SEEK_SET) < 0)
2000 fdisk_fatal(unable_to_seek);
2001 if (write(fd, sgilabel, SECTOR_SIZE) != SECTOR_SIZE)
2002 fdisk_fatal(unable_to_write);
2003 if (! strncmp(sgilabel->directory[0].vol_file_name, "sgilabel", 8)) {
2005 * keep this habit of first writing the "sgilabel".
2006 * I never tested whether it works without (AN 981002).
2008 sgiinfo *info = fill_sgiinfo();
2009 int infostartblock = SGI_SSWAP32(sgilabel->directory[0].vol_file_start);
2010 if (lseek(fd, (long long)infostartblock*
2011 SECTOR_SIZE, SEEK_SET) < 0)
2012 fdisk_fatal(unable_to_seek);
2013 if (write(fd, info, SECTOR_SIZE) != SECTOR_SIZE)
2014 fdisk_fatal(unable_to_write);
2020 compare_start(int *x, int *y) {
2022 * sort according to start sectors
2023 * and prefers largest partition:
2024 * entry zero is entire disk entry
2026 unsigned int i = *x;
2027 unsigned int j = *y;
2028 unsigned int a = sgi_get_start_sector(i);
2029 unsigned int b = sgi_get_start_sector(j);
2030 unsigned int c = sgi_get_num_sectors(i);
2031 unsigned int d = sgi_get_num_sectors(j);
2034 return (d > c) ? 1 : (d == c) ? 0 : -1;
2035 return (a > b) ? 1 : -1;
2040 verify_sgi(int verbose)
2042 int Index[16]; /* list of valid partitions */
2043 int sortcount = 0; /* number of used partitions, i.e. non-zero lengths */
2044 int entire = 0, i = 0;
2045 unsigned int start = 0;
2046 long long gap = 0; /* count unused blocks */
2047 unsigned int lastblock = sgi_get_lastblock();
2050 for (i=0; i<16; i++) {
2051 if (sgi_get_num_sectors(i) != 0) {
2052 Index[sortcount++]=i;
2053 if (sgi_get_sysid(i) == ENTIRE_DISK) {
2054 if (entire++ == 1) {
2056 printf(_("More than one entire disk entry present.\n"));
2061 if (sortcount == 0) {
2063 printf(_("No partitions defined\n"));
2064 return (lastblock > 0) ? 1 : (lastblock == 0) ? 0 : -1;
2066 qsort(Index, sortcount, sizeof(Index[0]), (void*)compare_start);
2067 if (sgi_get_sysid(Index[0]) == ENTIRE_DISK) {
2068 if ((Index[0] != 10) && verbose)
2069 printf(_("IRIX likes when Partition 11 covers the entire disk.\n"));
2070 if ((sgi_get_start_sector(Index[0]) != 0) && verbose)
2071 printf(_("The entire disk partition should start "
2073 "not at diskblock %d.\n"),
2074 sgi_get_start_sector(Index[0]));
2075 if (debug) /* I do not understand how some disks fulfil it */
2076 if ((sgi_get_num_sectors(Index[0]) != lastblock) && verbose)
2077 printf(_("The entire disk partition is only %d diskblock large,\n"
2078 "but the disk is %d diskblocks long.\n"),
2079 sgi_get_num_sectors(Index[0]), lastblock);
2080 lastblock = sgi_get_num_sectors(Index[0]);
2083 printf(_("One Partition (#11) should cover the entire disk.\n"));
2085 printf("sysid=%d\tpartition=%d\n",
2086 sgi_get_sysid(Index[0]), Index[0]+1);
2088 for (i=1, start=0; i<sortcount; i++) {
2089 int cylsize = sgi_get_nsect() * sgi_get_ntrks();
2091 if ((sgi_get_start_sector(Index[i]) % cylsize) != 0) {
2092 if (debug) /* I do not understand how some disks fulfil it */
2094 printf(_("Partition %d does not start on cylinder boundary.\n"),
2097 if (sgi_get_num_sectors(Index[i]) % cylsize != 0) {
2098 if (debug) /* I do not understand how some disks fulfil it */
2100 printf(_("Partition %d does not end on cylinder boundary.\n"),
2103 /* We cannot handle several "entire disk" entries. */
2104 if (sgi_get_sysid(Index[i]) == ENTIRE_DISK) continue;
2105 if (start > sgi_get_start_sector(Index[i])) {
2107 printf(_("The Partition %d and %d overlap by %d sectors.\n"),
2108 Index[i-1]+1, Index[i]+1,
2109 start - sgi_get_start_sector(Index[i]));
2110 if (gap > 0) gap = -gap;
2111 if (gap == 0) gap = -1;
2113 if (start < sgi_get_start_sector(Index[i])) {
2115 printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"),
2116 sgi_get_start_sector(Index[i]) - start,
2117 start, sgi_get_start_sector(Index[i])-1);
2118 gap += sgi_get_start_sector(Index[i]) - start;
2119 add2freelist(start, sgi_get_start_sector(Index[i]));
2121 start = sgi_get_start_sector(Index[i])
2122 + sgi_get_num_sectors(Index[i]);
2125 printf("%2d:%12d\t%12d\t%12d\n", Index[i],
2126 sgi_get_start_sector(Index[i]),
2127 sgi_get_num_sectors(Index[i]),
2128 sgi_get_sysid(Index[i]));
2131 if (start < lastblock) {
2133 printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"),
2134 lastblock - start, start, lastblock-1);
2135 gap += lastblock - start;
2136 add2freelist(start, lastblock);
2139 * Done with arithmetics
2140 * Go for details now
2143 if (!sgi_get_num_sectors(sgi_get_bootpartition())) {
2144 printf(_("\nThe boot partition does not exist.\n"));
2146 if (!sgi_get_num_sectors(sgi_get_swappartition())) {
2147 printf(_("\nThe swap partition does not exist.\n"));
2149 if ((sgi_get_sysid(sgi_get_swappartition()) != SGI_SWAP)
2150 && (sgi_get_sysid(sgi_get_swappartition()) != LINUX_SWAP))
2151 printf(_("\nThe swap partition has no swap type.\n"));
2153 if (sgi_check_bootfile("/unix"))
2154 printf(_("\tYou have chosen an unusual boot file name.\n"));
2156 return (gap > 0) ? 1 : (gap == 0) ? 0 : -1;
2162 * returned value is:
2163 * = 0 : disk is properly filled to the rim
2164 * < 0 : there is an overlap
2165 * > 0 : there is still some vacant space
2167 return verify_sgi(0);
2171 sgi_change_sysid( int i, int sys )
2173 if( sgi_get_num_sectors(i) == 0 ) /* caught already before, ... */
2175 printf(_("Sorry You may change the Tag of non-empty partitions.\n"));
2178 if( ((sys != ENTIRE_DISK ) && (sys != SGI_VOLHDR))
2179 && (sgi_get_start_sector(i)<1) )
2182 _("It is highly recommended that the partition at offset 0\n"
2183 "is of type \"SGI volhdr\", the IRIX system will rely on it to\n"
2184 "retrieve from its directory standalone tools like sash and fx.\n"
2185 "Only the \"SGI volume\" entire disk section may violate this.\n"
2186 "Type YES if you are sure about tagging this partition differently.\n"));
2187 if (strcmp (line_ptr, _("YES\n")))
2190 sgilabel->partitions[i].id = SGI_SSWAP32(sys);
2193 /* returns partition index of first entry marked as entire disk */
2199 if(sgi_get_sysid(i) == SGI_VOLUME)
2205 sgi_set_partition(int i, unsigned int start, unsigned int length, int sys) {
2207 sgilabel->partitions[i].id = SGI_SSWAP32(sys);
2208 sgilabel->partitions[i].num_sectors = SGI_SSWAP32(length);
2209 sgilabel->partitions[i].start_sector = SGI_SSWAP32(start);
2211 if (sgi_gaps() < 0) /* rebuild freelist */
2212 printf(_("Do You know, You got a partition overlap on the disk?\n"));
2216 sgi_set_entire(void) {
2219 for(n=10; n < partitions; n++) {
2220 if(!sgi_get_num_sectors(n) ) {
2221 sgi_set_partition(n, 0, sgi_get_lastblock(), SGI_VOLUME);
2228 sgi_set_volhdr(void)
2231 for( n=8; n<partitions; n++ )
2233 if(!sgi_get_num_sectors( n ) )
2236 * 5 cylinders is an arbitrary value I like
2237 * IRIX 5.3 stored files in the volume header
2238 * (like sash, symmon, fx, ide) with ca. 3200
2241 if( heads * sectors * 5 < sgi_get_lastblock() )
2242 sgi_set_partition( n, 0, heads * sectors * 5, SGI_VOLHDR );
2249 sgi_delete_partition( int i )
2251 sgi_set_partition( i, 0, 0, 0 );
2255 sgi_add_partition( int n, int sys )
2258 unsigned int first=0, last=0;
2262 } else if ( n == 8 ) {
2265 if(sgi_get_num_sectors(n)) {
2266 printf(_("Partition %d is already defined. Delete "
2267 "it before re-adding it.\n"), n + 1);
2270 if( (sgi_entire() == -1) && (sys != SGI_VOLUME) ) {
2271 printf(_("Attempting to generate entire disk entry automatically.\n"));
2275 if( (sgi_gaps() == 0) && (sys != SGI_VOLUME) ) {
2276 printf(_("The entire disk is already covered with partitions.\n"));
2279 if(sgi_gaps() < 0) {
2280 printf(_("You got a partition overlap on the disk. Fix it first!\n"));
2283 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
2285 if(sys == SGI_VOLUME) {
2286 last = sgi_get_lastblock();
2287 first = read_int(0, 0, last-1, 0, mesg);
2289 printf(_("It is highly recommended that eleventh partition\n"
2290 "covers the entire disk and is of type `SGI volume'\n"));
2293 first = freelist[0].first;
2294 last = freelist[0].last;
2295 first = read_int(scround(first), scround(first), scround(last)-1,
2298 if (display_in_cyl_units)
2299 first *= units_per_sector;
2301 first = first; /* align to cylinder if you know how ... */
2303 last = isinfreelist(first);
2305 printf(_("You will get a partition overlap on the disk. "
2306 "Fix it first!\n"));
2310 snprintf(mesg, sizeof(mesg), _(" Last %s"), str_units(SINGULAR));
2311 last = read_int(scround(first), scround(last)-1, scround(last)-1,
2312 scround(first), mesg)+1;
2313 if (display_in_cyl_units)
2314 last *= units_per_sector;
2316 last = last; /* align to cylinder if You know how ... */
2317 if( (sys == SGI_VOLUME) && ( first != 0 || last != sgi_get_lastblock() ) )
2318 printf(_("It is highly recommended that eleventh partition\n"
2319 "covers the entire disk and is of type `SGI volume'\n"));
2320 sgi_set_partition( n, first, last-first, sys );
2323 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
2325 create_sgilabel(void)
2327 struct hd_geometry geometry;
2334 long longsectors; /* the number of sectors on the device */
2335 int res; /* the result from the ioctl */
2336 int sec_fac; /* the sector factor */
2338 sec_fac = sector_size / 512; /* determine the sector factor */
2341 _("Building a new SGI disklabel. Changes will remain in memory only,\n"
2342 "until you decide to write them. After that, of course, the previous\n"
2343 "content will be unrecoverably lost.\n\n"));
2345 sgi_other_endian = (BYTE_ORDER == LITTLE_ENDIAN);
2346 res = ioctl(fd, BLKGETSIZE, &longsectors);
2347 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
2348 heads = geometry.heads;
2349 sectors = geometry.sectors;
2351 /* the get device size ioctl was successful */
2352 cylinders = longsectors / (heads * sectors);
2353 cylinders /= sec_fac;
2355 /* otherwise print error and use truncated version */
2356 cylinders = geometry.cylinders;
2358 _("Warning: BLKGETSIZE ioctl failed on %s. "
2359 "Using geometry cylinder value of %d.\n"
2360 "This value may be truncated for devices"
2361 " > 33.8 GB.\n"), disk_device, cylinders);
2364 for (i = 0; i < 4; i++) {
2366 if(valid_part_table_flag(MBRbuffer)) {
2367 if(get_part_table(i)->sys_ind) {
2368 old[i].sysid = get_part_table(i)->sys_ind;
2369 old[i].start = get_start_sect(get_part_table(i));
2370 old[i].nsect = get_nr_sects(get_part_table(i));
2371 printf(_("Trying to keep parameters of partition %d.\n"), i);
2373 printf(_("ID=%02x\tSTART=%d\tLENGTH=%d\n"),
2374 old[i].sysid, old[i].start, old[i].nsect);
2379 memset(MBRbuffer, 0, sizeof(MBRbuffer));
2380 sgilabel->magic = SGI_SSWAP32(SGI_LABEL_MAGIC);
2381 sgilabel->boot_part = SGI_SSWAP16(0);
2382 sgilabel->swap_part = SGI_SSWAP16(1);
2384 /* sizeof(sgilabel->boot_file) = 16 > 6 */
2385 memset(sgilabel->boot_file, 0, 16);
2386 strcpy(sgilabel->boot_file, "/unix");
2388 sgilabel->devparam.skew = (0);
2389 sgilabel->devparam.gap1 = (0);
2390 sgilabel->devparam.gap2 = (0);
2391 sgilabel->devparam.sparecyl = (0);
2392 sgilabel->devparam.pcylcount = SGI_SSWAP16(geometry.cylinders);
2393 sgilabel->devparam.head_vol0 = SGI_SSWAP16(0);
2394 sgilabel->devparam.ntrks = SGI_SSWAP16(geometry.heads);
2395 /* tracks/cylinder (heads) */
2396 sgilabel->devparam.cmd_tag_queue_depth = (0);
2397 sgilabel->devparam.unused0 = (0);
2398 sgilabel->devparam.unused1 = SGI_SSWAP16(0);
2399 sgilabel->devparam.nsect = SGI_SSWAP16(geometry.sectors);
2401 sgilabel->devparam.bytes = SGI_SSWAP16(512);
2402 sgilabel->devparam.ilfact = SGI_SSWAP16(1);
2403 sgilabel->devparam.flags = SGI_SSWAP32(TRACK_FWD|
2404 IGNORE_ERRORS|RESEEK);
2405 sgilabel->devparam.datarate = SGI_SSWAP32(0);
2406 sgilabel->devparam.retries_on_error = SGI_SSWAP32(1);
2407 sgilabel->devparam.ms_per_word = SGI_SSWAP32(0);
2408 sgilabel->devparam.xylogics_gap1 = SGI_SSWAP16(0);
2409 sgilabel->devparam.xylogics_syncdelay = SGI_SSWAP16(0);
2410 sgilabel->devparam.xylogics_readdelay = SGI_SSWAP16(0);
2411 sgilabel->devparam.xylogics_gap2 = SGI_SSWAP16(0);
2412 sgilabel->devparam.xylogics_readgate = SGI_SSWAP16(0);
2413 sgilabel->devparam.xylogics_writecont = SGI_SSWAP16(0);
2414 memset( &(sgilabel->directory), 0, sizeof(struct volume_directory)*15 );
2415 memset( &(sgilabel->partitions), 0, sizeof(struct sgi_partition)*16 );
2421 for (i = 0; i < 4; i++) {
2423 sgi_set_partition(i, old[i].start, old[i].nsect, old[i].sysid);
2431 /* do nothing in the beginning */
2433 #endif /* CONFIG_FEATURE_FDISK_ADVANCED */
2435 /* _____________________________________________________________
2441 sgiinfo *info = calloc(1, sizeof(sgiinfo));
2443 info->magic=SGI_SSWAP32(SGI_INFO_MAGIC);
2444 info->b1=SGI_SSWAP32(-1);
2445 info->b2=SGI_SSWAP16(-1);
2446 info->b3=SGI_SSWAP16(1);
2447 /* You may want to replace this string !!!!!!! */
2448 strcpy( info->scsi_string, "IBM OEM 0662S12 3 30" );
2449 strcpy( info->serial, "0000" );
2450 info->check1816 = SGI_SSWAP16(18*256 +16 );
2451 strcpy( info->installer, "Sfx version 5.3, Oct 18, 1994" );
2454 #endif /* SGI_LABEL */
2457 #ifdef CONFIG_FEATURE_SUN_LABEL
2461 * I think this is mostly, or entirely, due to
2462 * Jakub Jelinek (jj@sunsite.mff.cuni.cz), July 1996
2464 * Merged with fdisk for other architectures, aeb, June 1998.
2466 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
2467 * Internationalization
2471 static int sun_other_endian;
2472 static int scsi_disk;
2476 #define IDE0_MAJOR 3
2479 #define IDE1_MAJOR 22
2482 static void guess_device_type(void) {
2483 struct stat bootstat;
2485 if (fstat (fd, &bootstat) < 0) {
2488 } else if (S_ISBLK(bootstat.st_mode)
2489 && (major(bootstat.st_rdev) == IDE0_MAJOR ||
2490 major(bootstat.st_rdev) == IDE1_MAJOR)) {
2493 } else if (S_ISBLK(bootstat.st_mode)
2494 && major(bootstat.st_rdev) == FLOPPY_MAJOR) {
2503 static const struct systypes sun_sys_types[] = {
2504 /* 0 */ {"\x00" "Empty" },
2505 /* 1 */ {"\x01" "Boot" },
2506 /* 2 */ {"\x02" "SunOS root" },
2507 /* SUNOS_SWAP */ {"\x03" "SunOS swap" },
2508 /* 4 */ {"\x04" "SunOS usr" },
2509 /* WHOLE_DISK */ {"\x05" "Whole disk" },
2510 /* 6 */ {"\x06" "SunOS stand" },
2511 /* 7 */ {"\x07" "SunOS var" },
2512 /* 8 */ {"\x08" "SunOS home" },
2513 /* LINUX_SWAP */ {"\x82" "Linux swap" },
2514 /* LINUX_NATIVE */ {"\x83" "Linux native" },
2515 /* 0x8e */ {"\x8e" "Linux LVM" },
2516 /* New (2.2.x) raid partition with autodetect using persistent superblock */
2517 /* 0xfd */ {"\xfd" "Linux raid autodetect" },
2523 set_sun_partition(int i, uint start, uint stop, int sysid) {
2524 sunlabel->infos[i].id = sysid;
2525 sunlabel->partitions[i].start_cylinder =
2526 SUN_SSWAP32(start / (heads * sectors));
2527 sunlabel->partitions[i].num_sectors =
2528 SUN_SSWAP32(stop - start);
2535 sunlabel->magic = 0;
2540 check_sun_label(void) {
2541 unsigned short *ush;
2544 if (sunlabel->magic != SUN_LABEL_MAGIC &&
2545 sunlabel->magic != SUN_LABEL_MAGIC_SWAPPED) {
2547 sun_other_endian = 0;
2550 sun_other_endian = (sunlabel->magic == SUN_LABEL_MAGIC_SWAPPED);
2551 ush = ((unsigned short *) (sunlabel + 1)) - 1;
2552 for (csum = 0; ush >= (unsigned short *)sunlabel;) csum ^= *ush--;
2554 fprintf(stderr,_("Detected sun disklabel with wrong checksum.\n"
2555 "Probably you'll have to set all the values,\n"
2556 "e.g. heads, sectors, cylinders and partitions\n"
2557 "or force a fresh label (s command in main menu)\n"));
2559 heads = SUN_SSWAP16(sunlabel->ntrks);
2560 cylinders = SUN_SSWAP16(sunlabel->ncyl);
2561 sectors = SUN_SSWAP16(sunlabel->nsect);
2569 static const struct sun_predefined_drives {
2572 unsigned short sparecyl;
2573 unsigned short ncyl;
2574 unsigned short nacyl;
2575 unsigned short pcylcount;
2576 unsigned short ntrks;
2577 unsigned short nsect;
2578 unsigned short rspeed;
2580 {"Quantum","ProDrive 80S",1,832,2,834,6,34,3662},
2581 {"Quantum","ProDrive 105S",1,974,2,1019,6,35,3662},
2582 {"CDC","Wren IV 94171-344",3,1545,2,1549,9,46,3600},
2583 {"IBM","DPES-31080",0,4901,2,4903,4,108,5400},
2584 {"IBM","DORS-32160",0,1015,2,1017,67,62,5400},
2585 {"IBM","DNES-318350",0,11199,2,11474,10,320,7200},
2586 {"SEAGATE","ST34371",0,3880,2,3882,16,135,7228},
2587 {"","SUN0104",1,974,2,1019,6,35,3662},
2588 {"","SUN0207",4,1254,2,1272,9,36,3600},
2589 {"","SUN0327",3,1545,2,1549,9,46,3600},
2590 {"","SUN0340",0,1538,2,1544,6,72,4200},
2591 {"","SUN0424",2,1151,2,2500,9,80,4400},
2592 {"","SUN0535",0,1866,2,2500,7,80,5400},
2593 {"","SUN0669",5,1614,2,1632,15,54,3600},
2594 {"","SUN1.0G",5,1703,2,1931,15,80,3597},
2595 {"","SUN1.05",0,2036,2,2038,14,72,5400},
2596 {"","SUN1.3G",6,1965,2,3500,17,80,5400},
2597 {"","SUN2.1G",0,2733,2,3500,19,80,5400},
2598 {"IOMEGA","Jaz",0,1019,2,1021,64,32,5394},
2601 static const struct sun_predefined_drives *
2602 sun_autoconfigure_scsi(void) {
2603 const struct sun_predefined_drives *p = NULL;
2605 #ifdef SCSI_IOCTL_GET_IDLUN
2615 if (!ioctl(fd, SCSI_IOCTL_GET_IDLUN, &id)) {
2617 "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n",
2619 ((id[0]>>24)&0xff)-/*PROC_SCSI_SCSI+PROC_SCSI_FILE*/33,
2621 /* This is very wrong (works only if you have one HBA),
2622 but I haven't found a way how to get hostno
2623 from the current kernel */
2629 pfd = fopen("/proc/scsi/scsi","r");
2631 while (fgets(buffer2,2048,pfd)) {
2632 if (!strcmp(buffer, buffer2)) {
2633 if (fgets(buffer2,2048,pfd)) {
2634 q = strstr(buffer2,"Vendor: ");
2639 *q++ = 0; /* truncate vendor name */
2640 q = strstr(q,"Model: ");
2645 q = strstr(q," Rev: ");
2648 for (i = 0; i < SIZE(sun_drives); i++) {
2649 if (*sun_drives[i].vendor && strcasecmp(sun_drives[i].vendor, vendor))
2651 if (!strstr(model, sun_drives[i].model))
2653 printf(_("Autoconfigure found a %s%s%s\n"),sun_drives[i].vendor,(*sun_drives[i].vendor) ? " " : "",sun_drives[i].model);
2671 static void create_sunlabel(void)
2673 struct hd_geometry geometry;
2677 const struct sun_predefined_drives *p = NULL;
2680 _("Building a new sun disklabel. Changes will remain in memory only,\n"
2681 "until you decide to write them. After that, of course, the previous\n"
2682 "content won't be recoverable.\n\n"));
2683 #if BYTE_ORDER == LITTLE_ENDIAN
2684 sun_other_endian = 1;
2686 sun_other_endian = 0;
2688 memset(MBRbuffer, 0, sizeof(MBRbuffer));
2689 sunlabel->magic = SUN_SSWAP16(SUN_LABEL_MAGIC);
2691 puts(_("Drive type\n"
2692 " ? auto configure\n"
2693 " 0 custom (with hardware detected defaults)"));
2694 for (i = 0; i < SIZE(sun_drives); i++) {
2695 printf(" %c %s%s%s\n",
2696 i + 'a', sun_drives[i].vendor,
2697 (*sun_drives[i].vendor) ? " " : "",
2698 sun_drives[i].model);
2701 c = read_char(_("Select type (? for auto, 0 for custom): "));
2702 if (c >= 'a' && c < 'a' + SIZE(sun_drives)) {
2703 p = sun_drives + c - 'a';
2705 } else if (c >= 'A' && c < 'A' + SIZE(sun_drives)) {
2706 p = sun_drives + c - 'A';
2708 } else if (c == '0') {
2710 } else if (c == '?' && scsi_disk) {
2711 p = sun_autoconfigure_scsi();
2713 printf(_("Autoconfigure failed.\n"));
2720 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
2721 heads = geometry.heads;
2722 sectors = geometry.sectors;
2723 cylinders = geometry.cylinders;
2730 sunlabel->nacyl = 0;
2731 sunlabel->pcylcount = SUN_SSWAP16(cylinders);
2732 sunlabel->rspeed = SUN_SSWAP16(300);
2733 sunlabel->ilfact = SUN_SSWAP16(1);
2734 sunlabel->sparecyl = 0;
2736 heads = read_int(1,heads,1024,0,_("Heads"));
2737 sectors = read_int(1,sectors,1024,0,_("Sectors/track"));
2739 cylinders = read_int(1,cylinders-2,65535,0,_("Cylinders"));
2741 cylinders = read_int(1,0,65535,0,_("Cylinders"));
2743 SUN_SSWAP16(read_int(0,2,65535,0,
2744 _("Alternate cylinders")));
2745 sunlabel->pcylcount =
2746 SUN_SSWAP16(read_int(0,cylinders+SUN_SSWAP16(sunlabel->nacyl),
2747 65535,0,_("Physical cylinders")));
2749 SUN_SSWAP16(read_int(1,5400,100000,0,
2750 _("Rotation speed (rpm)")));
2752 SUN_SSWAP16(read_int(1,1,32,0,_("Interleave factor")));
2753 sunlabel->sparecyl =
2754 SUN_SSWAP16(read_int(0,0,sectors,0,
2755 _("Extra sectors per cylinder")));
2758 sunlabel->sparecyl = SUN_SSWAP16(p->sparecyl);
2759 sunlabel->ncyl = SUN_SSWAP16(p->ncyl);
2760 sunlabel->nacyl = SUN_SSWAP16(p->nacyl);
2761 sunlabel->pcylcount = SUN_SSWAP16(p->pcylcount);
2762 sunlabel->ntrks = SUN_SSWAP16(p->ntrks);
2763 sunlabel->nsect = SUN_SSWAP16(p->nsect);
2764 sunlabel->rspeed = SUN_SSWAP16(p->rspeed);
2765 sunlabel->ilfact = SUN_SSWAP16(1);
2766 cylinders = p->ncyl;
2769 puts(_("You may change all the disk params from the x menu"));
2772 snprintf(sunlabel->info, sizeof(sunlabel->info),
2773 "%s%s%s cyl %d alt %d hd %d sec %d",
2774 p ? p->vendor : "", (p && *p->vendor) ? " " : "",
2776 : (floppy ? _("3,5\" floppy") : _("Linux custom")),
2777 cylinders, SUN_SSWAP16(sunlabel->nacyl), heads, sectors);
2779 sunlabel->ntrks = SUN_SSWAP16(heads);
2780 sunlabel->nsect = SUN_SSWAP16(sectors);
2781 sunlabel->ncyl = SUN_SSWAP16(cylinders);
2783 set_sun_partition(0, 0, cylinders * heads * sectors, LINUX_NATIVE);
2785 if (cylinders * heads * sectors >= 150 * 2048) {
2786 ndiv = cylinders - (50 * 2048 / (heads * sectors)); /* 50M swap */
2788 ndiv = cylinders * 2 / 3;
2789 set_sun_partition(0, 0, ndiv * heads * sectors, LINUX_NATIVE);
2790 set_sun_partition(1, ndiv * heads * sectors, cylinders * heads * sectors, LINUX_SWAP);
2791 sunlabel->infos[1].flags |= 0x01; /* Not mountable */
2793 set_sun_partition(2, 0, cylinders * heads * sectors, WHOLE_DISK);
2795 unsigned short *ush = (unsigned short *)sunlabel;
2796 unsigned short csum = 0;
2797 while(ush < (unsigned short *)(&sunlabel->csum))
2799 sunlabel->csum = csum;
2802 set_all_unchanged();
2804 get_boot(create_empty_sun);
2808 toggle_sunflags(int i, unsigned char mask) {
2809 if (sunlabel->infos[i].flags & mask)
2810 sunlabel->infos[i].flags &= ~mask;
2811 else sunlabel->infos[i].flags |= mask;
2816 fetch_sun(uint *starts, uint *lens, uint *start, uint *stop) {
2817 int i, continuous = 1;
2818 *start = 0; *stop = cylinders * heads * sectors;
2819 for (i = 0; i < partitions; i++) {
2820 if (sunlabel->partitions[i].num_sectors
2821 && sunlabel->infos[i].id
2822 && sunlabel->infos[i].id != WHOLE_DISK) {
2823 starts[i] = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
2824 lens[i] = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
2826 if (starts[i] == *start)
2828 else if (starts[i] + lens[i] >= *stop)
2832 /* There will be probably more gaps
2833 than one, so lets check afterwards */
2842 static uint *verify_sun_starts;
2845 verify_sun_cmp(int *a, int *b) {
2846 if (*a == -1) return 1;
2847 if (*b == -1) return -1;
2848 if (verify_sun_starts[*a] > verify_sun_starts[*b]) return 1;
2854 uint starts[8], lens[8], start, stop;
2855 int i,j,k,starto,endo;
2858 verify_sun_starts = starts;
2859 fetch_sun(starts,lens,&start,&stop);
2860 for (k = 0; k < 7; k++) {
2861 for (i = 0; i < 8; i++) {
2862 if (k && (lens[i] % (heads * sectors))) {
2863 printf(_("Partition %d doesn't end on cylinder boundary\n"), i+1);
2866 for (j = 0; j < i; j++)
2868 if (starts[j] == starts[i]+lens[i]) {
2869 starts[j] = starts[i]; lens[j] += lens[i];
2871 } else if (starts[i] == starts[j]+lens[j]){
2875 if (starts[i] < starts[j]+lens[j] &&
2876 starts[j] < starts[i]+lens[i]) {
2878 if (starts[j] > starto)
2880 endo = starts[i]+lens[i];
2881 if (starts[j]+lens[j] < endo)
2882 endo = starts[j]+lens[j];
2883 printf(_("Partition %d overlaps with others in "
2884 "sectors %d-%d\n"), i+1, starto, endo);
2891 for (i = 0; i < 8; i++) {
2897 qsort(array,SIZE(array),sizeof(array[0]),
2898 (int (*)(const void *,const void *)) verify_sun_cmp);
2899 if (array[0] == -1) {
2900 printf(_("No partitions defined\n"));
2903 stop = cylinders * heads * sectors;
2904 if (starts[array[0]])
2905 printf(_("Unused gap - sectors 0-%d\n"),starts[array[0]]);
2906 for (i = 0; i < 7 && array[i+1] != -1; i++) {
2907 printf(_("Unused gap - sectors %d-%d\n"),starts[array[i]]+lens[array[i]],starts[array[i+1]]);
2909 start = starts[array[i]]+lens[array[i]];
2911 printf(_("Unused gap - sectors %d-%d\n"),start,stop);
2915 add_sun_partition(int n, int sys) {
2916 uint start, stop, stop2;
2917 uint starts[8], lens[8];
2923 if (sunlabel->partitions[n].num_sectors && sunlabel->infos[n].id) {
2924 printf(_("Partition %d is already defined. Delete "
2925 "it before re-adding it.\n"), n + 1);
2929 fetch_sun(starts,lens,&start,&stop);
2930 if (stop <= start) {
2934 printf(_("Other partitions already cover the whole disk.\nDelete "
2935 "some/shrink them before retry.\n"));
2939 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
2942 first = read_int(0, 0, 0, 0, mesg);
2944 first = read_int(scround(start), scround(stop)+1,
2945 scround(stop), 0, mesg);
2946 if (display_in_cyl_units)
2947 first *= units_per_sector;
2949 /* Starting sector has to be properly aligned */
2950 first = (first + heads * sectors - 1) / (heads * sectors);
2951 if (n == 2 && first != 0)
2953 It is highly recommended that the third partition covers the whole disk\n\
2954 and is of type `Whole disk'\n");
2955 /* ewt asks to add: "don't start a partition at cyl 0"
2956 However, edmundo@rano.demon.co.uk writes:
2957 "In addition to having a Sun partition table, to be able to
2958 boot from the disc, the first partition, /dev/sdX1, must
2959 start at cylinder 0. This means that /dev/sdX1 contains
2960 the partition table and the boot block, as these are the
2961 first two sectors of the disc. Therefore you must be
2962 careful what you use /dev/sdX1 for. In particular, you must
2963 not use a partition starting at cylinder 0 for Linux swap,
2964 as that would overwrite the partition table and the boot
2965 block. You may, however, use such a partition for a UFS
2966 or EXT2 file system, as these file systems leave the first
2967 1024 bytes undisturbed. */
2968 /* On the other hand, one should not use partitions
2969 starting at block 0 in an md, or the label will
2971 for (i = 0; i < partitions; i++)
2972 if (lens[i] && starts[i] <= first
2973 && starts[i] + lens[i] > first)
2975 if (i < partitions && !whole_disk) {
2976 if (n == 2 && !first) {
2980 printf(_("Sector %d is already allocated\n"), first);
2984 stop = cylinders * heads * sectors;
2986 for (i = 0; i < partitions; i++) {
2987 if (starts[i] > first && starts[i] < stop)
2990 snprintf(mesg, sizeof(mesg),
2991 _("Last %s or +size or +sizeM or +sizeK"),
2992 str_units(SINGULAR));
2994 last = read_int(scround(stop2), scround(stop2), scround(stop2),
2996 else if (n == 2 && !first)
2997 last = read_int(scround(first), scround(stop2), scround(stop2),
2998 scround(first), mesg);
3000 last = read_int(scround(first), scround(stop), scround(stop),
3001 scround(first), mesg);
3002 if (display_in_cyl_units)
3003 last *= units_per_sector;
3004 if (n == 2 && !first) {
3005 if (last >= stop2) {
3008 } else if (last > stop) {
3010 _("You haven't covered the whole disk with the 3rd partition, but your value\n"
3011 "%d %s covers some other partition. Your entry has been changed\n"
3013 scround(last), str_units(SINGULAR),
3014 scround(stop), str_units(SINGULAR));
3017 } else if (!whole_disk && last > stop)
3020 if (whole_disk) sys = WHOLE_DISK;
3021 set_sun_partition(n, first, last, sys);
3025 sun_delete_partition(int i) {
3028 if (i == 2 && sunlabel->infos[i].id == WHOLE_DISK &&
3029 !sunlabel->partitions[i].start_cylinder &&
3030 (nsec = SUN_SSWAP32(sunlabel->partitions[i].num_sectors))
3031 == heads * sectors * cylinders)
3032 printf(_("If you want to maintain SunOS/Solaris compatibility, "
3033 "consider leaving this\n"
3034 "partition as Whole disk (5), starting at 0, with %u "
3035 "sectors\n"), nsec);
3036 sunlabel->infos[i].id = 0;
3037 sunlabel->partitions[i].num_sectors = 0;
3041 sun_change_sysid(int i, int sys) {
3042 if (sys == LINUX_SWAP && !sunlabel->partitions[i].start_cylinder) {
3044 _("It is highly recommended that the partition at offset 0\n"
3045 "is UFS, EXT2FS filesystem or SunOS swap. Putting Linux swap\n"
3046 "there may destroy your partition table and bootblock.\n"
3047 "Type YES if you're very sure you would like that partition\n"
3048 "tagged with 82 (Linux swap): "));
3049 if (strcmp (line_ptr, _("YES\n")))
3055 /* swaps are not mountable by default */
3056 sunlabel->infos[i].flags |= 0x01;
3059 /* assume other types are mountable;
3060 user can change it anyway */
3061 sunlabel->infos[i].flags &= ~0x01;
3064 sunlabel->infos[i].id = sys;
3068 sun_list_table(int xtra) {
3071 w = strlen(disk_device);
3074 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d rpm\n"
3075 "%d cylinders, %d alternate cylinders, %d physical cylinders\n"
3076 "%d extra sects/cyl, interleave %d:1\n"
3078 "Units = %s of %d * 512 bytes\n\n"),
3079 disk_device, heads, sectors, SUN_SSWAP16(sunlabel->rspeed),
3080 cylinders, SUN_SSWAP16(sunlabel->nacyl),
3081 SUN_SSWAP16(sunlabel->pcylcount),
3082 SUN_SSWAP16(sunlabel->sparecyl),
3083 SUN_SSWAP16(sunlabel->ilfact),
3085 str_units(PLURAL), units_per_sector);
3088 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d cylinders\n"
3089 "Units = %s of %d * 512 bytes\n\n"),
3090 disk_device, heads, sectors, cylinders,
3091 str_units(PLURAL), units_per_sector);
3093 printf(_("%*s Flag Start End Blocks Id System\n"),
3094 w + 1, _("Device"));
3095 for (i = 0 ; i < partitions; i++) {
3096 if (sunlabel->partitions[i].num_sectors) {
3097 uint32_t start = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
3098 uint32_t len = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
3100 "%s %c%c %9ld %9ld %9ld%c %2x %s\n",
3101 /* device */ partname(disk_device, i+1, w),
3102 /* flags */ (sunlabel->infos[i].flags & 0x01) ? 'u' : ' ',
3103 (sunlabel->infos[i].flags & 0x10) ? 'r' : ' ',
3104 /* start */ (long) scround(start),
3105 /* end */ (long) scround(start+len),
3106 /* odd flag on end */ (long) len / 2, len & 1 ? '+' : ' ',
3107 /* type id */ sunlabel->infos[i].id,
3108 /* type name */ partition_type(sunlabel->infos[i].id));
3113 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3116 sun_set_alt_cyl(void) {
3118 SUN_SSWAP16(read_int(0,SUN_SSWAP16(sunlabel->nacyl), 65535, 0,
3119 _("Number of alternate cylinders")));
3123 sun_set_ncyl(int cyl) {
3124 sunlabel->ncyl = SUN_SSWAP16(cyl);
3128 sun_set_xcyl(void) {
3129 sunlabel->sparecyl =
3130 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->sparecyl), sectors, 0,
3131 _("Extra sectors per cylinder")));
3135 sun_set_ilfact(void) {
3137 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->ilfact), 32, 0,
3138 _("Interleave factor")));
3142 sun_set_rspeed(void) {
3144 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->rspeed), 100000, 0,
3145 _("Rotation speed (rpm)")));
3149 sun_set_pcylcount(void) {
3150 sunlabel->pcylcount =
3151 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->pcylcount), 65535, 0,
3152 _("Number of physical cylinders")));
3154 #endif /* CONFIG_FEATURE_FDISK_ADVANCED */
3157 sun_write_table(void) {
3158 unsigned short *ush = (unsigned short *)sunlabel;
3159 unsigned short csum = 0;
3161 while(ush < (unsigned short *)(&sunlabel->csum))
3163 sunlabel->csum = csum;
3164 if (lseek(fd, 0, SEEK_SET) < 0)
3165 fdisk_fatal(unable_to_seek);
3166 if (write(fd, sunlabel, SECTOR_SIZE) != SECTOR_SIZE)
3167 fdisk_fatal(unable_to_write);
3169 #endif /* SUN_LABEL */
3171 /* DOS partition types */
3173 static const struct systypes i386_sys_types[] = {
3176 {"\x04" "FAT16 <32M"},
3177 {"\x05" "Extended"}, /* DOS 3.3+ extended partition */
3178 {"\x06" "FAT16"}, /* DOS 16-bit >=32M */
3179 {"\x07" "HPFS/NTFS"}, /* OS/2 IFS, eg, HPFS or NTFS or QNX */
3180 {"\x0a" "OS/2 Boot Manager"},/* OS/2 Boot Manager */
3181 {"\x0b" "Win95 FAT32"},
3182 {"\x0c" "Win95 FAT32 (LBA)"},/* LBA really is `Extended Int 13h' */
3183 {"\x0e" "Win95 FAT16 (LBA)"},
3184 {"\x0f" "Win95 Ext'd (LBA)"},
3185 {"\x11" "Hidden FAT12"},
3186 {"\x12" "Compaq diagnostics"},
3187 {"\x14" "Hidden FAT16 <32M"},
3188 {"\x16" "Hidden FAT16"},
3189 {"\x17" "Hidden HPFS/NTFS"},
3190 {"\x1b" "Hidden Win95 FAT32"},
3191 {"\x1c" "Hidden Win95 FAT32 (LBA)"},
3192 {"\x1e" "Hidden Win95 FAT16 (LBA)"},
3193 {"\x3c" "PartitionMagic recovery"},
3194 {"\x41" "PPC PReP Boot"},
3196 {"\x63" "GNU HURD or SysV"}, /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */
3197 {"\x80" "Old Minix"}, /* Minix 1.4a and earlier */
3198 {"\x81" "Minix / old Linux"},/* Minix 1.4b and later */
3199 {"\x82" "Linux swap"}, /* also Solaris */
3201 {"\x84" "OS/2 hidden C: drive"},
3202 {"\x85" "Linux extended"},
3203 {"\x86" "NTFS volume set"},
3204 {"\x87" "NTFS volume set"},
3205 {"\x8e" "Linux LVM"},
3206 {"\x9f" "BSD/OS"}, /* BSDI */
3207 {"\xa0" "IBM Thinkpad hibernation"},
3208 {"\xa5" "FreeBSD"}, /* various BSD flavours */
3210 {"\xa8" "Darwin UFS"},
3212 {"\xab" "Darwin boot"},
3214 {"\xb8" "BSDI swap"},
3215 {"\xbe" "Solaris boot"},
3217 {"\xee" "EFI GPT"}, /* Intel EFI GUID Partition Table */
3218 {"\xef" "EFI (FAT-12/16/32)"},/* Intel EFI System Partition */
3219 {"\xf0" "Linux/PA-RISC boot"},/* Linux/PA-RISC boot loader */
3220 {"\xf2" "DOS secondary"}, /* DOS 3.3+ secondary */
3221 {"\xfd" "Linux raid autodetect"},/* New (2.2.x) raid partition with
3222 autodetect using persistent
3224 #ifdef CONFIG_WEIRD_PARTITION_TYPES
3225 {"\x02" "XENIX root"},
3226 {"\x03" "XENIX usr"},
3227 {"\x08" "AIX"}, /* AIX boot (AIX -- PS/2 port) or SplitDrive */
3228 {"\x09" "AIX bootable"}, /* AIX data or Coherent */
3230 {"\x18" "AST SmartSleep"},
3233 {"\x40" "Venix 80286"},
3235 {"\x4e" "QNX4.x 2nd part"},
3236 {"\x4f" "QNX4.x 3rd part"},
3237 {"\x50" "OnTrack DM"},
3238 {"\x51" "OnTrack DM6 Aux1"}, /* (or Novell) */
3239 {"\x52" "CP/M"}, /* CP/M or Microport SysV/AT */
3240 {"\x53" "OnTrack DM6 Aux3"},
3241 {"\x54" "OnTrackDM6"},
3242 {"\x55" "EZ-Drive"},
3243 {"\x56" "Golden Bow"},
3244 {"\x5c" "Priam Edisk"},
3245 {"\x61" "SpeedStor"},
3246 {"\x64" "Novell Netware 286"},
3247 {"\x65" "Novell Netware 386"},
3248 {"\x70" "DiskSecure Multi-Boot"},
3251 {"\x94" "Amoeba BBT"}, /* (bad block table) */
3252 {"\xa7" "NeXTSTEP"},
3253 {"\xbb" "Boot Wizard hidden"},
3254 {"\xc1" "DRDOS/sec (FAT-12)"},
3255 {"\xc4" "DRDOS/sec (FAT-16 < 32M)"},
3256 {"\xc6" "DRDOS/sec (FAT-16)"},
3258 {"\xda" "Non-FS data"},
3259 {"\xdb" "CP/M / CTOS / ..."},/* CP/M or Concurrent CP/M or
3260 Concurrent DOS or CTOS */
3261 {"\xde" "Dell Utility"}, /* Dell PowerEdge Server utilities */
3262 {"\xdf" "BootIt"}, /* BootIt EMBRM */
3263 {"\xe1" "DOS access"}, /* DOS access or SpeedStor 12-bit FAT
3264 extended partition */
3265 {"\xe3" "DOS R/O"}, /* DOS R/O or SpeedStor */
3266 {"\xe4" "SpeedStor"}, /* SpeedStor 16-bit FAT extended
3267 partition < 1024 cyl. */
3268 {"\xf1" "SpeedStor"},
3269 {"\xf4" "SpeedStor"}, /* SpeedStor large partition */
3270 {"\xfe" "LANstep"}, /* SpeedStor >1024 cyl. or LANstep */
3271 {"\xff" "BBT"}, /* Xenix Bad Block Table */
3278 /* A valid partition table sector ends in 0x55 0xaa */
3280 part_table_flag(const char *b) {
3281 return ((uint) b[510]) + (((uint) b[511]) << 8);
3285 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3287 write_part_table_flag(char *b) {
3292 /* start_sect and nr_sects are stored little endian on all machines */
3293 /* moreover, they are not aligned correctly */
3295 store4_little_endian(unsigned char *cp, unsigned int val) {
3296 cp[0] = (val & 0xff);
3297 cp[1] = ((val >> 8) & 0xff);
3298 cp[2] = ((val >> 16) & 0xff);
3299 cp[3] = ((val >> 24) & 0xff);
3301 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3304 read4_little_endian(const unsigned char *cp) {
3305 return (uint)(cp[0]) + ((uint)(cp[1]) << 8)
3306 + ((uint)(cp[2]) << 16) + ((uint)(cp[3]) << 24);
3309 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3311 set_start_sect(struct partition *p, unsigned int start_sect) {
3312 store4_little_endian(p->start4, start_sect);
3317 get_start_sect(const struct partition *p) {
3318 return read4_little_endian(p->start4);
3321 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3323 set_nr_sects(struct partition *p, unsigned int nr_sects) {
3324 store4_little_endian(p->size4, nr_sects);
3329 get_nr_sects(const struct partition *p) {
3330 return read4_little_endian(p->size4);
3333 /* normally O_RDWR, -l option gives O_RDONLY */
3334 static int type_open = O_RDWR;
3337 static int ext_index, /* the prime extended partition */
3338 listing, /* no aborts for fdisk -l */
3339 dos_compatible_flag = ~0;
3340 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3341 static int dos_changed;
3342 static int nowarn; /* no warnings for fdisk -l/-s */
3347 static uint user_cylinders, user_heads, user_sectors;
3348 static uint pt_heads, pt_sectors;
3349 static uint kern_heads, kern_sectors;
3351 static uint extended_offset; /* offset of link pointers */
3353 static unsigned long long total_number_of_sectors;
3356 static jmp_buf listingbuf;
3358 static void fdisk_fatal(enum failure why) {
3359 const char *message;
3363 longjmp(listingbuf, 1);
3367 case unable_to_open:
3368 message = "Unable to open %s\n";
3370 case unable_to_read:
3371 message = "Unable to read %s\n";
3373 case unable_to_seek:
3374 message = "Unable to seek on %s\n";
3376 case unable_to_write:
3377 message = "Unable to write %s\n";
3380 message = "BLKGETSIZE ioctl failed on %s\n";
3383 message = "Fatal error\n";
3386 fputc('\n', stderr);
3387 fprintf(stderr, message, disk_device);
3392 seek_sector(uint secno) {
3393 ext2_loff_t offset = (ext2_loff_t) secno * sector_size;
3394 if (lseek(fd, offset, SEEK_SET) == (ext2_loff_t) -1)
3395 fdisk_fatal(unable_to_seek);
3398 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3400 write_sector(uint secno, char *buf) {
3402 if (write(fd, buf, sector_size) != sector_size)
3403 fdisk_fatal(unable_to_write);
3407 /* Allocate a buffer and read a partition table sector */
3409 read_pte(struct pte *pe, uint offset) {
3411 pe->offset = offset;
3412 pe->sectorbuffer = (char *) xmalloc(sector_size);
3413 seek_sector(offset);
3414 if (read(fd, pe->sectorbuffer, sector_size) != sector_size)
3415 fdisk_fatal(unable_to_read);
3416 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3419 pe->part_table = pe->ext_pointer = NULL;
3423 get_partition_start(const struct pte *pe) {
3424 return pe->offset + get_start_sect(pe->part_table);
3427 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3429 * Avoid warning about DOS partitions when no DOS partition was changed.
3430 * Here a heuristic "is probably dos partition".
3431 * We might also do the opposite and warn in all cases except
3432 * for "is probably nondos partition".
3435 is_dos_partition(int t) {
3436 return (t == 1 || t == 4 || t == 6 ||
3437 t == 0x0b || t == 0x0c || t == 0x0e ||
3438 t == 0x11 || t == 0x12 || t == 0x14 || t == 0x16 ||
3439 t == 0x1b || t == 0x1c || t == 0x1e || t == 0x24 ||
3440 t == 0xc1 || t == 0xc4 || t == 0xc6);
3445 #ifdef CONFIG_FEATURE_SUN_LABEL
3447 puts(_("Command action"));
3448 puts(_("\ta\ttoggle a read only flag")); /* sun */
3449 puts(_("\tb\tedit bsd disklabel"));
3450 puts(_("\tc\ttoggle the mountable flag")); /* sun */
3451 puts(_("\td\tdelete a partition"));
3452 puts(_("\tl\tlist known partition types"));
3453 puts(_("\tm\tprint this menu"));
3454 puts(_("\tn\tadd a new partition"));
3455 puts(_("\to\tcreate a new empty DOS partition table"));
3456 puts(_("\tp\tprint the partition table"));
3457 puts(_("\tq\tquit without saving changes"));
3458 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3459 puts(_("\tt\tchange a partition's system id"));
3460 puts(_("\tu\tchange display/entry units"));
3461 puts(_("\tv\tverify the partition table"));
3462 puts(_("\tw\twrite table to disk and exit"));
3463 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3464 puts(_("\tx\textra functionality (experts only)"));
3468 #ifdef CONFIG_FEATURE_SGI_LABEL
3470 puts(_("Command action"));
3471 puts(_("\ta\tselect bootable partition")); /* sgi flavour */
3472 puts(_("\tb\tedit bootfile entry")); /* sgi */
3473 puts(_("\tc\tselect sgi swap partition")); /* sgi flavour */
3474 puts(_("\td\tdelete a partition"));
3475 puts(_("\tl\tlist known partition types"));
3476 puts(_("\tm\tprint this menu"));
3477 puts(_("\tn\tadd a new partition"));
3478 puts(_("\to\tcreate a new empty DOS partition table"));
3479 puts(_("\tp\tprint the partition table"));
3480 puts(_("\tq\tquit without saving changes"));
3481 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3482 puts(_("\tt\tchange a partition's system id"));
3483 puts(_("\tu\tchange display/entry units"));
3484 puts(_("\tv\tverify the partition table"));
3485 puts(_("\tw\twrite table to disk and exit"));
3488 #ifdef CONFIG_FEATURE_AIX_LABEL
3490 puts(_("Command action"));
3491 puts(_("\tm\tprint this menu"));
3492 puts(_("\to\tcreate a new empty DOS partition table"));
3493 puts(_("\tq\tquit without saving changes"));
3494 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3498 puts(_("Command action"));
3499 puts(_("\ta\ttoggle a bootable flag"));
3500 puts(_("\tb\tedit bsd disklabel"));
3501 puts(_("\tc\ttoggle the dos compatibility flag"));
3502 puts(_("\td\tdelete a partition"));
3503 puts(_("\tl\tlist known partition types"));
3504 puts(_("\tm\tprint this menu"));
3505 puts(_("\tn\tadd a new partition"));
3506 puts(_("\to\tcreate a new empty DOS partition table"));
3507 puts(_("\tp\tprint the partition table"));
3508 puts(_("\tq\tquit without saving changes"));
3509 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3510 puts(_("\tt\tchange a partition's system id"));
3511 puts(_("\tu\tchange display/entry units"));
3512 puts(_("\tv\tverify the partition table"));
3513 puts(_("\tw\twrite table to disk and exit"));
3514 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3515 puts(_("\tx\textra functionality (experts only)"));
3519 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3522 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3525 #ifdef CONFIG_FEATURE_SUN_LABEL
3527 puts(_("Command action"));
3528 puts(_("\ta\tchange number of alternate cylinders")); /*sun*/
3529 puts(_("\tc\tchange number of cylinders"));
3530 puts(_("\td\tprint the raw data in the partition table"));
3531 puts(_("\te\tchange number of extra sectors per cylinder"));/*sun*/
3532 puts(_("\th\tchange number of heads"));
3533 puts(_("\ti\tchange interleave factor")); /*sun*/
3534 puts(_("\to\tchange rotation speed (rpm)")); /*sun*/
3535 puts(_("\tm\tprint this menu"));
3536 puts(_("\tp\tprint the partition table"));
3537 puts(_("\tq\tquit without saving changes"));
3538 puts(_("\tr\treturn to main menu"));
3539 puts(_("\ts\tchange number of sectors/track"));
3540 puts(_("\tv\tverify the partition table"));
3541 puts(_("\tw\twrite table to disk and exit"));
3542 puts(_("\ty\tchange number of physical cylinders")); /*sun*/
3545 #ifdef CONFIG_FEATURE_SGI_LABEL
3547 puts(_("Command action"));
3548 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3549 puts(_("\tc\tchange number of cylinders"));
3550 puts(_("\td\tprint the raw data in the partition table"));
3551 puts(_("\te\tlist extended partitions")); /* !sun */
3552 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3553 puts(_("\th\tchange number of heads"));
3554 puts(_("\tm\tprint this menu"));
3555 puts(_("\tp\tprint the partition table"));
3556 puts(_("\tq\tquit without saving changes"));
3557 puts(_("\tr\treturn to main menu"));
3558 puts(_("\ts\tchange number of sectors/track"));
3559 puts(_("\tv\tverify the partition table"));
3560 puts(_("\tw\twrite table to disk and exit"));
3563 #ifdef CONFIG_FEATURE_AIX_LABEL
3565 puts(_("Command action"));
3566 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3567 puts(_("\tc\tchange number of cylinders"));
3568 puts(_("\td\tprint the raw data in the partition table"));
3569 puts(_("\te\tlist extended partitions")); /* !sun */
3570 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3571 puts(_("\th\tchange number of heads"));
3572 puts(_("\tm\tprint this menu"));
3573 puts(_("\tp\tprint the partition table"));
3574 puts(_("\tq\tquit without saving changes"));
3575 puts(_("\tr\treturn to main menu"));
3576 puts(_("\ts\tchange number of sectors/track"));
3577 puts(_("\tv\tverify the partition table"));
3578 puts(_("\tw\twrite table to disk and exit"));
3582 puts(_("Command action"));
3583 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3584 puts(_("\tc\tchange number of cylinders"));
3585 puts(_("\td\tprint the raw data in the partition table"));
3586 puts(_("\te\tlist extended partitions")); /* !sun */
3587 puts(_("\tf\tfix partition order")); /* !sun, !aix, !sgi */
3588 #ifdef CONFIG_FEATURE_SGI_LABEL
3589 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3591 puts(_("\th\tchange number of heads"));
3592 puts(_("\tm\tprint this menu"));
3593 puts(_("\tp\tprint the partition table"));
3594 puts(_("\tq\tquit without saving changes"));
3595 puts(_("\tr\treturn to main menu"));
3596 puts(_("\ts\tchange number of sectors/track"));
3597 puts(_("\tv\tverify the partition table"));
3598 puts(_("\tw\twrite table to disk and exit"));
3601 #endif /* ADVANCED mode */
3603 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3604 static const struct systypes *
3605 get_sys_types(void) {
3607 #ifdef CONFIG_FEATURE_SUN_LABEL
3608 sun_label ? sun_sys_types :
3610 #ifdef CONFIG_FEATURE_SGI_LABEL
3611 sgi_label ? sgi_sys_types :
3616 #define get_sys_types() i386_sys_types
3617 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3619 static const char *partition_type(unsigned char type)
3622 const struct systypes *types = get_sys_types();
3624 for (i=0; types[i].name; i++)
3625 if (types[i].name[0] == type)
3626 return types[i].name + 1;
3628 return _("Unknown");
3632 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3636 #ifdef CONFIG_FEATURE_SUN_LABEL
3637 sun_label ? sunlabel->infos[i].id :
3639 #ifdef CONFIG_FEATURE_SGI_LABEL
3640 sgi_label ? sgi_get_sysid(i) :
3642 ptes[i].part_table->sys_ind);
3645 void list_types(const struct systypes *sys)
3647 uint last[4], done = 0, next = 0, size;
3650 for (i = 0; sys[i].name; i++);
3653 for (i = 3; i >= 0; i--)
3654 last[3 - i] = done += (size + i - done) / (i + 1);
3658 printf("%c%2x %-15.15s", i ? ' ' : '\n',
3659 sys[next].name[0], partition_type(sys[next].name[0]));
3660 next = last[i++] + done;
3661 if (i > 3 || next >= last[i]) {
3665 } while (done < last[0]);
3668 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3671 is_cleared_partition(const struct partition *p) {
3672 return !(!p || p->boot_ind || p->head || p->sector || p->cyl ||
3673 p->sys_ind || p->end_head || p->end_sector || p->end_cyl ||
3674 get_start_sect(p) || get_nr_sects(p));
3678 clear_partition(struct partition *p) {
3681 memset(p, 0, sizeof(struct partition));
3684 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3686 set_partition(int i, int doext, uint start, uint stop, int sysid) {
3687 struct partition *p;
3691 p = ptes[i].ext_pointer;
3692 offset = extended_offset;
3694 p = ptes[i].part_table;
3695 offset = ptes[i].offset;
3699 set_start_sect(p, start - offset);
3700 set_nr_sects(p, stop - start + 1);
3701 if (dos_compatible_flag && (start/(sectors*heads) > 1023))
3702 start = heads*sectors*1024 - 1;
3703 set_hsc(p->head, p->sector, p->cyl, start);
3704 if (dos_compatible_flag && (stop/(sectors*heads) > 1023))
3705 stop = heads*sectors*1024 - 1;
3706 set_hsc(p->end_head, p->end_sector, p->end_cyl, stop);
3707 ptes[i].changed = 1;
3712 test_c(const char **m, const char *mesg) {
3715 fprintf(stderr, _("You must set"));
3717 fprintf(stderr, " %s", *m);
3725 warn_geometry(void) {
3726 const char *m = NULL;
3730 prev = test_c(&m, _("heads"));
3732 prev = test_c(&m, _("sectors"));
3734 prev = test_c(&m, _("cylinders"));
3738 fprintf(stderr, "%s%s.\n"
3739 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3740 "You can do this from the extra functions menu.\n"
3742 , prev ? _(" and ") : " ", m);
3747 static void update_units(void)
3749 int cyl_units = heads * sectors;
3751 if (display_in_cyl_units && cyl_units)
3752 units_per_sector = cyl_units;
3754 units_per_sector = 1; /* in sectors */
3757 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3759 warn_cylinders(void) {
3760 if (dos_label && cylinders > 1024 && !nowarn)
3761 fprintf(stderr, _("\n"
3762 "The number of cylinders for this disk is set to %d.\n"
3763 "There is nothing wrong with that, but this is larger than 1024,\n"
3764 "and could in certain setups cause problems with:\n"
3765 "1) software that runs at boot time (e.g., old versions of LILO)\n"
3766 "2) booting and partitioning software from other OSs\n"
3767 " (e.g., DOS FDISK, OS/2 FDISK)\n"),
3773 read_extended(int ext) {
3776 struct partition *p, *q;
3780 pex->ext_pointer = pex->part_table;
3782 p = pex->part_table;
3783 if (!get_start_sect(p)) {
3785 _("Bad offset in primary extended partition\n"));
3789 while (IS_EXTENDED (p->sys_ind)) {
3790 struct pte *pe = &ptes[partitions];
3792 if (partitions >= MAXIMUM_PARTS) {
3793 /* This is not a Linux restriction, but
3794 this program uses arrays of size MAXIMUM_PARTS.
3795 Do not try to `improve' this test. */
3796 struct pte *pre = &ptes[partitions-1];
3797 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3799 _("Warning: deleting partitions after %d\n"),
3803 clear_partition(pre->ext_pointer);
3807 read_pte(pe, extended_offset + get_start_sect(p));
3809 if (!extended_offset)
3810 extended_offset = get_start_sect(p);
3812 q = p = pt_offset(pe->sectorbuffer, 0);
3813 for (i = 0; i < 4; i++, p++) if (get_nr_sects(p)) {
3814 if (IS_EXTENDED (p->sys_ind)) {
3815 if (pe->ext_pointer)
3817 _("Warning: extra link "
3818 "pointer in partition table"
3819 " %d\n"), partitions + 1);
3821 pe->ext_pointer = p;
3822 } else if (p->sys_ind) {
3825 _("Warning: ignoring extra "
3826 "data in partition table"
3827 " %d\n"), partitions + 1);
3833 /* very strange code here... */
3834 if (!pe->part_table) {
3835 if (q != pe->ext_pointer)
3838 pe->part_table = q + 1;
3840 if (!pe->ext_pointer) {
3841 if (q != pe->part_table)
3842 pe->ext_pointer = q;
3844 pe->ext_pointer = q + 1;
3847 p = pe->ext_pointer;
3851 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3852 /* remove empty links */
3854 for (i = 4; i < partitions; i++) {
3855 struct pte *pe = &ptes[i];
3857 if (!get_nr_sects(pe->part_table) &&
3858 (partitions > 5 || ptes[4].part_table->sys_ind)) {
3859 printf("omitting empty partition (%d)\n", i+1);
3860 delete_partition(i);
3861 goto remove; /* numbering changed */
3867 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3869 create_doslabel(void) {
3873 _("Building a new DOS disklabel. Changes will remain in memory only,\n"
3874 "until you decide to write them. After that, of course, the previous\n"
3875 "content won't be recoverable.\n\n"));
3876 #ifdef CONFIG_FEATURE_SUN_LABEL
3877 sun_nolabel(); /* otherwise always recognised as sun */
3879 #ifdef CONFIG_FEATURE_SGI_LABEL
3880 sgi_nolabel(); /* otherwise always recognised as sgi */
3882 #ifdef CONFIG_FEATURE_AIX_LABEL
3885 #ifdef CONFIG_FEATURE_OSF_LABEL
3887 possibly_osf_label = 0;
3891 for (i = 510-64; i < 510; i++)
3893 write_part_table_flag(MBRbuffer);
3894 extended_offset = 0;
3895 set_all_unchanged();
3897 get_boot(create_empty_dos);
3899 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3902 get_sectorsize(void) {
3903 if (!user_set_sector_size &&
3904 get_kernel_revision() >= MAKE_VERSION(2,3,3)) {
3906 if (ioctl(fd, BLKSSZGET, &arg) == 0)
3908 if (sector_size != DEFAULT_SECTOR_SIZE)
3909 printf(_("Note: sector size is %d (not %d)\n"),
3910 sector_size, DEFAULT_SECTOR_SIZE);
3915 get_kernel_geometry(void) {
3916 struct hd_geometry geometry;
3918 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
3919 kern_heads = geometry.heads;
3920 kern_sectors = geometry.sectors;
3921 /* never use geometry.cylinders - it is truncated */
3926 get_partition_table_geometry(void) {
3927 const unsigned char *bufp = MBRbuffer;
3928 struct partition *p;
3929 int i, h, s, hh, ss;
3933 if (!(valid_part_table_flag(bufp)))
3937 for (i=0; i<4; i++) {
3938 p = pt_offset(bufp, i);
3939 if (p->sys_ind != 0) {
3940 h = p->end_head + 1;
3941 s = (p->end_sector & 077);
3946 } else if (hh != h || ss != s)
3951 if (!first && !bad) {
3958 get_geometry(void) {
3960 unsigned long long bytes; /* really u64 */
3963 sec_fac = sector_size / 512;
3964 #ifdef CONFIG_FEATURE_SUN_LABEL
3965 guess_device_type();
3967 heads = cylinders = sectors = 0;
3968 kern_heads = kern_sectors = 0;
3969 pt_heads = pt_sectors = 0;
3971 get_kernel_geometry();
3972 get_partition_table_geometry();
3974 heads = user_heads ? user_heads :
3975 pt_heads ? pt_heads :
3976 kern_heads ? kern_heads : 255;
3977 sectors = user_sectors ? user_sectors :
3978 pt_sectors ? pt_sectors :
3979 kern_sectors ? kern_sectors : 63;
3980 if (ioctl(fd, BLKGETSIZE64, &bytes) == 0) {
3983 unsigned long longsectors;
3985 if (ioctl(fd, BLKGETSIZE, &longsectors))
3987 bytes = ((unsigned long long) longsectors) << 9;
3990 total_number_of_sectors = (bytes >> 9);
3993 if (dos_compatible_flag)
3994 sector_offset = sectors;
3996 cylinders = total_number_of_sectors / (heads * sectors * sec_fac);
3998 cylinders = user_cylinders;
4002 * Read MBR. Returns:
4003 * -1: no 0xaa55 flag present (possibly entire disk BSD)
4004 * 0: found or created label
4008 get_boot(enum action what) {
4013 for (i = 0; i < 4; i++) {
4014 struct pte *pe = &ptes[i];
4016 pe->part_table = pt_offset(MBRbuffer, i);
4017 pe->ext_pointer = NULL;
4019 pe->sectorbuffer = MBRbuffer;
4020 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4021 pe->changed = (what == create_empty_dos);
4025 #ifdef CONFIG_FEATURE_SUN_LABEL
4026 if (what == create_empty_sun && check_sun_label())
4030 memset(MBRbuffer, 0, 512);
4032 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4033 if (what == create_empty_dos)
4034 goto got_dos_table; /* skip reading disk */
4036 if ((fd = open(disk_device, type_open)) < 0) {
4037 if ((fd = open(disk_device, O_RDONLY)) < 0) {
4038 if (what == try_only)
4040 fdisk_fatal(unable_to_open);
4042 printf(_("You will not be able to write "
4043 "the partition table.\n"));
4046 if (512 != read(fd, MBRbuffer, 512)) {
4047 if (what == try_only)
4049 fdisk_fatal(unable_to_read);
4052 if ((fd = open(disk_device, O_RDONLY)) < 0)
4054 if (512 != read(fd, MBRbuffer, 512))
4062 #ifdef CONFIG_FEATURE_SUN_LABEL
4063 if (check_sun_label())
4067 #ifdef CONFIG_FEATURE_SGI_LABEL
4068 if (check_sgi_label())
4072 #ifdef CONFIG_FEATURE_AIX_LABEL
4073 if (check_aix_label())
4077 #ifdef CONFIG_FEATURE_OSF_LABEL
4078 if (check_osf_label()) {
4079 possibly_osf_label = 1;
4080 if (!valid_part_table_flag(MBRbuffer)) {
4084 printf(_("This disk has both DOS and BSD magic.\n"
4085 "Give the 'b' command to go to BSD mode.\n"));
4089 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4093 if (!valid_part_table_flag(MBRbuffer)) {
4094 #ifndef CONFIG_FEATURE_FDISK_WRITABLE
4100 _("Device contains neither a valid DOS "
4101 "partition table, nor Sun, SGI or OSF "
4104 #ifdef CONFIG_FEATURE_SUN_LABEL
4113 case create_empty_dos:
4114 #ifdef CONFIG_FEATURE_SUN_LABEL
4115 case create_empty_sun:
4119 fprintf(stderr, _("Internal error\n"));
4122 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
4125 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4130 for (i = 0; i < 4; i++) {
4131 struct pte *pe = &ptes[i];
4133 if (IS_EXTENDED (pe->part_table->sys_ind)) {
4134 if (partitions != 4)
4135 fprintf(stderr, _("Ignoring extra extended "
4136 "partition %d\n"), i + 1);
4142 for (i = 3; i < partitions; i++) {
4143 struct pte *pe = &ptes[i];
4145 if (!valid_part_table_flag(pe->sectorbuffer)) {
4147 _("Warning: invalid flag 0x%04x of partition "
4148 "table %d will be corrected by w(rite)\n"),
4149 part_table_flag(pe->sectorbuffer), i + 1);
4150 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4159 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4161 * Print the message MESG, then read an integer between LOW and HIGH (inclusive).
4162 * If the user hits Enter, DFLT is returned.
4163 * Answers like +10 are interpreted as offsets from BASE.
4165 * There is no default if DFLT is not between LOW and HIGH.
4168 read_int(uint low, uint dflt, uint high, uint base, char *mesg)
4172 static char *ms = NULL;
4173 static int mslen = 0;
4175 if (!ms || strlen(mesg)+100 > mslen) {
4176 mslen = strlen(mesg)+200;
4177 ms = xrealloc(ms,mslen);
4180 if (dflt < low || dflt > high)
4184 snprintf(ms, mslen, _("%s (%u-%u, default %u): "),
4185 mesg, low, high, dflt);
4187 snprintf(ms, mslen, "%s (%u-%u): ",
4191 int use_default = default_ok;
4193 /* ask question and read answer */
4194 while (read_chars(ms) != '\n' && !isdigit(*line_ptr)
4195 && *line_ptr != '-' && *line_ptr != '+')
4198 if (*line_ptr == '+' || *line_ptr == '-') {
4199 int minus = (*line_ptr == '-');
4202 i = atoi(line_ptr+1);
4204 while (isdigit(*++line_ptr))
4207 switch (*line_ptr) {
4210 if (!display_in_cyl_units)
4211 i *= heads * sectors;
4225 absolute = 1000000000;
4231 unsigned long long bytes;
4234 bytes = (unsigned long long) i * absolute;
4235 unit = sector_size * units_per_sector;
4236 bytes += unit/2; /* round */
4245 while (isdigit(*line_ptr)) {
4251 printf(_("Using default value %u\n"), i = dflt);
4252 if (i >= low && i <= high)
4255 printf(_("Value out of range.\n"));
4261 get_partition(int warn, int max) {
4265 i = read_int(1, 0, max, 0, _("Partition number")) - 1;
4269 if ((!sun_label && !sgi_label && !pe->part_table->sys_ind)
4270 #ifdef CONFIG_FEATURE_SUN_LABEL
4272 (!sunlabel->partitions[i].num_sectors ||
4273 !sunlabel->infos[i].id))
4275 #ifdef CONFIG_FEATURE_SGI_LABEL
4276 || (sgi_label && (!sgi_get_num_sectors(i)))
4280 _("Warning: partition %d has empty type\n"),
4287 get_existing_partition(int warn, int max) {
4291 for (i = 0; i < max; i++) {
4292 struct pte *pe = &ptes[i];
4293 struct partition *p = pe->part_table;
4295 if (p && !is_cleared_partition(p)) {
4302 printf(_("Selected partition %d\n"), pno+1);
4305 printf(_("No partition is defined yet!\n"));
4309 return get_partition(warn, max);
4313 get_nonexisting_partition(int warn, int max) {
4317 for (i = 0; i < max; i++) {
4318 struct pte *pe = &ptes[i];
4319 struct partition *p = pe->part_table;
4321 if (p && is_cleared_partition(p)) {
4328 printf(_("Selected partition %d\n"), pno+1);
4331 printf(_("All primary partitions have been defined already!\n"));
4335 return get_partition(warn, max);
4339 void change_units(void)
4341 display_in_cyl_units = !display_in_cyl_units;
4343 printf(_("Changing display/entry units to %s\n"),
4348 toggle_active(int i) {
4349 struct pte *pe = &ptes[i];
4350 struct partition *p = pe->part_table;
4352 if (IS_EXTENDED (p->sys_ind) && !p->boot_ind)
4354 _("WARNING: Partition %d is an extended partition\n"),
4356 p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG);
4361 toggle_dos_compatibility_flag(void) {
4362 dos_compatible_flag = ~dos_compatible_flag;
4363 if (dos_compatible_flag) {
4364 sector_offset = sectors;
4365 printf(_("DOS Compatibility flag is set\n"));
4369 printf(_("DOS Compatibility flag is not set\n"));
4374 delete_partition(int i) {
4375 struct pte *pe = &ptes[i];
4376 struct partition *p = pe->part_table;
4377 struct partition *q = pe->ext_pointer;
4379 /* Note that for the fifth partition (i == 4) we don't actually
4380 * decrement partitions.
4383 if (warn_geometry())
4384 return; /* C/H/S not set */
4387 #ifdef CONFIG_FEATURE_SUN_LABEL
4389 sun_delete_partition(i);
4393 #ifdef CONFIG_FEATURE_SGI_LABEL
4395 sgi_delete_partition(i);
4401 if (IS_EXTENDED (p->sys_ind) && i == ext_index) {
4403 ptes[ext_index].ext_pointer = NULL;
4404 extended_offset = 0;
4410 if (!q->sys_ind && i > 4) {
4411 /* the last one in the chain - just delete */
4414 clear_partition(ptes[i].ext_pointer);
4415 ptes[i].changed = 1;
4417 /* not the last one - further ones will be moved down */
4419 /* delete this link in the chain */
4420 p = ptes[i-1].ext_pointer;
4422 set_start_sect(p, get_start_sect(q));
4423 set_nr_sects(p, get_nr_sects(q));
4424 ptes[i-1].changed = 1;
4425 } else if (partitions > 5) { /* 5 will be moved to 4 */
4426 /* the first logical in a longer chain */
4429 if (pe->part_table) /* prevent SEGFAULT */
4430 set_start_sect(pe->part_table,
4431 get_partition_start(pe) -
4433 pe->offset = extended_offset;
4437 if (partitions > 5) {
4439 while (i < partitions) {
4440 ptes[i] = ptes[i+1];
4444 /* the only logical: clear only */
4445 clear_partition(ptes[i].part_table);
4450 change_sysid(void) {
4451 int i, sys, origsys;
4452 struct partition *p;
4454 #ifdef CONFIG_FEATURE_SGI_LABEL
4455 /* If sgi_label then don't use get_existing_partition,
4456 let the user select a partition, since get_existing_partition()
4457 only works for Linux like partition tables. */
4459 i = get_existing_partition(0, partitions);
4461 i = get_partition(0, partitions);
4464 i = get_existing_partition(0, partitions);
4468 p = ptes[i].part_table;
4469 origsys = sys = get_sysid(i);
4471 /* if changing types T to 0 is allowed, then
4472 the reverse change must be allowed, too */
4473 if (!sys && !sgi_label && !sun_label && !get_nr_sects(p))
4474 printf(_("Partition %d does not exist yet!\n"), i + 1);
4476 sys = read_hex (get_sys_types());
4478 if (!sys && !sgi_label && !sun_label) {
4479 printf(_("Type 0 means free space to many systems\n"
4480 "(but not to Linux). Having partitions of\n"
4481 "type 0 is probably unwise. You can delete\n"
4482 "a partition using the `d' command.\n"));
4486 if (!sun_label && !sgi_label) {
4487 if (IS_EXTENDED (sys) != IS_EXTENDED (p->sys_ind)) {
4488 printf(_("You cannot change a partition into"
4489 " an extended one or vice versa\n"
4490 "Delete it first.\n"));
4496 #ifdef CONFIG_FEATURE_SUN_LABEL
4497 if (sun_label && i == 2 && sys != WHOLE_DISK)
4498 printf(_("Consider leaving partition 3 "
4499 "as Whole disk (5),\n"
4500 "as SunOS/Solaris expects it and "
4501 "even Linux likes it.\n\n"));
4503 #ifdef CONFIG_FEATURE_SGI_LABEL
4504 if (sgi_label && ((i == 10 && sys != ENTIRE_DISK)
4505 || (i == 8 && sys != 0)))
4506 printf(_("Consider leaving partition 9 "
4507 "as volume header (0),\nand "
4508 "partition 11 as entire volume (6)"
4509 "as IRIX expects it.\n\n"));
4513 #ifdef CONFIG_FEATURE_SUN_LABEL
4515 sun_change_sysid(i, sys);
4518 #ifdef CONFIG_FEATURE_SGI_LABEL
4520 sgi_change_sysid(i, sys);
4524 printf (_("Changed system type of partition %d "
4525 "to %x (%s)\n"), i + 1, sys,
4526 partition_type(sys));
4527 ptes[i].changed = 1;
4528 if (is_dos_partition(origsys) ||
4529 is_dos_partition(sys))
4535 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
4538 /* check_consistency() and long2chs() added Sat Mar 6 12:28:16 1993,
4539 * faith@cs.unc.edu, based on code fragments from pfdisk by Gordon W. Ross,
4540 * Jan. 1990 (version 1.2.1 by Gordon W. Ross Aug. 1990; Modified by S.
4541 * Lubkin Oct. 1991). */
4543 static void long2chs(ulong ls, uint *c, uint *h, uint *s) {
4544 int spc = heads * sectors;
4549 *s = ls % sectors + 1; /* sectors count from 1 */
4552 static void check_consistency(const struct partition *p, int partition) {
4553 uint pbc, pbh, pbs; /* physical beginning c, h, s */
4554 uint pec, peh, pes; /* physical ending c, h, s */
4555 uint lbc, lbh, lbs; /* logical beginning c, h, s */
4556 uint lec, leh, les; /* logical ending c, h, s */
4558 if (!heads || !sectors || (partition >= 4))
4559 return; /* do not check extended partitions */
4561 /* physical beginning c, h, s */
4562 pbc = (p->cyl & 0xff) | ((p->sector << 2) & 0x300);
4564 pbs = p->sector & 0x3f;
4566 /* physical ending c, h, s */
4567 pec = (p->end_cyl & 0xff) | ((p->end_sector << 2) & 0x300);
4569 pes = p->end_sector & 0x3f;
4571 /* compute logical beginning (c, h, s) */
4572 long2chs(get_start_sect(p), &lbc, &lbh, &lbs);
4574 /* compute logical ending (c, h, s) */
4575 long2chs(get_start_sect(p) + get_nr_sects(p) - 1, &lec, &leh, &les);
4577 /* Same physical / logical beginning? */
4578 if (cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) {
4579 printf(_("Partition %d has different physical/logical "
4580 "beginnings (non-Linux?):\n"), partition + 1);
4581 printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs);
4582 printf(_("logical=(%d, %d, %d)\n"),lbc, lbh, lbs);
4585 /* Same physical / logical ending? */
4586 if (cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) {
4587 printf(_("Partition %d has different physical/logical "
4588 "endings:\n"), partition + 1);
4589 printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
4590 printf(_("logical=(%d, %d, %d)\n"),lec, leh, les);
4594 /* Beginning on cylinder boundary? */
4595 if (pbh != !pbc || pbs != 1) {
4596 printf(_("Partition %i does not start on cylinder "
4597 "boundary:\n"), partition + 1);
4598 printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs);
4599 printf(_("should be (%d, %d, 1)\n"), pbc, !pbc);
4603 /* Ending on cylinder boundary? */
4604 if (peh != (heads - 1) || pes != sectors) {
4605 printf(_("Partition %i does not end on cylinder boundary.\n"),
4608 printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
4609 printf(_("should be (%d, %d, %d)\n"),
4610 pec, heads - 1, sectors);
4616 list_disk_geometry(void) {
4617 long long bytes = (total_number_of_sectors << 9);
4618 long megabytes = bytes/1000000;
4620 if (megabytes < 10000)
4621 printf(_("\nDisk %s: %ld MB, %lld bytes\n"),
4622 disk_device, megabytes, bytes);
4624 printf(_("\nDisk %s: %ld.%ld GB, %lld bytes\n"),
4625 disk_device, megabytes/1000, (megabytes/100)%10, bytes);
4626 printf(_("%d heads, %d sectors/track, %d cylinders"),
4627 heads, sectors, cylinders);
4628 if (units_per_sector == 1)
4629 printf(_(", total %llu sectors"),
4630 total_number_of_sectors / (sector_size/512));
4631 printf(_("\nUnits = %s of %d * %d = %d bytes\n\n"),
4633 units_per_sector, sector_size, units_per_sector * sector_size);
4637 * Check whether partition entries are ordered by their starting positions.
4638 * Return 0 if OK. Return i if partition i should have been earlier.
4639 * Two separate checks: primary and logical partitions.
4642 wrong_p_order(int *prev) {
4643 const struct pte *pe;
4644 const struct partition *p;
4645 uint last_p_start_pos = 0, p_start_pos;
4648 for (i = 0 ; i < partitions; i++) {
4651 last_p_start_pos = 0;
4654 if ((p = pe->part_table)->sys_ind) {
4655 p_start_pos = get_partition_start(pe);
4657 if (last_p_start_pos > p_start_pos) {
4663 last_p_start_pos = p_start_pos;
4670 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
4672 * Fix the chain of logicals.
4673 * extended_offset is unchanged, the set of sectors used is unchanged
4674 * The chain is sorted so that sectors increase, and so that
4675 * starting sectors increase.
4677 * After this it may still be that cfdisk doesnt like the table.
4678 * (This is because cfdisk considers expanded parts, from link to
4679 * end of partition, and these may still overlap.)
4681 * sfdisk /dev/hda > ohda; sfdisk /dev/hda < ohda
4685 fix_chain_of_logicals(void) {
4686 int j, oj, ojj, sj, sjj;
4687 struct partition *pj,*pjj,tmp;
4689 /* Stage 1: sort sectors but leave sector of part 4 */
4690 /* (Its sector is the global extended_offset.) */
4692 for (j = 5; j < partitions-1; j++) {
4693 oj = ptes[j].offset;
4694 ojj = ptes[j+1].offset;
4696 ptes[j].offset = ojj;
4697 ptes[j+1].offset = oj;
4698 pj = ptes[j].part_table;
4699 set_start_sect(pj, get_start_sect(pj)+oj-ojj);
4700 pjj = ptes[j+1].part_table;
4701 set_start_sect(pjj, get_start_sect(pjj)+ojj-oj);
4702 set_start_sect(ptes[j-1].ext_pointer,
4703 ojj-extended_offset);
4704 set_start_sect(ptes[j].ext_pointer,
4705 oj-extended_offset);
4710 /* Stage 2: sort starting sectors */
4712 for (j = 4; j < partitions-1; j++) {
4713 pj = ptes[j].part_table;
4714 pjj = ptes[j+1].part_table;
4715 sj = get_start_sect(pj);
4716 sjj = get_start_sect(pjj);
4717 oj = ptes[j].offset;
4718 ojj = ptes[j+1].offset;
4719 if (oj+sj > ojj+sjj) {
4723 set_start_sect(pj, ojj+sjj-oj);
4724 set_start_sect(pjj, oj+sj-ojj);
4729 /* Probably something was changed */
4730 for (j = 4; j < partitions; j++)
4731 ptes[j].changed = 1;
4736 fix_partition_table_order(void) {
4737 struct pte *pei, *pek;
4740 if (!wrong_p_order(NULL)) {
4741 printf(_("Nothing to do. Ordering is correct already.\n\n"));
4745 while ((i = wrong_p_order(&k)) != 0 && i < 4) {
4746 /* partition i should have come earlier, move it */
4747 /* We have to move data in the MBR */
4748 struct partition *pi, *pk, *pe, pbuf;
4752 pe = pei->ext_pointer;
4753 pei->ext_pointer = pek->ext_pointer;
4754 pek->ext_pointer = pe;
4756 pi = pei->part_table;
4757 pk = pek->part_table;
4759 memmove(&pbuf, pi, sizeof(struct partition));
4760 memmove(pi, pk, sizeof(struct partition));
4761 memmove(pk, &pbuf, sizeof(struct partition));
4763 pei->changed = pek->changed = 1;
4767 fix_chain_of_logicals();
4775 list_table(int xtra) {
4776 const struct partition *p;
4779 #ifdef CONFIG_FEATURE_SUN_LABEL
4781 sun_list_table(xtra);
4786 #ifdef CONFIG_FEATURE_SGI_LABEL
4788 sgi_list_table(xtra);
4793 list_disk_geometry();
4795 #ifdef CONFIG_FEATURE_OSF_LABEL
4797 xbsd_print_disklabel(xtra);
4802 /* Heuristic: we list partition 3 of /dev/foo as /dev/foo3,
4803 but if the device name ends in a digit, say /dev/foo1,
4804 then the partition is called /dev/foo1p3. */
4805 w = strlen(disk_device);
4806 if (w && isdigit(disk_device[w-1]))
4811 printf(_("%*s Boot Start End Blocks Id System\n"),
4814 for (i = 0; i < partitions; i++) {
4815 const struct pte *pe = &ptes[i];
4818 if (p && !is_cleared_partition(p)) {
4819 unsigned int psects = get_nr_sects(p);
4820 unsigned int pblocks = psects;
4821 unsigned int podd = 0;
4823 if (sector_size < 1024) {
4824 pblocks /= (1024 / sector_size);
4825 podd = psects % (1024 / sector_size);
4827 if (sector_size > 1024)
4828 pblocks *= (sector_size / 1024);
4830 "%s %c %11lu %11lu %11lu%c %2x %s\n",
4831 partname(disk_device, i+1, w+2),
4832 /* boot flag */ !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG
4834 /* start */ (unsigned long) cround(get_partition_start(pe)),
4835 /* end */ (unsigned long) cround(get_partition_start(pe) + psects
4836 - (psects ? 1 : 0)),
4837 /* odd flag on end */ (unsigned long) pblocks, podd ? '+' : ' ',
4838 /* type id */ p->sys_ind,
4839 /* type name */ partition_type(p->sys_ind));
4840 check_consistency(p, i);
4844 /* Is partition table in disk order? It need not be, but... */
4845 /* partition table entries are not checked for correct order if this
4846 is a sgi, sun or aix labeled disk... */
4847 if (dos_label && wrong_p_order(NULL)) {
4848 printf(_("\nPartition table entries are not in disk order\n"));
4852 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
4854 x_list_table(int extend) {
4855 const struct pte *pe;
4856 const struct partition *p;
4859 printf(_("\nDisk %s: %d heads, %d sectors, %d cylinders\n\n"),
4860 disk_device, heads, sectors, cylinders);
4861 printf(_("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n"));
4862 for (i = 0 ; i < partitions; i++) {
4864 p = (extend ? pe->ext_pointer : pe->part_table);
4866 printf("%2d %02x%4d%4d%5d%4d%4d%5d%11u%11u %02x\n",
4867 i + 1, p->boot_ind, p->head,
4869 cylinder(p->sector, p->cyl), p->end_head,
4870 sector(p->end_sector),
4871 cylinder(p->end_sector, p->end_cyl),
4872 get_start_sect(p), get_nr_sects(p), p->sys_ind);
4874 check_consistency(p, i);
4880 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4882 fill_bounds(uint *first, uint *last) {
4884 const struct pte *pe = &ptes[0];
4885 const struct partition *p;
4887 for (i = 0; i < partitions; pe++,i++) {
4889 if (!p->sys_ind || IS_EXTENDED (p->sys_ind)) {
4890 first[i] = 0xffffffff;
4893 first[i] = get_partition_start(pe);
4894 last[i] = first[i] + get_nr_sects(p) - 1;
4900 check(int n, uint h, uint s, uint c, uint start) {
4901 uint total, real_s, real_c;
4903 real_s = sector(s) - 1;
4904 real_c = cylinder(s, c);
4905 total = (real_c * sectors + real_s) * heads + h;
4907 fprintf(stderr, _("Warning: partition %d contains sector 0\n"), n);
4910 _("Partition %d: head %d greater than maximum %d\n"),
4912 if (real_s >= sectors)
4913 fprintf(stderr, _("Partition %d: sector %d greater than "
4914 "maximum %d\n"), n, s, sectors);
4915 if (real_c >= cylinders)
4916 fprintf(stderr, _("Partitions %d: cylinder %d greater than "
4917 "maximum %d\n"), n, real_c + 1, cylinders);
4918 if (cylinders <= 1024 && start != total)
4920 _("Partition %d: previous sectors %d disagrees with "
4921 "total %d\n"), n, start, total);
4928 uint first[partitions], last[partitions];
4929 struct partition *p;
4931 if (warn_geometry())
4934 #ifdef CONFIG_FEATURE_SUN_LABEL
4940 #ifdef CONFIG_FEATURE_SGI_LABEL
4947 fill_bounds(first, last);
4948 for (i = 0; i < partitions; i++) {
4949 struct pte *pe = &ptes[i];
4952 if (p->sys_ind && !IS_EXTENDED (p->sys_ind)) {
4953 check_consistency(p, i);
4954 if (get_partition_start(pe) < first[i])
4955 printf(_("Warning: bad start-of-data in "
4956 "partition %d\n"), i + 1);
4957 check(i + 1, p->end_head, p->end_sector, p->end_cyl,
4959 total += last[i] + 1 - first[i];
4960 for (j = 0; j < i; j++)
4961 if ((first[i] >= first[j] && first[i] <= last[j])
4962 || ((last[i] <= last[j] && last[i] >= first[j]))) {
4963 printf(_("Warning: partition %d overlaps "
4964 "partition %d.\n"), j + 1, i + 1);
4965 total += first[i] >= first[j] ?
4966 first[i] : first[j];
4967 total -= last[i] <= last[j] ?
4973 if (extended_offset) {
4974 struct pte *pex = &ptes[ext_index];
4975 uint e_last = get_start_sect(pex->part_table) +
4976 get_nr_sects(pex->part_table) - 1;
4978 for (i = 4; i < partitions; i++) {
4980 p = ptes[i].part_table;
4982 if (i != 4 || i + 1 < partitions)
4983 printf(_("Warning: partition %d "
4984 "is empty\n"), i + 1);
4986 else if (first[i] < extended_offset ||
4988 printf(_("Logical partition %d not entirely in "
4989 "partition %d\n"), i + 1, ext_index + 1);
4993 if (total > heads * sectors * cylinders)
4994 printf(_("Total allocated sectors %d greater than the maximum "
4995 "%d\n"), total, heads * sectors * cylinders);
4996 else if ((total = heads * sectors * cylinders - total) != 0)
4997 printf(_("%d unallocated sectors\n"), total);
5001 add_partition(int n, int sys) {
5002 char mesg[256]; /* 48 does not suffice in Japanese */
5004 struct partition *p = ptes[n].part_table;
5005 struct partition *q = ptes[ext_index].part_table;
5007 uint start, stop = 0, limit, temp,
5008 first[partitions], last[partitions];
5010 if (p && p->sys_ind) {
5011 printf(_("Partition %d is already defined. Delete "
5012 "it before re-adding it.\n"), n + 1);
5015 fill_bounds(first, last);
5017 start = sector_offset;
5018 if (display_in_cyl_units || !total_number_of_sectors)
5019 llimit = heads * sectors * cylinders - 1;
5021 llimit = total_number_of_sectors - 1;
5023 if (limit != llimit)
5025 if (extended_offset) {
5026 first[ext_index] = extended_offset;
5027 last[ext_index] = get_start_sect(q) +
5028 get_nr_sects(q) - 1;
5031 start = extended_offset + sector_offset;
5032 limit = get_start_sect(q) + get_nr_sects(q) - 1;
5034 if (display_in_cyl_units)
5035 for (i = 0; i < partitions; i++)
5036 first[i] = (cround(first[i]) - 1) * units_per_sector;
5038 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
5041 for (i = 0; i < partitions; i++) {
5044 if (start == ptes[i].offset)
5045 start += sector_offset;
5046 lastplusoff = last[i] + ((n<4) ? 0 : sector_offset);
5047 if (start >= first[i] && start <= lastplusoff)
5048 start = lastplusoff + 1;
5052 if (start >= temp+units_per_sector && readed) {
5053 printf(_("Sector %d is already allocated\n"), temp);
5057 if (!readed && start == temp) {
5060 saved_start = start;
5061 start = read_int(cround(saved_start), cround(saved_start), cround(limit),
5063 if (display_in_cyl_units) {
5064 start = (start - 1) * units_per_sector;
5065 if (start < saved_start) start = saved_start;
5069 } while (start != temp || !readed);
5070 if (n > 4) { /* NOT for fifth partition */
5071 struct pte *pe = &ptes[n];
5073 pe->offset = start - sector_offset;
5074 if (pe->offset == extended_offset) { /* must be corrected */
5076 if (sector_offset == 1)
5081 for (i = 0; i < partitions; i++) {
5082 struct pte *pe = &ptes[i];
5084 if (start < pe->offset && limit >= pe->offset)
5085 limit = pe->offset - 1;
5086 if (start < first[i] && limit >= first[i])
5087 limit = first[i] - 1;
5089 if (start > limit) {
5090 printf(_("No free sectors available\n"));
5095 if (cround(start) == cround(limit)) {
5098 snprintf(mesg, sizeof(mesg),
5099 _("Last %s or +size or +sizeM or +sizeK"),
5100 str_units(SINGULAR));
5101 stop = read_int(cround(start), cround(limit), cround(limit),
5102 cround(start), mesg);
5103 if (display_in_cyl_units) {
5104 stop = stop * units_per_sector - 1;
5110 set_partition(n, 0, start, stop, sys);
5112 set_partition(n - 1, 1, ptes[n].offset, stop, EXTENDED);
5114 if (IS_EXTENDED (sys)) {
5115 struct pte *pe4 = &ptes[4];
5116 struct pte *pen = &ptes[n];
5119 pen->ext_pointer = p;
5120 pe4->offset = extended_offset = start;
5121 pe4->sectorbuffer = xcalloc(1, sector_size);
5122 pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
5123 pe4->ext_pointer = pe4->part_table + 1;
5131 if (partitions > 5 || ptes[4].part_table->sys_ind) {
5132 struct pte *pe = &ptes[partitions];
5134 pe->sectorbuffer = xcalloc(1, sector_size);
5135 pe->part_table = pt_offset(pe->sectorbuffer, 0);
5136 pe->ext_pointer = pe->part_table + 1;
5141 add_partition(partitions - 1, LINUX_NATIVE);
5145 new_partition(void) {
5146 int i, free_primary = 0;
5148 if (warn_geometry())
5151 #ifdef CONFIG_FEATURE_SUN_LABEL
5153 add_sun_partition(get_partition(0, partitions), LINUX_NATIVE);
5157 #ifdef CONFIG_FEATURE_SGI_LABEL
5159 sgi_add_partition(get_partition(0, partitions), LINUX_NATIVE);
5163 #ifdef CONFIG_FEATURE_AIX_LABEL
5165 printf(_("\tSorry - this fdisk cannot handle AIX disk labels."
5166 "\n\tIf you want to add DOS-type partitions, create"
5167 "\n\ta new empty DOS partition table first. (Use o.)"
5169 "This will destroy the present disk contents.\n"));
5174 for (i = 0; i < 4; i++)
5175 free_primary += !ptes[i].part_table->sys_ind;
5177 if (!free_primary && partitions >= MAXIMUM_PARTS) {
5178 printf(_("The maximum number of partitions has been created\n"));
5182 if (!free_primary) {
5183 if (extended_offset)
5186 printf(_("You must delete some partition and add "
5187 "an extended partition first\n"));
5189 char c, line[LINE_LENGTH];
5190 snprintf(line, sizeof(line), "%s\n %s\n p primary "
5191 "partition (1-4)\n",
5192 "Command action", (extended_offset ?
5193 "l logical (5 or over)" : "e extended"));
5195 if ((c = read_char(line)) == 'p' || c == 'P') {
5196 i = get_nonexisting_partition(0, 4);
5198 add_partition(i, LINUX_NATIVE);
5201 else if (c == 'l' && extended_offset) {
5205 else if (c == 'e' && !extended_offset) {
5206 i = get_nonexisting_partition(0, 4);
5208 add_partition(i, EXTENDED);
5212 printf(_("Invalid partition number "
5213 "for type `%c'\n"), c);
5224 if (ptes[i].changed)
5225 ptes[3].changed = 1;
5226 for (i = 3; i < partitions; i++) {
5227 struct pte *pe = &ptes[i];
5230 write_part_table_flag(pe->sectorbuffer);
5231 write_sector(pe->offset, pe->sectorbuffer);
5235 #ifdef CONFIG_FEATURE_SGI_LABEL
5236 else if (sgi_label) {
5237 /* no test on change? the printf below might be mistaken */
5241 #ifdef CONFIG_FEATURE_SUN_LABEL
5242 else if (sun_label) {
5246 if (ptes[i].changed)
5253 printf(_("The partition table has been altered!\n\n"));
5254 reread_partition_table(1);
5258 reread_partition_table(int leave) {
5262 printf(_("Calling ioctl() to re-read partition table.\n"));
5265 if ((i = ioctl(fd, BLKRRPART)) != 0) {
5268 /* some kernel versions (1.2.x) seem to have trouble
5269 rereading the partition table, but if asked to do it
5270 twice, the second time works. - biro@yggdrasil.com */
5273 if ((i = ioctl(fd, BLKRRPART)) != 0)
5278 printf(_("\nWARNING: Re-reading the partition table "
5279 "failed with error %d: %s.\n"
5280 "The kernel still uses the old table.\n"
5281 "The new table will be used "
5282 "at the next reboot.\n"),
5283 error, strerror(error));
5288 _("\nWARNING: If you have created or modified any DOS 6.x\n"
5289 "partitions, please see the fdisk manual page for additional\n"
5295 printf(_("Syncing disks.\n"));
5297 sleep(4); /* for sync() */
5301 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
5303 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
5304 #define MAX_PER_LINE 16
5306 print_buffer(char pbuffer[]) {
5310 for (i = 0, l = 0; i < sector_size; i++, l++) {
5312 printf("0x%03X:", i);
5313 printf(" %02X", (unsigned char) pbuffer[i]);
5314 if (l == MAX_PER_LINE - 1) {
5329 printf(_("Device: %s\n"), disk_device);
5330 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
5331 if (sun_label || sgi_label)
5332 print_buffer(MBRbuffer);
5335 for (i = 3; i < partitions; i++)
5336 print_buffer(ptes[i].sectorbuffer);
5341 struct pte *pe = &ptes[i];
5342 struct partition *p = pe->part_table;
5345 if (warn_geometry())
5347 if (!p->sys_ind || !get_nr_sects(p) || IS_EXTENDED (p->sys_ind)) {
5348 printf(_("Partition %d has no data area\n"), i + 1);
5351 first = get_partition_start(pe);
5352 new = read_int(first, first, first + get_nr_sects(p) - 1, first,
5353 _("New beginning of data")) - pe->offset;
5355 if (new != get_nr_sects(p)) {
5356 first = get_nr_sects(p) + get_start_sect(p) - new;
5357 set_nr_sects(p, first);
5358 set_start_sect(p, new);
5369 c = tolower(read_char(_("Expert command (m for help): ")));
5372 #ifdef CONFIG_FEATURE_SUN_LABEL
5379 move_begin(get_partition(0, partitions));
5382 user_cylinders = cylinders =
5383 read_int(1, cylinders, 1048576, 0,
5384 _("Number of cylinders"));
5385 #ifdef CONFIG_FEATURE_SUN_LABEL
5387 sun_set_ncyl(cylinders);
5396 #ifdef CONFIG_FEATURE_SGI_LABEL
5401 #ifdef CONFIG_FEATURE_SUN_LABEL
5411 fix_partition_table_order();
5414 #ifdef CONFIG_FEATURE_SGI_LABEL
5419 user_heads = heads = read_int(1, heads, 256, 0,
5420 _("Number of heads"));
5424 #ifdef CONFIG_FEATURE_SUN_LABEL
5430 #ifdef CONFIG_FEATURE_SUN_LABEL
5436 #ifdef CONFIG_FEATURE_SUN_LABEL
5450 user_sectors = sectors = read_int(1, sectors, 63, 0,
5451 _("Number of sectors"));
5452 if (dos_compatible_flag) {
5453 sector_offset = sectors;
5454 fprintf(stderr, _("Warning: setting "
5455 "sector offset for DOS "
5464 write_table(); /* does not return */
5467 #ifdef CONFIG_FEATURE_SUN_LABEL
5469 sun_set_pcylcount();
5477 #endif /* ADVANCED mode */
5480 is_ide_cdrom_or_tape(const char *device) {
5483 struct stat statbuf;
5486 /* No device was given explicitly, and we are trying some
5487 likely things. But opening /dev/hdc may produce errors like
5488 "hdc: tray open or drive not ready"
5489 if it happens to be a CD-ROM drive. It even happens that
5490 the process hangs on the attempt to read a music CD.
5491 So try to be careful. This only works since 2.1.73. */
5493 if (strncmp("/dev/hd", device, 7))
5496 snprintf(buf, sizeof(buf), "/proc/ide/%s/media", device+5);
5497 procf = fopen(buf, "r");
5498 if (procf != NULL && fgets(buf, sizeof(buf), procf))
5499 is_ide = (!strncmp(buf, "cdrom", 5) ||
5500 !strncmp(buf, "tape", 4));
5502 /* Now when this proc file does not exist, skip the
5503 device when it is read-only. */
5504 if (stat(device, &statbuf) == 0)
5505 is_ide = ((statbuf.st_mode & 0222) == 0);
5513 try(const char *device, int user_specified) {
5516 disk_device = device;
5517 if (setjmp(listingbuf))
5519 if (!user_specified)
5520 if (is_ide_cdrom_or_tape(device))
5522 if ((fd = open(disk_device, type_open)) >= 0) {
5523 gb = get_boot(try_only);
5524 if (gb > 0) { /* I/O error */
5526 } else if (gb < 0) { /* no DOS signature */
5527 list_disk_geometry();
5530 #ifdef CONFIG_FEATURE_OSF_LABEL
5531 if (btrydev(device) < 0)
5534 _("Disk %s doesn't contain a valid "
5535 "partition table\n"), device);
5540 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5541 if (!sun_label && partitions > 4)
5542 delete_partition(ext_index);
5546 /* Ignore other errors, since we try IDE
5547 and SCSI hard disks which may not be
5548 installed on the system. */
5549 if (errno == EACCES) {
5550 fprintf(stderr, _("Cannot open %s\n"), device);
5556 /* for fdisk -l: try all things in /proc/partitions
5557 that look like a partition name (do not end in a digit) */
5561 char line[100], ptname[100], devname[120], *s;
5564 procpt = bb_wfopen(PROC_PARTITIONS, "r");
5566 while (fgets(line, sizeof(line), procpt)) {
5567 if (sscanf (line, " %d %d %d %[^\n ]",
5568 &ma, &mi, &sz, ptname) != 4)
5570 for (s = ptname; *s; s++);
5573 sprintf(devname, "/dev/%s", ptname);
5576 #ifdef CONFIG_FEATURE_CLEAN_UP
5581 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5583 unknown_command(int c) {
5584 printf(_("%c: unknown command\n"), c);
5588 int fdisk_main(int argc, char **argv) {
5590 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5593 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5599 * fdisk -l [-b sectorsize] [-u] device ...
5600 * fdisk -s [partition] ...
5601 * fdisk [-b sectorsize] [-u] device
5603 * Options -C, -H, -S set the geometry.
5606 while ((c = getopt(argc, argv, "b:C:H:lS:uvV"
5607 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5613 /* Ugly: this sector size is really per device,
5614 so cannot be combined with multiple disks,
5615 and te same goes for the C/H/S options.
5617 sector_size = atoi(optarg);
5618 if (sector_size != 512 && sector_size != 1024 &&
5619 sector_size != 2048)
5622 user_set_sector_size = 1;
5625 user_cylinders = atoi(optarg);
5628 user_heads = atoi(optarg);
5629 if (user_heads <= 0 || user_heads >= 256)
5633 user_sectors = atoi(optarg);
5634 if (user_sectors <= 0 || user_sectors >= 64)
5638 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5642 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5648 display_in_cyl_units = 0;
5652 printf("fdisk v" UTIL_LINUX_VERSION "\n");
5660 printf(_("This kernel finds the sector size itself - "
5661 "-b option ignored\n"));
5663 if (user_set_sector_size && argc-optind != 1)
5664 printf(_("Warning: the -b (set sector size) option should"
5665 " be used with one specified device\n"));
5668 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5672 type_open = O_RDONLY;
5673 if (argc > optind) {
5676 /* avoid gcc warning:
5677 variable `k' might be clobbered by `longjmp' */
5681 for (k=optind; k<argc; k++)
5684 /* we no longer have default device names */
5685 /* but, we can use /proc/partitions instead */
5689 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5693 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5699 type_open = O_RDONLY;
5701 opts = argc - optind;
5705 for (j = optind; j < argc; j++) {
5706 disk_device = argv[j];
5707 if ((fd = open(disk_device, type_open)) < 0)
5708 fdisk_fatal(unable_to_open);
5709 if (ioctl(fd, BLKGETSIZE, &size))
5710 fdisk_fatal(ioctl_error);
5713 printf("%ld\n", size/2);
5715 printf("%s: %ld\n", argv[j], size/2);
5721 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5722 if (argc-optind == 1)
5723 disk_device = argv[optind];
5729 #ifdef CONFIG_FEATURE_OSF_LABEL
5731 /* OSF label, and no DOS label */
5732 printf(_("Detected an OSF/1 disklabel on %s, entering "
5733 "disklabel mode.\n"),
5737 /* If we return we may want to make an empty DOS label? */
5743 c = tolower(read_char(_("Command (m for help): ")));
5747 toggle_active(get_partition(1, partitions));
5748 #ifdef CONFIG_FEATURE_SUN_LABEL
5750 toggle_sunflags(get_partition(1, partitions),
5753 #ifdef CONFIG_FEATURE_SGI_LABEL
5755 sgi_set_bootpartition(
5756 get_partition(1, partitions));
5762 #ifdef CONFIG_FEATURE_SGI_LABEL
5764 printf(_("\nThe current boot file is: %s\n"),
5765 sgi_get_bootfile());
5766 if (read_chars(_("Please enter the name of the "
5767 "new boot file: ")) == '\n')
5768 printf(_("Boot file unchanged\n"));
5770 sgi_set_bootfile(line_ptr);
5773 #ifdef CONFIG_FEATURE_OSF_LABEL
5779 toggle_dos_compatibility_flag();
5780 #ifdef CONFIG_FEATURE_SUN_LABEL
5782 toggle_sunflags(get_partition(1, partitions),
5785 #ifdef CONFIG_FEATURE_SGI_LABEL
5787 sgi_set_swappartition(
5788 get_partition(1, partitions));
5796 #ifdef CONFIG_FEATURE_SGI_LABEL
5797 /* If sgi_label then don't use get_existing_partition,
5798 let the user select a partition, since
5799 get_existing_partition() only works for Linux-like
5802 j = get_existing_partition(1, partitions);
5804 j = get_partition(1, partitions);
5807 j = get_existing_partition(1, partitions);
5810 delete_partition(j);
5814 #ifdef CONFIG_FEATURE_SGI_LABEL
5821 list_types(get_sys_types());
5840 #ifdef CONFIG_FEATURE_SUN_LABEL
5854 write_table(); /* does not return */
5856 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
5858 #ifdef CONFIG_FEATURE_SGI_LABEL
5861 _("\n\tSorry, no experts menu for SGI "
5862 "partition tables available.\n\n"));
5875 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */