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.12"
15 #define PROC_PARTITIONS "/proc/partitions"
18 #include <sys/types.h>
19 #include <sys/stat.h> /* stat */
28 #include <assert.h> /* assert */
31 #include <sys/ioctl.h>
32 #include <sys/param.h>
33 #include <sys/sysmacros.h> /* major */
35 #include <stdint.h> /* for uint32_t, uint16_t, uint8_t, int16_t, etc */
37 /* Copied from linux/major.h */
38 #define FLOPPY_MAJOR 2
40 #include <sys/utsname.h>
44 #define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r))
50 #define BLKRRPART _IO(0x12,95) /* re-read partition table */
51 #define BLKGETSIZE _IO(0x12,96) /* return device size */
52 #define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */
53 #define BLKSSZGET _IO(0x12,104) /* get block device sector size */
55 /* Avoid conflicts with the 2.6 kernel headers, which define
56 * _IOR rather differently */
58 #define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size))
59 #define BLKGETSIZE64 _IOR(0x12,114,uint64_t)
65 #define DEFAULT_SECTOR_SIZE 512
66 #define MAX_SECTOR_SIZE 2048
67 #define SECTOR_SIZE 512 /* still used in BSD code */
68 #define MAXIMUM_PARTS 60
70 #define ACTIVE_FLAG 0x80
73 #define WIN98_EXTENDED 0x0f
74 #define LINUX_PARTITION 0x81
75 #define LINUX_SWAP 0x82
76 #define LINUX_NATIVE 0x83
77 #define LINUX_EXTENDED 0x85
78 #define LINUX_LVM 0x8e
79 #define LINUX_RAID 0xfd
84 #define IS_EXTENDED(i) \
85 ((i) == EXTENDED || (i) == WIN98_EXTENDED || (i) == LINUX_EXTENDED)
87 #define SIZE(a) (sizeof(a)/sizeof((a)[0]))
89 #define cround(n) (display_in_cyl_units ? ((n)/units_per_sector)+1 : (n))
90 #define scround(x) (((x)+units_per_sector-1)/units_per_sector)
92 #ifdef CONFIG_FEATURE_SUN_LABEL
93 #define SCSI_IOCTL_GET_IDLUN 0x5382
97 /* including <linux/hdreg.h> also fails */
100 unsigned char sectors;
101 unsigned short cylinders;
105 #define HDIO_GETGEO 0x0301 /* get device geometry */
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 #if (MAX_SECTOR_SIZE) > (BUFSIZ+1)
121 static char MBRbuffer[MAX_SECTOR_SIZE];
123 # define MBRbuffer bb_common_bufsiz1
126 #ifdef CONFIG_FEATURE_SUN_LABEL
127 static int sun_label; /* looking at sun disklabel */
131 #ifdef CONFIG_FEATURE_SGI_LABEL
132 static int sgi_label; /* looking at sgi disklabel */
136 #ifdef CONFIG_FEATURE_AIX_LABEL
137 static int aix_label; /* looking at aix disklabel */
141 #ifdef CONFIG_FEATURE_OSF_LABEL
142 static int osf_label; /* looking at OSF/1 disklabel */
143 static int possibly_osf_label;
148 #define dos_label (!sun_label && !sgi_label && !aix_label && !osf_label)
150 static uint heads, sectors, cylinders;
151 static void update_units(void);
155 * return partition name - uses static storage unless buf is supplied
158 partname(const char *dev, int pno, int lth) {
159 static char buffer[80];
166 bufsiz = sizeof(buffer);
171 if (isdigit(dev[w-1]))
174 /* devfs kludge - note: fdisk partition names are not supposed
175 to equal kernel names, so there is no reason to do this */
176 if (strcmp (dev + w - 4, "disc") == 0) {
184 snprintf(bufp, bufsiz, "%*.*s%s%-2u",
185 lth-wp-2, w, dev, p, pno);
187 snprintf(bufp, bufsiz, "%.*s%s%-2u", w, dev, p, pno);
193 unsigned char boot_ind; /* 0x80 - active */
194 unsigned char head; /* starting head */
195 unsigned char sector; /* starting sector */
196 unsigned char cyl; /* starting cylinder */
197 unsigned char sys_ind; /* What partition type */
198 unsigned char end_head; /* end head */
199 unsigned char end_sector; /* end sector */
200 unsigned char end_cyl; /* end cylinder */
201 unsigned char start4[4]; /* starting sector counting from 0 */
202 unsigned char size4[4]; /* nr of sectors in partition */
203 } __attribute__((__packed__));
206 ioctl_error, unable_to_open, unable_to_read, unable_to_seek,
210 enum action {fdisk, require, try_only, create_empty_dos, create_empty_sun};
212 static const char *disk_device;
213 static int fd; /* the disk */
214 static int partitions = 4; /* maximum partition + 1 */
215 static uint display_in_cyl_units = 1;
216 static uint units_per_sector = 1;
217 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
218 static char *line_ptr;
219 static void change_units(void);
220 static void reread_partition_table(int leave);
221 static void delete_partition(int i);
222 static int get_partition(int warn, int max);
223 static void list_types(const struct systypes *sys);
224 static uint read_int(uint low, uint dflt, uint high, uint base, char *mesg);
226 static const char *partition_type(unsigned char type);
227 static void fdisk_fatal(enum failure why) __attribute__ ((noreturn));
228 static void get_geometry(void);
229 static int get_boot(enum action what);
234 #define hex_val(c) ({ \
236 isdigit(_c) ? _c - '0' : \
237 tolower(_c) + 10 - 'a'; \
241 #define LINE_LENGTH 800
242 #define pt_offset(b, n) ((struct partition *)((b) + 0x1be + \
243 (n) * sizeof(struct partition)))
244 #define sector(s) ((s) & 0x3f)
245 #define cylinder(s, c) ((c) | (((s) & 0xc0) << 2))
247 #define hsc2sector(h,s,c) (sector(s) - 1 + sectors * \
248 ((h) + heads * cylinder(s,c)))
249 #define set_hsc(h,s,c,sector) { \
250 s = sector % sectors + 1; \
252 h = sector % heads; \
255 s |= (sector >> 2) & 0xc0; \
259 static int32_t get_start_sect(const struct partition *p);
260 static int32_t get_nr_sects(const struct partition *p);
263 * per partition table entry data
265 * The four primary partitions have the same sectorbuffer (MBRbuffer)
266 * and have NULL ext_pointer.
267 * Each logical partition table entry has two pointers, one for the
268 * partition and one link to the next one.
271 struct partition *part_table; /* points into sectorbuffer */
272 struct partition *ext_pointer; /* points into sectorbuffer */
273 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
274 char changed; /* boolean */
276 off_t offset; /* disk sector number */
277 char *sectorbuffer; /* disk sector contents */
278 } ptes[MAXIMUM_PARTS];
281 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
283 set_all_unchanged(void) {
286 for (i = 0; i < MAXIMUM_PARTS; i++)
294 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
296 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_OSF_LABEL)
297 static struct partition *
298 get_part_table(int i) {
299 return ptes[i].part_table;
304 str_units(int n) { /* n==1: use singular */
306 return display_in_cyl_units ? _("cylinder") : _("sector");
308 return display_in_cyl_units ? _("cylinders") : _("sectors");
312 valid_part_table_flag(const char *mbuffer) {
313 const unsigned char *b = (const unsigned char *)mbuffer;
314 return (b[510] == 0x55 && b[511] == 0xaa);
317 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
318 static char line_buffer[LINE_LENGTH];
320 /* read line; return 0 or first char */
324 static int got_eof = 0;
326 fflush (stdout); /* requested by niles@scyld.com */
327 line_ptr = line_buffer;
328 if (!fgets(line_buffer, LINE_LENGTH, stdin)) {
330 got_eof++; /* user typed ^D ? */
332 fprintf(stderr, _("\ngot EOF thrice - exiting..\n"));
337 while (*line_ptr && !isgraph(*line_ptr))
343 read_char(const char *mesg)
347 } while (!read_line());
352 read_chars(const char *mesg)
363 read_hex(const struct systypes *sys)
369 read_char(_("Hex code (type L to list codes): "));
370 if (*line_ptr == 'l' || *line_ptr == 'L')
372 else if (isxdigit (*line_ptr))
376 hex = hex << 4 | hex_val(*line_ptr++);
377 while (isxdigit(*line_ptr));
382 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
384 #ifdef CONFIG_FEATURE_AIX_LABEL
386 * Copyright (C) Andreas Neuper, Sep 1998.
387 * This file may be redistributed under
388 * the terms of the GNU Public License.
392 unsigned int magic; /* expect AIX_LABEL_MAGIC */
393 unsigned int fillbytes1[124];
394 unsigned int physical_volume_id;
395 unsigned int fillbytes2[124];
398 #define AIX_LABEL_MAGIC 0xc9c2d4c1
399 #define AIX_LABEL_MAGIC_SWAPPED 0xc1d4c2c9
400 #define AIX_INFO_MAGIC 0x00072959
401 #define AIX_INFO_MAGIC_SWAPPED 0x59290700
403 #define aixlabel ((aix_partition *)MBRbuffer)
408 * 1999-03-20 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
409 * Internationalization
411 * 2003-03-20 Phillip Kesling <pkesling@sgi.com>
415 static int aix_other_endian;
416 static short aix_volumes=1;
419 * only dealing with free blocks here
425 _("\n\tThere is a valid AIX label on this disk.\n"
426 "\tUnfortunately Linux cannot handle these\n"
427 "\tdisks at the moment. Nevertheless some\n"
429 "\t1. fdisk will destroy its contents on write.\n"
430 "\t2. Be sure that this disk is NOT a still vital\n"
431 "\t part of a volume group. (Otherwise you may\n"
432 "\t erase the other disks as well, if unmirrored.)\n"
433 "\t3. Before deleting this physical volume be sure\n"
434 "\t to remove the disk logically from your AIX\n"
435 "\t machine. (Otherwise you become an AIXpert).")
445 memset( MBRbuffer, 0, sizeof(MBRbuffer) ); /* avoid fdisk cores */
450 check_aix_label( void )
452 if (aixlabel->magic != AIX_LABEL_MAGIC &&
453 aixlabel->magic != AIX_LABEL_MAGIC_SWAPPED) {
455 aix_other_endian = 0;
458 aix_other_endian = (aixlabel->magic == AIX_LABEL_MAGIC_SWAPPED);
464 aix_nolabel(); /* %% */
465 aix_label = 1; /* %% */
468 #endif /* AIX_LABEL */
470 #ifdef CONFIG_FEATURE_OSF_LABEL
472 * Copyright (c) 1987, 1988 Regents of the University of California.
473 * All rights reserved.
475 * Redistribution and use in source and binary forms, with or without
476 * modification, are permitted provided that the following conditions
478 * 1. Redistributions of source code must retain the above copyright
479 * notice, this list of conditions and the following disclaimer.
480 * 2. Redistributions in binary form must reproduce the above copyright
481 * notice, this list of conditions and the following disclaimer in the
482 * documentation and/or other materials provided with the distribution.
483 * 3. All advertising materials mentioning features or use of this software
484 * must display the following acknowledgment:
485 * This product includes software developed by the University of
486 * California, Berkeley and its contributors.
487 * 4. Neither the name of the University nor the names of its contributors
488 * may be used to endorse or promote products derived from this software
489 * without specific prior written permission.
491 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
492 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
493 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
494 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
495 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
496 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
497 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
498 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
499 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
500 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
505 #ifndef BSD_DISKMAGIC
506 #define BSD_DISKMAGIC ((uint32_t) 0x82564557)
509 #ifndef BSD_MAXPARTITIONS
510 #define BSD_MAXPARTITIONS 16
513 #define BSD_LINUX_BOOTDIR "/usr/ucb/mdec"
515 #if defined (i386) || defined (__sparc__) || defined (__arm__) || defined (__mips__) || defined (__s390__) || defined (__sh__) || defined(__x86_64__)
516 #define BSD_LABELSECTOR 1
517 #define BSD_LABELOFFSET 0
518 #elif defined (__alpha__) || defined (__powerpc__) || defined (__ia64__) || defined (__hppa__)
519 #define BSD_LABELSECTOR 0
520 #define BSD_LABELOFFSET 64
521 #elif defined (__s390__) || defined (__s390x__)
522 #define BSD_LABELSECTOR 1
523 #define BSD_LABELOFFSET 0
525 #error unknown architecture
528 #define BSD_BBSIZE 8192 /* size of boot area, with label */
529 #define BSD_SBSIZE 8192 /* max size of fs superblock */
531 struct xbsd_disklabel {
532 uint32_t d_magic; /* the magic number */
533 int16_t d_type; /* drive type */
534 int16_t d_subtype; /* controller/d_type specific */
535 char d_typename[16]; /* type name, e.g. "eagle" */
536 char d_packname[16]; /* pack identifier */
538 uint32_t d_secsize; /* # of bytes per sector */
539 uint32_t d_nsectors; /* # of data sectors per track */
540 uint32_t d_ntracks; /* # of tracks per cylinder */
541 uint32_t d_ncylinders; /* # of data cylinders per unit */
542 uint32_t d_secpercyl; /* # of data sectors per cylinder */
543 uint32_t d_secperunit; /* # of data sectors per unit */
545 * Spares (bad sector replacements) below
546 * are not counted in d_nsectors or d_secpercyl.
547 * Spare sectors are assumed to be physical sectors
548 * which occupy space at the end of each track and/or cylinder.
550 uint16_t d_sparespertrack; /* # of spare sectors per track */
551 uint16_t d_sparespercyl; /* # of spare sectors per cylinder */
553 * Alternate cylinders include maintenance, replacement,
554 * configuration description areas, etc.
556 uint32_t d_acylinders; /* # of alt. cylinders per unit */
558 /* hardware characteristics: */
560 * d_interleave, d_trackskew and d_cylskew describe perturbations
561 * in the media format used to compensate for a slow controller.
562 * Interleave is physical sector interleave, set up by the formatter
563 * or controller when formatting. When interleaving is in use,
564 * logically adjacent sectors are not physically contiguous,
565 * but instead are separated by some number of sectors.
566 * It is specified as the ratio of physical sectors traversed
567 * per logical sector. Thus an interleave of 1:1 implies contiguous
568 * layout, while 2:1 implies that logical sector 0 is separated
569 * by one sector from logical sector 1.
570 * d_trackskew is the offset of sector 0 on track N
571 * relative to sector 0 on track N-1 on the same cylinder.
572 * Finally, d_cylskew is the offset of sector 0 on cylinder N
573 * relative to sector 0 on cylinder N-1.
575 uint16_t d_rpm; /* rotational speed */
576 uint16_t d_interleave; /* hardware sector interleave */
577 uint16_t d_trackskew; /* sector 0 skew, per track */
578 uint16_t d_cylskew; /* sector 0 skew, per cylinder */
579 uint32_t d_headswitch; /* head switch time, usec */
580 uint32_t d_trkseek; /* track-to-track seek, usec */
581 uint32_t d_flags; /* generic flags */
583 uint32_t d_drivedata[NDDATA]; /* drive-type specific information */
585 uint32_t d_spare[NSPARE]; /* reserved for future use */
586 uint32_t d_magic2; /* the magic number (again) */
587 uint16_t d_checksum; /* xor of data incl. partitions */
588 /* filesystem and partition information: */
589 uint16_t d_npartitions; /* number of partitions in following */
590 uint32_t d_bbsize; /* size of boot area at sn0, bytes */
591 uint32_t d_sbsize; /* max size of fs superblock, bytes */
592 struct xbsd_partition { /* the partition table */
593 uint32_t p_size; /* number of sectors in partition */
594 uint32_t p_offset; /* starting sector */
595 uint32_t p_fsize; /* filesystem basic fragment size */
596 uint8_t p_fstype; /* filesystem type, see below */
597 uint8_t p_frag; /* filesystem fragments per block */
598 uint16_t p_cpg; /* filesystem cylinders per group */
599 } d_partitions[BSD_MAXPARTITIONS]; /* actually may be more */
603 #define BSD_DTYPE_SMD 1 /* SMD, XSMD; VAX hp/up */
604 #define BSD_DTYPE_MSCP 2 /* MSCP */
605 #define BSD_DTYPE_DEC 3 /* other DEC (rk, rl) */
606 #define BSD_DTYPE_SCSI 4 /* SCSI */
607 #define BSD_DTYPE_ESDI 5 /* ESDI interface */
608 #define BSD_DTYPE_ST506 6 /* ST506 etc. */
609 #define BSD_DTYPE_HPIB 7 /* CS/80 on HP-IB */
610 #define BSD_DTYPE_HPFL 8 /* HP Fiber-link */
611 #define BSD_DTYPE_FLOPPY 10 /* floppy */
613 /* d_subtype values: */
614 #define BSD_DSTYPE_INDOSPART 0x8 /* is inside dos partition */
615 #define BSD_DSTYPE_DOSPART(s) ((s) & 3) /* dos partition number */
616 #define BSD_DSTYPE_GEOMETRY 0x10 /* drive params in label */
619 static const char * const xbsd_dktypenames[] = {
633 #define BSD_DKMAXTYPES (sizeof(xbsd_dktypenames) / sizeof(xbsd_dktypenames[0]) - 1)
637 * Filesystem type and version.
638 * Used to interpret other filesystem-specific
639 * per-partition information.
641 #define BSD_FS_UNUSED 0 /* unused */
642 #define BSD_FS_SWAP 1 /* swap */
643 #define BSD_FS_V6 2 /* Sixth Edition */
644 #define BSD_FS_V7 3 /* Seventh Edition */
645 #define BSD_FS_SYSV 4 /* System V */
646 #define BSD_FS_V71K 5 /* V7 with 1K blocks (4.1, 2.9) */
647 #define BSD_FS_V8 6 /* Eighth Edition, 4K blocks */
648 #define BSD_FS_BSDFFS 7 /* 4.2BSD fast file system */
649 #define BSD_FS_BSDLFS 9 /* 4.4BSD log-structured file system */
650 #define BSD_FS_OTHER 10 /* in use, but unknown/unsupported */
651 #define BSD_FS_HPFS 11 /* OS/2 high-performance file system */
652 #define BSD_FS_ISO9660 12 /* ISO-9660 filesystem (cdrom) */
653 #define BSD_FS_ISOFS BSD_FS_ISO9660
654 #define BSD_FS_BOOT 13 /* partition contains bootstrap */
655 #define BSD_FS_ADOS 14 /* AmigaDOS fast file system */
656 #define BSD_FS_HFS 15 /* Macintosh HFS */
657 #define BSD_FS_ADVFS 16 /* Digital Unix AdvFS */
659 /* this is annoying, but it's also the way it is :-( */
661 #define BSD_FS_EXT2 8 /* ext2 file system */
663 #define BSD_FS_MSDOS 8 /* MS-DOS file system */
667 static const struct systypes xbsd_fstypes[] = {
668 /* BSD_FS_UNUSED */ {"\x00" "unused"},
669 /* BSD_FS_SWAP */ {"\x01" "swap"},
670 /* BSD_FS_V6 */ {"\x02" "Version 6"},
671 /* BSD_FS_V7 */ {"\x03" "Version 7"},
672 /* BSD_FS_SYSV */ {"\x04" "System V"},
673 /* BSD_FS_V71K */ {"\x05" "4.1BSD"},
674 /* BSD_FS_V8 */ {"\x06" "Eighth Edition"},
675 /* BSD_FS_BSDFFS */ {"\x07" "4.2BSD"},
677 /* BSD_FS_EXT2 */ {"\x08" "ext2"},
679 /* BSD_FS_MSDOS */ {"\x08" "MS-DOS"},
681 /* BSD_FS_BSDLFS */ {"\x09" "4.4LFS"},
682 /* BSD_FS_OTHER */ {"\x0a" "unknown"},
683 /* BSD_FS_HPFS */ {"\x0b" "HPFS"},
684 /* BSD_FS_ISO9660 */ {"\x0c" "ISO-9660"},
685 /* BSD_FS_BOOT */ {"\x0d" "boot"},
686 /* BSD_FS_ADOS */ {"\x0e" "ADOS"},
687 /* BSD_FS_HFS */ {"\x0f" "HFS"},
688 /* BSD_FS_ADVFS */ {"\x10" "AdvFS"},
691 #define BSD_FSMAXTYPES (SIZE(xbsd_fstypes)-1)
696 * flags shared by various drives:
698 #define BSD_D_REMOVABLE 0x01 /* removable media */
699 #define BSD_D_ECC 0x02 /* supports ECC */
700 #define BSD_D_BADSECT 0x04 /* supports bad sector forw. */
701 #define BSD_D_RAMDISK 0x08 /* disk emulator */
702 #define BSD_D_CHAIN 0x10 /* can do back-back transfers */
703 #define BSD_D_DOSPART 0x20 /* within MSDOS partition */
705 #endif /* OSF_LABEL */
708 * Copyright (C) Andreas Neuper, Sep 1998.
709 * This file may be modified and redistributed under
710 * the terms of the GNU Public License.
713 struct device_parameter { /* 48 bytes */
717 unsigned char sparecyl;
718 unsigned short pcylcount;
719 unsigned short head_vol0;
720 unsigned short ntrks; /* tracks in cyl 0 or vol 0 */
721 unsigned char cmd_tag_queue_depth;
722 unsigned char unused0;
723 unsigned short unused1;
724 unsigned short nsect; /* sectors/tracks in cyl 0 or vol 0 */
725 unsigned short bytes;
726 unsigned short ilfact;
727 unsigned int flags; /* controller flags */
728 unsigned int datarate;
729 unsigned int retries_on_error;
730 unsigned int ms_per_word;
731 unsigned short xylogics_gap1;
732 unsigned short xylogics_syncdelay;
733 unsigned short xylogics_readdelay;
734 unsigned short xylogics_gap2;
735 unsigned short xylogics_readgate;
736 unsigned short xylogics_writecont;
739 #define SGI_VOLHDR 0x00
740 /* 1 and 2 were used for drive types no longer supported by SGI */
741 #define SGI_SWAP 0x03
742 /* 4 and 5 were for filesystem types SGI haven't ever supported on MIPS CPUs */
743 #define SGI_VOLUME 0x06
745 #define SGI_LVOL 0x08
746 #define SGI_RLVOL 0x09
748 #define SGI_XFSLOG 0x0b
751 #define ENTIRE_DISK SGI_VOLUME
755 #define SECTOR_SLIP 0x01
756 #define SECTOR_FWD 0x02
757 #define TRACK_FWD 0x04
758 #define TRACK_MULTIVOL 0x08
759 #define IGNORE_ERRORS 0x10
761 #define ENABLE_CMDTAGQ 0x40
764 unsigned int magic; /* expect SGI_LABEL_MAGIC */
765 unsigned short boot_part; /* active boot partition */
766 unsigned short swap_part; /* active swap partition */
767 unsigned char boot_file[16]; /* name of the bootfile */
768 struct device_parameter devparam; /* 1 * 48 bytes */
769 struct volume_directory { /* 15 * 16 bytes */
770 unsigned char vol_file_name[8]; /* a character array */
771 unsigned int vol_file_start; /* number of logical block */
772 unsigned int vol_file_size; /* number of bytes */
774 struct sgi_partition { /* 16 * 12 bytes */
775 unsigned int num_sectors; /* number of blocks */
776 unsigned int start_sector; /* must be cylinder aligned */
780 unsigned int fillbytes;
784 unsigned int magic; /* looks like a magic number */
793 unsigned char scsi_string[50];
794 unsigned char serial[137];
795 unsigned short check1816;
796 unsigned char installer[225];
799 #define SGI_LABEL_MAGIC 0x0be5a941
800 #define SGI_LABEL_MAGIC_SWAPPED 0x41a9e50b
801 #define SGI_INFO_MAGIC 0x00072959
802 #define SGI_INFO_MAGIC_SWAPPED 0x59290700
803 #define SGI_SSWAP16(x) (sgi_other_endian ? __swap16(x) \
805 #define SGI_SSWAP32(x) (sgi_other_endian ? __swap32(x) \
808 #define sgilabel ((sgi_partition *)MBRbuffer)
809 #define sgiparam (sgilabel->devparam)
812 unsigned char info[128]; /* Informative text string */
813 unsigned char spare0[14];
815 unsigned char spare1;
817 unsigned char spare2;
820 unsigned char spare1[246]; /* Boot information etc. */
821 unsigned short rspeed; /* Disk rotational speed */
822 unsigned short pcylcount; /* Physical cylinder count */
823 unsigned short sparecyl; /* extra sects per cylinder */
824 unsigned char spare2[4]; /* More magic... */
825 unsigned short ilfact; /* Interleave factor */
826 unsigned short ncyl; /* Data cylinder count */
827 unsigned short nacyl; /* Alt. cylinder count */
828 unsigned short ntrks; /* Tracks per cylinder */
829 unsigned short nsect; /* Sectors per track */
830 unsigned char spare3[4]; /* Even more magic... */
831 struct sun_partition {
832 uint32_t start_cylinder;
833 uint32_t num_sectors;
835 unsigned short magic; /* Magic number */
836 unsigned short csum; /* Label xor'd checksum */
840 #define SUN_LABEL_MAGIC 0xDABE
841 #define SUN_LABEL_MAGIC_SWAPPED 0xBEDA
842 #define sunlabel ((sun_partition *)MBRbuffer)
843 #define SUN_SSWAP16(x) (sun_other_endian ? __swap16(x) \
845 #define SUN_SSWAP32(x) (sun_other_endian ? __swap32(x) \
849 #ifdef CONFIG_FEATURE_OSF_LABEL
852 19990319 - Arnaldo Carvalho de Melo <acme@conectiva.com.br> - i18n/nls
854 20000101 - David Huggins-Daines <dhuggins@linuxcare.com> - Better
855 support for OSF/1 disklabels on Alpha.
856 Also fixed unaligned accesses in alpha_bootblock_checksum()
859 #define FREEBSD_PARTITION 0xa5
860 #define NETBSD_PARTITION 0xa9
862 static void xbsd_delete_part (void);
863 static void xbsd_new_part (void);
864 static void xbsd_write_disklabel (void);
865 static int xbsd_create_disklabel (void);
866 static void xbsd_edit_disklabel (void);
867 static void xbsd_write_bootstrap (void);
868 static void xbsd_change_fstype (void);
869 static int xbsd_get_part_index (int max);
870 static int xbsd_check_new_partition (int *i);
871 static void xbsd_list_types (void);
872 static u_short xbsd_dkcksum (struct xbsd_disklabel *lp);
873 static int xbsd_initlabel (struct partition *p, struct xbsd_disklabel *d,
875 static int xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d);
876 static int xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d);
878 #if defined (__alpha__)
879 static void alpha_bootblock_checksum (char *boot);
882 #if !defined (__alpha__)
883 static int xbsd_translate_fstype (int linux_type);
884 static void xbsd_link_part (void);
885 static struct partition *xbsd_part;
886 static int xbsd_part_index;
889 #if defined (__alpha__)
890 /* We access this through a uint64_t * when checksumming */
891 static char disklabelbuffer[BSD_BBSIZE] __attribute__((aligned(8)));
893 static char disklabelbuffer[BSD_BBSIZE];
896 static struct xbsd_disklabel xbsd_dlabel;
898 #define bsd_cround(n) \
899 (display_in_cyl_units ? ((n)/xbsd_dlabel.d_secpercyl) + 1 : (n))
902 * Test whether the whole disk has BSD disk label magic.
904 * Note: often reformatting with DOS-type label leaves the BSD magic,
905 * so this does not mean that there is a BSD disk label.
908 check_osf_label(void) {
909 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
914 static void xbsd_print_disklabel(int);
917 btrydev (const char * dev) {
918 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
920 printf(_("\nBSD label for device: %s\n"), dev);
921 xbsd_print_disklabel (0);
927 puts (_("Command action"));
928 puts (_("\td\tdelete a BSD partition"));
929 puts (_("\te\tedit drive data"));
930 puts (_("\ti\tinstall bootstrap"));
931 puts (_("\tl\tlist known filesystem types"));
932 puts (_("\tm\tprint this menu"));
933 puts (_("\tn\tadd a new BSD partition"));
934 puts (_("\tp\tprint BSD partition table"));
935 puts (_("\tq\tquit without saving changes"));
936 puts (_("\tr\treturn to main menu"));
937 puts (_("\ts\tshow complete disklabel"));
938 puts (_("\tt\tchange a partition's filesystem id"));
939 puts (_("\tu\tchange units (cylinders/sectors)"));
940 puts (_("\tw\twrite disklabel to disk"));
941 #if !defined (__alpha__)
942 puts (_("\tx\tlink BSD partition to non-BSD partition"));
946 #if !defined (__alpha__)
953 is_bsd_partition_type(int type) {
954 return (type == FREEBSD_PARTITION ||
955 type == hidden(FREEBSD_PARTITION) ||
956 type == NETBSD_PARTITION ||
957 type == hidden(NETBSD_PARTITION));
963 #if !defined (__alpha__)
967 for (t=0; t<4; t++) {
968 p = get_part_table(t);
969 if (p && is_bsd_partition_type(p->sys_ind)) {
972 ss = get_start_sect(xbsd_part);
974 fprintf (stderr, _("Partition %s has invalid starting sector 0.\n"),
975 partname(disk_device, t+1, 0));
978 printf (_("Reading disklabel of %s at sector %d.\n"),
979 partname(disk_device, t+1, 0), ss + BSD_LABELSECTOR);
980 if (xbsd_readlabel (xbsd_part, &xbsd_dlabel) == 0)
981 if (xbsd_create_disklabel () == 0)
988 printf (_("There is no *BSD partition on %s.\n"), disk_device);
992 #elif defined (__alpha__)
994 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
995 if (xbsd_create_disklabel () == 0)
996 exit ( EXIT_SUCCESS );
1002 switch (tolower (read_char (_("BSD disklabel command (m for help): ")))) {
1004 xbsd_delete_part ();
1007 xbsd_edit_disklabel ();
1010 xbsd_write_bootstrap ();
1019 xbsd_print_disklabel (0);
1023 exit ( EXIT_SUCCESS );
1027 xbsd_print_disklabel (1);
1030 xbsd_change_fstype ();
1036 xbsd_write_disklabel ();
1038 #if !defined (__alpha__)
1051 xbsd_delete_part (void)
1055 i = xbsd_get_part_index (xbsd_dlabel.d_npartitions);
1056 xbsd_dlabel.d_partitions[i].p_size = 0;
1057 xbsd_dlabel.d_partitions[i].p_offset = 0;
1058 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
1059 if (xbsd_dlabel.d_npartitions == i + 1)
1060 while (xbsd_dlabel.d_partitions[xbsd_dlabel.d_npartitions-1].p_size == 0)
1061 xbsd_dlabel.d_npartitions--;
1065 xbsd_new_part (void)
1071 if (!xbsd_check_new_partition (&i))
1074 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
1075 begin = get_start_sect(xbsd_part);
1076 end = begin + get_nr_sects(xbsd_part) - 1;
1079 end = xbsd_dlabel.d_secperunit - 1;
1082 snprintf (mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
1083 begin = read_int (bsd_cround (begin), bsd_cround (begin), bsd_cround (end),
1086 if (display_in_cyl_units)
1087 begin = (begin - 1) * xbsd_dlabel.d_secpercyl;
1089 snprintf (mesg, sizeof(mesg), _("Last %s or +size or +sizeM or +sizeK"),
1090 str_units(SINGULAR));
1091 end = read_int (bsd_cround (begin), bsd_cround (end), bsd_cround (end),
1092 bsd_cround (begin), mesg);
1094 if (display_in_cyl_units)
1095 end = end * xbsd_dlabel.d_secpercyl - 1;
1097 xbsd_dlabel.d_partitions[i].p_size = end - begin + 1;
1098 xbsd_dlabel.d_partitions[i].p_offset = begin;
1099 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
1103 xbsd_print_disklabel (int show_all) {
1104 struct xbsd_disklabel *lp = &xbsd_dlabel;
1105 struct xbsd_partition *pp;
1109 #if defined (__alpha__)
1110 printf("# %s:\n", disk_device);
1112 printf("# %s:\n", partname(disk_device, xbsd_part_index+1, 0));
1114 if ((unsigned) lp->d_type < BSD_DKMAXTYPES)
1115 printf(_("type: %s\n"), xbsd_dktypenames[lp->d_type]);
1117 printf(_("type: %d\n"), lp->d_type);
1118 printf(_("disk: %.*s\n"), (int) sizeof(lp->d_typename), lp->d_typename);
1119 printf(_("label: %.*s\n"), (int) sizeof(lp->d_packname), lp->d_packname);
1120 printf(_("flags:"));
1121 if (lp->d_flags & BSD_D_REMOVABLE)
1122 printf(_(" removable"));
1123 if (lp->d_flags & BSD_D_ECC)
1125 if (lp->d_flags & BSD_D_BADSECT)
1126 printf(_(" badsect"));
1128 /* On various machines the fields of *lp are short/int/long */
1129 /* In order to avoid problems, we cast them all to long. */
1130 printf(_("bytes/sector: %ld\n"), (long) lp->d_secsize);
1131 printf(_("sectors/track: %ld\n"), (long) lp->d_nsectors);
1132 printf(_("tracks/cylinder: %ld\n"), (long) lp->d_ntracks);
1133 printf(_("sectors/cylinder: %ld\n"), (long) lp->d_secpercyl);
1134 printf(_("cylinders: %ld\n"), (long) lp->d_ncylinders);
1135 printf(_("rpm: %d\n"), lp->d_rpm);
1136 printf(_("interleave: %d\n"), lp->d_interleave);
1137 printf(_("trackskew: %d\n"), lp->d_trackskew);
1138 printf(_("cylinderskew: %d\n"), lp->d_cylskew);
1139 printf(_("headswitch: %ld\t\t# milliseconds\n"),
1140 (long) lp->d_headswitch);
1141 printf(_("track-to-track seek: %ld\t# milliseconds\n"),
1142 (long) lp->d_trkseek);
1143 printf(_("drivedata: "));
1144 for (i = NDDATA - 1; i >= 0; i--)
1145 if (lp->d_drivedata[i])
1149 for (j = 0; j <= i; j++)
1150 printf("%ld ", (long) lp->d_drivedata[j]);
1152 printf(_("\n%d partitions:\n"), lp->d_npartitions);
1153 printf(_("# start end size fstype [fsize bsize cpg]\n"));
1154 pp = lp->d_partitions;
1155 for (i = 0; i < lp->d_npartitions; i++, pp++) {
1157 if (display_in_cyl_units && lp->d_secpercyl) {
1158 printf(" %c: %8ld%c %8ld%c %8ld%c ",
1160 (long) pp->p_offset / lp->d_secpercyl + 1,
1161 (pp->p_offset % lp->d_secpercyl) ? '*' : ' ',
1162 (long) (pp->p_offset + pp->p_size + lp->d_secpercyl - 1)
1164 ((pp->p_offset + pp->p_size) % lp->d_secpercyl) ? '*' : ' ',
1165 (long) pp->p_size / lp->d_secpercyl,
1166 (pp->p_size % lp->d_secpercyl) ? '*' : ' ');
1168 printf(" %c: %8ld %8ld %8ld ",
1170 (long) pp->p_offset,
1171 (long) pp->p_offset + pp->p_size - 1,
1174 if ((unsigned) pp->p_fstype < BSD_FSMAXTYPES)
1175 printf("%8.8s", xbsd_fstypes[pp->p_fstype].name);
1177 printf("%8x", pp->p_fstype);
1178 switch (pp->p_fstype) {
1180 printf(" %5ld %5ld %5.5s ",
1181 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, "");
1185 printf(" %5ld %5ld %5d ",
1186 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag,
1191 printf("%22.22s", "");
1200 xbsd_write_disklabel (void) {
1201 #if defined (__alpha__)
1202 printf (_("Writing disklabel to %s.\n"), disk_device);
1203 xbsd_writelabel (NULL, &xbsd_dlabel);
1205 printf (_("Writing disklabel to %s.\n"),
1206 partname(disk_device, xbsd_part_index+1, 0));
1207 xbsd_writelabel (xbsd_part, &xbsd_dlabel);
1209 reread_partition_table(0); /* no exit yet */
1213 xbsd_create_disklabel (void) {
1216 #if defined (__alpha__)
1217 fprintf (stderr, _("%s contains no disklabel.\n"), disk_device);
1219 fprintf (stderr, _("%s contains no disklabel.\n"),
1220 partname(disk_device, xbsd_part_index+1, 0));
1224 c = read_char (_("Do you want to create a disklabel? (y/n) "));
1225 if (c == 'y' || c == 'Y') {
1226 if (xbsd_initlabel (
1227 #if defined (__alpha__) || defined (__powerpc__) || defined (__hppa__) || \
1228 defined (__s390__) || defined (__s390x__)
1229 NULL, &xbsd_dlabel, 0
1231 xbsd_part, &xbsd_dlabel, xbsd_part_index
1234 xbsd_print_disklabel (1);
1238 } else if (c == 'n')
1244 edit_int (int def, char *mesg)
1247 fputs (mesg, stdout);
1248 printf (" (%d): ", def);
1252 while (!isdigit (*line_ptr));
1253 return atoi (line_ptr);
1257 xbsd_edit_disklabel (void)
1259 struct xbsd_disklabel *d;
1263 #if defined (__alpha__) || defined (__ia64__)
1264 d -> d_secsize = (u_long) edit_int ((u_long) d -> d_secsize ,_("bytes/sector"));
1265 d -> d_nsectors = (u_long) edit_int ((u_long) d -> d_nsectors ,_("sectors/track"));
1266 d -> d_ntracks = (u_long) edit_int ((u_long) d -> d_ntracks ,_("tracks/cylinder"));
1267 d -> d_ncylinders = (u_long) edit_int ((u_long) d -> d_ncylinders ,_("cylinders"));
1270 /* d -> d_secpercyl can be != d -> d_nsectors * d -> d_ntracks */
1273 d -> d_secpercyl = (u_long) edit_int ((u_long) d -> d_nsectors * d -> d_ntracks,
1274 _("sectors/cylinder"));
1275 if (d -> d_secpercyl <= d -> d_nsectors * d -> d_ntracks)
1278 printf (_("Must be <= sectors/track * tracks/cylinder (default).\n"));
1280 d -> d_rpm = (u_short) edit_int ((u_short) d -> d_rpm ,_("rpm"));
1281 d -> d_interleave = (u_short) edit_int ((u_short) d -> d_interleave,_("interleave"));
1282 d -> d_trackskew = (u_short) edit_int ((u_short) d -> d_trackskew ,_("trackskew"));
1283 d -> d_cylskew = (u_short) edit_int ((u_short) d -> d_cylskew ,_("cylinderskew"));
1284 d -> d_headswitch = (u_long) edit_int ((u_long) d -> d_headswitch ,_("headswitch"));
1285 d -> d_trkseek = (u_long) edit_int ((u_long) d -> d_trkseek ,_("track-to-track seek"));
1287 d -> d_secperunit = d -> d_secpercyl * d -> d_ncylinders;
1291 xbsd_get_bootstrap (char *path, void *ptr, int size)
1295 if ((fdb = open (path, O_RDONLY)) < 0)
1300 if (read (fdb, ptr, size) < 0)
1306 printf (" ... %s\n", path);
1314 printf (_("\nSyncing disks.\n"));
1320 xbsd_write_bootstrap (void)
1322 char *bootdir = BSD_LINUX_BOOTDIR;
1323 char path[MAXPATHLEN];
1325 struct xbsd_disklabel dl;
1329 if (xbsd_dlabel.d_type == BSD_DTYPE_SCSI)
1334 printf (_("Bootstrap: %sboot -> boot%s (%s): "),
1335 dkbasename, dkbasename, dkbasename);
1337 line_ptr[strlen (line_ptr)-1] = '\0';
1338 dkbasename = line_ptr;
1340 snprintf (path, sizeof(path), "%s/%sboot", bootdir, dkbasename);
1341 if (!xbsd_get_bootstrap (path, disklabelbuffer, (int) xbsd_dlabel.d_secsize))
1344 /* We need a backup of the disklabel (xbsd_dlabel might have changed). */
1345 d = &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE];
1346 bcopy (d, &dl, sizeof (struct xbsd_disklabel));
1348 /* The disklabel will be overwritten by 0's from bootxx anyway */
1349 bzero (d, sizeof (struct xbsd_disklabel));
1351 snprintf (path, sizeof(path), "%s/boot%s", bootdir, dkbasename);
1352 if (!xbsd_get_bootstrap (path, &disklabelbuffer[xbsd_dlabel.d_secsize],
1353 (int) xbsd_dlabel.d_bbsize - xbsd_dlabel.d_secsize))
1356 e = d + sizeof (struct xbsd_disklabel);
1357 for (p=d; p < e; p++)
1359 fprintf (stderr, _("Bootstrap overlaps with disk label!\n"));
1360 exit ( EXIT_FAILURE );
1363 bcopy (&dl, d, sizeof (struct xbsd_disklabel));
1365 #if defined (__powerpc__) || defined (__hppa__)
1367 #elif defined (__alpha__)
1369 alpha_bootblock_checksum (disklabelbuffer);
1371 sector = get_start_sect(xbsd_part);
1374 if (lseek (fd, sector * SECTOR_SIZE, SEEK_SET) == -1)
1375 fdisk_fatal (unable_to_seek);
1376 if (BSD_BBSIZE != write (fd, disklabelbuffer, BSD_BBSIZE))
1377 fdisk_fatal (unable_to_write);
1379 #if defined (__alpha__)
1380 printf (_("Bootstrap installed on %s.\n"), disk_device);
1382 printf (_("Bootstrap installed on %s.\n"),
1383 partname (disk_device, xbsd_part_index+1, 0));
1390 xbsd_change_fstype (void)
1394 i = xbsd_get_part_index (xbsd_dlabel.d_npartitions);
1395 xbsd_dlabel.d_partitions[i].p_fstype = read_hex (xbsd_fstypes);
1399 xbsd_get_part_index (int max)
1404 snprintf (prompt, sizeof(prompt), _("Partition (a-%c): "), 'a' + max - 1);
1406 l = tolower (read_char (prompt));
1407 while (l < 'a' || l > 'a' + max - 1);
1412 xbsd_check_new_partition (int *i) {
1414 /* room for more? various BSD flavours have different maxima */
1415 if (xbsd_dlabel.d_npartitions == BSD_MAXPARTITIONS) {
1418 for (t = 0; t < BSD_MAXPARTITIONS; t++)
1419 if (xbsd_dlabel.d_partitions[t].p_size == 0)
1422 if (t == BSD_MAXPARTITIONS) {
1423 fprintf (stderr, _("The maximum number of partitions "
1424 "has been created\n"));
1429 *i = xbsd_get_part_index (BSD_MAXPARTITIONS);
1431 if (*i >= xbsd_dlabel.d_npartitions)
1432 xbsd_dlabel.d_npartitions = (*i) + 1;
1434 if (xbsd_dlabel.d_partitions[*i].p_size != 0) {
1435 fprintf (stderr, _("This partition already exists.\n"));
1443 xbsd_list_types (void) {
1444 list_types (xbsd_fstypes);
1448 xbsd_dkcksum (struct xbsd_disklabel *lp) {
1449 u_short *start, *end;
1452 start = (u_short *) lp;
1453 end = (u_short *) &lp->d_partitions[lp->d_npartitions];
1460 xbsd_initlabel (struct partition *p, struct xbsd_disklabel *d, int pindex) {
1461 struct xbsd_partition *pp;
1464 bzero (d, sizeof (struct xbsd_disklabel));
1466 d -> d_magic = BSD_DISKMAGIC;
1468 if (strncmp (disk_device, "/dev/sd", 7) == 0)
1469 d -> d_type = BSD_DTYPE_SCSI;
1471 d -> d_type = BSD_DTYPE_ST506;
1473 #if 0 /* not used (at least not written to disk) by NetBSD/i386 1.0 */
1474 d -> d_subtype = BSD_DSTYPE_INDOSPART & pindex;
1477 #if !defined (__alpha__)
1478 d -> d_flags = BSD_D_DOSPART;
1482 d -> d_secsize = SECTOR_SIZE; /* bytes/sector */
1483 d -> d_nsectors = sectors; /* sectors/track */
1484 d -> d_ntracks = heads; /* tracks/cylinder (heads) */
1485 d -> d_ncylinders = cylinders;
1486 d -> d_secpercyl = sectors * heads;/* sectors/cylinder */
1487 if (d -> d_secpercyl == 0)
1488 d -> d_secpercyl = 1; /* avoid segfaults */
1489 d -> d_secperunit = d -> d_secpercyl * d -> d_ncylinders;
1492 d -> d_interleave = 1;
1493 d -> d_trackskew = 0;
1495 d -> d_headswitch = 0;
1498 d -> d_magic2 = BSD_DISKMAGIC;
1499 d -> d_bbsize = BSD_BBSIZE;
1500 d -> d_sbsize = BSD_SBSIZE;
1502 #if !defined (__alpha__)
1503 d -> d_npartitions = 4;
1504 pp = &d -> d_partitions[2]; /* Partition C should be
1505 the NetBSD partition */
1506 pp -> p_offset = get_start_sect(p);
1507 pp -> p_size = get_nr_sects(p);
1508 pp -> p_fstype = BSD_FS_UNUSED;
1509 pp = &d -> d_partitions[3]; /* Partition D should be
1512 pp -> p_size = d -> d_secperunit;
1513 pp -> p_fstype = BSD_FS_UNUSED;
1514 #elif defined (__alpha__)
1515 d -> d_npartitions = 3;
1516 pp = &d -> d_partitions[2]; /* Partition C should be
1519 pp -> p_size = d -> d_secperunit;
1520 pp -> p_fstype = BSD_FS_UNUSED;
1527 * Read a xbsd_disklabel from sector 0 or from the starting sector of p.
1528 * If it has the right magic, return 1.
1531 xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d)
1535 /* p is used only to get the starting sector */
1536 #if !defined (__alpha__)
1537 sector = (p ? get_start_sect(p) : 0);
1538 #elif defined (__alpha__)
1542 if (lseek (fd, sector * SECTOR_SIZE, SEEK_SET) == -1)
1543 fdisk_fatal (unable_to_seek);
1544 if (BSD_BBSIZE != read (fd, disklabelbuffer, BSD_BBSIZE))
1545 fdisk_fatal (unable_to_read);
1547 bcopy (&disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
1548 d, sizeof (struct xbsd_disklabel));
1550 if (d -> d_magic != BSD_DISKMAGIC || d -> d_magic2 != BSD_DISKMAGIC)
1553 for (t = d -> d_npartitions; t < BSD_MAXPARTITIONS; t++) {
1554 d -> d_partitions[t].p_size = 0;
1555 d -> d_partitions[t].p_offset = 0;
1556 d -> d_partitions[t].p_fstype = BSD_FS_UNUSED;
1559 if (d -> d_npartitions > BSD_MAXPARTITIONS)
1560 fprintf (stderr, _("Warning: too many partitions "
1561 "(%d, maximum is %d).\n"),
1562 d -> d_npartitions, BSD_MAXPARTITIONS);
1567 xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d)
1569 unsigned int sector;
1571 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
1572 sector = get_start_sect(p) + BSD_LABELSECTOR;
1574 sector = BSD_LABELSECTOR;
1577 d -> d_checksum = 0;
1578 d -> d_checksum = xbsd_dkcksum (d);
1580 /* This is necessary if we want to write the bootstrap later,
1581 otherwise we'd write the old disklabel with the bootstrap.
1583 bcopy (d, &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
1584 sizeof (struct xbsd_disklabel));
1586 #if defined (__alpha__) && BSD_LABELSECTOR == 0
1587 alpha_bootblock_checksum (disklabelbuffer);
1588 if (lseek (fd, 0, SEEK_SET) == -1)
1589 fdisk_fatal (unable_to_seek);
1590 if (BSD_BBSIZE != write (fd, disklabelbuffer, BSD_BBSIZE))
1591 fdisk_fatal (unable_to_write);
1593 if (lseek (fd, sector * SECTOR_SIZE + BSD_LABELOFFSET,
1595 fdisk_fatal (unable_to_seek);
1596 if (sizeof (struct xbsd_disklabel) != write (fd, d, sizeof (struct xbsd_disklabel)))
1597 fdisk_fatal (unable_to_write);
1606 #if !defined (__alpha__)
1608 xbsd_translate_fstype (int linux_type)
1612 case 0x01: /* DOS 12-bit FAT */
1613 case 0x04: /* DOS 16-bit <32M */
1614 case 0x06: /* DOS 16-bit >=32M */
1615 case 0xe1: /* DOS access */
1616 case 0xe3: /* DOS R/O */
1617 case 0xf2: /* DOS secondary */
1618 return BSD_FS_MSDOS;
1619 case 0x07: /* OS/2 HPFS */
1622 return BSD_FS_OTHER;
1627 xbsd_link_part (void)
1630 struct partition *p;
1632 k = get_partition (1, partitions);
1634 if (!xbsd_check_new_partition (&i))
1637 p = get_part_table(k);
1639 xbsd_dlabel.d_partitions[i].p_size = get_nr_sects(p);
1640 xbsd_dlabel.d_partitions[i].p_offset = get_start_sect(p);
1641 xbsd_dlabel.d_partitions[i].p_fstype = xbsd_translate_fstype(p->sys_ind);
1645 #if defined (__alpha__)
1647 #if !defined(__GLIBC__)
1648 typedef unsigned long long uint64_t;
1652 alpha_bootblock_checksum (char *boot)
1657 dp = (uint64_t *)boot;
1659 for (i = 0; i < 63; i++)
1663 #endif /* __alpha__ */
1665 #endif /* OSF_LABEL */
1667 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
1668 static inline unsigned short
1669 __swap16(unsigned short x) {
1670 return (((uint16_t)(x) & 0xFF) << 8) | (((uint16_t)(x) & 0xFF00) >> 8);
1673 static inline uint32_t
1674 __swap32(uint32_t x) {
1675 return (((x & 0xFF) << 24) |
1676 ((x & 0xFF00) << 8) |
1677 ((x & 0xFF0000) >> 8) |
1678 ((x & 0xFF000000) >> 24));
1682 #ifdef CONFIG_FEATURE_SGI_LABEL
1687 * Copyright (C) Andreas Neuper, Sep 1998.
1688 * This file may be modified and redistributed under
1689 * the terms of the GNU Public License.
1691 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
1692 * Internationalization
1696 static int sgi_other_endian;
1698 static short sgi_volumes=1;
1701 * only dealing with free blocks here
1704 typedef struct { unsigned int first; unsigned int last; } freeblocks;
1705 static freeblocks freelist[17]; /* 16 partitions can produce 17 vacant slots */
1708 setfreelist(int i, unsigned int f, unsigned int l) {
1709 freelist[i].first = f;
1710 freelist[i].last = l;
1714 add2freelist(unsigned int f, unsigned int l) {
1716 for ( ; i < 17 ; i++)
1717 if (freelist[i].last == 0)
1719 setfreelist(i, f, l);
1723 clearfreelist(void) {
1726 for (i = 0; i < 17 ; i++)
1727 setfreelist(i, 0, 0);
1731 isinfreelist(unsigned int b) {
1734 for (i = 0; i < 17 ; i++)
1735 if (freelist[i].first <= b && freelist[i].last >= b)
1736 return freelist[i].last;
1739 /* return last vacant block of this stride (never 0). */
1740 /* the '>=' is not quite correct, but simplifies the code */
1742 * end of free blocks section
1745 static const struct systypes sgi_sys_types[] = {
1746 /* SGI_VOLHDR */ {"\x00" "SGI volhdr" },
1747 /* 0x01 */ {"\x01" "SGI trkrepl" },
1748 /* 0x02 */ {"\x02" "SGI secrepl" },
1749 /* SGI_SWAP */ {"\x03" "SGI raw" },
1750 /* 0x04 */ {"\x04" "SGI bsd" },
1751 /* 0x05 */ {"\x05" "SGI sysv" },
1752 /* ENTIRE_DISK */ {"\x06" "SGI volume" },
1753 /* SGI_EFS */ {"\x07" "SGI efs" },
1754 /* 0x08 */ {"\x08" "SGI lvol" },
1755 /* 0x09 */ {"\x09" "SGI rlvol" },
1756 /* SGI_XFS */ {"\x0a" "SGI xfs" },
1757 /* SGI_XFSLOG */ {"\x0b" "SGI xfslog" },
1758 /* SGI_XLV */ {"\x0c" "SGI xlv" },
1759 /* SGI_XVM */ {"\x0d" "SGI xvm" },
1760 /* LINUX_SWAP */ {"\x82" "Linux swap" },
1761 /* LINUX_NATIVE */ {"\x83" "Linux native" },
1762 /* LINUX_LVM */ {"\x8d" "Linux LVM" },
1763 /* LINUX_RAID */ {"\xfd" "Linux RAID" },
1769 sgi_get_nsect(void) {
1770 return SGI_SSWAP16(sgilabel->devparam.nsect);
1774 sgi_get_ntrks(void) {
1775 return SGI_SSWAP16(sgilabel->devparam.ntrks);
1780 sgilabel->magic = 0;
1786 two_s_complement_32bit_sum(unsigned int* base, int size /* in bytes */) {
1790 size /= sizeof(unsigned int);
1791 for (i = 0; i < size; i++)
1792 sum -= SGI_SSWAP32(base[i]);
1797 check_sgi_label(void) {
1798 if (sizeof(sgilabel) > 512) {
1800 _("According to MIPS Computer Systems, Inc the "
1801 "Label must not contain more than 512 bytes\n"));
1805 if (sgilabel->magic != SGI_LABEL_MAGIC &&
1806 sgilabel->magic != SGI_LABEL_MAGIC_SWAPPED) {
1808 sgi_other_endian = 0;
1812 sgi_other_endian = (sgilabel->magic == SGI_LABEL_MAGIC_SWAPPED);
1814 * test for correct checksum
1816 if (two_s_complement_32bit_sum((unsigned int*)sgilabel,
1817 sizeof(*sgilabel))) {
1819 _("Detected sgi disklabel with wrong checksum.\n"));
1829 sgi_get_start_sector(int i) {
1830 return SGI_SSWAP32(sgilabel->partitions[i].start_sector);
1834 sgi_get_num_sectors(int i) {
1835 return SGI_SSWAP32(sgilabel->partitions[i].num_sectors);
1839 sgi_get_sysid(int i)
1841 return SGI_SSWAP32(sgilabel->partitions[i].id);
1845 sgi_get_bootpartition(void)
1847 return SGI_SSWAP16(sgilabel->boot_part);
1851 sgi_get_swappartition(void)
1853 return SGI_SSWAP16(sgilabel->swap_part);
1857 sgi_list_table(int xtra) {
1859 int kpi = 0; /* kernel partition ID */
1862 printf(_("\nDisk %s (SGI disk label): %d heads, %d sectors\n"
1863 "%d cylinders, %d physical cylinders\n"
1864 "%d extra sects/cyl, interleave %d:1\n"
1866 "Units = %s of %d * 512 bytes\n\n"),
1867 disk_device, heads, sectors, cylinders,
1868 SGI_SSWAP16(sgiparam.pcylcount),
1869 SGI_SSWAP16(sgiparam.sparecyl),
1870 SGI_SSWAP16(sgiparam.ilfact),
1872 str_units(PLURAL), units_per_sector);
1874 printf( _("\nDisk %s (SGI disk label): "
1875 "%d heads, %d sectors, %d cylinders\n"
1876 "Units = %s of %d * 512 bytes\n\n"),
1877 disk_device, heads, sectors, cylinders,
1878 str_units(PLURAL), units_per_sector );
1881 w = strlen(disk_device);
1882 wd = strlen(_("Device"));
1886 printf(_("----- partitions -----\n"
1887 "Pt# %*s Info Start End Sectors Id System\n"),
1888 w + 2, _("Device"));
1889 for (i = 0 ; i < partitions; i++) {
1890 if( sgi_get_num_sectors(i) || debug ) {
1891 uint32_t start = sgi_get_start_sector(i);
1892 uint32_t len = sgi_get_num_sectors(i);
1893 kpi++; /* only count nonempty partitions */
1895 "%2d: %s %4s %9ld %9ld %9ld %2x %s\n",
1896 /* fdisk part number */ i+1,
1897 /* device */ partname(disk_device, kpi, w+3),
1898 /* flags */ (sgi_get_swappartition() == i) ? "swap" :
1899 /* flags */ (sgi_get_bootpartition() == i) ? "boot" : " ",
1900 /* start */ (long) scround(start),
1901 /* end */ (long) scround(start+len)-1,
1902 /* no odd flag on end */ (long) len,
1903 /* type id */ sgi_get_sysid(i),
1904 /* type name */ partition_type(sgi_get_sysid(i)));
1907 printf(_("----- Bootinfo -----\nBootfile: %s\n"
1908 "----- Directory Entries -----\n"),
1909 sgilabel->boot_file);
1910 for (i = 0 ; i < sgi_volumes; i++) {
1911 if (sgilabel->directory[i].vol_file_size) {
1912 uint32_t start = SGI_SSWAP32(sgilabel->directory[i].vol_file_start);
1913 uint32_t len = SGI_SSWAP32(sgilabel->directory[i].vol_file_size);
1914 char*name = sgilabel->directory[i].vol_file_name;
1916 printf(_("%2d: %-10s sector%5u size%8u\n"),
1917 i, name, (unsigned int) start, (unsigned int) len);
1923 sgi_set_bootpartition( int i )
1925 sgilabel->boot_part = SGI_SSWAP16(((short)i));
1929 sgi_get_lastblock(void) {
1930 return heads * sectors * cylinders;
1934 sgi_set_swappartition( int i ) {
1935 sgilabel->swap_part = SGI_SSWAP16(((short)i));
1939 sgi_check_bootfile(const char* aFile) {
1941 if (strlen(aFile) < 3) /* "/a\n" is minimum */ {
1942 printf(_("\nInvalid Bootfile!\n"
1943 "\tThe bootfile must be an absolute non-zero pathname,\n"
1944 "\te.g. \"/unix\" or \"/unix.save\".\n"));
1947 if (strlen(aFile) > 16) {
1948 printf(_("\n\tName of Bootfile too long: "
1949 "16 bytes maximum.\n"));
1952 if (aFile[0] != '/') {
1953 printf(_("\n\tBootfile must have a "
1954 "fully qualified pathname.\n"));
1959 if (strncmp(aFile, sgilabel->boot_file, 16)) {
1960 printf(_("\n\tBe aware, that the bootfile is not checked for existence.\n\t"
1961 "SGI's default is \"/unix\" and for backup \"/unix.save\".\n"));
1962 /* filename is correct and did change */
1965 return 0; /* filename did not change */
1969 sgi_get_bootfile(void) {
1970 return sgilabel->boot_file;
1974 sgi_set_bootfile(const char* aFile) {
1977 if (sgi_check_bootfile(aFile)) {
1979 if ((aFile[i] != '\n') /* in principle caught again by next line */
1980 && (strlen(aFile) > i))
1981 sgilabel->boot_file[i] = aFile[i];
1983 sgilabel->boot_file[i] = 0;
1986 printf(_("\n\tBootfile is changed to \"%s\".\n"), sgilabel->boot_file);
1991 create_sgiinfo(void)
1993 /* I keep SGI's habit to write the sgilabel to the second block */
1994 sgilabel->directory[0].vol_file_start = SGI_SSWAP32(2);
1995 sgilabel->directory[0].vol_file_size = SGI_SSWAP32(sizeof(sgiinfo));
1996 strncpy(sgilabel->directory[0].vol_file_name, "sgilabel", 8);
1999 static sgiinfo *fill_sgiinfo(void);
2002 sgi_write_table(void) {
2004 sgilabel->csum = SGI_SSWAP32(two_s_complement_32bit_sum(
2005 (unsigned int*)sgilabel,
2006 sizeof(*sgilabel)));
2007 assert(two_s_complement_32bit_sum(
2008 (unsigned int*)sgilabel, sizeof(*sgilabel)) == 0);
2009 if (lseek(fd, 0, SEEK_SET) < 0)
2010 fdisk_fatal(unable_to_seek);
2011 if (write(fd, sgilabel, SECTOR_SIZE) != SECTOR_SIZE)
2012 fdisk_fatal(unable_to_write);
2013 if (! strncmp(sgilabel->directory[0].vol_file_name, "sgilabel", 8)) {
2015 * keep this habit of first writing the "sgilabel".
2016 * I never tested whether it works without (AN 981002).
2018 sgiinfo *info = fill_sgiinfo();
2019 int infostartblock = SGI_SSWAP32(sgilabel->directory[0].vol_file_start);
2020 if (lseek(fd, infostartblock*SECTOR_SIZE, SEEK_SET) < 0)
2021 fdisk_fatal(unable_to_seek);
2022 if (write(fd, info, SECTOR_SIZE) != SECTOR_SIZE)
2023 fdisk_fatal(unable_to_write);
2029 compare_start(int *x, int *y) {
2031 * sort according to start sectors
2032 * and prefers largest partition:
2033 * entry zero is entire disk entry
2035 unsigned int i = *x;
2036 unsigned int j = *y;
2037 unsigned int a = sgi_get_start_sector(i);
2038 unsigned int b = sgi_get_start_sector(j);
2039 unsigned int c = sgi_get_num_sectors(i);
2040 unsigned int d = sgi_get_num_sectors(j);
2043 return (d > c) ? 1 : (d == c) ? 0 : -1;
2044 return (a > b) ? 1 : -1;
2049 verify_sgi(int verbose)
2051 int Index[16]; /* list of valid partitions */
2052 int sortcount = 0; /* number of used partitions, i.e. non-zero lengths */
2053 int entire = 0, i = 0;
2054 unsigned int start = 0;
2055 long long gap = 0; /* count unused blocks */
2056 unsigned int lastblock = sgi_get_lastblock();
2059 for (i=0; i<16; i++) {
2060 if (sgi_get_num_sectors(i) != 0) {
2061 Index[sortcount++]=i;
2062 if (sgi_get_sysid(i) == ENTIRE_DISK) {
2063 if (entire++ == 1) {
2065 printf(_("More than one entire disk entry present.\n"));
2070 if (sortcount == 0) {
2072 printf(_("No partitions defined\n"));
2073 return (lastblock > 0) ? 1 : (lastblock == 0) ? 0 : -1;
2075 qsort(Index, sortcount, sizeof(Index[0]), (void*)compare_start);
2076 if (sgi_get_sysid(Index[0]) == ENTIRE_DISK) {
2077 if ((Index[0] != 10) && verbose)
2078 printf(_("IRIX likes when Partition 11 covers the entire disk.\n"));
2079 if ((sgi_get_start_sector(Index[0]) != 0) && verbose)
2080 printf(_("The entire disk partition should start "
2082 "not at diskblock %d.\n"),
2083 sgi_get_start_sector(Index[0]));
2084 if (debug) /* I do not understand how some disks fulfil it */
2085 if ((sgi_get_num_sectors(Index[0]) != lastblock) && verbose)
2086 printf(_("The entire disk partition is only %d diskblock large,\n"
2087 "but the disk is %d diskblocks long.\n"),
2088 sgi_get_num_sectors(Index[0]), lastblock);
2089 lastblock = sgi_get_num_sectors(Index[0]);
2092 printf(_("One Partition (#11) should cover the entire disk.\n"));
2094 printf("sysid=%d\tpartition=%d\n",
2095 sgi_get_sysid(Index[0]), Index[0]+1);
2097 for (i=1, start=0; i<sortcount; i++) {
2098 int cylsize = sgi_get_nsect() * sgi_get_ntrks();
2100 if ((sgi_get_start_sector(Index[i]) % cylsize) != 0) {
2101 if (debug) /* I do not understand how some disks fulfil it */
2103 printf(_("Partition %d does not start on cylinder boundary.\n"),
2106 if (sgi_get_num_sectors(Index[i]) % cylsize != 0) {
2107 if (debug) /* I do not understand how some disks fulfil it */
2109 printf(_("Partition %d does not end on cylinder boundary.\n"),
2112 /* We cannot handle several "entire disk" entries. */
2113 if (sgi_get_sysid(Index[i]) == ENTIRE_DISK) continue;
2114 if (start > sgi_get_start_sector(Index[i])) {
2116 printf(_("The Partition %d and %d overlap by %d sectors.\n"),
2117 Index[i-1]+1, Index[i]+1,
2118 start - sgi_get_start_sector(Index[i]));
2119 if (gap > 0) gap = -gap;
2120 if (gap == 0) gap = -1;
2122 if (start < sgi_get_start_sector(Index[i])) {
2124 printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"),
2125 sgi_get_start_sector(Index[i]) - start,
2126 start, sgi_get_start_sector(Index[i])-1);
2127 gap += sgi_get_start_sector(Index[i]) - start;
2128 add2freelist(start, sgi_get_start_sector(Index[i]));
2130 start = sgi_get_start_sector(Index[i])
2131 + sgi_get_num_sectors(Index[i]);
2134 printf("%2d:%12d\t%12d\t%12d\n", Index[i],
2135 sgi_get_start_sector(Index[i]),
2136 sgi_get_num_sectors(Index[i]),
2137 sgi_get_sysid(Index[i]));
2140 if (start < lastblock) {
2142 printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"),
2143 lastblock - start, start, lastblock-1);
2144 gap += lastblock - start;
2145 add2freelist(start, lastblock);
2148 * Done with arithmetics
2149 * Go for details now
2152 if (!sgi_get_num_sectors(sgi_get_bootpartition())) {
2153 printf(_("\nThe boot partition does not exist.\n"));
2155 if (!sgi_get_num_sectors(sgi_get_swappartition())) {
2156 printf(_("\nThe swap partition does not exist.\n"));
2158 if ((sgi_get_sysid(sgi_get_swappartition()) != SGI_SWAP)
2159 && (sgi_get_sysid(sgi_get_swappartition()) != LINUX_SWAP))
2160 printf(_("\nThe swap partition has no swap type.\n"));
2162 if (sgi_check_bootfile("/unix"))
2163 printf(_("\tYou have chosen an unusual boot file name.\n"));
2165 return (gap > 0) ? 1 : (gap == 0) ? 0 : -1;
2171 * returned value is:
2172 * = 0 : disk is properly filled to the rim
2173 * < 0 : there is an overlap
2174 * > 0 : there is still some vacant space
2176 return verify_sgi(0);
2180 sgi_change_sysid( int i, int sys )
2182 if( sgi_get_num_sectors(i) == 0 ) /* caught already before, ... */
2184 printf(_("Sorry You may change the Tag of non-empty partitions.\n"));
2187 if( ((sys != ENTIRE_DISK ) && (sys != SGI_VOLHDR))
2188 && (sgi_get_start_sector(i)<1) )
2191 _("It is highly recommended that the partition at offset 0\n"
2192 "is of type \"SGI volhdr\", the IRIX system will rely on it to\n"
2193 "retrieve from its directory standalone tools like sash and fx.\n"
2194 "Only the \"SGI volume\" entire disk section may violate this.\n"
2195 "Type YES if you are sure about tagging this partition differently.\n"));
2196 if (strcmp (line_ptr, _("YES\n")))
2199 sgilabel->partitions[i].id = SGI_SSWAP32(sys);
2202 /* returns partition index of first entry marked as entire disk */
2208 if(sgi_get_sysid(i) == SGI_VOLUME)
2214 sgi_set_partition(int i, unsigned int start, unsigned int length, int sys) {
2216 sgilabel->partitions[i].id = SGI_SSWAP32(sys);
2217 sgilabel->partitions[i].num_sectors = SGI_SSWAP32(length);
2218 sgilabel->partitions[i].start_sector = SGI_SSWAP32(start);
2220 if (sgi_gaps() < 0) /* rebuild freelist */
2221 printf(_("Do You know, You got a partition overlap on the disk?\n"));
2225 sgi_set_entire(void) {
2228 for(n=10; n < partitions; n++) {
2229 if(!sgi_get_num_sectors(n) ) {
2230 sgi_set_partition(n, 0, sgi_get_lastblock(), SGI_VOLUME);
2237 sgi_set_volhdr(void)
2240 for( n=8; n<partitions; n++ )
2242 if(!sgi_get_num_sectors( n ) )
2245 * 5 cylinders is an arbitrary value I like
2246 * IRIX 5.3 stored files in the volume header
2247 * (like sash, symmon, fx, ide) with ca. 3200
2250 if( heads * sectors * 5 < sgi_get_lastblock() )
2251 sgi_set_partition( n, 0, heads * sectors * 5, SGI_VOLHDR );
2258 sgi_delete_partition( int i )
2260 sgi_set_partition( i, 0, 0, 0 );
2264 sgi_add_partition( int n, int sys )
2267 unsigned int first=0, last=0;
2271 } else if ( n == 8 ) {
2274 if(sgi_get_num_sectors(n)) {
2275 printf(_("Partition %d is already defined. Delete "
2276 "it before re-adding it.\n"), n + 1);
2279 if( (sgi_entire() == -1) && (sys != SGI_VOLUME) ) {
2280 printf(_("Attempting to generate entire disk entry automatically.\n"));
2284 if( (sgi_gaps() == 0) && (sys != SGI_VOLUME) ) {
2285 printf(_("The entire disk is already covered with partitions.\n"));
2288 if(sgi_gaps() < 0) {
2289 printf(_("You got a partition overlap on the disk. Fix it first!\n"));
2292 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
2294 if(sys == SGI_VOLUME) {
2295 last = sgi_get_lastblock();
2296 first = read_int(0, 0, last-1, 0, mesg);
2298 printf(_("It is highly recommended that eleventh partition\n"
2299 "covers the entire disk and is of type `SGI volume'\n"));
2302 first = freelist[0].first;
2303 last = freelist[0].last;
2304 first = read_int(scround(first), scround(first), scround(last)-1,
2307 if (display_in_cyl_units)
2308 first *= units_per_sector;
2310 first = first; /* align to cylinder if you know how ... */
2312 last = isinfreelist(first);
2314 printf(_("You will get a partition overlap on the disk. "
2315 "Fix it first!\n"));
2319 snprintf(mesg, sizeof(mesg), _(" Last %s"), str_units(SINGULAR));
2320 last = read_int(scround(first), scround(last)-1, scround(last)-1,
2321 scround(first), mesg)+1;
2322 if (display_in_cyl_units)
2323 last *= units_per_sector;
2325 last = last; /* align to cylinder if You know how ... */
2326 if( (sys == SGI_VOLUME) && ( first != 0 || last != sgi_get_lastblock() ) )
2327 printf(_("It is highly recommended that eleventh partition\n"
2328 "covers the entire disk and is of type `SGI volume'\n"));
2329 sgi_set_partition( n, first, last-first, sys );
2332 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
2334 create_sgilabel(void)
2336 struct hd_geometry geometry;
2343 long longsectors; /* the number of sectors on the device */
2344 int res; /* the result from the ioctl */
2345 int sec_fac; /* the sector factor */
2347 sec_fac = sector_size / 512; /* determine the sector factor */
2350 _("Building a new SGI disklabel. Changes will remain in memory only,\n"
2351 "until you decide to write them. After that, of course, the previous\n"
2352 "content will be unrecoverably lost.\n\n"));
2354 sgi_other_endian = (BYTE_ORDER == LITTLE_ENDIAN);
2355 res = ioctl(fd, BLKGETSIZE, &longsectors);
2356 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
2357 heads = geometry.heads;
2358 sectors = geometry.sectors;
2360 /* the get device size ioctl was successful */
2361 cylinders = longsectors / (heads * sectors);
2362 cylinders /= sec_fac;
2364 /* otherwise print error and use truncated version */
2365 cylinders = geometry.cylinders;
2367 _("Warning: BLKGETSIZE ioctl failed on %s. "
2368 "Using geometry cylinder value of %d.\n"
2369 "This value may be truncated for devices"
2370 " > 33.8 GB.\n"), disk_device, cylinders);
2373 for (i = 0; i < 4; i++) {
2375 if(valid_part_table_flag(MBRbuffer)) {
2376 if(get_part_table(i)->sys_ind) {
2377 old[i].sysid = get_part_table(i)->sys_ind;
2378 old[i].start = get_start_sect(get_part_table(i));
2379 old[i].nsect = get_nr_sects(get_part_table(i));
2380 printf(_("Trying to keep parameters of partition %d.\n"), i);
2382 printf(_("ID=%02x\tSTART=%d\tLENGTH=%d\n"),
2383 old[i].sysid, old[i].start, old[i].nsect);
2388 memset(MBRbuffer, 0, sizeof(MBRbuffer));
2389 sgilabel->magic = SGI_SSWAP32(SGI_LABEL_MAGIC);
2390 sgilabel->boot_part = SGI_SSWAP16(0);
2391 sgilabel->swap_part = SGI_SSWAP16(1);
2393 /* sizeof(sgilabel->boot_file) = 16 > 6 */
2394 memset(sgilabel->boot_file, 0, 16);
2395 strcpy(sgilabel->boot_file, "/unix");
2397 sgilabel->devparam.skew = (0);
2398 sgilabel->devparam.gap1 = (0);
2399 sgilabel->devparam.gap2 = (0);
2400 sgilabel->devparam.sparecyl = (0);
2401 sgilabel->devparam.pcylcount = SGI_SSWAP16(geometry.cylinders);
2402 sgilabel->devparam.head_vol0 = SGI_SSWAP16(0);
2403 sgilabel->devparam.ntrks = SGI_SSWAP16(geometry.heads);
2404 /* tracks/cylinder (heads) */
2405 sgilabel->devparam.cmd_tag_queue_depth = (0);
2406 sgilabel->devparam.unused0 = (0);
2407 sgilabel->devparam.unused1 = SGI_SSWAP16(0);
2408 sgilabel->devparam.nsect = SGI_SSWAP16(geometry.sectors);
2410 sgilabel->devparam.bytes = SGI_SSWAP16(512);
2411 sgilabel->devparam.ilfact = SGI_SSWAP16(1);
2412 sgilabel->devparam.flags = SGI_SSWAP32(TRACK_FWD|
2413 IGNORE_ERRORS|RESEEK);
2414 sgilabel->devparam.datarate = SGI_SSWAP32(0);
2415 sgilabel->devparam.retries_on_error = SGI_SSWAP32(1);
2416 sgilabel->devparam.ms_per_word = SGI_SSWAP32(0);
2417 sgilabel->devparam.xylogics_gap1 = SGI_SSWAP16(0);
2418 sgilabel->devparam.xylogics_syncdelay = SGI_SSWAP16(0);
2419 sgilabel->devparam.xylogics_readdelay = SGI_SSWAP16(0);
2420 sgilabel->devparam.xylogics_gap2 = SGI_SSWAP16(0);
2421 sgilabel->devparam.xylogics_readgate = SGI_SSWAP16(0);
2422 sgilabel->devparam.xylogics_writecont = SGI_SSWAP16(0);
2423 memset( &(sgilabel->directory), 0, sizeof(struct volume_directory)*15 );
2424 memset( &(sgilabel->partitions), 0, sizeof(struct sgi_partition)*16 );
2430 for (i = 0; i < 4; i++) {
2432 sgi_set_partition(i, old[i].start, old[i].nsect, old[i].sysid);
2440 /* do nothing in the beginning */
2442 #endif /* CONFIG_FEATURE_FDISK_ADVANCED */
2444 /* _____________________________________________________________
2450 sgiinfo *info = calloc(1, sizeof(sgiinfo));
2452 info->magic=SGI_SSWAP32(SGI_INFO_MAGIC);
2453 info->b1=SGI_SSWAP32(-1);
2454 info->b2=SGI_SSWAP16(-1);
2455 info->b3=SGI_SSWAP16(1);
2456 /* You may want to replace this string !!!!!!! */
2457 strcpy( info->scsi_string, "IBM OEM 0662S12 3 30" );
2458 strcpy( info->serial, "0000" );
2459 info->check1816 = SGI_SSWAP16(18*256 +16 );
2460 strcpy( info->installer, "Sfx version 5.3, Oct 18, 1994" );
2463 #endif /* SGI_LABEL */
2466 #ifdef CONFIG_FEATURE_SUN_LABEL
2470 * I think this is mostly, or entirely, due to
2471 * Jakub Jelinek (jj@sunsite.mff.cuni.cz), July 1996
2473 * Merged with fdisk for other architectures, aeb, June 1998.
2475 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
2476 * Internationalization
2480 static int sun_other_endian;
2481 static int scsi_disk;
2485 #define IDE0_MAJOR 3
2488 #define IDE1_MAJOR 22
2491 static void guess_device_type(void) {
2492 struct stat bootstat;
2494 if (fstat (fd, &bootstat) < 0) {
2497 } else if (S_ISBLK(bootstat.st_mode)
2498 && (major(bootstat.st_rdev) == IDE0_MAJOR ||
2499 major(bootstat.st_rdev) == IDE1_MAJOR)) {
2502 } else if (S_ISBLK(bootstat.st_mode)
2503 && major(bootstat.st_rdev) == FLOPPY_MAJOR) {
2512 static const struct systypes sun_sys_types[] = {
2513 /* 0 */ {"\x00" "Empty" },
2514 /* 1 */ {"\x01" "Boot" },
2515 /* 2 */ {"\x02" "SunOS root" },
2516 /* SUNOS_SWAP */ {"\x03" "SunOS swap" },
2517 /* 4 */ {"\x04" "SunOS usr" },
2518 /* WHOLE_DISK */ {"\x05" "Whole disk" },
2519 /* 6 */ {"\x06" "SunOS stand" },
2520 /* 7 */ {"\x07" "SunOS var" },
2521 /* 8 */ {"\x08" "SunOS home" },
2522 /* LINUX_SWAP */ {"\x82" "Linux swap" },
2523 /* LINUX_NATIVE */ {"\x83" "Linux native" },
2524 /* 0x8e */ {"\x8e" "Linux LVM" },
2525 /* New (2.2.x) raid partition with autodetect using persistent superblock */
2526 /* 0xfd */ {"\xfd" "Linux raid autodetect" },
2532 set_sun_partition(int i, uint start, uint stop, int sysid) {
2533 sunlabel->infos[i].id = sysid;
2534 sunlabel->partitions[i].start_cylinder =
2535 SUN_SSWAP32(start / (heads * sectors));
2536 sunlabel->partitions[i].num_sectors =
2537 SUN_SSWAP32(stop - start);
2544 sunlabel->magic = 0;
2549 check_sun_label(void) {
2550 unsigned short *ush;
2553 if (sunlabel->magic != SUN_LABEL_MAGIC &&
2554 sunlabel->magic != SUN_LABEL_MAGIC_SWAPPED) {
2556 sun_other_endian = 0;
2559 sun_other_endian = (sunlabel->magic == SUN_LABEL_MAGIC_SWAPPED);
2560 ush = ((unsigned short *) (sunlabel + 1)) - 1;
2561 for (csum = 0; ush >= (unsigned short *)sunlabel;) csum ^= *ush--;
2563 fprintf(stderr,_("Detected sun disklabel with wrong checksum.\n"
2564 "Probably you'll have to set all the values,\n"
2565 "e.g. heads, sectors, cylinders and partitions\n"
2566 "or force a fresh label (s command in main menu)\n"));
2568 heads = SUN_SSWAP16(sunlabel->ntrks);
2569 cylinders = SUN_SSWAP16(sunlabel->ncyl);
2570 sectors = SUN_SSWAP16(sunlabel->nsect);
2578 static const struct sun_predefined_drives {
2581 unsigned short sparecyl;
2582 unsigned short ncyl;
2583 unsigned short nacyl;
2584 unsigned short pcylcount;
2585 unsigned short ntrks;
2586 unsigned short nsect;
2587 unsigned short rspeed;
2589 {"Quantum","ProDrive 80S",1,832,2,834,6,34,3662},
2590 {"Quantum","ProDrive 105S",1,974,2,1019,6,35,3662},
2591 {"CDC","Wren IV 94171-344",3,1545,2,1549,9,46,3600},
2592 {"IBM","DPES-31080",0,4901,2,4903,4,108,5400},
2593 {"IBM","DORS-32160",0,1015,2,1017,67,62,5400},
2594 {"IBM","DNES-318350",0,11199,2,11474,10,320,7200},
2595 {"SEAGATE","ST34371",0,3880,2,3882,16,135,7228},
2596 {"","SUN0104",1,974,2,1019,6,35,3662},
2597 {"","SUN0207",4,1254,2,1272,9,36,3600},
2598 {"","SUN0327",3,1545,2,1549,9,46,3600},
2599 {"","SUN0340",0,1538,2,1544,6,72,4200},
2600 {"","SUN0424",2,1151,2,2500,9,80,4400},
2601 {"","SUN0535",0,1866,2,2500,7,80,5400},
2602 {"","SUN0669",5,1614,2,1632,15,54,3600},
2603 {"","SUN1.0G",5,1703,2,1931,15,80,3597},
2604 {"","SUN1.05",0,2036,2,2038,14,72,5400},
2605 {"","SUN1.3G",6,1965,2,3500,17,80,5400},
2606 {"","SUN2.1G",0,2733,2,3500,19,80,5400},
2607 {"IOMEGA","Jaz",0,1019,2,1021,64,32,5394},
2610 static const struct sun_predefined_drives *
2611 sun_autoconfigure_scsi(void) {
2612 const struct sun_predefined_drives *p = NULL;
2614 #ifdef SCSI_IOCTL_GET_IDLUN
2624 if (!ioctl(fd, SCSI_IOCTL_GET_IDLUN, &id)) {
2626 "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n",
2628 ((id[0]>>24)&0xff)-/*PROC_SCSI_SCSI+PROC_SCSI_FILE*/33,
2630 /* This is very wrong (works only if you have one HBA),
2631 but I haven't found a way how to get hostno
2632 from the current kernel */
2638 pfd = fopen("/proc/scsi/scsi","r");
2640 while (fgets(buffer2,2048,pfd)) {
2641 if (!strcmp(buffer, buffer2)) {
2642 if (fgets(buffer2,2048,pfd)) {
2643 q = strstr(buffer2,"Vendor: ");
2648 *q++ = 0; /* truncate vendor name */
2649 q = strstr(q,"Model: ");
2654 q = strstr(q," Rev: ");
2657 for (i = 0; i < SIZE(sun_drives); i++) {
2658 if (*sun_drives[i].vendor && strcasecmp(sun_drives[i].vendor, vendor))
2660 if (!strstr(model, sun_drives[i].model))
2662 printf(_("Autoconfigure found a %s%s%s\n"),sun_drives[i].vendor,(*sun_drives[i].vendor) ? " " : "",sun_drives[i].model);
2680 static void create_sunlabel(void)
2682 struct hd_geometry geometry;
2686 const struct sun_predefined_drives *p = NULL;
2689 _("Building a new sun disklabel. Changes will remain in memory only,\n"
2690 "until you decide to write them. After that, of course, the previous\n"
2691 "content won't be recoverable.\n\n"));
2692 #if BYTE_ORDER == LITTLE_ENDIAN
2693 sun_other_endian = 1;
2695 sun_other_endian = 0;
2697 memset(MBRbuffer, 0, sizeof(MBRbuffer));
2698 sunlabel->magic = SUN_SSWAP16(SUN_LABEL_MAGIC);
2700 puts(_("Drive type\n"
2701 " ? auto configure\n"
2702 " 0 custom (with hardware detected defaults)"));
2703 for (i = 0; i < SIZE(sun_drives); i++) {
2704 printf(" %c %s%s%s\n",
2705 i + 'a', sun_drives[i].vendor,
2706 (*sun_drives[i].vendor) ? " " : "",
2707 sun_drives[i].model);
2710 c = read_char(_("Select type (? for auto, 0 for custom): "));
2711 if (c >= 'a' && c < 'a' + SIZE(sun_drives)) {
2712 p = sun_drives + c - 'a';
2714 } else if (c >= 'A' && c < 'A' + SIZE(sun_drives)) {
2715 p = sun_drives + c - 'A';
2717 } else if (c == '0') {
2719 } else if (c == '?' && scsi_disk) {
2720 p = sun_autoconfigure_scsi();
2722 printf(_("Autoconfigure failed.\n"));
2729 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
2730 heads = geometry.heads;
2731 sectors = geometry.sectors;
2732 cylinders = geometry.cylinders;
2739 sunlabel->nacyl = 0;
2740 sunlabel->pcylcount = SUN_SSWAP16(cylinders);
2741 sunlabel->rspeed = SUN_SSWAP16(300);
2742 sunlabel->ilfact = SUN_SSWAP16(1);
2743 sunlabel->sparecyl = 0;
2745 heads = read_int(1,heads,1024,0,_("Heads"));
2746 sectors = read_int(1,sectors,1024,0,_("Sectors/track"));
2748 cylinders = read_int(1,cylinders-2,65535,0,_("Cylinders"));
2750 cylinders = read_int(1,0,65535,0,_("Cylinders"));
2752 SUN_SSWAP16(read_int(0,2,65535,0,
2753 _("Alternate cylinders")));
2754 sunlabel->pcylcount =
2755 SUN_SSWAP16(read_int(0,cylinders+SUN_SSWAP16(sunlabel->nacyl),
2756 65535,0,_("Physical cylinders")));
2758 SUN_SSWAP16(read_int(1,5400,100000,0,
2759 _("Rotation speed (rpm)")));
2761 SUN_SSWAP16(read_int(1,1,32,0,_("Interleave factor")));
2762 sunlabel->sparecyl =
2763 SUN_SSWAP16(read_int(0,0,sectors,0,
2764 _("Extra sectors per cylinder")));
2767 sunlabel->sparecyl = SUN_SSWAP16(p->sparecyl);
2768 sunlabel->ncyl = SUN_SSWAP16(p->ncyl);
2769 sunlabel->nacyl = SUN_SSWAP16(p->nacyl);
2770 sunlabel->pcylcount = SUN_SSWAP16(p->pcylcount);
2771 sunlabel->ntrks = SUN_SSWAP16(p->ntrks);
2772 sunlabel->nsect = SUN_SSWAP16(p->nsect);
2773 sunlabel->rspeed = SUN_SSWAP16(p->rspeed);
2774 sunlabel->ilfact = SUN_SSWAP16(1);
2775 cylinders = p->ncyl;
2778 puts(_("You may change all the disk params from the x menu"));
2781 snprintf((char *)(sunlabel->info), sizeof(sunlabel->info),
2782 "%s%s%s cyl %d alt %d hd %d sec %d",
2783 p ? p->vendor : "", (p && *p->vendor) ? " " : "",
2785 : (floppy ? _("3,5\" floppy") : _("Linux custom")),
2786 cylinders, SUN_SSWAP16(sunlabel->nacyl), heads, sectors);
2788 sunlabel->ntrks = SUN_SSWAP16(heads);
2789 sunlabel->nsect = SUN_SSWAP16(sectors);
2790 sunlabel->ncyl = SUN_SSWAP16(cylinders);
2792 set_sun_partition(0, 0, cylinders * heads * sectors, LINUX_NATIVE);
2794 if (cylinders * heads * sectors >= 150 * 2048) {
2795 ndiv = cylinders - (50 * 2048 / (heads * sectors)); /* 50M swap */
2797 ndiv = cylinders * 2 / 3;
2798 set_sun_partition(0, 0, ndiv * heads * sectors, LINUX_NATIVE);
2799 set_sun_partition(1, ndiv * heads * sectors, cylinders * heads * sectors, LINUX_SWAP);
2800 sunlabel->infos[1].flags |= 0x01; /* Not mountable */
2802 set_sun_partition(2, 0, cylinders * heads * sectors, WHOLE_DISK);
2804 unsigned short *ush = (unsigned short *)sunlabel;
2805 unsigned short csum = 0;
2806 while(ush < (unsigned short *)(&sunlabel->csum))
2808 sunlabel->csum = csum;
2811 set_all_unchanged();
2813 get_boot(create_empty_sun);
2817 toggle_sunflags(int i, unsigned char mask) {
2818 if (sunlabel->infos[i].flags & mask)
2819 sunlabel->infos[i].flags &= ~mask;
2820 else sunlabel->infos[i].flags |= mask;
2825 fetch_sun(uint *starts, uint *lens, uint *start, uint *stop) {
2826 int i, continuous = 1;
2827 *start = 0; *stop = cylinders * heads * sectors;
2828 for (i = 0; i < partitions; i++) {
2829 if (sunlabel->partitions[i].num_sectors
2830 && sunlabel->infos[i].id
2831 && sunlabel->infos[i].id != WHOLE_DISK) {
2832 starts[i] = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
2833 lens[i] = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
2835 if (starts[i] == *start)
2837 else if (starts[i] + lens[i] >= *stop)
2841 /* There will be probably more gaps
2842 than one, so lets check afterwards */
2851 static uint *verify_sun_starts;
2854 verify_sun_cmp(int *a, int *b) {
2855 if (*a == -1) return 1;
2856 if (*b == -1) return -1;
2857 if (verify_sun_starts[*a] > verify_sun_starts[*b]) return 1;
2863 uint starts[8], lens[8], start, stop;
2864 int i,j,k,starto,endo;
2867 verify_sun_starts = starts;
2868 fetch_sun(starts,lens,&start,&stop);
2869 for (k = 0; k < 7; k++) {
2870 for (i = 0; i < 8; i++) {
2871 if (k && (lens[i] % (heads * sectors))) {
2872 printf(_("Partition %d doesn't end on cylinder boundary\n"), i+1);
2875 for (j = 0; j < i; j++)
2877 if (starts[j] == starts[i]+lens[i]) {
2878 starts[j] = starts[i]; lens[j] += lens[i];
2880 } else if (starts[i] == starts[j]+lens[j]){
2884 if (starts[i] < starts[j]+lens[j] &&
2885 starts[j] < starts[i]+lens[i]) {
2887 if (starts[j] > starto)
2889 endo = starts[i]+lens[i];
2890 if (starts[j]+lens[j] < endo)
2891 endo = starts[j]+lens[j];
2892 printf(_("Partition %d overlaps with others in "
2893 "sectors %d-%d\n"), i+1, starto, endo);
2900 for (i = 0; i < 8; i++) {
2906 qsort(array,SIZE(array),sizeof(array[0]),
2907 (int (*)(const void *,const void *)) verify_sun_cmp);
2908 if (array[0] == -1) {
2909 printf(_("No partitions defined\n"));
2912 stop = cylinders * heads * sectors;
2913 if (starts[array[0]])
2914 printf(_("Unused gap - sectors 0-%d\n"),starts[array[0]]);
2915 for (i = 0; i < 7 && array[i+1] != -1; i++) {
2916 printf(_("Unused gap - sectors %d-%d\n"),starts[array[i]]+lens[array[i]],starts[array[i+1]]);
2918 start = starts[array[i]]+lens[array[i]];
2920 printf(_("Unused gap - sectors %d-%d\n"),start,stop);
2924 add_sun_partition(int n, int sys) {
2925 uint start, stop, stop2;
2926 uint starts[8], lens[8];
2932 if (sunlabel->partitions[n].num_sectors && sunlabel->infos[n].id) {
2933 printf(_("Partition %d is already defined. Delete "
2934 "it before re-adding it.\n"), n + 1);
2938 fetch_sun(starts,lens,&start,&stop);
2939 if (stop <= start) {
2943 printf(_("Other partitions already cover the whole disk.\nDelete "
2944 "some/shrink them before retry.\n"));
2948 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
2951 first = read_int(0, 0, 0, 0, mesg);
2953 first = read_int(scround(start), scround(stop)+1,
2954 scround(stop), 0, mesg);
2955 if (display_in_cyl_units)
2956 first *= units_per_sector;
2958 /* Starting sector has to be properly aligned */
2959 first = (first + heads * sectors - 1) / (heads * sectors);
2960 if (n == 2 && first != 0)
2962 It is highly recommended that the third partition covers the whole disk\n\
2963 and is of type `Whole disk'\n");
2964 /* ewt asks to add: "don't start a partition at cyl 0"
2965 However, edmundo@rano.demon.co.uk writes:
2966 "In addition to having a Sun partition table, to be able to
2967 boot from the disc, the first partition, /dev/sdX1, must
2968 start at cylinder 0. This means that /dev/sdX1 contains
2969 the partition table and the boot block, as these are the
2970 first two sectors of the disc. Therefore you must be
2971 careful what you use /dev/sdX1 for. In particular, you must
2972 not use a partition starting at cylinder 0 for Linux swap,
2973 as that would overwrite the partition table and the boot
2974 block. You may, however, use such a partition for a UFS
2975 or EXT2 file system, as these file systems leave the first
2976 1024 bytes undisturbed. */
2977 /* On the other hand, one should not use partitions
2978 starting at block 0 in an md, or the label will
2980 for (i = 0; i < partitions; i++)
2981 if (lens[i] && starts[i] <= first
2982 && starts[i] + lens[i] > first)
2984 if (i < partitions && !whole_disk) {
2985 if (n == 2 && !first) {
2989 printf(_("Sector %d is already allocated\n"), first);
2993 stop = cylinders * heads * sectors;
2995 for (i = 0; i < partitions; i++) {
2996 if (starts[i] > first && starts[i] < stop)
2999 snprintf(mesg, sizeof(mesg),
3000 _("Last %s or +size or +sizeM or +sizeK"),
3001 str_units(SINGULAR));
3003 last = read_int(scround(stop2), scround(stop2), scround(stop2),
3005 else if (n == 2 && !first)
3006 last = read_int(scround(first), scround(stop2), scround(stop2),
3007 scround(first), mesg);
3009 last = read_int(scround(first), scround(stop), scround(stop),
3010 scround(first), mesg);
3011 if (display_in_cyl_units)
3012 last *= units_per_sector;
3013 if (n == 2 && !first) {
3014 if (last >= stop2) {
3017 } else if (last > stop) {
3019 _("You haven't covered the whole disk with the 3rd partition, but your value\n"
3020 "%d %s covers some other partition. Your entry has been changed\n"
3022 scround(last), str_units(SINGULAR),
3023 scround(stop), str_units(SINGULAR));
3026 } else if (!whole_disk && last > stop)
3029 if (whole_disk) sys = WHOLE_DISK;
3030 set_sun_partition(n, first, last, sys);
3034 sun_delete_partition(int i) {
3037 if (i == 2 && sunlabel->infos[i].id == WHOLE_DISK &&
3038 !sunlabel->partitions[i].start_cylinder &&
3039 (nsec = SUN_SSWAP32(sunlabel->partitions[i].num_sectors))
3040 == heads * sectors * cylinders)
3041 printf(_("If you want to maintain SunOS/Solaris compatibility, "
3042 "consider leaving this\n"
3043 "partition as Whole disk (5), starting at 0, with %u "
3044 "sectors\n"), nsec);
3045 sunlabel->infos[i].id = 0;
3046 sunlabel->partitions[i].num_sectors = 0;
3050 sun_change_sysid(int i, int sys) {
3051 if (sys == LINUX_SWAP && !sunlabel->partitions[i].start_cylinder) {
3053 _("It is highly recommended that the partition at offset 0\n"
3054 "is UFS, EXT2FS filesystem or SunOS swap. Putting Linux swap\n"
3055 "there may destroy your partition table and bootblock.\n"
3056 "Type YES if you're very sure you would like that partition\n"
3057 "tagged with 82 (Linux swap): "));
3058 if (strcmp (line_ptr, _("YES\n")))
3064 /* swaps are not mountable by default */
3065 sunlabel->infos[i].flags |= 0x01;
3068 /* assume other types are mountable;
3069 user can change it anyway */
3070 sunlabel->infos[i].flags &= ~0x01;
3073 sunlabel->infos[i].id = sys;
3077 sun_list_table(int xtra) {
3080 w = strlen(disk_device);
3083 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d rpm\n"
3084 "%d cylinders, %d alternate cylinders, %d physical cylinders\n"
3085 "%d extra sects/cyl, interleave %d:1\n"
3087 "Units = %s of %d * 512 bytes\n\n"),
3088 disk_device, heads, sectors, SUN_SSWAP16(sunlabel->rspeed),
3089 cylinders, SUN_SSWAP16(sunlabel->nacyl),
3090 SUN_SSWAP16(sunlabel->pcylcount),
3091 SUN_SSWAP16(sunlabel->sparecyl),
3092 SUN_SSWAP16(sunlabel->ilfact),
3094 str_units(PLURAL), units_per_sector);
3097 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d cylinders\n"
3098 "Units = %s of %d * 512 bytes\n\n"),
3099 disk_device, heads, sectors, cylinders,
3100 str_units(PLURAL), units_per_sector);
3102 printf(_("%*s Flag Start End Blocks Id System\n"),
3103 w + 1, _("Device"));
3104 for (i = 0 ; i < partitions; i++) {
3105 if (sunlabel->partitions[i].num_sectors) {
3106 uint32_t start = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
3107 uint32_t len = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
3109 "%s %c%c %9ld %9ld %9ld%c %2x %s\n",
3110 /* device */ partname(disk_device, i+1, w),
3111 /* flags */ (sunlabel->infos[i].flags & 0x01) ? 'u' : ' ',
3112 (sunlabel->infos[i].flags & 0x10) ? 'r' : ' ',
3113 /* start */ (long) scround(start),
3114 /* end */ (long) scround(start+len),
3115 /* odd flag on end */ (long) len / 2, len & 1 ? '+' : ' ',
3116 /* type id */ sunlabel->infos[i].id,
3117 /* type name */ partition_type(sunlabel->infos[i].id));
3122 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3125 sun_set_alt_cyl(void) {
3127 SUN_SSWAP16(read_int(0,SUN_SSWAP16(sunlabel->nacyl), 65535, 0,
3128 _("Number of alternate cylinders")));
3132 sun_set_ncyl(int cyl) {
3133 sunlabel->ncyl = SUN_SSWAP16(cyl);
3137 sun_set_xcyl(void) {
3138 sunlabel->sparecyl =
3139 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->sparecyl), sectors, 0,
3140 _("Extra sectors per cylinder")));
3144 sun_set_ilfact(void) {
3146 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->ilfact), 32, 0,
3147 _("Interleave factor")));
3151 sun_set_rspeed(void) {
3153 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->rspeed), 100000, 0,
3154 _("Rotation speed (rpm)")));
3158 sun_set_pcylcount(void) {
3159 sunlabel->pcylcount =
3160 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->pcylcount), 65535, 0,
3161 _("Number of physical cylinders")));
3163 #endif /* CONFIG_FEATURE_FDISK_ADVANCED */
3166 sun_write_table(void) {
3167 unsigned short *ush = (unsigned short *)sunlabel;
3168 unsigned short csum = 0;
3170 while(ush < (unsigned short *)(&sunlabel->csum))
3172 sunlabel->csum = csum;
3173 if (lseek(fd, 0, SEEK_SET) < 0)
3174 fdisk_fatal(unable_to_seek);
3175 if (write(fd, sunlabel, SECTOR_SIZE) != SECTOR_SIZE)
3176 fdisk_fatal(unable_to_write);
3178 #endif /* SUN_LABEL */
3180 /* DOS partition types */
3182 static const struct systypes i386_sys_types[] = {
3185 {"\x04" "FAT16 <32M"},
3186 {"\x05" "Extended"}, /* DOS 3.3+ extended partition */
3187 {"\x06" "FAT16"}, /* DOS 16-bit >=32M */
3188 {"\x07" "HPFS/NTFS"}, /* OS/2 IFS, eg, HPFS or NTFS or QNX */
3189 {"\x0a" "OS/2 Boot Manager"},/* OS/2 Boot Manager */
3190 {"\x0b" "Win95 FAT32"},
3191 {"\x0c" "Win95 FAT32 (LBA)"},/* LBA really is `Extended Int 13h' */
3192 {"\x0e" "Win95 FAT16 (LBA)"},
3193 {"\x0f" "Win95 Ext'd (LBA)"},
3194 {"\x11" "Hidden FAT12"},
3195 {"\x12" "Compaq diagnostics"},
3196 {"\x14" "Hidden FAT16 <32M"},
3197 {"\x16" "Hidden FAT16"},
3198 {"\x17" "Hidden HPFS/NTFS"},
3199 {"\x1b" "Hidden Win95 FAT32"},
3200 {"\x1c" "Hidden Win95 FAT32 (LBA)"},
3201 {"\x1e" "Hidden Win95 FAT16 (LBA)"},
3202 {"\x3c" "PartitionMagic recovery"},
3203 {"\x41" "PPC PReP Boot"},
3205 {"\x63" "GNU HURD or SysV"}, /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */
3206 {"\x80" "Old Minix"}, /* Minix 1.4a and earlier */
3207 {"\x81" "Minix / old Linux"},/* Minix 1.4b and later */
3208 {"\x82" "Linux swap"}, /* also Solaris */
3210 {"\x84" "OS/2 hidden C: drive"},
3211 {"\x85" "Linux extended"},
3212 {"\x86" "NTFS volume set"},
3213 {"\x87" "NTFS volume set"},
3214 {"\x8e" "Linux LVM"},
3215 {"\x9f" "BSD/OS"}, /* BSDI */
3216 {"\xa0" "IBM Thinkpad hibernation"},
3217 {"\xa5" "FreeBSD"}, /* various BSD flavours */
3219 {"\xa8" "Darwin UFS"},
3221 {"\xab" "Darwin boot"},
3223 {"\xb8" "BSDI swap"},
3224 {"\xbe" "Solaris boot"},
3226 {"\xee" "EFI GPT"}, /* Intel EFI GUID Partition Table */
3227 {"\xef" "EFI (FAT-12/16/32)"},/* Intel EFI System Partition */
3228 {"\xf0" "Linux/PA-RISC boot"},/* Linux/PA-RISC boot loader */
3229 {"\xf2" "DOS secondary"}, /* DOS 3.3+ secondary */
3230 {"\xfd" "Linux raid autodetect"},/* New (2.2.x) raid partition with
3231 autodetect using persistent
3233 #ifdef CONFIG_WEIRD_PARTITION_TYPES
3234 {"\x02" "XENIX root"},
3235 {"\x03" "XENIX usr"},
3236 {"\x08" "AIX"}, /* AIX boot (AIX -- PS/2 port) or SplitDrive */
3237 {"\x09" "AIX bootable"}, /* AIX data or Coherent */
3239 {"\x18" "AST SmartSleep"},
3242 {"\x40" "Venix 80286"},
3244 {"\x4e" "QNX4.x 2nd part"},
3245 {"\x4f" "QNX4.x 3rd part"},
3246 {"\x50" "OnTrack DM"},
3247 {"\x51" "OnTrack DM6 Aux1"}, /* (or Novell) */
3248 {"\x52" "CP/M"}, /* CP/M or Microport SysV/AT */
3249 {"\x53" "OnTrack DM6 Aux3"},
3250 {"\x54" "OnTrackDM6"},
3251 {"\x55" "EZ-Drive"},
3252 {"\x56" "Golden Bow"},
3253 {"\x5c" "Priam Edisk"},
3254 {"\x61" "SpeedStor"},
3255 {"\x64" "Novell Netware 286"},
3256 {"\x65" "Novell Netware 386"},
3257 {"\x70" "DiskSecure Multi-Boot"},
3260 {"\x94" "Amoeba BBT"}, /* (bad block table) */
3261 {"\xa7" "NeXTSTEP"},
3262 {"\xbb" "Boot Wizard hidden"},
3263 {"\xc1" "DRDOS/sec (FAT-12)"},
3264 {"\xc4" "DRDOS/sec (FAT-16 < 32M)"},
3265 {"\xc6" "DRDOS/sec (FAT-16)"},
3267 {"\xda" "Non-FS data"},
3268 {"\xdb" "CP/M / CTOS / ..."},/* CP/M or Concurrent CP/M or
3269 Concurrent DOS or CTOS */
3270 {"\xde" "Dell Utility"}, /* Dell PowerEdge Server utilities */
3271 {"\xdf" "BootIt"}, /* BootIt EMBRM */
3272 {"\xe1" "DOS access"}, /* DOS access or SpeedStor 12-bit FAT
3273 extended partition */
3274 {"\xe3" "DOS R/O"}, /* DOS R/O or SpeedStor */
3275 {"\xe4" "SpeedStor"}, /* SpeedStor 16-bit FAT extended
3276 partition < 1024 cyl. */
3277 {"\xf1" "SpeedStor"},
3278 {"\xf4" "SpeedStor"}, /* SpeedStor large partition */
3279 {"\xfe" "LANstep"}, /* SpeedStor >1024 cyl. or LANstep */
3280 {"\xff" "BBT"}, /* Xenix Bad Block Table */
3287 /* A valid partition table sector ends in 0x55 0xaa */
3289 part_table_flag(const char *b) {
3290 return ((uint) b[510]) + (((uint) b[511]) << 8);
3294 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3296 write_part_table_flag(char *b) {
3301 /* start_sect and nr_sects are stored little endian on all machines */
3302 /* moreover, they are not aligned correctly */
3304 store4_little_endian(unsigned char *cp, unsigned int val) {
3305 cp[0] = (val & 0xff);
3306 cp[1] = ((val >> 8) & 0xff);
3307 cp[2] = ((val >> 16) & 0xff);
3308 cp[3] = ((val >> 24) & 0xff);
3310 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3313 read4_little_endian(const unsigned char *cp) {
3314 return (uint)(cp[0]) + ((uint)(cp[1]) << 8)
3315 + ((uint)(cp[2]) << 16) + ((uint)(cp[3]) << 24);
3318 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3320 set_start_sect(struct partition *p, unsigned int start_sect) {
3321 store4_little_endian(p->start4, start_sect);
3326 get_start_sect(const struct partition *p) {
3327 return read4_little_endian(p->start4);
3330 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3332 set_nr_sects(struct partition *p, int32_t nr_sects) {
3333 store4_little_endian(p->size4, nr_sects);
3338 get_nr_sects(const struct partition *p) {
3339 return read4_little_endian(p->size4);
3342 /* normally O_RDWR, -l option gives O_RDONLY */
3343 static int type_open = O_RDWR;
3346 static int ext_index, /* the prime extended partition */
3347 listing, /* no aborts for fdisk -l */
3348 dos_compatible_flag = ~0;
3349 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3350 static int dos_changed;
3351 static int nowarn; /* no warnings for fdisk -l/-s */
3356 static uint user_cylinders, user_heads, user_sectors;
3357 static uint pt_heads, pt_sectors;
3358 static uint kern_heads, kern_sectors;
3360 static off_t extended_offset; /* offset of link pointers */
3362 static unsigned long long total_number_of_sectors;
3365 static jmp_buf listingbuf;
3367 static void fdisk_fatal(enum failure why) {
3368 const char *message;
3372 longjmp(listingbuf, 1);
3376 case unable_to_open:
3377 message = "Unable to open %s\n";
3379 case unable_to_read:
3380 message = "Unable to read %s\n";
3382 case unable_to_seek:
3383 message = "Unable to seek on %s\n";
3385 case unable_to_write:
3386 message = "Unable to write %s\n";
3389 message = "BLKGETSIZE ioctl failed on %s\n";
3392 message = "Fatal error\n";
3395 fputc('\n', stderr);
3396 fprintf(stderr, message, disk_device);
3401 seek_sector(off_t secno) {
3402 off_t offset = secno * sector_size;
3403 if (lseek(fd, offset, SEEK_SET) == (off_t) -1)
3404 fdisk_fatal(unable_to_seek);
3407 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3409 write_sector(off_t secno, char *buf) {
3411 if (write(fd, buf, sector_size) != sector_size)
3412 fdisk_fatal(unable_to_write);
3416 /* Allocate a buffer and read a partition table sector */
3418 read_pte(struct pte *pe, off_t offset) {
3420 pe->offset = offset;
3421 pe->sectorbuffer = (char *) xmalloc(sector_size);
3422 seek_sector(offset);
3423 if (read(fd, pe->sectorbuffer, sector_size) != sector_size)
3424 fdisk_fatal(unable_to_read);
3425 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3428 pe->part_table = pe->ext_pointer = NULL;
3432 get_partition_start(const struct pte *pe) {
3433 return pe->offset + get_start_sect(pe->part_table);
3436 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3438 * Avoid warning about DOS partitions when no DOS partition was changed.
3439 * Here a heuristic "is probably dos partition".
3440 * We might also do the opposite and warn in all cases except
3441 * for "is probably nondos partition".
3444 is_dos_partition(int t) {
3445 return (t == 1 || t == 4 || t == 6 ||
3446 t == 0x0b || t == 0x0c || t == 0x0e ||
3447 t == 0x11 || t == 0x12 || t == 0x14 || t == 0x16 ||
3448 t == 0x1b || t == 0x1c || t == 0x1e || t == 0x24 ||
3449 t == 0xc1 || t == 0xc4 || t == 0xc6);
3454 #ifdef CONFIG_FEATURE_SUN_LABEL
3456 puts(_("Command action"));
3457 puts(_("\ta\ttoggle a read only flag")); /* sun */
3458 puts(_("\tb\tedit bsd disklabel"));
3459 puts(_("\tc\ttoggle the mountable flag")); /* sun */
3460 puts(_("\td\tdelete a partition"));
3461 puts(_("\tl\tlist known partition types"));
3462 puts(_("\tm\tprint this menu"));
3463 puts(_("\tn\tadd a new partition"));
3464 puts(_("\to\tcreate a new empty DOS partition table"));
3465 puts(_("\tp\tprint the partition table"));
3466 puts(_("\tq\tquit without saving changes"));
3467 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3468 puts(_("\tt\tchange a partition's system id"));
3469 puts(_("\tu\tchange display/entry units"));
3470 puts(_("\tv\tverify the partition table"));
3471 puts(_("\tw\twrite table to disk and exit"));
3472 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3473 puts(_("\tx\textra functionality (experts only)"));
3477 #ifdef CONFIG_FEATURE_SGI_LABEL
3479 puts(_("Command action"));
3480 puts(_("\ta\tselect bootable partition")); /* sgi flavour */
3481 puts(_("\tb\tedit bootfile entry")); /* sgi */
3482 puts(_("\tc\tselect sgi swap partition")); /* sgi flavour */
3483 puts(_("\td\tdelete a partition"));
3484 puts(_("\tl\tlist known partition types"));
3485 puts(_("\tm\tprint this menu"));
3486 puts(_("\tn\tadd a new partition"));
3487 puts(_("\to\tcreate a new empty DOS partition table"));
3488 puts(_("\tp\tprint the partition table"));
3489 puts(_("\tq\tquit without saving changes"));
3490 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3491 puts(_("\tt\tchange a partition's system id"));
3492 puts(_("\tu\tchange display/entry units"));
3493 puts(_("\tv\tverify the partition table"));
3494 puts(_("\tw\twrite table to disk and exit"));
3497 #ifdef CONFIG_FEATURE_AIX_LABEL
3499 puts(_("Command action"));
3500 puts(_("\tm\tprint this menu"));
3501 puts(_("\to\tcreate a new empty DOS partition table"));
3502 puts(_("\tq\tquit without saving changes"));
3503 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3507 puts(_("Command action"));
3508 puts(_("\ta\ttoggle a bootable flag"));
3509 puts(_("\tb\tedit bsd disklabel"));
3510 puts(_("\tc\ttoggle the dos compatibility flag"));
3511 puts(_("\td\tdelete a partition"));
3512 puts(_("\tl\tlist known partition types"));
3513 puts(_("\tm\tprint this menu"));
3514 puts(_("\tn\tadd a new partition"));
3515 puts(_("\to\tcreate a new empty DOS partition table"));
3516 puts(_("\tp\tprint the partition table"));
3517 puts(_("\tq\tquit without saving changes"));
3518 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3519 puts(_("\tt\tchange a partition's system id"));
3520 puts(_("\tu\tchange display/entry units"));
3521 puts(_("\tv\tverify the partition table"));
3522 puts(_("\tw\twrite table to disk and exit"));
3523 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3524 puts(_("\tx\textra functionality (experts only)"));
3528 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3531 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3534 #ifdef CONFIG_FEATURE_SUN_LABEL
3536 puts(_("Command action"));
3537 puts(_("\ta\tchange number of alternate cylinders")); /*sun*/
3538 puts(_("\tc\tchange number of cylinders"));
3539 puts(_("\td\tprint the raw data in the partition table"));
3540 puts(_("\te\tchange number of extra sectors per cylinder"));/*sun*/
3541 puts(_("\th\tchange number of heads"));
3542 puts(_("\ti\tchange interleave factor")); /*sun*/
3543 puts(_("\to\tchange rotation speed (rpm)")); /*sun*/
3544 puts(_("\tm\tprint this menu"));
3545 puts(_("\tp\tprint the partition table"));
3546 puts(_("\tq\tquit without saving changes"));
3547 puts(_("\tr\treturn to main menu"));
3548 puts(_("\ts\tchange number of sectors/track"));
3549 puts(_("\tv\tverify the partition table"));
3550 puts(_("\tw\twrite table to disk and exit"));
3551 puts(_("\ty\tchange number of physical cylinders")); /*sun*/
3554 #ifdef CONFIG_FEATURE_SGI_LABEL
3556 puts(_("Command action"));
3557 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3558 puts(_("\tc\tchange number of cylinders"));
3559 puts(_("\td\tprint the raw data in the partition table"));
3560 puts(_("\te\tlist extended partitions")); /* !sun */
3561 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3562 puts(_("\th\tchange number of heads"));
3563 puts(_("\tm\tprint this menu"));
3564 puts(_("\tp\tprint the partition table"));
3565 puts(_("\tq\tquit without saving changes"));
3566 puts(_("\tr\treturn to main menu"));
3567 puts(_("\ts\tchange number of sectors/track"));
3568 puts(_("\tv\tverify the partition table"));
3569 puts(_("\tw\twrite table to disk and exit"));
3572 #ifdef CONFIG_FEATURE_AIX_LABEL
3574 puts(_("Command action"));
3575 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3576 puts(_("\tc\tchange number of cylinders"));
3577 puts(_("\td\tprint the raw data in the partition table"));
3578 puts(_("\te\tlist extended partitions")); /* !sun */
3579 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3580 puts(_("\th\tchange number of heads"));
3581 puts(_("\tm\tprint this menu"));
3582 puts(_("\tp\tprint the partition table"));
3583 puts(_("\tq\tquit without saving changes"));
3584 puts(_("\tr\treturn to main menu"));
3585 puts(_("\ts\tchange number of sectors/track"));
3586 puts(_("\tv\tverify the partition table"));
3587 puts(_("\tw\twrite table to disk and exit"));
3591 puts(_("Command action"));
3592 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3593 puts(_("\tc\tchange number of cylinders"));
3594 puts(_("\td\tprint the raw data in the partition table"));
3595 puts(_("\te\tlist extended partitions")); /* !sun */
3596 puts(_("\tf\tfix partition order")); /* !sun, !aix, !sgi */
3597 #ifdef CONFIG_FEATURE_SGI_LABEL
3598 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3600 puts(_("\th\tchange number of heads"));
3601 puts(_("\tm\tprint this menu"));
3602 puts(_("\tp\tprint the partition table"));
3603 puts(_("\tq\tquit without saving changes"));
3604 puts(_("\tr\treturn to main menu"));
3605 puts(_("\ts\tchange number of sectors/track"));
3606 puts(_("\tv\tverify the partition table"));
3607 puts(_("\tw\twrite table to disk and exit"));
3610 #endif /* ADVANCED mode */
3612 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3613 static const struct systypes *
3614 get_sys_types(void) {
3616 #ifdef CONFIG_FEATURE_SUN_LABEL
3617 sun_label ? sun_sys_types :
3619 #ifdef CONFIG_FEATURE_SGI_LABEL
3620 sgi_label ? sgi_sys_types :
3625 #define get_sys_types() i386_sys_types
3626 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3628 static const char *partition_type(unsigned char type)
3631 const struct systypes *types = get_sys_types();
3633 for (i=0; types[i].name; i++)
3634 if ((unsigned char )types[i].name[0] == type)
3635 return types[i].name + 1;
3637 return _("Unknown");
3641 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3645 #ifdef CONFIG_FEATURE_SUN_LABEL
3646 sun_label ? sunlabel->infos[i].id :
3648 #ifdef CONFIG_FEATURE_SGI_LABEL
3649 sgi_label ? sgi_get_sysid(i) :
3651 ptes[i].part_table->sys_ind);
3654 void list_types(const struct systypes *sys)
3656 uint last[4], done = 0, next = 0, size;
3659 for (i = 0; sys[i].name; i++);
3662 for (i = 3; i >= 0; i--)
3663 last[3 - i] = done += (size + i - done) / (i + 1);
3667 printf("%c%2x %-15.15s", i ? ' ' : '\n',
3668 (unsigned char)sys[next].name[0],
3669 partition_type((unsigned char)sys[next].name[0]));
3670 next = last[i++] + done;
3671 if (i > 3 || next >= last[i]) {
3675 } while (done < last[0]);
3678 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3681 is_cleared_partition(const struct partition *p) {
3682 return !(!p || p->boot_ind || p->head || p->sector || p->cyl ||
3683 p->sys_ind || p->end_head || p->end_sector || p->end_cyl ||
3684 get_start_sect(p) || get_nr_sects(p));
3688 clear_partition(struct partition *p) {
3691 memset(p, 0, sizeof(struct partition));
3694 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3696 set_partition(int i, int doext, off_t start, off_t stop, int sysid) {
3697 struct partition *p;
3701 p = ptes[i].ext_pointer;
3702 offset = extended_offset;
3704 p = ptes[i].part_table;
3705 offset = ptes[i].offset;
3709 set_start_sect(p, start - offset);
3710 set_nr_sects(p, stop - start + 1);
3711 if (dos_compatible_flag && (start/(sectors*heads) > 1023))
3712 start = heads*sectors*1024 - 1;
3713 set_hsc(p->head, p->sector, p->cyl, start);
3714 if (dos_compatible_flag && (stop/(sectors*heads) > 1023))
3715 stop = heads*sectors*1024 - 1;
3716 set_hsc(p->end_head, p->end_sector, p->end_cyl, stop);
3717 ptes[i].changed = 1;
3722 test_c(const char **m, const char *mesg) {
3725 fprintf(stderr, _("You must set"));
3727 fprintf(stderr, " %s", *m);
3735 warn_geometry(void) {
3736 const char *m = NULL;
3740 prev = test_c(&m, _("heads"));
3742 prev = test_c(&m, _("sectors"));
3744 prev = test_c(&m, _("cylinders"));
3748 fprintf(stderr, "%s%s.\n"
3749 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3750 "You can do this from the extra functions menu.\n"
3752 , prev ? _(" and ") : " ", m);
3757 static void update_units(void)
3759 int cyl_units = heads * sectors;
3761 if (display_in_cyl_units && cyl_units)
3762 units_per_sector = cyl_units;
3764 units_per_sector = 1; /* in sectors */
3767 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3769 warn_cylinders(void) {
3770 if (dos_label && cylinders > 1024 && !nowarn)
3771 fprintf(stderr, _("\n"
3772 "The number of cylinders for this disk is set to %d.\n"
3773 "There is nothing wrong with that, but this is larger than 1024,\n"
3774 "and could in certain setups cause problems with:\n"
3775 "1) software that runs at boot time (e.g., old versions of LILO)\n"
3776 "2) booting and partitioning software from other OSs\n"
3777 " (e.g., DOS FDISK, OS/2 FDISK)\n"),
3783 read_extended(int ext) {
3786 struct partition *p, *q;
3790 pex->ext_pointer = pex->part_table;
3792 p = pex->part_table;
3793 if (!get_start_sect(p)) {
3795 _("Bad offset in primary extended partition\n"));
3799 while (IS_EXTENDED (p->sys_ind)) {
3800 struct pte *pe = &ptes[partitions];
3802 if (partitions >= MAXIMUM_PARTS) {
3803 /* This is not a Linux restriction, but
3804 this program uses arrays of size MAXIMUM_PARTS.
3805 Do not try to `improve' this test. */
3806 struct pte *pre = &ptes[partitions-1];
3807 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3809 _("Warning: deleting partitions after %d\n"),
3813 clear_partition(pre->ext_pointer);
3817 read_pte(pe, extended_offset + get_start_sect(p));
3819 if (!extended_offset)
3820 extended_offset = get_start_sect(p);
3822 q = p = pt_offset(pe->sectorbuffer, 0);
3823 for (i = 0; i < 4; i++, p++) if (get_nr_sects(p)) {
3824 if (IS_EXTENDED (p->sys_ind)) {
3825 if (pe->ext_pointer)
3827 _("Warning: extra link "
3828 "pointer in partition table"
3829 " %d\n"), partitions + 1);
3831 pe->ext_pointer = p;
3832 } else if (p->sys_ind) {
3835 _("Warning: ignoring extra "
3836 "data in partition table"
3837 " %d\n"), partitions + 1);
3843 /* very strange code here... */
3844 if (!pe->part_table) {
3845 if (q != pe->ext_pointer)
3848 pe->part_table = q + 1;
3850 if (!pe->ext_pointer) {
3851 if (q != pe->part_table)
3852 pe->ext_pointer = q;
3854 pe->ext_pointer = q + 1;
3857 p = pe->ext_pointer;
3861 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3862 /* remove empty links */
3864 for (i = 4; i < partitions; i++) {
3865 struct pte *pe = &ptes[i];
3867 if (!get_nr_sects(pe->part_table) &&
3868 (partitions > 5 || ptes[4].part_table->sys_ind)) {
3869 printf("omitting empty partition (%d)\n", i+1);
3870 delete_partition(i);
3871 goto remove; /* numbering changed */
3877 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3879 create_doslabel(void) {
3883 _("Building a new DOS disklabel. Changes will remain in memory only,\n"
3884 "until you decide to write them. After that, of course, the previous\n"
3885 "content won't be recoverable.\n\n"));
3886 #ifdef CONFIG_FEATURE_SUN_LABEL
3887 sun_nolabel(); /* otherwise always recognised as sun */
3889 #ifdef CONFIG_FEATURE_SGI_LABEL
3890 sgi_nolabel(); /* otherwise always recognised as sgi */
3892 #ifdef CONFIG_FEATURE_AIX_LABEL
3895 #ifdef CONFIG_FEATURE_OSF_LABEL
3897 possibly_osf_label = 0;
3901 for (i = 510-64; i < 510; i++)
3903 write_part_table_flag(MBRbuffer);
3904 extended_offset = 0;
3905 set_all_unchanged();
3907 get_boot(create_empty_dos);
3909 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3912 get_sectorsize(void) {
3913 if (!user_set_sector_size &&
3914 get_kernel_revision() >= MAKE_VERSION(2,3,3)) {
3916 if (ioctl(fd, BLKSSZGET, &arg) == 0)
3918 if (sector_size != DEFAULT_SECTOR_SIZE)
3919 printf(_("Note: sector size is %d (not %d)\n"),
3920 sector_size, DEFAULT_SECTOR_SIZE);
3925 get_kernel_geometry(void) {
3926 struct hd_geometry geometry;
3928 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
3929 kern_heads = geometry.heads;
3930 kern_sectors = geometry.sectors;
3931 /* never use geometry.cylinders - it is truncated */
3936 get_partition_table_geometry(void) {
3937 const unsigned char *bufp = (const unsigned char *)MBRbuffer;
3938 struct partition *p;
3939 int i, h, s, hh, ss;
3943 if (!(valid_part_table_flag(bufp)))
3947 for (i=0; i<4; i++) {
3948 p = pt_offset(bufp, i);
3949 if (p->sys_ind != 0) {
3950 h = p->end_head + 1;
3951 s = (p->end_sector & 077);
3956 } else if (hh != h || ss != s)
3961 if (!first && !bad) {
3968 get_geometry(void) {
3970 unsigned long long bytes; /* really u64 */
3973 sec_fac = sector_size / 512;
3974 #ifdef CONFIG_FEATURE_SUN_LABEL
3975 guess_device_type();
3977 heads = cylinders = sectors = 0;
3978 kern_heads = kern_sectors = 0;
3979 pt_heads = pt_sectors = 0;
3981 get_kernel_geometry();
3982 get_partition_table_geometry();
3984 heads = user_heads ? user_heads :
3985 pt_heads ? pt_heads :
3986 kern_heads ? kern_heads : 255;
3987 sectors = user_sectors ? user_sectors :
3988 pt_sectors ? pt_sectors :
3989 kern_sectors ? kern_sectors : 63;
3990 if (ioctl(fd, BLKGETSIZE64, &bytes) == 0) {
3993 unsigned long longsectors;
3995 if (ioctl(fd, BLKGETSIZE, &longsectors))
3997 bytes = ((unsigned long long) longsectors) << 9;
4000 total_number_of_sectors = (bytes >> 9);
4003 if (dos_compatible_flag)
4004 sector_offset = sectors;
4006 cylinders = total_number_of_sectors / (heads * sectors * sec_fac);
4008 cylinders = user_cylinders;
4012 * Read MBR. Returns:
4013 * -1: no 0xaa55 flag present (possibly entire disk BSD)
4014 * 0: found or created label
4018 get_boot(enum action what) {
4023 for (i = 0; i < 4; i++) {
4024 struct pte *pe = &ptes[i];
4026 pe->part_table = pt_offset(MBRbuffer, i);
4027 pe->ext_pointer = NULL;
4029 pe->sectorbuffer = MBRbuffer;
4030 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4031 pe->changed = (what == create_empty_dos);
4035 #ifdef CONFIG_FEATURE_SUN_LABEL
4036 if (what == create_empty_sun && check_sun_label())
4040 memset(MBRbuffer, 0, 512);
4042 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4043 if (what == create_empty_dos)
4044 goto got_dos_table; /* skip reading disk */
4046 if ((fd = open(disk_device, type_open)) < 0) {
4047 if ((fd = open(disk_device, O_RDONLY)) < 0) {
4048 if (what == try_only)
4050 fdisk_fatal(unable_to_open);
4052 printf(_("You will not be able to write "
4053 "the partition table.\n"));
4056 if (512 != read(fd, MBRbuffer, 512)) {
4057 if (what == try_only)
4059 fdisk_fatal(unable_to_read);
4062 if ((fd = open(disk_device, O_RDONLY)) < 0)
4064 if (512 != read(fd, MBRbuffer, 512))
4072 #ifdef CONFIG_FEATURE_SUN_LABEL
4073 if (check_sun_label())
4077 #ifdef CONFIG_FEATURE_SGI_LABEL
4078 if (check_sgi_label())
4082 #ifdef CONFIG_FEATURE_AIX_LABEL
4083 if (check_aix_label())
4087 #ifdef CONFIG_FEATURE_OSF_LABEL
4088 if (check_osf_label()) {
4089 possibly_osf_label = 1;
4090 if (!valid_part_table_flag(MBRbuffer)) {
4094 printf(_("This disk has both DOS and BSD magic.\n"
4095 "Give the 'b' command to go to BSD mode.\n"));
4099 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4103 if (!valid_part_table_flag(MBRbuffer)) {
4104 #ifndef CONFIG_FEATURE_FDISK_WRITABLE
4110 _("Device contains neither a valid DOS "
4111 "partition table, nor Sun, SGI or OSF "
4114 #ifdef CONFIG_FEATURE_SUN_LABEL
4123 case create_empty_dos:
4124 #ifdef CONFIG_FEATURE_SUN_LABEL
4125 case create_empty_sun:
4129 fprintf(stderr, _("Internal error\n"));
4132 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
4135 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4140 for (i = 0; i < 4; i++) {
4141 struct pte *pe = &ptes[i];
4143 if (IS_EXTENDED (pe->part_table->sys_ind)) {
4144 if (partitions != 4)
4145 fprintf(stderr, _("Ignoring extra extended "
4146 "partition %d\n"), i + 1);
4152 for (i = 3; i < partitions; i++) {
4153 struct pte *pe = &ptes[i];
4155 if (!valid_part_table_flag(pe->sectorbuffer)) {
4157 _("Warning: invalid flag 0x%04x of partition "
4158 "table %d will be corrected by w(rite)\n"),
4159 part_table_flag(pe->sectorbuffer), i + 1);
4160 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4169 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4171 * Print the message MESG, then read an integer between LOW and HIGH (inclusive).
4172 * If the user hits Enter, DFLT is returned.
4173 * Answers like +10 are interpreted as offsets from BASE.
4175 * There is no default if DFLT is not between LOW and HIGH.
4178 read_int(uint low, uint dflt, uint high, uint base, char *mesg)
4182 static char *ms = NULL;
4183 static int mslen = 0;
4185 if (!ms || strlen(mesg)+100 > mslen) {
4186 mslen = strlen(mesg)+200;
4187 ms = xrealloc(ms,mslen);
4190 if (dflt < low || dflt > high)
4194 snprintf(ms, mslen, _("%s (%u-%u, default %u): "),
4195 mesg, low, high, dflt);
4197 snprintf(ms, mslen, "%s (%u-%u): ",
4201 int use_default = default_ok;
4203 /* ask question and read answer */
4204 while (read_chars(ms) != '\n' && !isdigit(*line_ptr)
4205 && *line_ptr != '-' && *line_ptr != '+')
4208 if (*line_ptr == '+' || *line_ptr == '-') {
4209 int minus = (*line_ptr == '-');
4212 i = atoi(line_ptr+1);
4214 while (isdigit(*++line_ptr))
4217 switch (*line_ptr) {
4220 if (!display_in_cyl_units)
4221 i *= heads * sectors;
4235 absolute = 1000000000;
4241 unsigned long long bytes;
4244 bytes = (unsigned long long) i * absolute;
4245 unit = sector_size * units_per_sector;
4246 bytes += unit/2; /* round */
4255 while (isdigit(*line_ptr)) {
4261 printf(_("Using default value %u\n"), i = dflt);
4262 if (i >= low && i <= high)
4265 printf(_("Value out of range.\n"));
4271 get_partition(int warn, int max) {
4275 i = read_int(1, 0, max, 0, _("Partition number")) - 1;
4279 if ((!sun_label && !sgi_label && !pe->part_table->sys_ind)
4280 #ifdef CONFIG_FEATURE_SUN_LABEL
4282 (!sunlabel->partitions[i].num_sectors ||
4283 !sunlabel->infos[i].id))
4285 #ifdef CONFIG_FEATURE_SGI_LABEL
4286 || (sgi_label && (!sgi_get_num_sectors(i)))
4290 _("Warning: partition %d has empty type\n"),
4297 get_existing_partition(int warn, int max) {
4301 for (i = 0; i < max; i++) {
4302 struct pte *pe = &ptes[i];
4303 struct partition *p = pe->part_table;
4305 if (p && !is_cleared_partition(p)) {
4312 printf(_("Selected partition %d\n"), pno+1);
4315 printf(_("No partition is defined yet!\n"));
4319 return get_partition(warn, max);
4323 get_nonexisting_partition(int warn, int max) {
4327 for (i = 0; i < max; i++) {
4328 struct pte *pe = &ptes[i];
4329 struct partition *p = pe->part_table;
4331 if (p && is_cleared_partition(p)) {
4338 printf(_("Selected partition %d\n"), pno+1);
4341 printf(_("All primary partitions have been defined already!\n"));
4345 return get_partition(warn, max);
4349 void change_units(void)
4351 display_in_cyl_units = !display_in_cyl_units;
4353 printf(_("Changing display/entry units to %s\n"),
4358 toggle_active(int i) {
4359 struct pte *pe = &ptes[i];
4360 struct partition *p = pe->part_table;
4362 if (IS_EXTENDED (p->sys_ind) && !p->boot_ind)
4364 _("WARNING: Partition %d is an extended partition\n"),
4366 p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG);
4371 toggle_dos_compatibility_flag(void) {
4372 dos_compatible_flag = ~dos_compatible_flag;
4373 if (dos_compatible_flag) {
4374 sector_offset = sectors;
4375 printf(_("DOS Compatibility flag is set\n"));
4379 printf(_("DOS Compatibility flag is not set\n"));
4384 delete_partition(int i) {
4385 struct pte *pe = &ptes[i];
4386 struct partition *p = pe->part_table;
4387 struct partition *q = pe->ext_pointer;
4389 /* Note that for the fifth partition (i == 4) we don't actually
4390 * decrement partitions.
4393 if (warn_geometry())
4394 return; /* C/H/S not set */
4397 #ifdef CONFIG_FEATURE_SUN_LABEL
4399 sun_delete_partition(i);
4403 #ifdef CONFIG_FEATURE_SGI_LABEL
4405 sgi_delete_partition(i);
4411 if (IS_EXTENDED (p->sys_ind) && i == ext_index) {
4413 ptes[ext_index].ext_pointer = NULL;
4414 extended_offset = 0;
4420 if (!q->sys_ind && i > 4) {
4421 /* the last one in the chain - just delete */
4424 clear_partition(ptes[i].ext_pointer);
4425 ptes[i].changed = 1;
4427 /* not the last one - further ones will be moved down */
4429 /* delete this link in the chain */
4430 p = ptes[i-1].ext_pointer;
4432 set_start_sect(p, get_start_sect(q));
4433 set_nr_sects(p, get_nr_sects(q));
4434 ptes[i-1].changed = 1;
4435 } else if (partitions > 5) { /* 5 will be moved to 4 */
4436 /* the first logical in a longer chain */
4439 if (pe->part_table) /* prevent SEGFAULT */
4440 set_start_sect(pe->part_table,
4441 get_partition_start(pe) -
4443 pe->offset = extended_offset;
4447 if (partitions > 5) {
4449 while (i < partitions) {
4450 ptes[i] = ptes[i+1];
4454 /* the only logical: clear only */
4455 clear_partition(ptes[i].part_table);
4460 change_sysid(void) {
4461 int i, sys, origsys;
4462 struct partition *p;
4464 #ifdef CONFIG_FEATURE_SGI_LABEL
4465 /* If sgi_label then don't use get_existing_partition,
4466 let the user select a partition, since get_existing_partition()
4467 only works for Linux like partition tables. */
4469 i = get_existing_partition(0, partitions);
4471 i = get_partition(0, partitions);
4474 i = get_existing_partition(0, partitions);
4478 p = ptes[i].part_table;
4479 origsys = sys = get_sysid(i);
4481 /* if changing types T to 0 is allowed, then
4482 the reverse change must be allowed, too */
4483 if (!sys && !sgi_label && !sun_label && !get_nr_sects(p))
4484 printf(_("Partition %d does not exist yet!\n"), i + 1);
4486 sys = read_hex (get_sys_types());
4488 if (!sys && !sgi_label && !sun_label) {
4489 printf(_("Type 0 means free space to many systems\n"
4490 "(but not to Linux). Having partitions of\n"
4491 "type 0 is probably unwise. You can delete\n"
4492 "a partition using the `d' command.\n"));
4496 if (!sun_label && !sgi_label) {
4497 if (IS_EXTENDED (sys) != IS_EXTENDED (p->sys_ind)) {
4498 printf(_("You cannot change a partition into"
4499 " an extended one or vice versa\n"
4500 "Delete it first.\n"));
4506 #ifdef CONFIG_FEATURE_SUN_LABEL
4507 if (sun_label && i == 2 && sys != WHOLE_DISK)
4508 printf(_("Consider leaving partition 3 "
4509 "as Whole disk (5),\n"
4510 "as SunOS/Solaris expects it and "
4511 "even Linux likes it.\n\n"));
4513 #ifdef CONFIG_FEATURE_SGI_LABEL
4514 if (sgi_label && ((i == 10 && sys != ENTIRE_DISK)
4515 || (i == 8 && sys != 0)))
4516 printf(_("Consider leaving partition 9 "
4517 "as volume header (0),\nand "
4518 "partition 11 as entire volume (6)"
4519 "as IRIX expects it.\n\n"));
4523 #ifdef CONFIG_FEATURE_SUN_LABEL
4525 sun_change_sysid(i, sys);
4528 #ifdef CONFIG_FEATURE_SGI_LABEL
4530 sgi_change_sysid(i, sys);
4534 printf (_("Changed system type of partition %d "
4535 "to %x (%s)\n"), i + 1, sys,
4536 partition_type(sys));
4537 ptes[i].changed = 1;
4538 if (is_dos_partition(origsys) ||
4539 is_dos_partition(sys))
4545 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
4548 /* check_consistency() and long2chs() added Sat Mar 6 12:28:16 1993,
4549 * faith@cs.unc.edu, based on code fragments from pfdisk by Gordon W. Ross,
4550 * Jan. 1990 (version 1.2.1 by Gordon W. Ross Aug. 1990; Modified by S.
4551 * Lubkin Oct. 1991). */
4553 static void long2chs(ulong ls, uint *c, uint *h, uint *s) {
4554 int spc = heads * sectors;
4559 *s = ls % sectors + 1; /* sectors count from 1 */
4562 static void check_consistency(const struct partition *p, int partition) {
4563 uint pbc, pbh, pbs; /* physical beginning c, h, s */
4564 uint pec, peh, pes; /* physical ending c, h, s */
4565 uint lbc, lbh, lbs; /* logical beginning c, h, s */
4566 uint lec, leh, les; /* logical ending c, h, s */
4568 if (!heads || !sectors || (partition >= 4))
4569 return; /* do not check extended partitions */
4571 /* physical beginning c, h, s */
4572 pbc = (p->cyl & 0xff) | ((p->sector << 2) & 0x300);
4574 pbs = p->sector & 0x3f;
4576 /* physical ending c, h, s */
4577 pec = (p->end_cyl & 0xff) | ((p->end_sector << 2) & 0x300);
4579 pes = p->end_sector & 0x3f;
4581 /* compute logical beginning (c, h, s) */
4582 long2chs(get_start_sect(p), &lbc, &lbh, &lbs);
4584 /* compute logical ending (c, h, s) */
4585 long2chs(get_start_sect(p) + get_nr_sects(p) - 1, &lec, &leh, &les);
4587 /* Same physical / logical beginning? */
4588 if (cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) {
4589 printf(_("Partition %d has different physical/logical "
4590 "beginnings (non-Linux?):\n"), partition + 1);
4591 printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs);
4592 printf(_("logical=(%d, %d, %d)\n"),lbc, lbh, lbs);
4595 /* Same physical / logical ending? */
4596 if (cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) {
4597 printf(_("Partition %d has different physical/logical "
4598 "endings:\n"), partition + 1);
4599 printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
4600 printf(_("logical=(%d, %d, %d)\n"),lec, leh, les);
4604 /* Beginning on cylinder boundary? */
4605 if (pbh != !pbc || pbs != 1) {
4606 printf(_("Partition %i does not start on cylinder "
4607 "boundary:\n"), partition + 1);
4608 printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs);
4609 printf(_("should be (%d, %d, 1)\n"), pbc, !pbc);
4613 /* Ending on cylinder boundary? */
4614 if (peh != (heads - 1) || pes != sectors) {
4615 printf(_("Partition %i does not end on cylinder boundary.\n"),
4618 printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
4619 printf(_("should be (%d, %d, %d)\n"),
4620 pec, heads - 1, sectors);
4626 list_disk_geometry(void) {
4627 long long bytes = (total_number_of_sectors << 9);
4628 long megabytes = bytes/1000000;
4630 if (megabytes < 10000)
4631 printf(_("\nDisk %s: %ld MB, %lld bytes\n"),
4632 disk_device, megabytes, bytes);
4634 printf(_("\nDisk %s: %ld.%ld GB, %lld bytes\n"),
4635 disk_device, megabytes/1000, (megabytes/100)%10, bytes);
4636 printf(_("%d heads, %d sectors/track, %d cylinders"),
4637 heads, sectors, cylinders);
4638 if (units_per_sector == 1)
4639 printf(_(", total %llu sectors"),
4640 total_number_of_sectors / (sector_size/512));
4641 printf(_("\nUnits = %s of %d * %d = %d bytes\n\n"),
4643 units_per_sector, sector_size, units_per_sector * sector_size);
4647 * Check whether partition entries are ordered by their starting positions.
4648 * Return 0 if OK. Return i if partition i should have been earlier.
4649 * Two separate checks: primary and logical partitions.
4652 wrong_p_order(int *prev) {
4653 const struct pte *pe;
4654 const struct partition *p;
4655 off_t last_p_start_pos = 0, p_start_pos;
4658 for (i = 0 ; i < partitions; i++) {
4661 last_p_start_pos = 0;
4664 if ((p = pe->part_table)->sys_ind) {
4665 p_start_pos = get_partition_start(pe);
4667 if (last_p_start_pos > p_start_pos) {
4673 last_p_start_pos = p_start_pos;
4680 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
4682 * Fix the chain of logicals.
4683 * extended_offset is unchanged, the set of sectors used is unchanged
4684 * The chain is sorted so that sectors increase, and so that
4685 * starting sectors increase.
4687 * After this it may still be that cfdisk doesnt like the table.
4688 * (This is because cfdisk considers expanded parts, from link to
4689 * end of partition, and these may still overlap.)
4691 * sfdisk /dev/hda > ohda; sfdisk /dev/hda < ohda
4695 fix_chain_of_logicals(void) {
4696 int j, oj, ojj, sj, sjj;
4697 struct partition *pj,*pjj,tmp;
4699 /* Stage 1: sort sectors but leave sector of part 4 */
4700 /* (Its sector is the global extended_offset.) */
4702 for (j = 5; j < partitions-1; j++) {
4703 oj = ptes[j].offset;
4704 ojj = ptes[j+1].offset;
4706 ptes[j].offset = ojj;
4707 ptes[j+1].offset = oj;
4708 pj = ptes[j].part_table;
4709 set_start_sect(pj, get_start_sect(pj)+oj-ojj);
4710 pjj = ptes[j+1].part_table;
4711 set_start_sect(pjj, get_start_sect(pjj)+ojj-oj);
4712 set_start_sect(ptes[j-1].ext_pointer,
4713 ojj-extended_offset);
4714 set_start_sect(ptes[j].ext_pointer,
4715 oj-extended_offset);
4720 /* Stage 2: sort starting sectors */
4722 for (j = 4; j < partitions-1; j++) {
4723 pj = ptes[j].part_table;
4724 pjj = ptes[j+1].part_table;
4725 sj = get_start_sect(pj);
4726 sjj = get_start_sect(pjj);
4727 oj = ptes[j].offset;
4728 ojj = ptes[j+1].offset;
4729 if (oj+sj > ojj+sjj) {
4733 set_start_sect(pj, ojj+sjj-oj);
4734 set_start_sect(pjj, oj+sj-ojj);
4739 /* Probably something was changed */
4740 for (j = 4; j < partitions; j++)
4741 ptes[j].changed = 1;
4746 fix_partition_table_order(void) {
4747 struct pte *pei, *pek;
4750 if (!wrong_p_order(NULL)) {
4751 printf(_("Nothing to do. Ordering is correct already.\n\n"));
4755 while ((i = wrong_p_order(&k)) != 0 && i < 4) {
4756 /* partition i should have come earlier, move it */
4757 /* We have to move data in the MBR */
4758 struct partition *pi, *pk, *pe, pbuf;
4762 pe = pei->ext_pointer;
4763 pei->ext_pointer = pek->ext_pointer;
4764 pek->ext_pointer = pe;
4766 pi = pei->part_table;
4767 pk = pek->part_table;
4769 memmove(&pbuf, pi, sizeof(struct partition));
4770 memmove(pi, pk, sizeof(struct partition));
4771 memmove(pk, &pbuf, sizeof(struct partition));
4773 pei->changed = pek->changed = 1;
4777 fix_chain_of_logicals();
4785 list_table(int xtra) {
4786 const struct partition *p;
4789 #ifdef CONFIG_FEATURE_SUN_LABEL
4791 sun_list_table(xtra);
4796 #ifdef CONFIG_FEATURE_SGI_LABEL
4798 sgi_list_table(xtra);
4803 list_disk_geometry();
4805 #ifdef CONFIG_FEATURE_OSF_LABEL
4807 xbsd_print_disklabel(xtra);
4812 /* Heuristic: we list partition 3 of /dev/foo as /dev/foo3,
4813 but if the device name ends in a digit, say /dev/foo1,
4814 then the partition is called /dev/foo1p3. */
4815 w = strlen(disk_device);
4816 if (w && isdigit(disk_device[w-1]))
4821 printf(_("%*s Boot Start End Blocks Id System\n"),
4824 for (i = 0; i < partitions; i++) {
4825 const struct pte *pe = &ptes[i];
4828 if (p && !is_cleared_partition(p)) {
4829 off_t psects = get_nr_sects(p);
4830 off_t pblocks = psects;
4831 unsigned int podd = 0;
4833 if (sector_size < 1024) {
4834 pblocks /= (1024 / sector_size);
4835 podd = psects % (1024 / sector_size);
4837 if (sector_size > 1024)
4838 pblocks *= (sector_size / 1024);
4840 "%s %c %11llu %11llu %11llu%c %2x %s\n",
4841 partname(disk_device, i+1, w+2),
4842 /* boot flag */ !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG
4844 /* start */ (unsigned long long) cround(get_partition_start(pe)),
4845 /* end */ (unsigned long long) cround(get_partition_start(pe) + psects
4846 - (psects ? 1 : 0)),
4847 /* odd flag on end */ (unsigned long long) pblocks, podd ? '+' : ' ',
4848 /* type id */ p->sys_ind,
4849 /* type name */ partition_type(p->sys_ind));
4850 check_consistency(p, i);
4854 /* Is partition table in disk order? It need not be, but... */
4855 /* partition table entries are not checked for correct order if this
4856 is a sgi, sun or aix labeled disk... */
4857 if (dos_label && wrong_p_order(NULL)) {
4858 printf(_("\nPartition table entries are not in disk order\n"));
4862 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
4864 x_list_table(int extend) {
4865 const struct pte *pe;
4866 const struct partition *p;
4869 printf(_("\nDisk %s: %d heads, %d sectors, %d cylinders\n\n"),
4870 disk_device, heads, sectors, cylinders);
4871 printf(_("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n"));
4872 for (i = 0 ; i < partitions; i++) {
4874 p = (extend ? pe->ext_pointer : pe->part_table);
4876 printf("%2d %02x%4d%4d%5d%4d%4d%5d%11u%11u %02x\n",
4877 i + 1, p->boot_ind, p->head,
4879 cylinder(p->sector, p->cyl), p->end_head,
4880 sector(p->end_sector),
4881 cylinder(p->end_sector, p->end_cyl),
4882 get_start_sect(p), get_nr_sects(p), p->sys_ind);
4884 check_consistency(p, i);
4890 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4892 fill_bounds(off_t *first, off_t *last) {
4894 const struct pte *pe = &ptes[0];
4895 const struct partition *p;
4897 for (i = 0; i < partitions; pe++,i++) {
4899 if (!p->sys_ind || IS_EXTENDED (p->sys_ind)) {
4900 first[i] = 0xffffffff;
4903 first[i] = get_partition_start(pe);
4904 last[i] = first[i] + get_nr_sects(p) - 1;
4910 check(int n, uint h, uint s, uint c, off_t start) {
4911 off_t total, real_s, real_c;
4913 real_s = sector(s) - 1;
4914 real_c = cylinder(s, c);
4915 total = (real_c * sectors + real_s) * heads + h;
4917 fprintf(stderr, _("Warning: partition %d contains sector 0\n"), n);
4920 _("Partition %d: head %d greater than maximum %d\n"),
4922 if (real_s >= sectors)
4923 fprintf(stderr, _("Partition %d: sector %d greater than "
4924 "maximum %d\n"), n, s, sectors);
4925 if (real_c >= cylinders)
4926 fprintf(stderr, _("Partitions %d: cylinder %llu greater than "
4927 "maximum %d\n"), n, (unsigned long long)real_c + 1, cylinders);
4928 if (cylinders <= 1024 && start != total)
4930 _("Partition %d: previous sectors %llu disagrees with "
4931 "total %llu\n"), n, (unsigned long long)start, (unsigned long long)total);
4938 off_t first[partitions], last[partitions];
4939 struct partition *p;
4941 if (warn_geometry())
4944 #ifdef CONFIG_FEATURE_SUN_LABEL
4950 #ifdef CONFIG_FEATURE_SGI_LABEL
4957 fill_bounds(first, last);
4958 for (i = 0; i < partitions; i++) {
4959 struct pte *pe = &ptes[i];
4962 if (p->sys_ind && !IS_EXTENDED (p->sys_ind)) {
4963 check_consistency(p, i);
4964 if (get_partition_start(pe) < first[i])
4965 printf(_("Warning: bad start-of-data in "
4966 "partition %d\n"), i + 1);
4967 check(i + 1, p->end_head, p->end_sector, p->end_cyl,
4969 total += last[i] + 1 - first[i];
4970 for (j = 0; j < i; j++)
4971 if ((first[i] >= first[j] && first[i] <= last[j])
4972 || ((last[i] <= last[j] && last[i] >= first[j]))) {
4973 printf(_("Warning: partition %d overlaps "
4974 "partition %d.\n"), j + 1, i + 1);
4975 total += first[i] >= first[j] ?
4976 first[i] : first[j];
4977 total -= last[i] <= last[j] ?
4983 if (extended_offset) {
4984 struct pte *pex = &ptes[ext_index];
4985 off_t e_last = get_start_sect(pex->part_table) +
4986 get_nr_sects(pex->part_table) - 1;
4988 for (i = 4; i < partitions; i++) {
4990 p = ptes[i].part_table;
4992 if (i != 4 || i + 1 < partitions)
4993 printf(_("Warning: partition %d "
4994 "is empty\n"), i + 1);
4996 else if (first[i] < extended_offset ||
4998 printf(_("Logical partition %d not entirely in "
4999 "partition %d\n"), i + 1, ext_index + 1);
5003 if (total > heads * sectors * cylinders)
5004 printf(_("Total allocated sectors %d greater than the maximum "
5005 "%d\n"), total, heads * sectors * cylinders);
5006 else if ((total = heads * sectors * cylinders - total) != 0)
5007 printf(_("%d unallocated sectors\n"), total);
5011 add_partition(int n, int sys) {
5012 char mesg[256]; /* 48 does not suffice in Japanese */
5014 struct partition *p = ptes[n].part_table;
5015 struct partition *q = ptes[ext_index].part_table;
5017 off_t start, stop = 0, limit, temp,
5018 first[partitions], last[partitions];
5020 if (p && p->sys_ind) {
5021 printf(_("Partition %d is already defined. Delete "
5022 "it before re-adding it.\n"), n + 1);
5025 fill_bounds(first, last);
5027 start = sector_offset;
5028 if (display_in_cyl_units || !total_number_of_sectors)
5029 llimit = heads * sectors * cylinders - 1;
5031 llimit = total_number_of_sectors - 1;
5033 if (limit != llimit)
5035 if (extended_offset) {
5036 first[ext_index] = extended_offset;
5037 last[ext_index] = get_start_sect(q) +
5038 get_nr_sects(q) - 1;
5041 start = extended_offset + sector_offset;
5042 limit = get_start_sect(q) + get_nr_sects(q) - 1;
5044 if (display_in_cyl_units)
5045 for (i = 0; i < partitions; i++)
5046 first[i] = (cround(first[i]) - 1) * units_per_sector;
5048 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
5051 for (i = 0; i < partitions; i++) {
5054 if (start == ptes[i].offset)
5055 start += sector_offset;
5056 lastplusoff = last[i] + ((n<4) ? 0 : sector_offset);
5057 if (start >= first[i] && start <= lastplusoff)
5058 start = lastplusoff + 1;
5062 if (start >= temp+units_per_sector && readed) {
5063 printf(_("Sector %llu is already allocated\n"), (unsigned long long)temp);
5067 if (!readed && start == temp) {
5070 saved_start = start;
5071 start = read_int(cround(saved_start), cround(saved_start), cround(limit),
5073 if (display_in_cyl_units) {
5074 start = (start - 1) * units_per_sector;
5075 if (start < saved_start) start = saved_start;
5079 } while (start != temp || !readed);
5080 if (n > 4) { /* NOT for fifth partition */
5081 struct pte *pe = &ptes[n];
5083 pe->offset = start - sector_offset;
5084 if (pe->offset == extended_offset) { /* must be corrected */
5086 if (sector_offset == 1)
5091 for (i = 0; i < partitions; i++) {
5092 struct pte *pe = &ptes[i];
5094 if (start < pe->offset && limit >= pe->offset)
5095 limit = pe->offset - 1;
5096 if (start < first[i] && limit >= first[i])
5097 limit = first[i] - 1;
5099 if (start > limit) {
5100 printf(_("No free sectors available\n"));
5105 if (cround(start) == cround(limit)) {
5108 snprintf(mesg, sizeof(mesg),
5109 _("Last %s or +size or +sizeM or +sizeK"),
5110 str_units(SINGULAR));
5111 stop = read_int(cround(start), cround(limit), cround(limit),
5112 cround(start), mesg);
5113 if (display_in_cyl_units) {
5114 stop = stop * units_per_sector - 1;
5120 set_partition(n, 0, start, stop, sys);
5122 set_partition(n - 1, 1, ptes[n].offset, stop, EXTENDED);
5124 if (IS_EXTENDED (sys)) {
5125 struct pte *pe4 = &ptes[4];
5126 struct pte *pen = &ptes[n];
5129 pen->ext_pointer = p;
5130 pe4->offset = extended_offset = start;
5131 pe4->sectorbuffer = xcalloc(1, sector_size);
5132 pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
5133 pe4->ext_pointer = pe4->part_table + 1;
5141 if (partitions > 5 || ptes[4].part_table->sys_ind) {
5142 struct pte *pe = &ptes[partitions];
5144 pe->sectorbuffer = xcalloc(1, sector_size);
5145 pe->part_table = pt_offset(pe->sectorbuffer, 0);
5146 pe->ext_pointer = pe->part_table + 1;
5151 add_partition(partitions - 1, LINUX_NATIVE);
5155 new_partition(void) {
5156 int i, free_primary = 0;
5158 if (warn_geometry())
5161 #ifdef CONFIG_FEATURE_SUN_LABEL
5163 add_sun_partition(get_partition(0, partitions), LINUX_NATIVE);
5167 #ifdef CONFIG_FEATURE_SGI_LABEL
5169 sgi_add_partition(get_partition(0, partitions), LINUX_NATIVE);
5173 #ifdef CONFIG_FEATURE_AIX_LABEL
5175 printf(_("\tSorry - this fdisk cannot handle AIX disk labels."
5176 "\n\tIf you want to add DOS-type partitions, create"
5177 "\n\ta new empty DOS partition table first. (Use o.)"
5179 "This will destroy the present disk contents.\n"));
5184 for (i = 0; i < 4; i++)
5185 free_primary += !ptes[i].part_table->sys_ind;
5187 if (!free_primary && partitions >= MAXIMUM_PARTS) {
5188 printf(_("The maximum number of partitions has been created\n"));
5192 if (!free_primary) {
5193 if (extended_offset)
5196 printf(_("You must delete some partition and add "
5197 "an extended partition first\n"));
5199 char c, line[LINE_LENGTH];
5200 snprintf(line, sizeof(line), "%s\n %s\n p primary "
5201 "partition (1-4)\n",
5202 "Command action", (extended_offset ?
5203 "l logical (5 or over)" : "e extended"));
5205 if ((c = read_char(line)) == 'p' || c == 'P') {
5206 i = get_nonexisting_partition(0, 4);
5208 add_partition(i, LINUX_NATIVE);
5211 else if (c == 'l' && extended_offset) {
5215 else if (c == 'e' && !extended_offset) {
5216 i = get_nonexisting_partition(0, 4);
5218 add_partition(i, EXTENDED);
5222 printf(_("Invalid partition number "
5223 "for type `%c'\n"), c);
5234 if (ptes[i].changed)
5235 ptes[3].changed = 1;
5236 for (i = 3; i < partitions; i++) {
5237 struct pte *pe = &ptes[i];
5240 write_part_table_flag(pe->sectorbuffer);
5241 write_sector(pe->offset, pe->sectorbuffer);
5245 #ifdef CONFIG_FEATURE_SGI_LABEL
5246 else if (sgi_label) {
5247 /* no test on change? the printf below might be mistaken */
5251 #ifdef CONFIG_FEATURE_SUN_LABEL
5252 else if (sun_label) {
5256 if (ptes[i].changed)
5263 printf(_("The partition table has been altered!\n\n"));
5264 reread_partition_table(1);
5268 reread_partition_table(int leave) {
5272 printf(_("Calling ioctl() to re-read partition table.\n"));
5275 if ((i = ioctl(fd, BLKRRPART)) != 0) {
5278 /* some kernel versions (1.2.x) seem to have trouble
5279 rereading the partition table, but if asked to do it
5280 twice, the second time works. - biro@yggdrasil.com */
5283 if ((i = ioctl(fd, BLKRRPART)) != 0)
5288 printf(_("\nWARNING: Re-reading the partition table "
5289 "failed with error %d: %s.\n"
5290 "The kernel still uses the old table.\n"
5291 "The new table will be used "
5292 "at the next reboot.\n"),
5293 error, strerror(error));
5298 _("\nWARNING: If you have created or modified any DOS 6.x\n"
5299 "partitions, please see the fdisk manual page for additional\n"
5305 printf(_("Syncing disks.\n"));
5307 sleep(4); /* for sync() */
5311 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
5313 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
5314 #define MAX_PER_LINE 16
5316 print_buffer(char pbuffer[]) {
5320 for (i = 0, l = 0; i < sector_size; i++, l++) {
5322 printf("0x%03X:", i);
5323 printf(" %02X", (unsigned char) pbuffer[i]);
5324 if (l == MAX_PER_LINE - 1) {
5339 printf(_("Device: %s\n"), disk_device);
5340 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
5341 if (sun_label || sgi_label)
5342 print_buffer(MBRbuffer);
5345 for (i = 3; i < partitions; i++)
5346 print_buffer(ptes[i].sectorbuffer);
5351 struct pte *pe = &ptes[i];
5352 struct partition *p = pe->part_table;
5355 if (warn_geometry())
5357 if (!p->sys_ind || !get_nr_sects(p) || IS_EXTENDED (p->sys_ind)) {
5358 printf(_("Partition %d has no data area\n"), i + 1);
5361 first = get_partition_start(pe);
5362 new = read_int(first, first, first + get_nr_sects(p) - 1, first,
5363 _("New beginning of data")) - pe->offset;
5365 if (new != get_nr_sects(p)) {
5366 first = get_nr_sects(p) + get_start_sect(p) - new;
5367 set_nr_sects(p, first);
5368 set_start_sect(p, new);
5379 c = tolower(read_char(_("Expert command (m for help): ")));
5382 #ifdef CONFIG_FEATURE_SUN_LABEL
5389 move_begin(get_partition(0, partitions));
5392 user_cylinders = cylinders =
5393 read_int(1, cylinders, 1048576, 0,
5394 _("Number of cylinders"));
5395 #ifdef CONFIG_FEATURE_SUN_LABEL
5397 sun_set_ncyl(cylinders);
5406 #ifdef CONFIG_FEATURE_SGI_LABEL
5411 #ifdef CONFIG_FEATURE_SUN_LABEL
5421 fix_partition_table_order();
5424 #ifdef CONFIG_FEATURE_SGI_LABEL
5429 user_heads = heads = read_int(1, heads, 256, 0,
5430 _("Number of heads"));
5434 #ifdef CONFIG_FEATURE_SUN_LABEL
5440 #ifdef CONFIG_FEATURE_SUN_LABEL
5446 #ifdef CONFIG_FEATURE_SUN_LABEL
5460 user_sectors = sectors = read_int(1, sectors, 63, 0,
5461 _("Number of sectors"));
5462 if (dos_compatible_flag) {
5463 sector_offset = sectors;
5464 fprintf(stderr, _("Warning: setting "
5465 "sector offset for DOS "
5474 write_table(); /* does not return */
5477 #ifdef CONFIG_FEATURE_SUN_LABEL
5479 sun_set_pcylcount();
5487 #endif /* ADVANCED mode */
5490 is_ide_cdrom_or_tape(const char *device) {
5493 struct stat statbuf;
5496 /* No device was given explicitly, and we are trying some
5497 likely things. But opening /dev/hdc may produce errors like
5498 "hdc: tray open or drive not ready"
5499 if it happens to be a CD-ROM drive. It even happens that
5500 the process hangs on the attempt to read a music CD.
5501 So try to be careful. This only works since 2.1.73. */
5503 if (strncmp("/dev/hd", device, 7))
5506 snprintf(buf, sizeof(buf), "/proc/ide/%s/media", device+5);
5507 procf = fopen(buf, "r");
5508 if (procf != NULL && fgets(buf, sizeof(buf), procf))
5509 is_ide = (!strncmp(buf, "cdrom", 5) ||
5510 !strncmp(buf, "tape", 4));
5512 /* Now when this proc file does not exist, skip the
5513 device when it is read-only. */
5514 if (stat(device, &statbuf) == 0)
5515 is_ide = ((statbuf.st_mode & 0222) == 0);
5523 try(const char *device, int user_specified) {
5526 disk_device = device;
5527 if (setjmp(listingbuf))
5529 if (!user_specified)
5530 if (is_ide_cdrom_or_tape(device))
5532 if ((fd = open(disk_device, type_open)) >= 0) {
5533 gb = get_boot(try_only);
5534 if (gb > 0) { /* I/O error */
5536 } else if (gb < 0) { /* no DOS signature */
5537 list_disk_geometry();
5540 #ifdef CONFIG_FEATURE_OSF_LABEL
5541 if (btrydev(device) < 0)
5544 _("Disk %s doesn't contain a valid "
5545 "partition table\n"), device);
5550 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5551 if (!sun_label && partitions > 4)
5552 delete_partition(ext_index);
5556 /* Ignore other errors, since we try IDE
5557 and SCSI hard disks which may not be
5558 installed on the system. */
5559 if (errno == EACCES) {
5560 fprintf(stderr, _("Cannot open %s\n"), device);
5566 /* for fdisk -l: try all things in /proc/partitions
5567 that look like a partition name (do not end in a digit) */
5571 char line[100], ptname[100], devname[120], *s;
5574 procpt = bb_wfopen(PROC_PARTITIONS, "r");
5576 while (fgets(line, sizeof(line), procpt)) {
5577 if (sscanf (line, " %d %d %d %[^\n ]",
5578 &ma, &mi, &sz, ptname) != 4)
5580 for (s = ptname; *s; s++);
5583 sprintf(devname, "/dev/%s", ptname);
5586 #ifdef CONFIG_FEATURE_CLEAN_UP
5591 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5593 unknown_command(int c) {
5594 printf(_("%c: unknown command\n"), c);
5598 int fdisk_main(int argc, char **argv) {
5600 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5603 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5609 * fdisk -l [-b sectorsize] [-u] device ...
5610 * fdisk -s [partition] ...
5611 * fdisk [-b sectorsize] [-u] device
5613 * Options -C, -H, -S set the geometry.
5616 while ((c = getopt(argc, argv, "b:C:H:lS:uvV"
5617 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5623 /* Ugly: this sector size is really per device,
5624 so cannot be combined with multiple disks,
5625 and te same goes for the C/H/S options.
5627 sector_size = atoi(optarg);
5628 if (sector_size != 512 && sector_size != 1024 &&
5629 sector_size != 2048)
5632 user_set_sector_size = 1;
5635 user_cylinders = atoi(optarg);
5638 user_heads = atoi(optarg);
5639 if (user_heads <= 0 || user_heads >= 256)
5643 user_sectors = atoi(optarg);
5644 if (user_sectors <= 0 || user_sectors >= 64)
5648 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5652 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5658 display_in_cyl_units = 0;
5662 printf("fdisk v" UTIL_LINUX_VERSION "\n");
5670 printf(_("This kernel finds the sector size itself - "
5671 "-b option ignored\n"));
5673 if (user_set_sector_size && argc-optind != 1)
5674 printf(_("Warning: the -b (set sector size) option should"
5675 " be used with one specified device\n"));
5678 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5682 type_open = O_RDONLY;
5683 if (argc > optind) {
5686 /* avoid gcc warning:
5687 variable `k' might be clobbered by `longjmp' */
5691 for (k=optind; k<argc; k++)
5694 /* we no longer have default device names */
5695 /* but, we can use /proc/partitions instead */
5699 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5703 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5709 type_open = O_RDONLY;
5711 opts = argc - optind;
5715 for (j = optind; j < argc; j++) {
5716 disk_device = argv[j];
5717 if ((fd = open(disk_device, type_open)) < 0)
5718 fdisk_fatal(unable_to_open);
5719 if (ioctl(fd, BLKGETSIZE, &size))
5720 fdisk_fatal(ioctl_error);
5723 printf("%ld\n", size/2);
5725 printf("%s: %ld\n", argv[j], size/2);
5731 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5732 if (argc-optind == 1)
5733 disk_device = argv[optind];
5739 #ifdef CONFIG_FEATURE_OSF_LABEL
5741 /* OSF label, and no DOS label */
5742 printf(_("Detected an OSF/1 disklabel on %s, entering "
5743 "disklabel mode.\n"),
5747 /* If we return we may want to make an empty DOS label? */
5753 c = tolower(read_char(_("Command (m for help): ")));
5757 toggle_active(get_partition(1, partitions));
5758 #ifdef CONFIG_FEATURE_SUN_LABEL
5760 toggle_sunflags(get_partition(1, partitions),
5763 #ifdef CONFIG_FEATURE_SGI_LABEL
5765 sgi_set_bootpartition(
5766 get_partition(1, partitions));
5772 #ifdef CONFIG_FEATURE_SGI_LABEL
5774 printf(_("\nThe current boot file is: %s\n"),
5775 sgi_get_bootfile());
5776 if (read_chars(_("Please enter the name of the "
5777 "new boot file: ")) == '\n')
5778 printf(_("Boot file unchanged\n"));
5780 sgi_set_bootfile(line_ptr);
5783 #ifdef CONFIG_FEATURE_OSF_LABEL
5789 toggle_dos_compatibility_flag();
5790 #ifdef CONFIG_FEATURE_SUN_LABEL
5792 toggle_sunflags(get_partition(1, partitions),
5795 #ifdef CONFIG_FEATURE_SGI_LABEL
5797 sgi_set_swappartition(
5798 get_partition(1, partitions));
5806 #ifdef CONFIG_FEATURE_SGI_LABEL
5807 /* If sgi_label then don't use get_existing_partition,
5808 let the user select a partition, since
5809 get_existing_partition() only works for Linux-like
5812 j = get_existing_partition(1, partitions);
5814 j = get_partition(1, partitions);
5817 j = get_existing_partition(1, partitions);
5820 delete_partition(j);
5824 #ifdef CONFIG_FEATURE_SGI_LABEL
5831 list_types(get_sys_types());
5850 #ifdef CONFIG_FEATURE_SUN_LABEL
5864 write_table(); /* does not return */
5866 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
5868 #ifdef CONFIG_FEATURE_SGI_LABEL
5871 _("\n\tSorry, no experts menu for SGI "
5872 "partition tables available.\n\n"));
5885 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */