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 /* Force fdisk to transparently remap 32-bit interfaces
19 * to instead really use 64 bit interfaces, at least for
20 * glibc and uClibc... */
21 #ifndef __USE_FILE_OFFSET64
22 # ifdef FDISK_SUPPORT_LARGE_DISKS
23 # define __USE_FILE_OFFSET64 1
27 #include <sys/types.h>
28 #include <sys/stat.h> /* stat */
37 #include <assert.h> /* assert */
40 #include <sys/ioctl.h>
41 #include <sys/param.h>
42 #include <sys/sysmacros.h> /* major */
44 #include <stdint.h> /* for uint32_t, uint16_t, uint8_t, int16_t, etc */
46 /* Copied from linux/major.h */
47 #define FLOPPY_MAJOR 2
49 #include <sys/utsname.h>
53 #define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r))
59 #define BLKRRPART _IO(0x12,95) /* re-read partition table */
60 #define BLKGETSIZE _IO(0x12,96) /* return device size */
61 #define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */
62 #define BLKSSZGET _IO(0x12,104) /* get block device sector size */
64 /* Avoid conflicts with the 2.6 kernel headers, which define
65 * _IOR rather differently */
67 #define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size))
68 #define BLKGETSIZE64 _IOR(0x12,114,uint64_t)
74 #define DEFAULT_SECTOR_SIZE 512
75 #define MAX_SECTOR_SIZE 2048
76 #define SECTOR_SIZE 512 /* still used in BSD code */
77 #define MAXIMUM_PARTS 60
79 #define ACTIVE_FLAG 0x80
82 #define WIN98_EXTENDED 0x0f
83 #define LINUX_PARTITION 0x81
84 #define LINUX_SWAP 0x82
85 #define LINUX_NATIVE 0x83
86 #define LINUX_EXTENDED 0x85
87 #define LINUX_LVM 0x8e
88 #define LINUX_RAID 0xfd
93 #define IS_EXTENDED(i) \
94 ((i) == EXTENDED || (i) == WIN98_EXTENDED || (i) == LINUX_EXTENDED)
96 #define SIZE(a) (sizeof(a)/sizeof((a)[0]))
98 #define cround(n) (display_in_cyl_units ? ((n)/units_per_sector)+1 : (n))
99 #define scround(x) (((x)+units_per_sector-1)/units_per_sector)
101 #ifdef CONFIG_FEATURE_SUN_LABEL
102 #define SCSI_IOCTL_GET_IDLUN 0x5382
106 /* including <linux/hdreg.h> also fails */
109 unsigned char sectors;
110 unsigned short cylinders;
114 #define HDIO_GETGEO 0x0301 /* get device geometry */
118 const unsigned char *name;
121 static uint sector_size = DEFAULT_SECTOR_SIZE,
122 user_set_sector_size,
126 * Raw disk label. For DOS-type partition tables the MBR,
127 * with descriptions of the primary partitions.
129 static char MBRbuffer[MAX_SECTOR_SIZE];
131 #ifdef CONFIG_FEATURE_SUN_LABEL
132 static int sun_label; /* looking at sun disklabel */
136 #ifdef CONFIG_FEATURE_SGI_LABEL
137 static int sgi_label; /* looking at sgi disklabel */
141 #ifdef CONFIG_FEATURE_AIX_LABEL
142 static int aix_label; /* looking at aix disklabel */
146 #ifdef CONFIG_FEATURE_OSF_LABEL
147 static int osf_label; /* looking at OSF/1 disklabel */
148 static int possibly_osf_label;
153 #define dos_label (!sun_label && !sgi_label && !aix_label && !osf_label)
155 static uint heads, sectors, cylinders;
156 static void update_units(void);
160 * return partition name - uses static storage unless buf is supplied
163 partname(const char *dev, int pno, int lth) {
164 static char buffer[80];
171 bufsiz = sizeof(buffer);
176 if (isdigit(dev[w-1]))
179 /* devfs kludge - note: fdisk partition names are not supposed
180 to equal kernel names, so there is no reason to do this */
181 if (strcmp (dev + w - 4, "disc") == 0) {
189 snprintf(bufp, bufsiz, "%*.*s%s%-2u",
190 lth-wp-2, w, dev, p, pno);
192 snprintf(bufp, bufsiz, "%.*s%s%-2u", w, dev, p, pno);
198 unsigned char boot_ind; /* 0x80 - active */
199 unsigned char head; /* starting head */
200 unsigned char sector; /* starting sector */
201 unsigned char cyl; /* starting cylinder */
202 unsigned char sys_ind; /* What partition type */
203 unsigned char end_head; /* end head */
204 unsigned char end_sector; /* end sector */
205 unsigned char end_cyl; /* end cylinder */
206 unsigned char start4[4]; /* starting sector counting from 0 */
207 unsigned char size4[4]; /* nr of sectors in partition */
208 } __attribute__((__packed__));
211 ioctl_error, unable_to_open, unable_to_read, unable_to_seek,
215 enum action {fdisk, require, try_only, create_empty_dos, create_empty_sun};
217 static const char *disk_device;
218 static int fd; /* the disk */
219 static int partitions = 4; /* maximum partition + 1 */
220 static uint display_in_cyl_units = 1;
221 static uint units_per_sector = 1;
222 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
223 static char *line_ptr;
224 static void change_units(void);
225 static void reread_partition_table(int leave);
226 static void delete_partition(int i);
227 static int get_partition(int warn, int max);
228 static void list_types(const struct systypes *sys);
229 static uint read_int(uint low, uint dflt, uint high, uint base, char *mesg);
231 static const char *partition_type(unsigned char type);
232 static void fdisk_fatal(enum failure why) __attribute__ ((noreturn));
233 static void get_geometry(void);
234 static int get_boot(enum action what);
239 #define hex_val(c) ({ \
241 isdigit(_c) ? _c - '0' : \
242 tolower(_c) + 10 - 'a'; \
246 #define LINE_LENGTH 800
247 #define pt_offset(b, n) ((struct partition *)((b) + 0x1be + \
248 (n) * sizeof(struct partition)))
249 #define sector(s) ((s) & 0x3f)
250 #define cylinder(s, c) ((c) | (((s) & 0xc0) << 2))
252 #define hsc2sector(h,s,c) (sector(s) - 1 + sectors * \
253 ((h) + heads * cylinder(s,c)))
254 #define set_hsc(h,s,c,sector) { \
255 s = sector % sectors + 1; \
257 h = sector % heads; \
260 s |= (sector >> 2) & 0xc0; \
264 static unsigned int get_start_sect(const struct partition *p);
265 static unsigned int get_nr_sects(const struct partition *p);
268 * per partition table entry data
270 * The four primary partitions have the same sectorbuffer (MBRbuffer)
271 * and have NULL ext_pointer.
272 * Each logical partition table entry has two pointers, one for the
273 * partition and one link to the next one.
276 struct partition *part_table; /* points into sectorbuffer */
277 struct partition *ext_pointer; /* points into sectorbuffer */
278 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
279 char changed; /* boolean */
281 uint offset; /* disk sector number */
282 char *sectorbuffer; /* disk sector contents */
283 } ptes[MAXIMUM_PARTS];
286 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
288 set_all_unchanged(void) {
291 for (i = 0; i < MAXIMUM_PARTS; i++)
299 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
301 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_OSF_LABEL)
302 static struct partition *
303 get_part_table(int i) {
304 return ptes[i].part_table;
309 str_units(int n) { /* n==1: use singular */
311 return display_in_cyl_units ? _("cylinder") : _("sector");
313 return display_in_cyl_units ? _("cylinders") : _("sectors");
317 valid_part_table_flag(const unsigned char *b) {
318 return (b[510] == 0x55 && b[511] == 0xaa);
321 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
322 static char line_buffer[LINE_LENGTH];
324 /* read line; return 0 or first char */
328 static int got_eof = 0;
330 fflush (stdout); /* requested by niles@scyld.com */
331 line_ptr = line_buffer;
332 if (!fgets(line_buffer, LINE_LENGTH, stdin)) {
334 got_eof++; /* user typed ^D ? */
336 fprintf(stderr, _("\ngot EOF thrice - exiting..\n"));
341 while (*line_ptr && !isgraph(*line_ptr))
347 read_char(const char *mesg)
351 } while (!read_line());
356 read_chars(const char *mesg)
367 read_hex(const struct systypes *sys)
373 read_char(_("Hex code (type L to list codes): "));
374 if (*line_ptr == 'l' || *line_ptr == 'L')
376 else if (isxdigit (*line_ptr))
380 hex = hex << 4 | hex_val(*line_ptr++);
381 while (isxdigit(*line_ptr));
386 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
388 #ifdef CONFIG_FEATURE_AIX_LABEL
390 * Copyright (C) Andreas Neuper, Sep 1998.
391 * This file may be redistributed under
392 * the terms of the GNU Public License.
396 unsigned int magic; /* expect AIX_LABEL_MAGIC */
397 unsigned int fillbytes1[124];
398 unsigned int physical_volume_id;
399 unsigned int fillbytes2[124];
402 #define AIX_LABEL_MAGIC 0xc9c2d4c1
403 #define AIX_LABEL_MAGIC_SWAPPED 0xc1d4c2c9
404 #define AIX_INFO_MAGIC 0x00072959
405 #define AIX_INFO_MAGIC_SWAPPED 0x59290700
407 #define aixlabel ((aix_partition *)MBRbuffer)
412 * 1999-03-20 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
413 * Internationalization
415 * 2003-03-20 Phillip Kesling <pkesling@sgi.com>
419 static int aix_other_endian;
420 static short aix_volumes=1;
423 * only dealing with free blocks here
429 _("\n\tThere is a valid AIX label on this disk.\n"
430 "\tUnfortunately Linux cannot handle these\n"
431 "\tdisks at the moment. Nevertheless some\n"
433 "\t1. fdisk will destroy its contents on write.\n"
434 "\t2. Be sure that this disk is NOT a still vital\n"
435 "\t part of a volume group. (Otherwise you may\n"
436 "\t erase the other disks as well, if unmirrored.)\n"
437 "\t3. Before deleting this physical volume be sure\n"
438 "\t to remove the disk logically from your AIX\n"
439 "\t machine. (Otherwise you become an AIXpert).")
449 memset( MBRbuffer, 0, sizeof(MBRbuffer) ); /* avoid fdisk cores */
454 check_aix_label( void )
456 if (aixlabel->magic != AIX_LABEL_MAGIC &&
457 aixlabel->magic != AIX_LABEL_MAGIC_SWAPPED) {
459 aix_other_endian = 0;
462 aix_other_endian = (aixlabel->magic == AIX_LABEL_MAGIC_SWAPPED);
468 aix_nolabel(); /* %% */
469 aix_label = 1; /* %% */
472 #endif /* AIX_LABEL */
474 #ifdef CONFIG_FEATURE_OSF_LABEL
476 * Copyright (c) 1987, 1988 Regents of the University of California.
477 * All rights reserved.
479 * Redistribution and use in source and binary forms, with or without
480 * modification, are permitted provided that the following conditions
482 * 1. Redistributions of source code must retain the above copyright
483 * notice, this list of conditions and the following disclaimer.
484 * 2. Redistributions in binary form must reproduce the above copyright
485 * notice, this list of conditions and the following disclaimer in the
486 * documentation and/or other materials provided with the distribution.
487 * 3. All advertising materials mentioning features or use of this software
488 * must display the following acknowledgment:
489 * This product includes software developed by the University of
490 * California, Berkeley and its contributors.
491 * 4. Neither the name of the University nor the names of its contributors
492 * may be used to endorse or promote products derived from this software
493 * without specific prior written permission.
495 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
496 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
497 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
498 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
499 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
500 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
501 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
502 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
503 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
504 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
509 #ifndef BSD_DISKMAGIC
510 #define BSD_DISKMAGIC ((uint32_t) 0x82564557)
513 #ifndef BSD_MAXPARTITIONS
514 #define BSD_MAXPARTITIONS 16
517 #define BSD_LINUX_BOOTDIR "/usr/ucb/mdec"
519 #if defined (i386) || defined (__sparc__) || defined (__arm__) || defined (__mips__) || defined (__s390__) || defined (__sh__) || defined(__x86_64__)
520 #define BSD_LABELSECTOR 1
521 #define BSD_LABELOFFSET 0
522 #elif defined (__alpha__) || defined (__powerpc__) || defined (__ia64__) || defined (__hppa__)
523 #define BSD_LABELSECTOR 0
524 #define BSD_LABELOFFSET 64
525 #elif defined (__s390__) || defined (__s390x__)
526 #define BSD_LABELSECTOR 1
527 #define BSD_LABELOFFSET 0
529 #error unknown architecture
532 #define BSD_BBSIZE 8192 /* size of boot area, with label */
533 #define BSD_SBSIZE 8192 /* max size of fs superblock */
535 struct xbsd_disklabel {
536 uint32_t d_magic; /* the magic number */
537 int16_t d_type; /* drive type */
538 int16_t d_subtype; /* controller/d_type specific */
539 char d_typename[16]; /* type name, e.g. "eagle" */
540 char d_packname[16]; /* pack identifier */
542 uint32_t d_secsize; /* # of bytes per sector */
543 uint32_t d_nsectors; /* # of data sectors per track */
544 uint32_t d_ntracks; /* # of tracks per cylinder */
545 uint32_t d_ncylinders; /* # of data cylinders per unit */
546 uint32_t d_secpercyl; /* # of data sectors per cylinder */
547 uint32_t d_secperunit; /* # of data sectors per unit */
549 * Spares (bad sector replacements) below
550 * are not counted in d_nsectors or d_secpercyl.
551 * Spare sectors are assumed to be physical sectors
552 * which occupy space at the end of each track and/or cylinder.
554 uint16_t d_sparespertrack; /* # of spare sectors per track */
555 uint16_t d_sparespercyl; /* # of spare sectors per cylinder */
557 * Alternate cylinders include maintenance, replacement,
558 * configuration description areas, etc.
560 uint32_t d_acylinders; /* # of alt. cylinders per unit */
562 /* hardware characteristics: */
564 * d_interleave, d_trackskew and d_cylskew describe perturbations
565 * in the media format used to compensate for a slow controller.
566 * Interleave is physical sector interleave, set up by the formatter
567 * or controller when formatting. When interleaving is in use,
568 * logically adjacent sectors are not physically contiguous,
569 * but instead are separated by some number of sectors.
570 * It is specified as the ratio of physical sectors traversed
571 * per logical sector. Thus an interleave of 1:1 implies contiguous
572 * layout, while 2:1 implies that logical sector 0 is separated
573 * by one sector from logical sector 1.
574 * d_trackskew is the offset of sector 0 on track N
575 * relative to sector 0 on track N-1 on the same cylinder.
576 * Finally, d_cylskew is the offset of sector 0 on cylinder N
577 * relative to sector 0 on cylinder N-1.
579 uint16_t d_rpm; /* rotational speed */
580 uint16_t d_interleave; /* hardware sector interleave */
581 uint16_t d_trackskew; /* sector 0 skew, per track */
582 uint16_t d_cylskew; /* sector 0 skew, per cylinder */
583 uint32_t d_headswitch; /* head switch time, usec */
584 uint32_t d_trkseek; /* track-to-track seek, usec */
585 uint32_t d_flags; /* generic flags */
587 uint32_t d_drivedata[NDDATA]; /* drive-type specific information */
589 uint32_t d_spare[NSPARE]; /* reserved for future use */
590 uint32_t d_magic2; /* the magic number (again) */
591 uint16_t d_checksum; /* xor of data incl. partitions */
592 /* filesystem and partition information: */
593 uint16_t d_npartitions; /* number of partitions in following */
594 uint32_t d_bbsize; /* size of boot area at sn0, bytes */
595 uint32_t d_sbsize; /* max size of fs superblock, bytes */
596 struct xbsd_partition { /* the partition table */
597 uint32_t p_size; /* number of sectors in partition */
598 uint32_t p_offset; /* starting sector */
599 uint32_t p_fsize; /* filesystem basic fragment size */
600 uint8_t p_fstype; /* filesystem type, see below */
601 uint8_t p_frag; /* filesystem fragments per block */
602 uint16_t p_cpg; /* filesystem cylinders per group */
603 } d_partitions[BSD_MAXPARTITIONS]; /* actually may be more */
607 #define BSD_DTYPE_SMD 1 /* SMD, XSMD; VAX hp/up */
608 #define BSD_DTYPE_MSCP 2 /* MSCP */
609 #define BSD_DTYPE_DEC 3 /* other DEC (rk, rl) */
610 #define BSD_DTYPE_SCSI 4 /* SCSI */
611 #define BSD_DTYPE_ESDI 5 /* ESDI interface */
612 #define BSD_DTYPE_ST506 6 /* ST506 etc. */
613 #define BSD_DTYPE_HPIB 7 /* CS/80 on HP-IB */
614 #define BSD_DTYPE_HPFL 8 /* HP Fiber-link */
615 #define BSD_DTYPE_FLOPPY 10 /* floppy */
617 /* d_subtype values: */
618 #define BSD_DSTYPE_INDOSPART 0x8 /* is inside dos partition */
619 #define BSD_DSTYPE_DOSPART(s) ((s) & 3) /* dos partition number */
620 #define BSD_DSTYPE_GEOMETRY 0x10 /* drive params in label */
623 static const char * const xbsd_dktypenames[] = {
637 #define BSD_DKMAXTYPES (sizeof(xbsd_dktypenames) / sizeof(xbsd_dktypenames[0]) - 1)
641 * Filesystem type and version.
642 * Used to interpret other filesystem-specific
643 * per-partition information.
645 #define BSD_FS_UNUSED 0 /* unused */
646 #define BSD_FS_SWAP 1 /* swap */
647 #define BSD_FS_V6 2 /* Sixth Edition */
648 #define BSD_FS_V7 3 /* Seventh Edition */
649 #define BSD_FS_SYSV 4 /* System V */
650 #define BSD_FS_V71K 5 /* V7 with 1K blocks (4.1, 2.9) */
651 #define BSD_FS_V8 6 /* Eighth Edition, 4K blocks */
652 #define BSD_FS_BSDFFS 7 /* 4.2BSD fast file system */
653 #define BSD_FS_BSDLFS 9 /* 4.4BSD log-structured file system */
654 #define BSD_FS_OTHER 10 /* in use, but unknown/unsupported */
655 #define BSD_FS_HPFS 11 /* OS/2 high-performance file system */
656 #define BSD_FS_ISO9660 12 /* ISO-9660 filesystem (cdrom) */
657 #define BSD_FS_ISOFS BSD_FS_ISO9660
658 #define BSD_FS_BOOT 13 /* partition contains bootstrap */
659 #define BSD_FS_ADOS 14 /* AmigaDOS fast file system */
660 #define BSD_FS_HFS 15 /* Macintosh HFS */
661 #define BSD_FS_ADVFS 16 /* Digital Unix AdvFS */
663 /* this is annoying, but it's also the way it is :-( */
665 #define BSD_FS_EXT2 8 /* ext2 file system */
667 #define BSD_FS_MSDOS 8 /* MS-DOS file system */
671 static const struct systypes xbsd_fstypes[] = {
672 /* BSD_FS_UNUSED */ {"\x00" "unused"},
673 /* BSD_FS_SWAP */ {"\x01" "swap"},
674 /* BSD_FS_V6 */ {"\x02" "Version 6"},
675 /* BSD_FS_V7 */ {"\x03" "Version 7"},
676 /* BSD_FS_SYSV */ {"\x04" "System V"},
677 /* BSD_FS_V71K */ {"\x05" "4.1BSD"},
678 /* BSD_FS_V8 */ {"\x06" "Eighth Edition"},
679 /* BSD_FS_BSDFFS */ {"\x07" "4.2BSD"},
681 /* BSD_FS_EXT2 */ {"\x08" "ext2"},
683 /* BSD_FS_MSDOS */ {"\x08" "MS-DOS"},
685 /* BSD_FS_BSDLFS */ {"\x09" "4.4LFS"},
686 /* BSD_FS_OTHER */ {"\x0a" "unknown"},
687 /* BSD_FS_HPFS */ {"\x0b" "HPFS"},
688 /* BSD_FS_ISO9660 */ {"\x0c" "ISO-9660"},
689 /* BSD_FS_BOOT */ {"\x0d" "boot"},
690 /* BSD_FS_ADOS */ {"\x0e" "ADOS"},
691 /* BSD_FS_HFS */ {"\x0f" "HFS"},
692 /* BSD_FS_ADVFS */ {"\x10" "AdvFS"},
695 #define BSD_FSMAXTYPES (SIZE(xbsd_fstypes)-1)
700 * flags shared by various drives:
702 #define BSD_D_REMOVABLE 0x01 /* removable media */
703 #define BSD_D_ECC 0x02 /* supports ECC */
704 #define BSD_D_BADSECT 0x04 /* supports bad sector forw. */
705 #define BSD_D_RAMDISK 0x08 /* disk emulator */
706 #define BSD_D_CHAIN 0x10 /* can do back-back transfers */
707 #define BSD_D_DOSPART 0x20 /* within MSDOS partition */
709 #endif /* OSF_LABEL */
712 * Copyright (C) Andreas Neuper, Sep 1998.
713 * This file may be modified and redistributed under
714 * the terms of the GNU Public License.
717 struct device_parameter { /* 48 bytes */
721 unsigned char sparecyl;
722 unsigned short pcylcount;
723 unsigned short head_vol0;
724 unsigned short ntrks; /* tracks in cyl 0 or vol 0 */
725 unsigned char cmd_tag_queue_depth;
726 unsigned char unused0;
727 unsigned short unused1;
728 unsigned short nsect; /* sectors/tracks in cyl 0 or vol 0 */
729 unsigned short bytes;
730 unsigned short ilfact;
731 unsigned int flags; /* controller flags */
732 unsigned int datarate;
733 unsigned int retries_on_error;
734 unsigned int ms_per_word;
735 unsigned short xylogics_gap1;
736 unsigned short xylogics_syncdelay;
737 unsigned short xylogics_readdelay;
738 unsigned short xylogics_gap2;
739 unsigned short xylogics_readgate;
740 unsigned short xylogics_writecont;
743 #define SGI_VOLHDR 0x00
744 /* 1 and 2 were used for drive types no longer supported by SGI */
745 #define SGI_SWAP 0x03
746 /* 4 and 5 were for filesystem types SGI haven't ever supported on MIPS CPUs */
747 #define SGI_VOLUME 0x06
749 #define SGI_LVOL 0x08
750 #define SGI_RLVOL 0x09
752 #define SGI_XFSLOG 0x0b
755 #define ENTIRE_DISK SGI_VOLUME
759 #define SECTOR_SLIP 0x01
760 #define SECTOR_FWD 0x02
761 #define TRACK_FWD 0x04
762 #define TRACK_MULTIVOL 0x08
763 #define IGNORE_ERRORS 0x10
765 #define ENABLE_CMDTAGQ 0x40
768 unsigned int magic; /* expect SGI_LABEL_MAGIC */
769 unsigned short boot_part; /* active boot partition */
770 unsigned short swap_part; /* active swap partition */
771 unsigned char boot_file[16]; /* name of the bootfile */
772 struct device_parameter devparam; /* 1 * 48 bytes */
773 struct volume_directory { /* 15 * 16 bytes */
774 unsigned char vol_file_name[8]; /* a character array */
775 unsigned int vol_file_start; /* number of logical block */
776 unsigned int vol_file_size; /* number of bytes */
778 struct sgi_partition { /* 16 * 12 bytes */
779 unsigned int num_sectors; /* number of blocks */
780 unsigned int start_sector; /* must be cylinder aligned */
784 unsigned int fillbytes;
788 unsigned int magic; /* looks like a magic number */
797 unsigned char scsi_string[50];
798 unsigned char serial[137];
799 unsigned short check1816;
800 unsigned char installer[225];
803 #define SGI_LABEL_MAGIC 0x0be5a941
804 #define SGI_LABEL_MAGIC_SWAPPED 0x41a9e50b
805 #define SGI_INFO_MAGIC 0x00072959
806 #define SGI_INFO_MAGIC_SWAPPED 0x59290700
807 #define SGI_SSWAP16(x) (sgi_other_endian ? __swap16(x) \
809 #define SGI_SSWAP32(x) (sgi_other_endian ? __swap32(x) \
812 #define sgilabel ((sgi_partition *)MBRbuffer)
813 #define sgiparam (sgilabel->devparam)
816 unsigned char info[128]; /* Informative text string */
817 unsigned char spare0[14];
819 unsigned char spare1;
821 unsigned char spare2;
824 unsigned char spare1[246]; /* Boot information etc. */
825 unsigned short rspeed; /* Disk rotational speed */
826 unsigned short pcylcount; /* Physical cylinder count */
827 unsigned short sparecyl; /* extra sects per cylinder */
828 unsigned char spare2[4]; /* More magic... */
829 unsigned short ilfact; /* Interleave factor */
830 unsigned short ncyl; /* Data cylinder count */
831 unsigned short nacyl; /* Alt. cylinder count */
832 unsigned short ntrks; /* Tracks per cylinder */
833 unsigned short nsect; /* Sectors per track */
834 unsigned char spare3[4]; /* Even more magic... */
835 struct sun_partition {
836 uint32_t start_cylinder;
837 uint32_t num_sectors;
839 unsigned short magic; /* Magic number */
840 unsigned short csum; /* Label xor'd checksum */
844 #define SUN_LABEL_MAGIC 0xDABE
845 #define SUN_LABEL_MAGIC_SWAPPED 0xBEDA
846 #define sunlabel ((sun_partition *)MBRbuffer)
847 #define SUN_SSWAP16(x) (sun_other_endian ? __swap16(x) \
849 #define SUN_SSWAP32(x) (sun_other_endian ? __swap32(x) \
853 #ifdef CONFIG_FEATURE_OSF_LABEL
856 19990319 - Arnaldo Carvalho de Melo <acme@conectiva.com.br> - i18n/nls
858 20000101 - David Huggins-Daines <dhuggins@linuxcare.com> - Better
859 support for OSF/1 disklabels on Alpha.
860 Also fixed unaligned accesses in alpha_bootblock_checksum()
863 #define FREEBSD_PARTITION 0xa5
864 #define NETBSD_PARTITION 0xa9
866 static void xbsd_delete_part (void);
867 static void xbsd_new_part (void);
868 static void xbsd_write_disklabel (void);
869 static int xbsd_create_disklabel (void);
870 static void xbsd_edit_disklabel (void);
871 static void xbsd_write_bootstrap (void);
872 static void xbsd_change_fstype (void);
873 static int xbsd_get_part_index (int max);
874 static int xbsd_check_new_partition (int *i);
875 static void xbsd_list_types (void);
876 static u_short xbsd_dkcksum (struct xbsd_disklabel *lp);
877 static int xbsd_initlabel (struct partition *p, struct xbsd_disklabel *d,
879 static int xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d);
880 static int xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d);
882 #if defined (__alpha__)
883 static void alpha_bootblock_checksum (char *boot);
886 #if !defined (__alpha__)
887 static int xbsd_translate_fstype (int linux_type);
888 static void xbsd_link_part (void);
889 static struct partition *xbsd_part;
890 static int xbsd_part_index;
893 #if defined (__alpha__)
894 /* We access this through a uint64_t * when checksumming */
895 static char disklabelbuffer[BSD_BBSIZE] __attribute__((aligned(8)));
897 static char disklabelbuffer[BSD_BBSIZE];
900 static struct xbsd_disklabel xbsd_dlabel;
902 #define bsd_cround(n) \
903 (display_in_cyl_units ? ((n)/xbsd_dlabel.d_secpercyl) + 1 : (n))
906 * Test whether the whole disk has BSD disk label magic.
908 * Note: often reformatting with DOS-type label leaves the BSD magic,
909 * so this does not mean that there is a BSD disk label.
912 check_osf_label(void) {
913 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
918 static void xbsd_print_disklabel(int);
921 btrydev (const char * dev) {
922 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
924 printf(_("\nBSD label for device: %s\n"), dev);
925 xbsd_print_disklabel (0);
931 puts (_("Command action"));
932 puts (_("\td\tdelete a BSD partition"));
933 puts (_("\te\tedit drive data"));
934 puts (_("\ti\tinstall bootstrap"));
935 puts (_("\tl\tlist known filesystem types"));
936 puts (_("\tm\tprint this menu"));
937 puts (_("\tn\tadd a new BSD partition"));
938 puts (_("\tp\tprint BSD partition table"));
939 puts (_("\tq\tquit without saving changes"));
940 puts (_("\tr\treturn to main menu"));
941 puts (_("\ts\tshow complete disklabel"));
942 puts (_("\tt\tchange a partition's filesystem id"));
943 puts (_("\tu\tchange units (cylinders/sectors)"));
944 puts (_("\tw\twrite disklabel to disk"));
945 #if !defined (__alpha__)
946 puts (_("\tx\tlink BSD partition to non-BSD partition"));
950 #if !defined (__alpha__)
957 is_bsd_partition_type(int type) {
958 return (type == FREEBSD_PARTITION ||
959 type == hidden(FREEBSD_PARTITION) ||
960 type == NETBSD_PARTITION ||
961 type == hidden(NETBSD_PARTITION));
967 #if !defined (__alpha__)
971 for (t=0; t<4; t++) {
972 p = get_part_table(t);
973 if (p && is_bsd_partition_type(p->sys_ind)) {
976 ss = get_start_sect(xbsd_part);
978 fprintf (stderr, _("Partition %s has invalid starting sector 0.\n"),
979 partname(disk_device, t+1, 0));
982 printf (_("Reading disklabel of %s at sector %d.\n"),
983 partname(disk_device, t+1, 0), ss + BSD_LABELSECTOR);
984 if (xbsd_readlabel (xbsd_part, &xbsd_dlabel) == 0)
985 if (xbsd_create_disklabel () == 0)
992 printf (_("There is no *BSD partition on %s.\n"), disk_device);
996 #elif defined (__alpha__)
998 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
999 if (xbsd_create_disklabel () == 0)
1000 exit ( EXIT_SUCCESS );
1006 switch (tolower (read_char (_("BSD disklabel command (m for help): ")))) {
1008 xbsd_delete_part ();
1011 xbsd_edit_disklabel ();
1014 xbsd_write_bootstrap ();
1023 xbsd_print_disklabel (0);
1027 exit ( EXIT_SUCCESS );
1031 xbsd_print_disklabel (1);
1034 xbsd_change_fstype ();
1040 xbsd_write_disklabel ();
1042 #if !defined (__alpha__)
1055 xbsd_delete_part (void)
1059 i = xbsd_get_part_index (xbsd_dlabel.d_npartitions);
1060 xbsd_dlabel.d_partitions[i].p_size = 0;
1061 xbsd_dlabel.d_partitions[i].p_offset = 0;
1062 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
1063 if (xbsd_dlabel.d_npartitions == i + 1)
1064 while (xbsd_dlabel.d_partitions[xbsd_dlabel.d_npartitions-1].p_size == 0)
1065 xbsd_dlabel.d_npartitions--;
1069 xbsd_new_part (void)
1075 if (!xbsd_check_new_partition (&i))
1078 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
1079 begin = get_start_sect(xbsd_part);
1080 end = begin + get_nr_sects(xbsd_part) - 1;
1083 end = xbsd_dlabel.d_secperunit - 1;
1086 snprintf (mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
1087 begin = read_int (bsd_cround (begin), bsd_cround (begin), bsd_cround (end),
1090 if (display_in_cyl_units)
1091 begin = (begin - 1) * xbsd_dlabel.d_secpercyl;
1093 snprintf (mesg, sizeof(mesg), _("Last %s or +size or +sizeM or +sizeK"),
1094 str_units(SINGULAR));
1095 end = read_int (bsd_cround (begin), bsd_cround (end), bsd_cround (end),
1096 bsd_cround (begin), mesg);
1098 if (display_in_cyl_units)
1099 end = end * xbsd_dlabel.d_secpercyl - 1;
1101 xbsd_dlabel.d_partitions[i].p_size = end - begin + 1;
1102 xbsd_dlabel.d_partitions[i].p_offset = begin;
1103 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
1107 xbsd_print_disklabel (int show_all) {
1108 struct xbsd_disklabel *lp = &xbsd_dlabel;
1109 struct xbsd_partition *pp;
1113 #if defined (__alpha__)
1114 printf("# %s:\n", disk_device);
1116 printf("# %s:\n", partname(disk_device, xbsd_part_index+1, 0));
1118 if ((unsigned) lp->d_type < BSD_DKMAXTYPES)
1119 printf(_("type: %s\n"), xbsd_dktypenames[lp->d_type]);
1121 printf(_("type: %d\n"), lp->d_type);
1122 printf(_("disk: %.*s\n"), (int) sizeof(lp->d_typename), lp->d_typename);
1123 printf(_("label: %.*s\n"), (int) sizeof(lp->d_packname), lp->d_packname);
1124 printf(_("flags:"));
1125 if (lp->d_flags & BSD_D_REMOVABLE)
1126 printf(_(" removable"));
1127 if (lp->d_flags & BSD_D_ECC)
1129 if (lp->d_flags & BSD_D_BADSECT)
1130 printf(_(" badsect"));
1132 /* On various machines the fields of *lp are short/int/long */
1133 /* In order to avoid problems, we cast them all to long. */
1134 printf(_("bytes/sector: %ld\n"), (long) lp->d_secsize);
1135 printf(_("sectors/track: %ld\n"), (long) lp->d_nsectors);
1136 printf(_("tracks/cylinder: %ld\n"), (long) lp->d_ntracks);
1137 printf(_("sectors/cylinder: %ld\n"), (long) lp->d_secpercyl);
1138 printf(_("cylinders: %ld\n"), (long) lp->d_ncylinders);
1139 printf(_("rpm: %d\n"), lp->d_rpm);
1140 printf(_("interleave: %d\n"), lp->d_interleave);
1141 printf(_("trackskew: %d\n"), lp->d_trackskew);
1142 printf(_("cylinderskew: %d\n"), lp->d_cylskew);
1143 printf(_("headswitch: %ld\t\t# milliseconds\n"),
1144 (long) lp->d_headswitch);
1145 printf(_("track-to-track seek: %ld\t# milliseconds\n"),
1146 (long) lp->d_trkseek);
1147 printf(_("drivedata: "));
1148 for (i = NDDATA - 1; i >= 0; i--)
1149 if (lp->d_drivedata[i])
1153 for (j = 0; j <= i; j++)
1154 printf("%ld ", (long) lp->d_drivedata[j]);
1156 printf(_("\n%d partitions:\n"), lp->d_npartitions);
1157 printf(_("# start end size fstype [fsize bsize cpg]\n"));
1158 pp = lp->d_partitions;
1159 for (i = 0; i < lp->d_npartitions; i++, pp++) {
1161 if (display_in_cyl_units && lp->d_secpercyl) {
1162 printf(" %c: %8ld%c %8ld%c %8ld%c ",
1164 (long) pp->p_offset / lp->d_secpercyl + 1,
1165 (pp->p_offset % lp->d_secpercyl) ? '*' : ' ',
1166 (long) (pp->p_offset + pp->p_size + lp->d_secpercyl - 1)
1168 ((pp->p_offset + pp->p_size) % lp->d_secpercyl) ? '*' : ' ',
1169 (long) pp->p_size / lp->d_secpercyl,
1170 (pp->p_size % lp->d_secpercyl) ? '*' : ' ');
1172 printf(" %c: %8ld %8ld %8ld ",
1174 (long) pp->p_offset,
1175 (long) pp->p_offset + pp->p_size - 1,
1178 if ((unsigned) pp->p_fstype < BSD_FSMAXTYPES)
1179 printf("%8.8s", xbsd_fstypes[pp->p_fstype].name);
1181 printf("%8x", pp->p_fstype);
1182 switch (pp->p_fstype) {
1184 printf(" %5ld %5ld %5.5s ",
1185 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, "");
1189 printf(" %5ld %5ld %5d ",
1190 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag,
1195 printf("%22.22s", "");
1204 xbsd_write_disklabel (void) {
1205 #if defined (__alpha__)
1206 printf (_("Writing disklabel to %s.\n"), disk_device);
1207 xbsd_writelabel (NULL, &xbsd_dlabel);
1209 printf (_("Writing disklabel to %s.\n"),
1210 partname(disk_device, xbsd_part_index+1, 0));
1211 xbsd_writelabel (xbsd_part, &xbsd_dlabel);
1213 reread_partition_table(0); /* no exit yet */
1217 xbsd_create_disklabel (void) {
1220 #if defined (__alpha__)
1221 fprintf (stderr, _("%s contains no disklabel.\n"), disk_device);
1223 fprintf (stderr, _("%s contains no disklabel.\n"),
1224 partname(disk_device, xbsd_part_index+1, 0));
1228 c = read_char (_("Do you want to create a disklabel? (y/n) "));
1229 if (c == 'y' || c == 'Y') {
1230 if (xbsd_initlabel (
1231 #if defined (__alpha__) || defined (__powerpc__) || defined (__hppa__) || \
1232 defined (__s390__) || defined (__s390x__)
1233 NULL, &xbsd_dlabel, 0
1235 xbsd_part, &xbsd_dlabel, xbsd_part_index
1238 xbsd_print_disklabel (1);
1242 } else if (c == 'n')
1248 edit_int (int def, char *mesg)
1251 fputs (mesg, stdout);
1252 printf (" (%d): ", def);
1256 while (!isdigit (*line_ptr));
1257 return atoi (line_ptr);
1261 xbsd_edit_disklabel (void)
1263 struct xbsd_disklabel *d;
1267 #if defined (__alpha__) || defined (__ia64__)
1268 d -> d_secsize = (u_long) edit_int ((u_long) d -> d_secsize ,_("bytes/sector"));
1269 d -> d_nsectors = (u_long) edit_int ((u_long) d -> d_nsectors ,_("sectors/track"));
1270 d -> d_ntracks = (u_long) edit_int ((u_long) d -> d_ntracks ,_("tracks/cylinder"));
1271 d -> d_ncylinders = (u_long) edit_int ((u_long) d -> d_ncylinders ,_("cylinders"));
1274 /* d -> d_secpercyl can be != d -> d_nsectors * d -> d_ntracks */
1277 d -> d_secpercyl = (u_long) edit_int ((u_long) d -> d_nsectors * d -> d_ntracks,
1278 _("sectors/cylinder"));
1279 if (d -> d_secpercyl <= d -> d_nsectors * d -> d_ntracks)
1282 printf (_("Must be <= sectors/track * tracks/cylinder (default).\n"));
1284 d -> d_rpm = (u_short) edit_int ((u_short) d -> d_rpm ,_("rpm"));
1285 d -> d_interleave = (u_short) edit_int ((u_short) d -> d_interleave,_("interleave"));
1286 d -> d_trackskew = (u_short) edit_int ((u_short) d -> d_trackskew ,_("trackskew"));
1287 d -> d_cylskew = (u_short) edit_int ((u_short) d -> d_cylskew ,_("cylinderskew"));
1288 d -> d_headswitch = (u_long) edit_int ((u_long) d -> d_headswitch ,_("headswitch"));
1289 d -> d_trkseek = (u_long) edit_int ((u_long) d -> d_trkseek ,_("track-to-track seek"));
1291 d -> d_secperunit = d -> d_secpercyl * d -> d_ncylinders;
1295 xbsd_get_bootstrap (char *path, void *ptr, int size)
1299 if ((fdb = open (path, O_RDONLY)) < 0)
1304 if (read (fdb, ptr, size) < 0)
1310 printf (" ... %s\n", path);
1318 printf (_("\nSyncing disks.\n"));
1324 xbsd_write_bootstrap (void)
1326 char *bootdir = BSD_LINUX_BOOTDIR;
1327 char path[MAXPATHLEN];
1329 struct xbsd_disklabel dl;
1333 if (xbsd_dlabel.d_type == BSD_DTYPE_SCSI)
1338 printf (_("Bootstrap: %sboot -> boot%s (%s): "),
1339 dkbasename, dkbasename, dkbasename);
1341 line_ptr[strlen (line_ptr)-1] = '\0';
1342 dkbasename = line_ptr;
1344 snprintf (path, sizeof(path), "%s/%sboot", bootdir, dkbasename);
1345 if (!xbsd_get_bootstrap (path, disklabelbuffer, (int) xbsd_dlabel.d_secsize))
1348 /* We need a backup of the disklabel (xbsd_dlabel might have changed). */
1349 d = &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE];
1350 bcopy (d, &dl, sizeof (struct xbsd_disklabel));
1352 /* The disklabel will be overwritten by 0's from bootxx anyway */
1353 bzero (d, sizeof (struct xbsd_disklabel));
1355 snprintf (path, sizeof(path), "%s/boot%s", bootdir, dkbasename);
1356 if (!xbsd_get_bootstrap (path, &disklabelbuffer[xbsd_dlabel.d_secsize],
1357 (int) xbsd_dlabel.d_bbsize - xbsd_dlabel.d_secsize))
1360 e = d + sizeof (struct xbsd_disklabel);
1361 for (p=d; p < e; p++)
1363 fprintf (stderr, _("Bootstrap overlaps with disk label!\n"));
1364 exit ( EXIT_FAILURE );
1367 bcopy (&dl, d, sizeof (struct xbsd_disklabel));
1369 #if defined (__powerpc__) || defined (__hppa__)
1371 #elif defined (__alpha__)
1373 alpha_bootblock_checksum (disklabelbuffer);
1375 sector = get_start_sect(xbsd_part);
1378 if (lseek (fd, sector * SECTOR_SIZE, SEEK_SET) == -1)
1379 fdisk_fatal (unable_to_seek);
1380 if (BSD_BBSIZE != write (fd, disklabelbuffer, BSD_BBSIZE))
1381 fdisk_fatal (unable_to_write);
1383 #if defined (__alpha__)
1384 printf (_("Bootstrap installed on %s.\n"), disk_device);
1386 printf (_("Bootstrap installed on %s.\n"),
1387 partname (disk_device, xbsd_part_index+1, 0));
1394 xbsd_change_fstype (void)
1398 i = xbsd_get_part_index (xbsd_dlabel.d_npartitions);
1399 xbsd_dlabel.d_partitions[i].p_fstype = read_hex (xbsd_fstypes);
1403 xbsd_get_part_index (int max)
1408 snprintf (prompt, sizeof(prompt), _("Partition (a-%c): "), 'a' + max - 1);
1410 l = tolower (read_char (prompt));
1411 while (l < 'a' || l > 'a' + max - 1);
1416 xbsd_check_new_partition (int *i) {
1418 /* room for more? various BSD flavours have different maxima */
1419 if (xbsd_dlabel.d_npartitions == BSD_MAXPARTITIONS) {
1422 for (t = 0; t < BSD_MAXPARTITIONS; t++)
1423 if (xbsd_dlabel.d_partitions[t].p_size == 0)
1426 if (t == BSD_MAXPARTITIONS) {
1427 fprintf (stderr, _("The maximum number of partitions "
1428 "has been created\n"));
1433 *i = xbsd_get_part_index (BSD_MAXPARTITIONS);
1435 if (*i >= xbsd_dlabel.d_npartitions)
1436 xbsd_dlabel.d_npartitions = (*i) + 1;
1438 if (xbsd_dlabel.d_partitions[*i].p_size != 0) {
1439 fprintf (stderr, _("This partition already exists.\n"));
1447 xbsd_list_types (void) {
1448 list_types (xbsd_fstypes);
1452 xbsd_dkcksum (struct xbsd_disklabel *lp) {
1453 u_short *start, *end;
1456 start = (u_short *) lp;
1457 end = (u_short *) &lp->d_partitions[lp->d_npartitions];
1464 xbsd_initlabel (struct partition *p, struct xbsd_disklabel *d, int pindex) {
1465 struct xbsd_partition *pp;
1468 bzero (d, sizeof (struct xbsd_disklabel));
1470 d -> d_magic = BSD_DISKMAGIC;
1472 if (strncmp (disk_device, "/dev/sd", 7) == 0)
1473 d -> d_type = BSD_DTYPE_SCSI;
1475 d -> d_type = BSD_DTYPE_ST506;
1477 #if 0 /* not used (at least not written to disk) by NetBSD/i386 1.0 */
1478 d -> d_subtype = BSD_DSTYPE_INDOSPART & pindex;
1481 #if !defined (__alpha__)
1482 d -> d_flags = BSD_D_DOSPART;
1486 d -> d_secsize = SECTOR_SIZE; /* bytes/sector */
1487 d -> d_nsectors = sectors; /* sectors/track */
1488 d -> d_ntracks = heads; /* tracks/cylinder (heads) */
1489 d -> d_ncylinders = cylinders;
1490 d -> d_secpercyl = sectors * heads;/* sectors/cylinder */
1491 if (d -> d_secpercyl == 0)
1492 d -> d_secpercyl = 1; /* avoid segfaults */
1493 d -> d_secperunit = d -> d_secpercyl * d -> d_ncylinders;
1496 d -> d_interleave = 1;
1497 d -> d_trackskew = 0;
1499 d -> d_headswitch = 0;
1502 d -> d_magic2 = BSD_DISKMAGIC;
1503 d -> d_bbsize = BSD_BBSIZE;
1504 d -> d_sbsize = BSD_SBSIZE;
1506 #if !defined (__alpha__)
1507 d -> d_npartitions = 4;
1508 pp = &d -> d_partitions[2]; /* Partition C should be
1509 the NetBSD partition */
1510 pp -> p_offset = get_start_sect(p);
1511 pp -> p_size = get_nr_sects(p);
1512 pp -> p_fstype = BSD_FS_UNUSED;
1513 pp = &d -> d_partitions[3]; /* Partition D should be
1516 pp -> p_size = d -> d_secperunit;
1517 pp -> p_fstype = BSD_FS_UNUSED;
1518 #elif defined (__alpha__)
1519 d -> d_npartitions = 3;
1520 pp = &d -> d_partitions[2]; /* Partition C should be
1523 pp -> p_size = d -> d_secperunit;
1524 pp -> p_fstype = BSD_FS_UNUSED;
1531 * Read a xbsd_disklabel from sector 0 or from the starting sector of p.
1532 * If it has the right magic, return 1.
1535 xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d)
1539 /* p is used only to get the starting sector */
1540 #if !defined (__alpha__)
1541 sector = (p ? get_start_sect(p) : 0);
1542 #elif defined (__alpha__)
1546 if (lseek (fd, sector * SECTOR_SIZE, SEEK_SET) == -1)
1547 fdisk_fatal (unable_to_seek);
1548 if (BSD_BBSIZE != read (fd, disklabelbuffer, BSD_BBSIZE))
1549 fdisk_fatal (unable_to_read);
1551 bcopy (&disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
1552 d, sizeof (struct xbsd_disklabel));
1554 if (d -> d_magic != BSD_DISKMAGIC || d -> d_magic2 != BSD_DISKMAGIC)
1557 for (t = d -> d_npartitions; t < BSD_MAXPARTITIONS; t++) {
1558 d -> d_partitions[t].p_size = 0;
1559 d -> d_partitions[t].p_offset = 0;
1560 d -> d_partitions[t].p_fstype = BSD_FS_UNUSED;
1563 if (d -> d_npartitions > BSD_MAXPARTITIONS)
1564 fprintf (stderr, _("Warning: too many partitions "
1565 "(%d, maximum is %d).\n"),
1566 d -> d_npartitions, BSD_MAXPARTITIONS);
1571 xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d)
1573 unsigned int sector;
1575 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
1576 sector = get_start_sect(p) + BSD_LABELSECTOR;
1578 sector = BSD_LABELSECTOR;
1581 d -> d_checksum = 0;
1582 d -> d_checksum = xbsd_dkcksum (d);
1584 /* This is necessary if we want to write the bootstrap later,
1585 otherwise we'd write the old disklabel with the bootstrap.
1587 bcopy (d, &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
1588 sizeof (struct xbsd_disklabel));
1590 #if defined (__alpha__) && BSD_LABELSECTOR == 0
1591 alpha_bootblock_checksum (disklabelbuffer);
1592 if (lseek (fd, 0, SEEK_SET) == -1)
1593 fdisk_fatal (unable_to_seek);
1594 if (BSD_BBSIZE != write (fd, disklabelbuffer, BSD_BBSIZE))
1595 fdisk_fatal (unable_to_write);
1597 if (lseek (fd, sector * SECTOR_SIZE + BSD_LABELOFFSET,
1599 fdisk_fatal (unable_to_seek);
1600 if (sizeof (struct xbsd_disklabel) != write (fd, d, sizeof (struct xbsd_disklabel)))
1601 fdisk_fatal (unable_to_write);
1610 #if !defined (__alpha__)
1612 xbsd_translate_fstype (int linux_type)
1616 case 0x01: /* DOS 12-bit FAT */
1617 case 0x04: /* DOS 16-bit <32M */
1618 case 0x06: /* DOS 16-bit >=32M */
1619 case 0xe1: /* DOS access */
1620 case 0xe3: /* DOS R/O */
1621 case 0xf2: /* DOS secondary */
1622 return BSD_FS_MSDOS;
1623 case 0x07: /* OS/2 HPFS */
1626 return BSD_FS_OTHER;
1631 xbsd_link_part (void)
1634 struct partition *p;
1636 k = get_partition (1, partitions);
1638 if (!xbsd_check_new_partition (&i))
1641 p = get_part_table(k);
1643 xbsd_dlabel.d_partitions[i].p_size = get_nr_sects(p);
1644 xbsd_dlabel.d_partitions[i].p_offset = get_start_sect(p);
1645 xbsd_dlabel.d_partitions[i].p_fstype = xbsd_translate_fstype(p->sys_ind);
1649 #if defined (__alpha__)
1651 #if !defined(__GLIBC__)
1652 typedef unsigned long long uint64_t;
1656 alpha_bootblock_checksum (char *boot)
1661 dp = (uint64_t *)boot;
1663 for (i = 0; i < 63; i++)
1667 #endif /* __alpha__ */
1669 #endif /* OSF_LABEL */
1671 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
1672 static inline unsigned short
1673 __swap16(unsigned short x) {
1674 return (((uint16_t)(x) & 0xFF) << 8) | (((uint16_t)(x) & 0xFF00) >> 8);
1677 static inline uint32_t
1678 __swap32(uint32_t x) {
1679 return (((x & 0xFF) << 24) |
1680 ((x & 0xFF00) << 8) |
1681 ((x & 0xFF0000) >> 8) |
1682 ((x & 0xFF000000) >> 24));
1686 #ifdef CONFIG_FEATURE_SGI_LABEL
1691 * Copyright (C) Andreas Neuper, Sep 1998.
1692 * This file may be modified and redistributed under
1693 * the terms of the GNU Public License.
1695 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
1696 * Internationalization
1700 static int sgi_other_endian;
1702 static short sgi_volumes=1;
1705 * only dealing with free blocks here
1708 typedef struct { unsigned int first; unsigned int last; } freeblocks;
1709 static freeblocks freelist[17]; /* 16 partitions can produce 17 vacant slots */
1712 setfreelist(int i, unsigned int f, unsigned int l) {
1713 freelist[i].first = f;
1714 freelist[i].last = l;
1718 add2freelist(unsigned int f, unsigned int l) {
1720 for ( ; i < 17 ; i++)
1721 if (freelist[i].last == 0)
1723 setfreelist(i, f, l);
1727 clearfreelist(void) {
1730 for (i = 0; i < 17 ; i++)
1731 setfreelist(i, 0, 0);
1735 isinfreelist(unsigned int b) {
1738 for (i = 0; i < 17 ; i++)
1739 if (freelist[i].first <= b && freelist[i].last >= b)
1740 return freelist[i].last;
1743 /* return last vacant block of this stride (never 0). */
1744 /* the '>=' is not quite correct, but simplifies the code */
1746 * end of free blocks section
1749 static const struct systypes sgi_sys_types[] = {
1750 /* SGI_VOLHDR */ {"\x00" "SGI volhdr" },
1751 /* 0x01 */ {"\x01" "SGI trkrepl" },
1752 /* 0x02 */ {"\x02" "SGI secrepl" },
1753 /* SGI_SWAP */ {"\x03" "SGI raw" },
1754 /* 0x04 */ {"\x04" "SGI bsd" },
1755 /* 0x05 */ {"\x05" "SGI sysv" },
1756 /* ENTIRE_DISK */ {"\x06" "SGI volume" },
1757 /* SGI_EFS */ {"\x07" "SGI efs" },
1758 /* 0x08 */ {"\x08" "SGI lvol" },
1759 /* 0x09 */ {"\x09" "SGI rlvol" },
1760 /* SGI_XFS */ {"\x0a" "SGI xfs" },
1761 /* SGI_XFSLOG */ {"\x0b" "SGI xfslog" },
1762 /* SGI_XLV */ {"\x0c" "SGI xlv" },
1763 /* SGI_XVM */ {"\x0d" "SGI xvm" },
1764 /* LINUX_SWAP */ {"\x82" "Linux swap" },
1765 /* LINUX_NATIVE */ {"\x83" "Linux native" },
1766 /* LINUX_LVM */ {"\x8d" "Linux LVM" },
1767 /* LINUX_RAID */ {"\xfd" "Linux RAID" },
1773 sgi_get_nsect(void) {
1774 return SGI_SSWAP16(sgilabel->devparam.nsect);
1778 sgi_get_ntrks(void) {
1779 return SGI_SSWAP16(sgilabel->devparam.ntrks);
1784 sgilabel->magic = 0;
1790 two_s_complement_32bit_sum(unsigned int* base, int size /* in bytes */) {
1794 size /= sizeof(unsigned int);
1795 for (i = 0; i < size; i++)
1796 sum -= SGI_SSWAP32(base[i]);
1801 check_sgi_label(void) {
1802 if (sizeof(sgilabel) > 512) {
1804 _("According to MIPS Computer Systems, Inc the "
1805 "Label must not contain more than 512 bytes\n"));
1809 if (sgilabel->magic != SGI_LABEL_MAGIC &&
1810 sgilabel->magic != SGI_LABEL_MAGIC_SWAPPED) {
1812 sgi_other_endian = 0;
1816 sgi_other_endian = (sgilabel->magic == SGI_LABEL_MAGIC_SWAPPED);
1818 * test for correct checksum
1820 if (two_s_complement_32bit_sum((unsigned int*)sgilabel,
1821 sizeof(*sgilabel))) {
1823 _("Detected sgi disklabel with wrong checksum.\n"));
1833 sgi_get_start_sector(int i) {
1834 return SGI_SSWAP32(sgilabel->partitions[i].start_sector);
1838 sgi_get_num_sectors(int i) {
1839 return SGI_SSWAP32(sgilabel->partitions[i].num_sectors);
1843 sgi_get_sysid(int i)
1845 return SGI_SSWAP32(sgilabel->partitions[i].id);
1849 sgi_get_bootpartition(void)
1851 return SGI_SSWAP16(sgilabel->boot_part);
1855 sgi_get_swappartition(void)
1857 return SGI_SSWAP16(sgilabel->swap_part);
1861 sgi_list_table(int xtra) {
1863 int kpi = 0; /* kernel partition ID */
1866 printf(_("\nDisk %s (SGI disk label): %d heads, %d sectors\n"
1867 "%d cylinders, %d physical cylinders\n"
1868 "%d extra sects/cyl, interleave %d:1\n"
1870 "Units = %s of %d * 512 bytes\n\n"),
1871 disk_device, heads, sectors, cylinders,
1872 SGI_SSWAP16(sgiparam.pcylcount),
1873 SGI_SSWAP16(sgiparam.sparecyl),
1874 SGI_SSWAP16(sgiparam.ilfact),
1876 str_units(PLURAL), units_per_sector);
1878 printf( _("\nDisk %s (SGI disk label): "
1879 "%d heads, %d sectors, %d cylinders\n"
1880 "Units = %s of %d * 512 bytes\n\n"),
1881 disk_device, heads, sectors, cylinders,
1882 str_units(PLURAL), units_per_sector );
1885 w = strlen(disk_device);
1886 wd = strlen(_("Device"));
1890 printf(_("----- partitions -----\n"
1891 "Pt# %*s Info Start End Sectors Id System\n"),
1892 w + 2, _("Device"));
1893 for (i = 0 ; i < partitions; i++) {
1894 if( sgi_get_num_sectors(i) || debug ) {
1895 uint32_t start = sgi_get_start_sector(i);
1896 uint32_t len = sgi_get_num_sectors(i);
1897 kpi++; /* only count nonempty partitions */
1899 "%2d: %s %4s %9ld %9ld %9ld %2x %s\n",
1900 /* fdisk part number */ i+1,
1901 /* device */ partname(disk_device, kpi, w+3),
1902 /* flags */ (sgi_get_swappartition() == i) ? "swap" :
1903 /* flags */ (sgi_get_bootpartition() == i) ? "boot" : " ",
1904 /* start */ (long) scround(start),
1905 /* end */ (long) scround(start+len)-1,
1906 /* no odd flag on end */ (long) len,
1907 /* type id */ sgi_get_sysid(i),
1908 /* type name */ partition_type(sgi_get_sysid(i)));
1911 printf(_("----- Bootinfo -----\nBootfile: %s\n"
1912 "----- Directory Entries -----\n"),
1913 sgilabel->boot_file);
1914 for (i = 0 ; i < sgi_volumes; i++) {
1915 if (sgilabel->directory[i].vol_file_size) {
1916 uint32_t start = SGI_SSWAP32(sgilabel->directory[i].vol_file_start);
1917 uint32_t len = SGI_SSWAP32(sgilabel->directory[i].vol_file_size);
1918 char*name = sgilabel->directory[i].vol_file_name;
1920 printf(_("%2d: %-10s sector%5u size%8u\n"),
1921 i, name, (unsigned int) start, (unsigned int) len);
1927 sgi_set_bootpartition( int i )
1929 sgilabel->boot_part = SGI_SSWAP16(((short)i));
1933 sgi_get_lastblock(void) {
1934 return heads * sectors * cylinders;
1938 sgi_set_swappartition( int i ) {
1939 sgilabel->swap_part = SGI_SSWAP16(((short)i));
1943 sgi_check_bootfile(const char* aFile) {
1945 if (strlen(aFile) < 3) /* "/a\n" is minimum */ {
1946 printf(_("\nInvalid Bootfile!\n"
1947 "\tThe bootfile must be an absolute non-zero pathname,\n"
1948 "\te.g. \"/unix\" or \"/unix.save\".\n"));
1951 if (strlen(aFile) > 16) {
1952 printf(_("\n\tName of Bootfile too long: "
1953 "16 bytes maximum.\n"));
1956 if (aFile[0] != '/') {
1957 printf(_("\n\tBootfile must have a "
1958 "fully qualified pathname.\n"));
1963 if (strncmp(aFile, sgilabel->boot_file, 16)) {
1964 printf(_("\n\tBe aware, that the bootfile is not checked for existence.\n\t"
1965 "SGI's default is \"/unix\" and for backup \"/unix.save\".\n"));
1966 /* filename is correct and did change */
1969 return 0; /* filename did not change */
1973 sgi_get_bootfile(void) {
1974 return sgilabel->boot_file;
1978 sgi_set_bootfile(const char* aFile) {
1981 if (sgi_check_bootfile(aFile)) {
1983 if ((aFile[i] != '\n') /* in principle caught again by next line */
1984 && (strlen(aFile) > i))
1985 sgilabel->boot_file[i] = aFile[i];
1987 sgilabel->boot_file[i] = 0;
1990 printf(_("\n\tBootfile is changed to \"%s\".\n"), sgilabel->boot_file);
1995 create_sgiinfo(void)
1997 /* I keep SGI's habit to write the sgilabel to the second block */
1998 sgilabel->directory[0].vol_file_start = SGI_SSWAP32(2);
1999 sgilabel->directory[0].vol_file_size = SGI_SSWAP32(sizeof(sgiinfo));
2000 strncpy(sgilabel->directory[0].vol_file_name, "sgilabel", 8);
2003 static sgiinfo *fill_sgiinfo(void);
2006 sgi_write_table(void) {
2008 sgilabel->csum = SGI_SSWAP32(two_s_complement_32bit_sum(
2009 (unsigned int*)sgilabel,
2010 sizeof(*sgilabel)));
2011 assert(two_s_complement_32bit_sum(
2012 (unsigned int*)sgilabel, sizeof(*sgilabel)) == 0);
2013 if (lseek(fd, 0, SEEK_SET) < 0)
2014 fdisk_fatal(unable_to_seek);
2015 if (write(fd, sgilabel, SECTOR_SIZE) != SECTOR_SIZE)
2016 fdisk_fatal(unable_to_write);
2017 if (! strncmp(sgilabel->directory[0].vol_file_name, "sgilabel", 8)) {
2019 * keep this habit of first writing the "sgilabel".
2020 * I never tested whether it works without (AN 981002).
2022 sgiinfo *info = fill_sgiinfo();
2023 int infostartblock = SGI_SSWAP32(sgilabel->directory[0].vol_file_start);
2024 if (lseek(fd, infostartblock*SECTOR_SIZE, SEEK_SET) < 0)
2025 fdisk_fatal(unable_to_seek);
2026 if (write(fd, info, SECTOR_SIZE) != SECTOR_SIZE)
2027 fdisk_fatal(unable_to_write);
2033 compare_start(int *x, int *y) {
2035 * sort according to start sectors
2036 * and prefers largest partition:
2037 * entry zero is entire disk entry
2039 unsigned int i = *x;
2040 unsigned int j = *y;
2041 unsigned int a = sgi_get_start_sector(i);
2042 unsigned int b = sgi_get_start_sector(j);
2043 unsigned int c = sgi_get_num_sectors(i);
2044 unsigned int d = sgi_get_num_sectors(j);
2047 return (d > c) ? 1 : (d == c) ? 0 : -1;
2048 return (a > b) ? 1 : -1;
2053 verify_sgi(int verbose)
2055 int Index[16]; /* list of valid partitions */
2056 int sortcount = 0; /* number of used partitions, i.e. non-zero lengths */
2057 int entire = 0, i = 0;
2058 unsigned int start = 0;
2059 long long gap = 0; /* count unused blocks */
2060 unsigned int lastblock = sgi_get_lastblock();
2063 for (i=0; i<16; i++) {
2064 if (sgi_get_num_sectors(i) != 0) {
2065 Index[sortcount++]=i;
2066 if (sgi_get_sysid(i) == ENTIRE_DISK) {
2067 if (entire++ == 1) {
2069 printf(_("More than one entire disk entry present.\n"));
2074 if (sortcount == 0) {
2076 printf(_("No partitions defined\n"));
2077 return (lastblock > 0) ? 1 : (lastblock == 0) ? 0 : -1;
2079 qsort(Index, sortcount, sizeof(Index[0]), (void*)compare_start);
2080 if (sgi_get_sysid(Index[0]) == ENTIRE_DISK) {
2081 if ((Index[0] != 10) && verbose)
2082 printf(_("IRIX likes when Partition 11 covers the entire disk.\n"));
2083 if ((sgi_get_start_sector(Index[0]) != 0) && verbose)
2084 printf(_("The entire disk partition should start "
2086 "not at diskblock %d.\n"),
2087 sgi_get_start_sector(Index[0]));
2088 if (debug) /* I do not understand how some disks fulfil it */
2089 if ((sgi_get_num_sectors(Index[0]) != lastblock) && verbose)
2090 printf(_("The entire disk partition is only %d diskblock large,\n"
2091 "but the disk is %d diskblocks long.\n"),
2092 sgi_get_num_sectors(Index[0]), lastblock);
2093 lastblock = sgi_get_num_sectors(Index[0]);
2096 printf(_("One Partition (#11) should cover the entire disk.\n"));
2098 printf("sysid=%d\tpartition=%d\n",
2099 sgi_get_sysid(Index[0]), Index[0]+1);
2101 for (i=1, start=0; i<sortcount; i++) {
2102 int cylsize = sgi_get_nsect() * sgi_get_ntrks();
2104 if ((sgi_get_start_sector(Index[i]) % cylsize) != 0) {
2105 if (debug) /* I do not understand how some disks fulfil it */
2107 printf(_("Partition %d does not start on cylinder boundary.\n"),
2110 if (sgi_get_num_sectors(Index[i]) % cylsize != 0) {
2111 if (debug) /* I do not understand how some disks fulfil it */
2113 printf(_("Partition %d does not end on cylinder boundary.\n"),
2116 /* We cannot handle several "entire disk" entries. */
2117 if (sgi_get_sysid(Index[i]) == ENTIRE_DISK) continue;
2118 if (start > sgi_get_start_sector(Index[i])) {
2120 printf(_("The Partition %d and %d overlap by %d sectors.\n"),
2121 Index[i-1]+1, Index[i]+1,
2122 start - sgi_get_start_sector(Index[i]));
2123 if (gap > 0) gap = -gap;
2124 if (gap == 0) gap = -1;
2126 if (start < sgi_get_start_sector(Index[i])) {
2128 printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"),
2129 sgi_get_start_sector(Index[i]) - start,
2130 start, sgi_get_start_sector(Index[i])-1);
2131 gap += sgi_get_start_sector(Index[i]) - start;
2132 add2freelist(start, sgi_get_start_sector(Index[i]));
2134 start = sgi_get_start_sector(Index[i])
2135 + sgi_get_num_sectors(Index[i]);
2138 printf("%2d:%12d\t%12d\t%12d\n", Index[i],
2139 sgi_get_start_sector(Index[i]),
2140 sgi_get_num_sectors(Index[i]),
2141 sgi_get_sysid(Index[i]));
2144 if (start < lastblock) {
2146 printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"),
2147 lastblock - start, start, lastblock-1);
2148 gap += lastblock - start;
2149 add2freelist(start, lastblock);
2152 * Done with arithmetics
2153 * Go for details now
2156 if (!sgi_get_num_sectors(sgi_get_bootpartition())) {
2157 printf(_("\nThe boot partition does not exist.\n"));
2159 if (!sgi_get_num_sectors(sgi_get_swappartition())) {
2160 printf(_("\nThe swap partition does not exist.\n"));
2162 if ((sgi_get_sysid(sgi_get_swappartition()) != SGI_SWAP)
2163 && (sgi_get_sysid(sgi_get_swappartition()) != LINUX_SWAP))
2164 printf(_("\nThe swap partition has no swap type.\n"));
2166 if (sgi_check_bootfile("/unix"))
2167 printf(_("\tYou have chosen an unusual boot file name.\n"));
2169 return (gap > 0) ? 1 : (gap == 0) ? 0 : -1;
2175 * returned value is:
2176 * = 0 : disk is properly filled to the rim
2177 * < 0 : there is an overlap
2178 * > 0 : there is still some vacant space
2180 return verify_sgi(0);
2184 sgi_change_sysid( int i, int sys )
2186 if( sgi_get_num_sectors(i) == 0 ) /* caught already before, ... */
2188 printf(_("Sorry You may change the Tag of non-empty partitions.\n"));
2191 if( ((sys != ENTIRE_DISK ) && (sys != SGI_VOLHDR))
2192 && (sgi_get_start_sector(i)<1) )
2195 _("It is highly recommended that the partition at offset 0\n"
2196 "is of type \"SGI volhdr\", the IRIX system will rely on it to\n"
2197 "retrieve from its directory standalone tools like sash and fx.\n"
2198 "Only the \"SGI volume\" entire disk section may violate this.\n"
2199 "Type YES if you are sure about tagging this partition differently.\n"));
2200 if (strcmp (line_ptr, _("YES\n")))
2203 sgilabel->partitions[i].id = SGI_SSWAP32(sys);
2206 /* returns partition index of first entry marked as entire disk */
2212 if(sgi_get_sysid(i) == SGI_VOLUME)
2218 sgi_set_partition(int i, unsigned int start, unsigned int length, int sys) {
2220 sgilabel->partitions[i].id = SGI_SSWAP32(sys);
2221 sgilabel->partitions[i].num_sectors = SGI_SSWAP32(length);
2222 sgilabel->partitions[i].start_sector = SGI_SSWAP32(start);
2224 if (sgi_gaps() < 0) /* rebuild freelist */
2225 printf(_("Do You know, You got a partition overlap on the disk?\n"));
2229 sgi_set_entire(void) {
2232 for(n=10; n < partitions; n++) {
2233 if(!sgi_get_num_sectors(n) ) {
2234 sgi_set_partition(n, 0, sgi_get_lastblock(), SGI_VOLUME);
2241 sgi_set_volhdr(void)
2244 for( n=8; n<partitions; n++ )
2246 if(!sgi_get_num_sectors( n ) )
2249 * 5 cylinders is an arbitrary value I like
2250 * IRIX 5.3 stored files in the volume header
2251 * (like sash, symmon, fx, ide) with ca. 3200
2254 if( heads * sectors * 5 < sgi_get_lastblock() )
2255 sgi_set_partition( n, 0, heads * sectors * 5, SGI_VOLHDR );
2262 sgi_delete_partition( int i )
2264 sgi_set_partition( i, 0, 0, 0 );
2268 sgi_add_partition( int n, int sys )
2271 unsigned int first=0, last=0;
2275 } else if ( n == 8 ) {
2278 if(sgi_get_num_sectors(n)) {
2279 printf(_("Partition %d is already defined. Delete "
2280 "it before re-adding it.\n"), n + 1);
2283 if( (sgi_entire() == -1) && (sys != SGI_VOLUME) ) {
2284 printf(_("Attempting to generate entire disk entry automatically.\n"));
2288 if( (sgi_gaps() == 0) && (sys != SGI_VOLUME) ) {
2289 printf(_("The entire disk is already covered with partitions.\n"));
2292 if(sgi_gaps() < 0) {
2293 printf(_("You got a partition overlap on the disk. Fix it first!\n"));
2296 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
2298 if(sys == SGI_VOLUME) {
2299 last = sgi_get_lastblock();
2300 first = read_int(0, 0, last-1, 0, mesg);
2302 printf(_("It is highly recommended that eleventh partition\n"
2303 "covers the entire disk and is of type `SGI volume'\n"));
2306 first = freelist[0].first;
2307 last = freelist[0].last;
2308 first = read_int(scround(first), scround(first), scround(last)-1,
2311 if (display_in_cyl_units)
2312 first *= units_per_sector;
2314 first = first; /* align to cylinder if you know how ... */
2316 last = isinfreelist(first);
2318 printf(_("You will get a partition overlap on the disk. "
2319 "Fix it first!\n"));
2323 snprintf(mesg, sizeof(mesg), _(" Last %s"), str_units(SINGULAR));
2324 last = read_int(scround(first), scround(last)-1, scround(last)-1,
2325 scround(first), mesg)+1;
2326 if (display_in_cyl_units)
2327 last *= units_per_sector;
2329 last = last; /* align to cylinder if You know how ... */
2330 if( (sys == SGI_VOLUME) && ( first != 0 || last != sgi_get_lastblock() ) )
2331 printf(_("It is highly recommended that eleventh partition\n"
2332 "covers the entire disk and is of type `SGI volume'\n"));
2333 sgi_set_partition( n, first, last-first, sys );
2336 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
2338 create_sgilabel(void)
2340 struct hd_geometry geometry;
2347 long longsectors; /* the number of sectors on the device */
2348 int res; /* the result from the ioctl */
2349 int sec_fac; /* the sector factor */
2351 sec_fac = sector_size / 512; /* determine the sector factor */
2354 _("Building a new SGI disklabel. Changes will remain in memory only,\n"
2355 "until you decide to write them. After that, of course, the previous\n"
2356 "content will be unrecoverably lost.\n\n"));
2358 sgi_other_endian = (BYTE_ORDER == LITTLE_ENDIAN);
2359 res = ioctl(fd, BLKGETSIZE, &longsectors);
2360 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
2361 heads = geometry.heads;
2362 sectors = geometry.sectors;
2364 /* the get device size ioctl was successful */
2365 cylinders = longsectors / (heads * sectors);
2366 cylinders /= sec_fac;
2368 /* otherwise print error and use truncated version */
2369 cylinders = geometry.cylinders;
2371 _("Warning: BLKGETSIZE ioctl failed on %s. "
2372 "Using geometry cylinder value of %d.\n"
2373 "This value may be truncated for devices"
2374 " > 33.8 GB.\n"), disk_device, cylinders);
2377 for (i = 0; i < 4; i++) {
2379 if(valid_part_table_flag(MBRbuffer)) {
2380 if(get_part_table(i)->sys_ind) {
2381 old[i].sysid = get_part_table(i)->sys_ind;
2382 old[i].start = get_start_sect(get_part_table(i));
2383 old[i].nsect = get_nr_sects(get_part_table(i));
2384 printf(_("Trying to keep parameters of partition %d.\n"), i);
2386 printf(_("ID=%02x\tSTART=%d\tLENGTH=%d\n"),
2387 old[i].sysid, old[i].start, old[i].nsect);
2392 memset(MBRbuffer, 0, sizeof(MBRbuffer));
2393 sgilabel->magic = SGI_SSWAP32(SGI_LABEL_MAGIC);
2394 sgilabel->boot_part = SGI_SSWAP16(0);
2395 sgilabel->swap_part = SGI_SSWAP16(1);
2397 /* sizeof(sgilabel->boot_file) = 16 > 6 */
2398 memset(sgilabel->boot_file, 0, 16);
2399 strcpy(sgilabel->boot_file, "/unix");
2401 sgilabel->devparam.skew = (0);
2402 sgilabel->devparam.gap1 = (0);
2403 sgilabel->devparam.gap2 = (0);
2404 sgilabel->devparam.sparecyl = (0);
2405 sgilabel->devparam.pcylcount = SGI_SSWAP16(geometry.cylinders);
2406 sgilabel->devparam.head_vol0 = SGI_SSWAP16(0);
2407 sgilabel->devparam.ntrks = SGI_SSWAP16(geometry.heads);
2408 /* tracks/cylinder (heads) */
2409 sgilabel->devparam.cmd_tag_queue_depth = (0);
2410 sgilabel->devparam.unused0 = (0);
2411 sgilabel->devparam.unused1 = SGI_SSWAP16(0);
2412 sgilabel->devparam.nsect = SGI_SSWAP16(geometry.sectors);
2414 sgilabel->devparam.bytes = SGI_SSWAP16(512);
2415 sgilabel->devparam.ilfact = SGI_SSWAP16(1);
2416 sgilabel->devparam.flags = SGI_SSWAP32(TRACK_FWD|
2417 IGNORE_ERRORS|RESEEK);
2418 sgilabel->devparam.datarate = SGI_SSWAP32(0);
2419 sgilabel->devparam.retries_on_error = SGI_SSWAP32(1);
2420 sgilabel->devparam.ms_per_word = SGI_SSWAP32(0);
2421 sgilabel->devparam.xylogics_gap1 = SGI_SSWAP16(0);
2422 sgilabel->devparam.xylogics_syncdelay = SGI_SSWAP16(0);
2423 sgilabel->devparam.xylogics_readdelay = SGI_SSWAP16(0);
2424 sgilabel->devparam.xylogics_gap2 = SGI_SSWAP16(0);
2425 sgilabel->devparam.xylogics_readgate = SGI_SSWAP16(0);
2426 sgilabel->devparam.xylogics_writecont = SGI_SSWAP16(0);
2427 memset( &(sgilabel->directory), 0, sizeof(struct volume_directory)*15 );
2428 memset( &(sgilabel->partitions), 0, sizeof(struct sgi_partition)*16 );
2434 for (i = 0; i < 4; i++) {
2436 sgi_set_partition(i, old[i].start, old[i].nsect, old[i].sysid);
2444 /* do nothing in the beginning */
2446 #endif /* CONFIG_FEATURE_FDISK_ADVANCED */
2448 /* _____________________________________________________________
2454 sgiinfo *info = calloc(1, sizeof(sgiinfo));
2456 info->magic=SGI_SSWAP32(SGI_INFO_MAGIC);
2457 info->b1=SGI_SSWAP32(-1);
2458 info->b2=SGI_SSWAP16(-1);
2459 info->b3=SGI_SSWAP16(1);
2460 /* You may want to replace this string !!!!!!! */
2461 strcpy( info->scsi_string, "IBM OEM 0662S12 3 30" );
2462 strcpy( info->serial, "0000" );
2463 info->check1816 = SGI_SSWAP16(18*256 +16 );
2464 strcpy( info->installer, "Sfx version 5.3, Oct 18, 1994" );
2467 #endif /* SGI_LABEL */
2470 #ifdef CONFIG_FEATURE_SUN_LABEL
2474 * I think this is mostly, or entirely, due to
2475 * Jakub Jelinek (jj@sunsite.mff.cuni.cz), July 1996
2477 * Merged with fdisk for other architectures, aeb, June 1998.
2479 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
2480 * Internationalization
2484 static int sun_other_endian;
2485 static int scsi_disk;
2489 #define IDE0_MAJOR 3
2492 #define IDE1_MAJOR 22
2495 static void guess_device_type(void) {
2496 struct stat bootstat;
2498 if (fstat (fd, &bootstat) < 0) {
2501 } else if (S_ISBLK(bootstat.st_mode)
2502 && (major(bootstat.st_rdev) == IDE0_MAJOR ||
2503 major(bootstat.st_rdev) == IDE1_MAJOR)) {
2506 } else if (S_ISBLK(bootstat.st_mode)
2507 && major(bootstat.st_rdev) == FLOPPY_MAJOR) {
2516 static const struct systypes sun_sys_types[] = {
2517 /* 0 */ {"\x00" "Empty" },
2518 /* 1 */ {"\x01" "Boot" },
2519 /* 2 */ {"\x02" "SunOS root" },
2520 /* SUNOS_SWAP */ {"\x03" "SunOS swap" },
2521 /* 4 */ {"\x04" "SunOS usr" },
2522 /* WHOLE_DISK */ {"\x05" "Whole disk" },
2523 /* 6 */ {"\x06" "SunOS stand" },
2524 /* 7 */ {"\x07" "SunOS var" },
2525 /* 8 */ {"\x08" "SunOS home" },
2526 /* LINUX_SWAP */ {"\x82" "Linux swap" },
2527 /* LINUX_NATIVE */ {"\x83" "Linux native" },
2528 /* 0x8e */ {"\x8e" "Linux LVM" },
2529 /* New (2.2.x) raid partition with autodetect using persistent superblock */
2530 /* 0xfd */ {"\xfd" "Linux raid autodetect" },
2536 set_sun_partition(int i, uint start, uint stop, int sysid) {
2537 sunlabel->infos[i].id = sysid;
2538 sunlabel->partitions[i].start_cylinder =
2539 SUN_SSWAP32(start / (heads * sectors));
2540 sunlabel->partitions[i].num_sectors =
2541 SUN_SSWAP32(stop - start);
2548 sunlabel->magic = 0;
2553 check_sun_label(void) {
2554 unsigned short *ush;
2557 if (sunlabel->magic != SUN_LABEL_MAGIC &&
2558 sunlabel->magic != SUN_LABEL_MAGIC_SWAPPED) {
2560 sun_other_endian = 0;
2563 sun_other_endian = (sunlabel->magic == SUN_LABEL_MAGIC_SWAPPED);
2564 ush = ((unsigned short *) (sunlabel + 1)) - 1;
2565 for (csum = 0; ush >= (unsigned short *)sunlabel;) csum ^= *ush--;
2567 fprintf(stderr,_("Detected sun disklabel with wrong checksum.\n"
2568 "Probably you'll have to set all the values,\n"
2569 "e.g. heads, sectors, cylinders and partitions\n"
2570 "or force a fresh label (s command in main menu)\n"));
2572 heads = SUN_SSWAP16(sunlabel->ntrks);
2573 cylinders = SUN_SSWAP16(sunlabel->ncyl);
2574 sectors = SUN_SSWAP16(sunlabel->nsect);
2582 static const struct sun_predefined_drives {
2585 unsigned short sparecyl;
2586 unsigned short ncyl;
2587 unsigned short nacyl;
2588 unsigned short pcylcount;
2589 unsigned short ntrks;
2590 unsigned short nsect;
2591 unsigned short rspeed;
2593 {"Quantum","ProDrive 80S",1,832,2,834,6,34,3662},
2594 {"Quantum","ProDrive 105S",1,974,2,1019,6,35,3662},
2595 {"CDC","Wren IV 94171-344",3,1545,2,1549,9,46,3600},
2596 {"IBM","DPES-31080",0,4901,2,4903,4,108,5400},
2597 {"IBM","DORS-32160",0,1015,2,1017,67,62,5400},
2598 {"IBM","DNES-318350",0,11199,2,11474,10,320,7200},
2599 {"SEAGATE","ST34371",0,3880,2,3882,16,135,7228},
2600 {"","SUN0104",1,974,2,1019,6,35,3662},
2601 {"","SUN0207",4,1254,2,1272,9,36,3600},
2602 {"","SUN0327",3,1545,2,1549,9,46,3600},
2603 {"","SUN0340",0,1538,2,1544,6,72,4200},
2604 {"","SUN0424",2,1151,2,2500,9,80,4400},
2605 {"","SUN0535",0,1866,2,2500,7,80,5400},
2606 {"","SUN0669",5,1614,2,1632,15,54,3600},
2607 {"","SUN1.0G",5,1703,2,1931,15,80,3597},
2608 {"","SUN1.05",0,2036,2,2038,14,72,5400},
2609 {"","SUN1.3G",6,1965,2,3500,17,80,5400},
2610 {"","SUN2.1G",0,2733,2,3500,19,80,5400},
2611 {"IOMEGA","Jaz",0,1019,2,1021,64,32,5394},
2614 static const struct sun_predefined_drives *
2615 sun_autoconfigure_scsi(void) {
2616 const struct sun_predefined_drives *p = NULL;
2618 #ifdef SCSI_IOCTL_GET_IDLUN
2628 if (!ioctl(fd, SCSI_IOCTL_GET_IDLUN, &id)) {
2630 "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n",
2632 ((id[0]>>24)&0xff)-/*PROC_SCSI_SCSI+PROC_SCSI_FILE*/33,
2634 /* This is very wrong (works only if you have one HBA),
2635 but I haven't found a way how to get hostno
2636 from the current kernel */
2642 pfd = fopen("/proc/scsi/scsi","r");
2644 while (fgets(buffer2,2048,pfd)) {
2645 if (!strcmp(buffer, buffer2)) {
2646 if (fgets(buffer2,2048,pfd)) {
2647 q = strstr(buffer2,"Vendor: ");
2652 *q++ = 0; /* truncate vendor name */
2653 q = strstr(q,"Model: ");
2658 q = strstr(q," Rev: ");
2661 for (i = 0; i < SIZE(sun_drives); i++) {
2662 if (*sun_drives[i].vendor && strcasecmp(sun_drives[i].vendor, vendor))
2664 if (!strstr(model, sun_drives[i].model))
2666 printf(_("Autoconfigure found a %s%s%s\n"),sun_drives[i].vendor,(*sun_drives[i].vendor) ? " " : "",sun_drives[i].model);
2684 static void create_sunlabel(void)
2686 struct hd_geometry geometry;
2690 const struct sun_predefined_drives *p = NULL;
2693 _("Building a new sun disklabel. Changes will remain in memory only,\n"
2694 "until you decide to write them. After that, of course, the previous\n"
2695 "content won't be recoverable.\n\n"));
2696 #if BYTE_ORDER == LITTLE_ENDIAN
2697 sun_other_endian = 1;
2699 sun_other_endian = 0;
2701 memset(MBRbuffer, 0, sizeof(MBRbuffer));
2702 sunlabel->magic = SUN_SSWAP16(SUN_LABEL_MAGIC);
2704 puts(_("Drive type\n"
2705 " ? auto configure\n"
2706 " 0 custom (with hardware detected defaults)"));
2707 for (i = 0; i < SIZE(sun_drives); i++) {
2708 printf(" %c %s%s%s\n",
2709 i + 'a', sun_drives[i].vendor,
2710 (*sun_drives[i].vendor) ? " " : "",
2711 sun_drives[i].model);
2714 c = read_char(_("Select type (? for auto, 0 for custom): "));
2715 if (c >= 'a' && c < 'a' + SIZE(sun_drives)) {
2716 p = sun_drives + c - 'a';
2718 } else if (c >= 'A' && c < 'A' + SIZE(sun_drives)) {
2719 p = sun_drives + c - 'A';
2721 } else if (c == '0') {
2723 } else if (c == '?' && scsi_disk) {
2724 p = sun_autoconfigure_scsi();
2726 printf(_("Autoconfigure failed.\n"));
2733 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
2734 heads = geometry.heads;
2735 sectors = geometry.sectors;
2736 cylinders = geometry.cylinders;
2743 sunlabel->nacyl = 0;
2744 sunlabel->pcylcount = SUN_SSWAP16(cylinders);
2745 sunlabel->rspeed = SUN_SSWAP16(300);
2746 sunlabel->ilfact = SUN_SSWAP16(1);
2747 sunlabel->sparecyl = 0;
2749 heads = read_int(1,heads,1024,0,_("Heads"));
2750 sectors = read_int(1,sectors,1024,0,_("Sectors/track"));
2752 cylinders = read_int(1,cylinders-2,65535,0,_("Cylinders"));
2754 cylinders = read_int(1,0,65535,0,_("Cylinders"));
2756 SUN_SSWAP16(read_int(0,2,65535,0,
2757 _("Alternate cylinders")));
2758 sunlabel->pcylcount =
2759 SUN_SSWAP16(read_int(0,cylinders+SUN_SSWAP16(sunlabel->nacyl),
2760 65535,0,_("Physical cylinders")));
2762 SUN_SSWAP16(read_int(1,5400,100000,0,
2763 _("Rotation speed (rpm)")));
2765 SUN_SSWAP16(read_int(1,1,32,0,_("Interleave factor")));
2766 sunlabel->sparecyl =
2767 SUN_SSWAP16(read_int(0,0,sectors,0,
2768 _("Extra sectors per cylinder")));
2771 sunlabel->sparecyl = SUN_SSWAP16(p->sparecyl);
2772 sunlabel->ncyl = SUN_SSWAP16(p->ncyl);
2773 sunlabel->nacyl = SUN_SSWAP16(p->nacyl);
2774 sunlabel->pcylcount = SUN_SSWAP16(p->pcylcount);
2775 sunlabel->ntrks = SUN_SSWAP16(p->ntrks);
2776 sunlabel->nsect = SUN_SSWAP16(p->nsect);
2777 sunlabel->rspeed = SUN_SSWAP16(p->rspeed);
2778 sunlabel->ilfact = SUN_SSWAP16(1);
2779 cylinders = p->ncyl;
2782 puts(_("You may change all the disk params from the x menu"));
2785 snprintf(sunlabel->info, sizeof(sunlabel->info),
2786 "%s%s%s cyl %d alt %d hd %d sec %d",
2787 p ? p->vendor : "", (p && *p->vendor) ? " " : "",
2789 : (floppy ? _("3,5\" floppy") : _("Linux custom")),
2790 cylinders, SUN_SSWAP16(sunlabel->nacyl), heads, sectors);
2792 sunlabel->ntrks = SUN_SSWAP16(heads);
2793 sunlabel->nsect = SUN_SSWAP16(sectors);
2794 sunlabel->ncyl = SUN_SSWAP16(cylinders);
2796 set_sun_partition(0, 0, cylinders * heads * sectors, LINUX_NATIVE);
2798 if (cylinders * heads * sectors >= 150 * 2048) {
2799 ndiv = cylinders - (50 * 2048 / (heads * sectors)); /* 50M swap */
2801 ndiv = cylinders * 2 / 3;
2802 set_sun_partition(0, 0, ndiv * heads * sectors, LINUX_NATIVE);
2803 set_sun_partition(1, ndiv * heads * sectors, cylinders * heads * sectors, LINUX_SWAP);
2804 sunlabel->infos[1].flags |= 0x01; /* Not mountable */
2806 set_sun_partition(2, 0, cylinders * heads * sectors, WHOLE_DISK);
2808 unsigned short *ush = (unsigned short *)sunlabel;
2809 unsigned short csum = 0;
2810 while(ush < (unsigned short *)(&sunlabel->csum))
2812 sunlabel->csum = csum;
2815 set_all_unchanged();
2817 get_boot(create_empty_sun);
2821 toggle_sunflags(int i, unsigned char mask) {
2822 if (sunlabel->infos[i].flags & mask)
2823 sunlabel->infos[i].flags &= ~mask;
2824 else sunlabel->infos[i].flags |= mask;
2829 fetch_sun(uint *starts, uint *lens, uint *start, uint *stop) {
2830 int i, continuous = 1;
2831 *start = 0; *stop = cylinders * heads * sectors;
2832 for (i = 0; i < partitions; i++) {
2833 if (sunlabel->partitions[i].num_sectors
2834 && sunlabel->infos[i].id
2835 && sunlabel->infos[i].id != WHOLE_DISK) {
2836 starts[i] = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
2837 lens[i] = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
2839 if (starts[i] == *start)
2841 else if (starts[i] + lens[i] >= *stop)
2845 /* There will be probably more gaps
2846 than one, so lets check afterwards */
2855 static uint *verify_sun_starts;
2858 verify_sun_cmp(int *a, int *b) {
2859 if (*a == -1) return 1;
2860 if (*b == -1) return -1;
2861 if (verify_sun_starts[*a] > verify_sun_starts[*b]) return 1;
2867 uint starts[8], lens[8], start, stop;
2868 int i,j,k,starto,endo;
2871 verify_sun_starts = starts;
2872 fetch_sun(starts,lens,&start,&stop);
2873 for (k = 0; k < 7; k++) {
2874 for (i = 0; i < 8; i++) {
2875 if (k && (lens[i] % (heads * sectors))) {
2876 printf(_("Partition %d doesn't end on cylinder boundary\n"), i+1);
2879 for (j = 0; j < i; j++)
2881 if (starts[j] == starts[i]+lens[i]) {
2882 starts[j] = starts[i]; lens[j] += lens[i];
2884 } else if (starts[i] == starts[j]+lens[j]){
2888 if (starts[i] < starts[j]+lens[j] &&
2889 starts[j] < starts[i]+lens[i]) {
2891 if (starts[j] > starto)
2893 endo = starts[i]+lens[i];
2894 if (starts[j]+lens[j] < endo)
2895 endo = starts[j]+lens[j];
2896 printf(_("Partition %d overlaps with others in "
2897 "sectors %d-%d\n"), i+1, starto, endo);
2904 for (i = 0; i < 8; i++) {
2910 qsort(array,SIZE(array),sizeof(array[0]),
2911 (int (*)(const void *,const void *)) verify_sun_cmp);
2912 if (array[0] == -1) {
2913 printf(_("No partitions defined\n"));
2916 stop = cylinders * heads * sectors;
2917 if (starts[array[0]])
2918 printf(_("Unused gap - sectors 0-%d\n"),starts[array[0]]);
2919 for (i = 0; i < 7 && array[i+1] != -1; i++) {
2920 printf(_("Unused gap - sectors %d-%d\n"),starts[array[i]]+lens[array[i]],starts[array[i+1]]);
2922 start = starts[array[i]]+lens[array[i]];
2924 printf(_("Unused gap - sectors %d-%d\n"),start,stop);
2928 add_sun_partition(int n, int sys) {
2929 uint start, stop, stop2;
2930 uint starts[8], lens[8];
2936 if (sunlabel->partitions[n].num_sectors && sunlabel->infos[n].id) {
2937 printf(_("Partition %d is already defined. Delete "
2938 "it before re-adding it.\n"), n + 1);
2942 fetch_sun(starts,lens,&start,&stop);
2943 if (stop <= start) {
2947 printf(_("Other partitions already cover the whole disk.\nDelete "
2948 "some/shrink them before retry.\n"));
2952 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
2955 first = read_int(0, 0, 0, 0, mesg);
2957 first = read_int(scround(start), scround(stop)+1,
2958 scround(stop), 0, mesg);
2959 if (display_in_cyl_units)
2960 first *= units_per_sector;
2962 /* Starting sector has to be properly aligned */
2963 first = (first + heads * sectors - 1) / (heads * sectors);
2964 if (n == 2 && first != 0)
2966 It is highly recommended that the third partition covers the whole disk\n\
2967 and is of type `Whole disk'\n");
2968 /* ewt asks to add: "don't start a partition at cyl 0"
2969 However, edmundo@rano.demon.co.uk writes:
2970 "In addition to having a Sun partition table, to be able to
2971 boot from the disc, the first partition, /dev/sdX1, must
2972 start at cylinder 0. This means that /dev/sdX1 contains
2973 the partition table and the boot block, as these are the
2974 first two sectors of the disc. Therefore you must be
2975 careful what you use /dev/sdX1 for. In particular, you must
2976 not use a partition starting at cylinder 0 for Linux swap,
2977 as that would overwrite the partition table and the boot
2978 block. You may, however, use such a partition for a UFS
2979 or EXT2 file system, as these file systems leave the first
2980 1024 bytes undisturbed. */
2981 /* On the other hand, one should not use partitions
2982 starting at block 0 in an md, or the label will
2984 for (i = 0; i < partitions; i++)
2985 if (lens[i] && starts[i] <= first
2986 && starts[i] + lens[i] > first)
2988 if (i < partitions && !whole_disk) {
2989 if (n == 2 && !first) {
2993 printf(_("Sector %d is already allocated\n"), first);
2997 stop = cylinders * heads * sectors;
2999 for (i = 0; i < partitions; i++) {
3000 if (starts[i] > first && starts[i] < stop)
3003 snprintf(mesg, sizeof(mesg),
3004 _("Last %s or +size or +sizeM or +sizeK"),
3005 str_units(SINGULAR));
3007 last = read_int(scround(stop2), scround(stop2), scround(stop2),
3009 else if (n == 2 && !first)
3010 last = read_int(scround(first), scround(stop2), scround(stop2),
3011 scround(first), mesg);
3013 last = read_int(scround(first), scround(stop), scround(stop),
3014 scround(first), mesg);
3015 if (display_in_cyl_units)
3016 last *= units_per_sector;
3017 if (n == 2 && !first) {
3018 if (last >= stop2) {
3021 } else if (last > stop) {
3023 _("You haven't covered the whole disk with the 3rd partition, but your value\n"
3024 "%d %s covers some other partition. Your entry has been changed\n"
3026 scround(last), str_units(SINGULAR),
3027 scround(stop), str_units(SINGULAR));
3030 } else if (!whole_disk && last > stop)
3033 if (whole_disk) sys = WHOLE_DISK;
3034 set_sun_partition(n, first, last, sys);
3038 sun_delete_partition(int i) {
3041 if (i == 2 && sunlabel->infos[i].id == WHOLE_DISK &&
3042 !sunlabel->partitions[i].start_cylinder &&
3043 (nsec = SUN_SSWAP32(sunlabel->partitions[i].num_sectors))
3044 == heads * sectors * cylinders)
3045 printf(_("If you want to maintain SunOS/Solaris compatibility, "
3046 "consider leaving this\n"
3047 "partition as Whole disk (5), starting at 0, with %u "
3048 "sectors\n"), nsec);
3049 sunlabel->infos[i].id = 0;
3050 sunlabel->partitions[i].num_sectors = 0;
3054 sun_change_sysid(int i, int sys) {
3055 if (sys == LINUX_SWAP && !sunlabel->partitions[i].start_cylinder) {
3057 _("It is highly recommended that the partition at offset 0\n"
3058 "is UFS, EXT2FS filesystem or SunOS swap. Putting Linux swap\n"
3059 "there may destroy your partition table and bootblock.\n"
3060 "Type YES if you're very sure you would like that partition\n"
3061 "tagged with 82 (Linux swap): "));
3062 if (strcmp (line_ptr, _("YES\n")))
3068 /* swaps are not mountable by default */
3069 sunlabel->infos[i].flags |= 0x01;
3072 /* assume other types are mountable;
3073 user can change it anyway */
3074 sunlabel->infos[i].flags &= ~0x01;
3077 sunlabel->infos[i].id = sys;
3081 sun_list_table(int xtra) {
3084 w = strlen(disk_device);
3087 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d rpm\n"
3088 "%d cylinders, %d alternate cylinders, %d physical cylinders\n"
3089 "%d extra sects/cyl, interleave %d:1\n"
3091 "Units = %s of %d * 512 bytes\n\n"),
3092 disk_device, heads, sectors, SUN_SSWAP16(sunlabel->rspeed),
3093 cylinders, SUN_SSWAP16(sunlabel->nacyl),
3094 SUN_SSWAP16(sunlabel->pcylcount),
3095 SUN_SSWAP16(sunlabel->sparecyl),
3096 SUN_SSWAP16(sunlabel->ilfact),
3098 str_units(PLURAL), units_per_sector);
3101 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d cylinders\n"
3102 "Units = %s of %d * 512 bytes\n\n"),
3103 disk_device, heads, sectors, cylinders,
3104 str_units(PLURAL), units_per_sector);
3106 printf(_("%*s Flag Start End Blocks Id System\n"),
3107 w + 1, _("Device"));
3108 for (i = 0 ; i < partitions; i++) {
3109 if (sunlabel->partitions[i].num_sectors) {
3110 uint32_t start = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
3111 uint32_t len = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
3113 "%s %c%c %9ld %9ld %9ld%c %2x %s\n",
3114 /* device */ partname(disk_device, i+1, w),
3115 /* flags */ (sunlabel->infos[i].flags & 0x01) ? 'u' : ' ',
3116 (sunlabel->infos[i].flags & 0x10) ? 'r' : ' ',
3117 /* start */ (long) scround(start),
3118 /* end */ (long) scround(start+len),
3119 /* odd flag on end */ (long) len / 2, len & 1 ? '+' : ' ',
3120 /* type id */ sunlabel->infos[i].id,
3121 /* type name */ partition_type(sunlabel->infos[i].id));
3126 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3129 sun_set_alt_cyl(void) {
3131 SUN_SSWAP16(read_int(0,SUN_SSWAP16(sunlabel->nacyl), 65535, 0,
3132 _("Number of alternate cylinders")));
3136 sun_set_ncyl(int cyl) {
3137 sunlabel->ncyl = SUN_SSWAP16(cyl);
3141 sun_set_xcyl(void) {
3142 sunlabel->sparecyl =
3143 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->sparecyl), sectors, 0,
3144 _("Extra sectors per cylinder")));
3148 sun_set_ilfact(void) {
3150 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->ilfact), 32, 0,
3151 _("Interleave factor")));
3155 sun_set_rspeed(void) {
3157 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->rspeed), 100000, 0,
3158 _("Rotation speed (rpm)")));
3162 sun_set_pcylcount(void) {
3163 sunlabel->pcylcount =
3164 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->pcylcount), 65535, 0,
3165 _("Number of physical cylinders")));
3167 #endif /* CONFIG_FEATURE_FDISK_ADVANCED */
3170 sun_write_table(void) {
3171 unsigned short *ush = (unsigned short *)sunlabel;
3172 unsigned short csum = 0;
3174 while(ush < (unsigned short *)(&sunlabel->csum))
3176 sunlabel->csum = csum;
3177 if (lseek(fd, 0, SEEK_SET) < 0)
3178 fdisk_fatal(unable_to_seek);
3179 if (write(fd, sunlabel, SECTOR_SIZE) != SECTOR_SIZE)
3180 fdisk_fatal(unable_to_write);
3182 #endif /* SUN_LABEL */
3184 /* DOS partition types */
3186 static const struct systypes i386_sys_types[] = {
3189 {"\x04" "FAT16 <32M"},
3190 {"\x05" "Extended"}, /* DOS 3.3+ extended partition */
3191 {"\x06" "FAT16"}, /* DOS 16-bit >=32M */
3192 {"\x07" "HPFS/NTFS"}, /* OS/2 IFS, eg, HPFS or NTFS or QNX */
3193 {"\x0a" "OS/2 Boot Manager"},/* OS/2 Boot Manager */
3194 {"\x0b" "Win95 FAT32"},
3195 {"\x0c" "Win95 FAT32 (LBA)"},/* LBA really is `Extended Int 13h' */
3196 {"\x0e" "Win95 FAT16 (LBA)"},
3197 {"\x0f" "Win95 Ext'd (LBA)"},
3198 {"\x11" "Hidden FAT12"},
3199 {"\x12" "Compaq diagnostics"},
3200 {"\x14" "Hidden FAT16 <32M"},
3201 {"\x16" "Hidden FAT16"},
3202 {"\x17" "Hidden HPFS/NTFS"},
3203 {"\x1b" "Hidden Win95 FAT32"},
3204 {"\x1c" "Hidden Win95 FAT32 (LBA)"},
3205 {"\x1e" "Hidden Win95 FAT16 (LBA)"},
3206 {"\x3c" "PartitionMagic recovery"},
3207 {"\x41" "PPC PReP Boot"},
3209 {"\x63" "GNU HURD or SysV"}, /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */
3210 {"\x80" "Old Minix"}, /* Minix 1.4a and earlier */
3211 {"\x81" "Minix / old Linux"},/* Minix 1.4b and later */
3212 {"\x82" "Linux swap"}, /* also Solaris */
3214 {"\x84" "OS/2 hidden C: drive"},
3215 {"\x85" "Linux extended"},
3216 {"\x86" "NTFS volume set"},
3217 {"\x87" "NTFS volume set"},
3218 {"\x8e" "Linux LVM"},
3219 {"\x9f" "BSD/OS"}, /* BSDI */
3220 {"\xa0" "IBM Thinkpad hibernation"},
3221 {"\xa5" "FreeBSD"}, /* various BSD flavours */
3223 {"\xa8" "Darwin UFS"},
3225 {"\xab" "Darwin boot"},
3227 {"\xb8" "BSDI swap"},
3228 {"\xbe" "Solaris boot"},
3230 {"\xee" "EFI GPT"}, /* Intel EFI GUID Partition Table */
3231 {"\xef" "EFI (FAT-12/16/32)"},/* Intel EFI System Partition */
3232 {"\xf0" "Linux/PA-RISC boot"},/* Linux/PA-RISC boot loader */
3233 {"\xf2" "DOS secondary"}, /* DOS 3.3+ secondary */
3234 {"\xfd" "Linux raid autodetect"},/* New (2.2.x) raid partition with
3235 autodetect using persistent
3237 #ifdef CONFIG_WEIRD_PARTITION_TYPES
3238 {"\x02" "XENIX root"},
3239 {"\x03" "XENIX usr"},
3240 {"\x08" "AIX"}, /* AIX boot (AIX -- PS/2 port) or SplitDrive */
3241 {"\x09" "AIX bootable"}, /* AIX data or Coherent */
3243 {"\x18" "AST SmartSleep"},
3246 {"\x40" "Venix 80286"},
3248 {"\x4e" "QNX4.x 2nd part"},
3249 {"\x4f" "QNX4.x 3rd part"},
3250 {"\x50" "OnTrack DM"},
3251 {"\x51" "OnTrack DM6 Aux1"}, /* (or Novell) */
3252 {"\x52" "CP/M"}, /* CP/M or Microport SysV/AT */
3253 {"\x53" "OnTrack DM6 Aux3"},
3254 {"\x54" "OnTrackDM6"},
3255 {"\x55" "EZ-Drive"},
3256 {"\x56" "Golden Bow"},
3257 {"\x5c" "Priam Edisk"},
3258 {"\x61" "SpeedStor"},
3259 {"\x64" "Novell Netware 286"},
3260 {"\x65" "Novell Netware 386"},
3261 {"\x70" "DiskSecure Multi-Boot"},
3264 {"\x94" "Amoeba BBT"}, /* (bad block table) */
3265 {"\xa7" "NeXTSTEP"},
3266 {"\xbb" "Boot Wizard hidden"},
3267 {"\xc1" "DRDOS/sec (FAT-12)"},
3268 {"\xc4" "DRDOS/sec (FAT-16 < 32M)"},
3269 {"\xc6" "DRDOS/sec (FAT-16)"},
3271 {"\xda" "Non-FS data"},
3272 {"\xdb" "CP/M / CTOS / ..."},/* CP/M or Concurrent CP/M or
3273 Concurrent DOS or CTOS */
3274 {"\xde" "Dell Utility"}, /* Dell PowerEdge Server utilities */
3275 {"\xdf" "BootIt"}, /* BootIt EMBRM */
3276 {"\xe1" "DOS access"}, /* DOS access or SpeedStor 12-bit FAT
3277 extended partition */
3278 {"\xe3" "DOS R/O"}, /* DOS R/O or SpeedStor */
3279 {"\xe4" "SpeedStor"}, /* SpeedStor 16-bit FAT extended
3280 partition < 1024 cyl. */
3281 {"\xf1" "SpeedStor"},
3282 {"\xf4" "SpeedStor"}, /* SpeedStor large partition */
3283 {"\xfe" "LANstep"}, /* SpeedStor >1024 cyl. or LANstep */
3284 {"\xff" "BBT"}, /* Xenix Bad Block Table */
3291 /* A valid partition table sector ends in 0x55 0xaa */
3293 part_table_flag(const char *b) {
3294 return ((uint) b[510]) + (((uint) b[511]) << 8);
3298 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3300 write_part_table_flag(char *b) {
3305 /* start_sect and nr_sects are stored little endian on all machines */
3306 /* moreover, they are not aligned correctly */
3308 store4_little_endian(unsigned char *cp, unsigned int val) {
3309 cp[0] = (val & 0xff);
3310 cp[1] = ((val >> 8) & 0xff);
3311 cp[2] = ((val >> 16) & 0xff);
3312 cp[3] = ((val >> 24) & 0xff);
3314 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3317 read4_little_endian(const unsigned char *cp) {
3318 return (uint)(cp[0]) + ((uint)(cp[1]) << 8)
3319 + ((uint)(cp[2]) << 16) + ((uint)(cp[3]) << 24);
3322 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3324 set_start_sect(struct partition *p, unsigned int start_sect) {
3325 store4_little_endian(p->start4, start_sect);
3330 get_start_sect(const struct partition *p) {
3331 return read4_little_endian(p->start4);
3334 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3336 set_nr_sects(struct partition *p, unsigned int nr_sects) {
3337 store4_little_endian(p->size4, nr_sects);
3342 get_nr_sects(const struct partition *p) {
3343 return read4_little_endian(p->size4);
3346 /* normally O_RDWR, -l option gives O_RDONLY */
3347 static int type_open = O_RDWR;
3350 static int ext_index, /* the prime extended partition */
3351 listing, /* no aborts for fdisk -l */
3352 dos_compatible_flag = ~0;
3353 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3354 static int dos_changed;
3355 static int nowarn; /* no warnings for fdisk -l/-s */
3360 static uint user_cylinders, user_heads, user_sectors;
3361 static uint pt_heads, pt_sectors;
3362 static uint kern_heads, kern_sectors;
3364 static uint extended_offset; /* offset of link pointers */
3366 static unsigned long long total_number_of_sectors;
3369 static jmp_buf listingbuf;
3371 static void fdisk_fatal(enum failure why) {
3372 const char *message;
3376 longjmp(listingbuf, 1);
3380 case unable_to_open:
3381 message = "Unable to open %s\n";
3383 case unable_to_read:
3384 message = "Unable to read %s\n";
3386 case unable_to_seek:
3387 message = "Unable to seek on %s\n";
3389 case unable_to_write:
3390 message = "Unable to write %s\n";
3393 message = "BLKGETSIZE ioctl failed on %s\n";
3396 message = "Fatal error\n";
3399 fputc('\n', stderr);
3400 fprintf(stderr, message, disk_device);
3405 seek_sector(uint secno) {
3406 off_t offset = secno * sector_size;
3407 if (lseek(fd, offset, SEEK_SET) == (off_t) -1)
3408 fdisk_fatal(unable_to_seek);
3411 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3413 write_sector(uint secno, char *buf) {
3415 if (write(fd, buf, sector_size) != sector_size)
3416 fdisk_fatal(unable_to_write);
3420 /* Allocate a buffer and read a partition table sector */
3422 read_pte(struct pte *pe, uint offset) {
3424 pe->offset = offset;
3425 pe->sectorbuffer = (char *) xmalloc(sector_size);
3426 seek_sector(offset);
3427 if (read(fd, pe->sectorbuffer, sector_size) != sector_size)
3428 fdisk_fatal(unable_to_read);
3429 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3432 pe->part_table = pe->ext_pointer = NULL;
3436 get_partition_start(const struct pte *pe) {
3437 return pe->offset + get_start_sect(pe->part_table);
3440 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3442 * Avoid warning about DOS partitions when no DOS partition was changed.
3443 * Here a heuristic "is probably dos partition".
3444 * We might also do the opposite and warn in all cases except
3445 * for "is probably nondos partition".
3448 is_dos_partition(int t) {
3449 return (t == 1 || t == 4 || t == 6 ||
3450 t == 0x0b || t == 0x0c || t == 0x0e ||
3451 t == 0x11 || t == 0x12 || t == 0x14 || t == 0x16 ||
3452 t == 0x1b || t == 0x1c || t == 0x1e || t == 0x24 ||
3453 t == 0xc1 || t == 0xc4 || t == 0xc6);
3458 #ifdef CONFIG_FEATURE_SUN_LABEL
3460 puts(_("Command action"));
3461 puts(_("\ta\ttoggle a read only flag")); /* sun */
3462 puts(_("\tb\tedit bsd disklabel"));
3463 puts(_("\tc\ttoggle the mountable flag")); /* sun */
3464 puts(_("\td\tdelete a partition"));
3465 puts(_("\tl\tlist known partition types"));
3466 puts(_("\tm\tprint this menu"));
3467 puts(_("\tn\tadd a new partition"));
3468 puts(_("\to\tcreate a new empty DOS partition table"));
3469 puts(_("\tp\tprint the partition table"));
3470 puts(_("\tq\tquit without saving changes"));
3471 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3472 puts(_("\tt\tchange a partition's system id"));
3473 puts(_("\tu\tchange display/entry units"));
3474 puts(_("\tv\tverify the partition table"));
3475 puts(_("\tw\twrite table to disk and exit"));
3476 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3477 puts(_("\tx\textra functionality (experts only)"));
3481 #ifdef CONFIG_FEATURE_SGI_LABEL
3483 puts(_("Command action"));
3484 puts(_("\ta\tselect bootable partition")); /* sgi flavour */
3485 puts(_("\tb\tedit bootfile entry")); /* sgi */
3486 puts(_("\tc\tselect sgi swap partition")); /* sgi flavour */
3487 puts(_("\td\tdelete a partition"));
3488 puts(_("\tl\tlist known partition types"));
3489 puts(_("\tm\tprint this menu"));
3490 puts(_("\tn\tadd a new partition"));
3491 puts(_("\to\tcreate a new empty DOS partition table"));
3492 puts(_("\tp\tprint the partition table"));
3493 puts(_("\tq\tquit without saving changes"));
3494 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3495 puts(_("\tt\tchange a partition's system id"));
3496 puts(_("\tu\tchange display/entry units"));
3497 puts(_("\tv\tverify the partition table"));
3498 puts(_("\tw\twrite table to disk and exit"));
3501 #ifdef CONFIG_FEATURE_AIX_LABEL
3503 puts(_("Command action"));
3504 puts(_("\tm\tprint this menu"));
3505 puts(_("\to\tcreate a new empty DOS partition table"));
3506 puts(_("\tq\tquit without saving changes"));
3507 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3511 puts(_("Command action"));
3512 puts(_("\ta\ttoggle a bootable flag"));
3513 puts(_("\tb\tedit bsd disklabel"));
3514 puts(_("\tc\ttoggle the dos compatibility flag"));
3515 puts(_("\td\tdelete a partition"));
3516 puts(_("\tl\tlist known partition types"));
3517 puts(_("\tm\tprint this menu"));
3518 puts(_("\tn\tadd a new partition"));
3519 puts(_("\to\tcreate a new empty DOS partition table"));
3520 puts(_("\tp\tprint the partition table"));
3521 puts(_("\tq\tquit without saving changes"));
3522 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3523 puts(_("\tt\tchange a partition's system id"));
3524 puts(_("\tu\tchange display/entry units"));
3525 puts(_("\tv\tverify the partition table"));
3526 puts(_("\tw\twrite table to disk and exit"));
3527 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3528 puts(_("\tx\textra functionality (experts only)"));
3532 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3535 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3538 #ifdef CONFIG_FEATURE_SUN_LABEL
3540 puts(_("Command action"));
3541 puts(_("\ta\tchange number of alternate cylinders")); /*sun*/
3542 puts(_("\tc\tchange number of cylinders"));
3543 puts(_("\td\tprint the raw data in the partition table"));
3544 puts(_("\te\tchange number of extra sectors per cylinder"));/*sun*/
3545 puts(_("\th\tchange number of heads"));
3546 puts(_("\ti\tchange interleave factor")); /*sun*/
3547 puts(_("\to\tchange rotation speed (rpm)")); /*sun*/
3548 puts(_("\tm\tprint this menu"));
3549 puts(_("\tp\tprint the partition table"));
3550 puts(_("\tq\tquit without saving changes"));
3551 puts(_("\tr\treturn to main menu"));
3552 puts(_("\ts\tchange number of sectors/track"));
3553 puts(_("\tv\tverify the partition table"));
3554 puts(_("\tw\twrite table to disk and exit"));
3555 puts(_("\ty\tchange number of physical cylinders")); /*sun*/
3558 #ifdef CONFIG_FEATURE_SGI_LABEL
3560 puts(_("Command action"));
3561 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3562 puts(_("\tc\tchange number of cylinders"));
3563 puts(_("\td\tprint the raw data in the partition table"));
3564 puts(_("\te\tlist extended partitions")); /* !sun */
3565 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3566 puts(_("\th\tchange number of heads"));
3567 puts(_("\tm\tprint this menu"));
3568 puts(_("\tp\tprint the partition table"));
3569 puts(_("\tq\tquit without saving changes"));
3570 puts(_("\tr\treturn to main menu"));
3571 puts(_("\ts\tchange number of sectors/track"));
3572 puts(_("\tv\tverify the partition table"));
3573 puts(_("\tw\twrite table to disk and exit"));
3576 #ifdef CONFIG_FEATURE_AIX_LABEL
3578 puts(_("Command action"));
3579 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3580 puts(_("\tc\tchange number of cylinders"));
3581 puts(_("\td\tprint the raw data in the partition table"));
3582 puts(_("\te\tlist extended partitions")); /* !sun */
3583 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3584 puts(_("\th\tchange number of heads"));
3585 puts(_("\tm\tprint this menu"));
3586 puts(_("\tp\tprint the partition table"));
3587 puts(_("\tq\tquit without saving changes"));
3588 puts(_("\tr\treturn to main menu"));
3589 puts(_("\ts\tchange number of sectors/track"));
3590 puts(_("\tv\tverify the partition table"));
3591 puts(_("\tw\twrite table to disk and exit"));
3595 puts(_("Command action"));
3596 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3597 puts(_("\tc\tchange number of cylinders"));
3598 puts(_("\td\tprint the raw data in the partition table"));
3599 puts(_("\te\tlist extended partitions")); /* !sun */
3600 puts(_("\tf\tfix partition order")); /* !sun, !aix, !sgi */
3601 #ifdef CONFIG_FEATURE_SGI_LABEL
3602 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3604 puts(_("\th\tchange number of heads"));
3605 puts(_("\tm\tprint this menu"));
3606 puts(_("\tp\tprint the partition table"));
3607 puts(_("\tq\tquit without saving changes"));
3608 puts(_("\tr\treturn to main menu"));
3609 puts(_("\ts\tchange number of sectors/track"));
3610 puts(_("\tv\tverify the partition table"));
3611 puts(_("\tw\twrite table to disk and exit"));
3614 #endif /* ADVANCED mode */
3616 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3617 static const struct systypes *
3618 get_sys_types(void) {
3620 #ifdef CONFIG_FEATURE_SUN_LABEL
3621 sun_label ? sun_sys_types :
3623 #ifdef CONFIG_FEATURE_SGI_LABEL
3624 sgi_label ? sgi_sys_types :
3629 #define get_sys_types() i386_sys_types
3630 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3632 static const char *partition_type(unsigned char type)
3635 const struct systypes *types = get_sys_types();
3637 for (i=0; types[i].name; i++)
3638 if (types[i].name[0] == type)
3639 return types[i].name + 1;
3641 return _("Unknown");
3645 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3649 #ifdef CONFIG_FEATURE_SUN_LABEL
3650 sun_label ? sunlabel->infos[i].id :
3652 #ifdef CONFIG_FEATURE_SGI_LABEL
3653 sgi_label ? sgi_get_sysid(i) :
3655 ptes[i].part_table->sys_ind);
3658 void list_types(const struct systypes *sys)
3660 uint last[4], done = 0, next = 0, size;
3663 for (i = 0; sys[i].name; i++);
3666 for (i = 3; i >= 0; i--)
3667 last[3 - i] = done += (size + i - done) / (i + 1);
3671 printf("%c%2x %-15.15s", i ? ' ' : '\n',
3672 sys[next].name[0], partition_type(sys[next].name[0]));
3673 next = last[i++] + done;
3674 if (i > 3 || next >= last[i]) {
3678 } while (done < last[0]);
3681 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3684 is_cleared_partition(const struct partition *p) {
3685 return !(!p || p->boot_ind || p->head || p->sector || p->cyl ||
3686 p->sys_ind || p->end_head || p->end_sector || p->end_cyl ||
3687 get_start_sect(p) || get_nr_sects(p));
3691 clear_partition(struct partition *p) {
3694 memset(p, 0, sizeof(struct partition));
3697 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3699 set_partition(int i, int doext, uint start, uint stop, int sysid) {
3700 struct partition *p;
3704 p = ptes[i].ext_pointer;
3705 offset = extended_offset;
3707 p = ptes[i].part_table;
3708 offset = ptes[i].offset;
3712 set_start_sect(p, start - offset);
3713 set_nr_sects(p, stop - start + 1);
3714 if (dos_compatible_flag && (start/(sectors*heads) > 1023))
3715 start = heads*sectors*1024 - 1;
3716 set_hsc(p->head, p->sector, p->cyl, start);
3717 if (dos_compatible_flag && (stop/(sectors*heads) > 1023))
3718 stop = heads*sectors*1024 - 1;
3719 set_hsc(p->end_head, p->end_sector, p->end_cyl, stop);
3720 ptes[i].changed = 1;
3725 test_c(const char **m, const char *mesg) {
3728 fprintf(stderr, _("You must set"));
3730 fprintf(stderr, " %s", *m);
3738 warn_geometry(void) {
3739 const char *m = NULL;
3743 prev = test_c(&m, _("heads"));
3745 prev = test_c(&m, _("sectors"));
3747 prev = test_c(&m, _("cylinders"));
3751 fprintf(stderr, "%s%s.\n"
3752 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3753 "You can do this from the extra functions menu.\n"
3755 , prev ? _(" and ") : " ", m);
3760 static void update_units(void)
3762 int cyl_units = heads * sectors;
3764 if (display_in_cyl_units && cyl_units)
3765 units_per_sector = cyl_units;
3767 units_per_sector = 1; /* in sectors */
3770 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3772 warn_cylinders(void) {
3773 if (dos_label && cylinders > 1024 && !nowarn)
3774 fprintf(stderr, _("\n"
3775 "The number of cylinders for this disk is set to %d.\n"
3776 "There is nothing wrong with that, but this is larger than 1024,\n"
3777 "and could in certain setups cause problems with:\n"
3778 "1) software that runs at boot time (e.g., old versions of LILO)\n"
3779 "2) booting and partitioning software from other OSs\n"
3780 " (e.g., DOS FDISK, OS/2 FDISK)\n"),
3786 read_extended(int ext) {
3789 struct partition *p, *q;
3793 pex->ext_pointer = pex->part_table;
3795 p = pex->part_table;
3796 if (!get_start_sect(p)) {
3798 _("Bad offset in primary extended partition\n"));
3802 while (IS_EXTENDED (p->sys_ind)) {
3803 struct pte *pe = &ptes[partitions];
3805 if (partitions >= MAXIMUM_PARTS) {
3806 /* This is not a Linux restriction, but
3807 this program uses arrays of size MAXIMUM_PARTS.
3808 Do not try to `improve' this test. */
3809 struct pte *pre = &ptes[partitions-1];
3810 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3812 _("Warning: deleting partitions after %d\n"),
3816 clear_partition(pre->ext_pointer);
3820 read_pte(pe, extended_offset + get_start_sect(p));
3822 if (!extended_offset)
3823 extended_offset = get_start_sect(p);
3825 q = p = pt_offset(pe->sectorbuffer, 0);
3826 for (i = 0; i < 4; i++, p++) if (get_nr_sects(p)) {
3827 if (IS_EXTENDED (p->sys_ind)) {
3828 if (pe->ext_pointer)
3830 _("Warning: extra link "
3831 "pointer in partition table"
3832 " %d\n"), partitions + 1);
3834 pe->ext_pointer = p;
3835 } else if (p->sys_ind) {
3838 _("Warning: ignoring extra "
3839 "data in partition table"
3840 " %d\n"), partitions + 1);
3846 /* very strange code here... */
3847 if (!pe->part_table) {
3848 if (q != pe->ext_pointer)
3851 pe->part_table = q + 1;
3853 if (!pe->ext_pointer) {
3854 if (q != pe->part_table)
3855 pe->ext_pointer = q;
3857 pe->ext_pointer = q + 1;
3860 p = pe->ext_pointer;
3864 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3865 /* remove empty links */
3867 for (i = 4; i < partitions; i++) {
3868 struct pte *pe = &ptes[i];
3870 if (!get_nr_sects(pe->part_table) &&
3871 (partitions > 5 || ptes[4].part_table->sys_ind)) {
3872 printf("omitting empty partition (%d)\n", i+1);
3873 delete_partition(i);
3874 goto remove; /* numbering changed */
3880 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3882 create_doslabel(void) {
3886 _("Building a new DOS disklabel. Changes will remain in memory only,\n"
3887 "until you decide to write them. After that, of course, the previous\n"
3888 "content won't be recoverable.\n\n"));
3889 #ifdef CONFIG_FEATURE_SUN_LABEL
3890 sun_nolabel(); /* otherwise always recognised as sun */
3892 #ifdef CONFIG_FEATURE_SGI_LABEL
3893 sgi_nolabel(); /* otherwise always recognised as sgi */
3895 #ifdef CONFIG_FEATURE_AIX_LABEL
3898 #ifdef CONFIG_FEATURE_OSF_LABEL
3900 possibly_osf_label = 0;
3904 for (i = 510-64; i < 510; i++)
3906 write_part_table_flag(MBRbuffer);
3907 extended_offset = 0;
3908 set_all_unchanged();
3910 get_boot(create_empty_dos);
3912 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3915 get_sectorsize(void) {
3916 if (!user_set_sector_size &&
3917 get_kernel_revision() >= MAKE_VERSION(2,3,3)) {
3919 if (ioctl(fd, BLKSSZGET, &arg) == 0)
3921 if (sector_size != DEFAULT_SECTOR_SIZE)
3922 printf(_("Note: sector size is %d (not %d)\n"),
3923 sector_size, DEFAULT_SECTOR_SIZE);
3928 get_kernel_geometry(void) {
3929 struct hd_geometry geometry;
3931 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
3932 kern_heads = geometry.heads;
3933 kern_sectors = geometry.sectors;
3934 /* never use geometry.cylinders - it is truncated */
3939 get_partition_table_geometry(void) {
3940 const unsigned char *bufp = MBRbuffer;
3941 struct partition *p;
3942 int i, h, s, hh, ss;
3946 if (!(valid_part_table_flag(bufp)))
3950 for (i=0; i<4; i++) {
3951 p = pt_offset(bufp, i);
3952 if (p->sys_ind != 0) {
3953 h = p->end_head + 1;
3954 s = (p->end_sector & 077);
3959 } else if (hh != h || ss != s)
3964 if (!first && !bad) {
3971 get_geometry(void) {
3973 unsigned long long bytes; /* really u64 */
3976 sec_fac = sector_size / 512;
3977 #ifdef CONFIG_FEATURE_SUN_LABEL
3978 guess_device_type();
3980 heads = cylinders = sectors = 0;
3981 kern_heads = kern_sectors = 0;
3982 pt_heads = pt_sectors = 0;
3984 get_kernel_geometry();
3985 get_partition_table_geometry();
3987 heads = user_heads ? user_heads :
3988 pt_heads ? pt_heads :
3989 kern_heads ? kern_heads : 255;
3990 sectors = user_sectors ? user_sectors :
3991 pt_sectors ? pt_sectors :
3992 kern_sectors ? kern_sectors : 63;
3993 if (ioctl(fd, BLKGETSIZE64, &bytes) == 0) {
3996 unsigned long longsectors;
3998 if (ioctl(fd, BLKGETSIZE, &longsectors))
4000 bytes = ((unsigned long long) longsectors) << 9;
4003 total_number_of_sectors = (bytes >> 9);
4006 if (dos_compatible_flag)
4007 sector_offset = sectors;
4009 cylinders = total_number_of_sectors / (heads * sectors * sec_fac);
4011 cylinders = user_cylinders;
4015 * Read MBR. Returns:
4016 * -1: no 0xaa55 flag present (possibly entire disk BSD)
4017 * 0: found or created label
4021 get_boot(enum action what) {
4026 for (i = 0; i < 4; i++) {
4027 struct pte *pe = &ptes[i];
4029 pe->part_table = pt_offset(MBRbuffer, i);
4030 pe->ext_pointer = NULL;
4032 pe->sectorbuffer = MBRbuffer;
4033 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4034 pe->changed = (what == create_empty_dos);
4038 #ifdef CONFIG_FEATURE_SUN_LABEL
4039 if (what == create_empty_sun && check_sun_label())
4043 memset(MBRbuffer, 0, 512);
4045 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4046 if (what == create_empty_dos)
4047 goto got_dos_table; /* skip reading disk */
4049 if ((fd = open(disk_device, type_open)) < 0) {
4050 if ((fd = open(disk_device, O_RDONLY)) < 0) {
4051 if (what == try_only)
4053 fdisk_fatal(unable_to_open);
4055 printf(_("You will not be able to write "
4056 "the partition table.\n"));
4059 if (512 != read(fd, MBRbuffer, 512)) {
4060 if (what == try_only)
4062 fdisk_fatal(unable_to_read);
4065 if ((fd = open(disk_device, O_RDONLY)) < 0)
4067 if (512 != read(fd, MBRbuffer, 512))
4075 #ifdef CONFIG_FEATURE_SUN_LABEL
4076 if (check_sun_label())
4080 #ifdef CONFIG_FEATURE_SGI_LABEL
4081 if (check_sgi_label())
4085 #ifdef CONFIG_FEATURE_AIX_LABEL
4086 if (check_aix_label())
4090 #ifdef CONFIG_FEATURE_OSF_LABEL
4091 if (check_osf_label()) {
4092 possibly_osf_label = 1;
4093 if (!valid_part_table_flag(MBRbuffer)) {
4097 printf(_("This disk has both DOS and BSD magic.\n"
4098 "Give the 'b' command to go to BSD mode.\n"));
4102 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4106 if (!valid_part_table_flag(MBRbuffer)) {
4107 #ifndef CONFIG_FEATURE_FDISK_WRITABLE
4113 _("Device contains neither a valid DOS "
4114 "partition table, nor Sun, SGI or OSF "
4117 #ifdef CONFIG_FEATURE_SUN_LABEL
4126 case create_empty_dos:
4127 #ifdef CONFIG_FEATURE_SUN_LABEL
4128 case create_empty_sun:
4132 fprintf(stderr, _("Internal error\n"));
4135 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
4138 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4143 for (i = 0; i < 4; i++) {
4144 struct pte *pe = &ptes[i];
4146 if (IS_EXTENDED (pe->part_table->sys_ind)) {
4147 if (partitions != 4)
4148 fprintf(stderr, _("Ignoring extra extended "
4149 "partition %d\n"), i + 1);
4155 for (i = 3; i < partitions; i++) {
4156 struct pte *pe = &ptes[i];
4158 if (!valid_part_table_flag(pe->sectorbuffer)) {
4160 _("Warning: invalid flag 0x%04x of partition "
4161 "table %d will be corrected by w(rite)\n"),
4162 part_table_flag(pe->sectorbuffer), i + 1);
4163 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4172 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4174 * Print the message MESG, then read an integer between LOW and HIGH (inclusive).
4175 * If the user hits Enter, DFLT is returned.
4176 * Answers like +10 are interpreted as offsets from BASE.
4178 * There is no default if DFLT is not between LOW and HIGH.
4181 read_int(uint low, uint dflt, uint high, uint base, char *mesg)
4185 static char *ms = NULL;
4186 static int mslen = 0;
4188 if (!ms || strlen(mesg)+100 > mslen) {
4189 mslen = strlen(mesg)+200;
4190 ms = xrealloc(ms,mslen);
4193 if (dflt < low || dflt > high)
4197 snprintf(ms, mslen, _("%s (%u-%u, default %u): "),
4198 mesg, low, high, dflt);
4200 snprintf(ms, mslen, "%s (%u-%u): ",
4204 int use_default = default_ok;
4206 /* ask question and read answer */
4207 while (read_chars(ms) != '\n' && !isdigit(*line_ptr)
4208 && *line_ptr != '-' && *line_ptr != '+')
4211 if (*line_ptr == '+' || *line_ptr == '-') {
4212 int minus = (*line_ptr == '-');
4215 i = atoi(line_ptr+1);
4217 while (isdigit(*++line_ptr))
4220 switch (*line_ptr) {
4223 if (!display_in_cyl_units)
4224 i *= heads * sectors;
4238 absolute = 1000000000;
4244 unsigned long long bytes;
4247 bytes = (unsigned long long) i * absolute;
4248 unit = sector_size * units_per_sector;
4249 bytes += unit/2; /* round */
4258 while (isdigit(*line_ptr)) {
4264 printf(_("Using default value %u\n"), i = dflt);
4265 if (i >= low && i <= high)
4268 printf(_("Value out of range.\n"));
4274 get_partition(int warn, int max) {
4278 i = read_int(1, 0, max, 0, _("Partition number")) - 1;
4282 if ((!sun_label && !sgi_label && !pe->part_table->sys_ind)
4283 #ifdef CONFIG_FEATURE_SUN_LABEL
4285 (!sunlabel->partitions[i].num_sectors ||
4286 !sunlabel->infos[i].id))
4288 #ifdef CONFIG_FEATURE_SGI_LABEL
4289 || (sgi_label && (!sgi_get_num_sectors(i)))
4293 _("Warning: partition %d has empty type\n"),
4300 get_existing_partition(int warn, int max) {
4304 for (i = 0; i < max; i++) {
4305 struct pte *pe = &ptes[i];
4306 struct partition *p = pe->part_table;
4308 if (p && !is_cleared_partition(p)) {
4315 printf(_("Selected partition %d\n"), pno+1);
4318 printf(_("No partition is defined yet!\n"));
4322 return get_partition(warn, max);
4326 get_nonexisting_partition(int warn, int max) {
4330 for (i = 0; i < max; i++) {
4331 struct pte *pe = &ptes[i];
4332 struct partition *p = pe->part_table;
4334 if (p && is_cleared_partition(p)) {
4341 printf(_("Selected partition %d\n"), pno+1);
4344 printf(_("All primary partitions have been defined already!\n"));
4348 return get_partition(warn, max);
4352 void change_units(void)
4354 display_in_cyl_units = !display_in_cyl_units;
4356 printf(_("Changing display/entry units to %s\n"),
4361 toggle_active(int i) {
4362 struct pte *pe = &ptes[i];
4363 struct partition *p = pe->part_table;
4365 if (IS_EXTENDED (p->sys_ind) && !p->boot_ind)
4367 _("WARNING: Partition %d is an extended partition\n"),
4369 p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG);
4374 toggle_dos_compatibility_flag(void) {
4375 dos_compatible_flag = ~dos_compatible_flag;
4376 if (dos_compatible_flag) {
4377 sector_offset = sectors;
4378 printf(_("DOS Compatibility flag is set\n"));
4382 printf(_("DOS Compatibility flag is not set\n"));
4387 delete_partition(int i) {
4388 struct pte *pe = &ptes[i];
4389 struct partition *p = pe->part_table;
4390 struct partition *q = pe->ext_pointer;
4392 /* Note that for the fifth partition (i == 4) we don't actually
4393 * decrement partitions.
4396 if (warn_geometry())
4397 return; /* C/H/S not set */
4400 #ifdef CONFIG_FEATURE_SUN_LABEL
4402 sun_delete_partition(i);
4406 #ifdef CONFIG_FEATURE_SGI_LABEL
4408 sgi_delete_partition(i);
4414 if (IS_EXTENDED (p->sys_ind) && i == ext_index) {
4416 ptes[ext_index].ext_pointer = NULL;
4417 extended_offset = 0;
4423 if (!q->sys_ind && i > 4) {
4424 /* the last one in the chain - just delete */
4427 clear_partition(ptes[i].ext_pointer);
4428 ptes[i].changed = 1;
4430 /* not the last one - further ones will be moved down */
4432 /* delete this link in the chain */
4433 p = ptes[i-1].ext_pointer;
4435 set_start_sect(p, get_start_sect(q));
4436 set_nr_sects(p, get_nr_sects(q));
4437 ptes[i-1].changed = 1;
4438 } else if (partitions > 5) { /* 5 will be moved to 4 */
4439 /* the first logical in a longer chain */
4442 if (pe->part_table) /* prevent SEGFAULT */
4443 set_start_sect(pe->part_table,
4444 get_partition_start(pe) -
4446 pe->offset = extended_offset;
4450 if (partitions > 5) {
4452 while (i < partitions) {
4453 ptes[i] = ptes[i+1];
4457 /* the only logical: clear only */
4458 clear_partition(ptes[i].part_table);
4463 change_sysid(void) {
4464 int i, sys, origsys;
4465 struct partition *p;
4467 #ifdef CONFIG_FEATURE_SGI_LABEL
4468 /* If sgi_label then don't use get_existing_partition,
4469 let the user select a partition, since get_existing_partition()
4470 only works for Linux like partition tables. */
4472 i = get_existing_partition(0, partitions);
4474 i = get_partition(0, partitions);
4477 i = get_existing_partition(0, partitions);
4481 p = ptes[i].part_table;
4482 origsys = sys = get_sysid(i);
4484 /* if changing types T to 0 is allowed, then
4485 the reverse change must be allowed, too */
4486 if (!sys && !sgi_label && !sun_label && !get_nr_sects(p))
4487 printf(_("Partition %d does not exist yet!\n"), i + 1);
4489 sys = read_hex (get_sys_types());
4491 if (!sys && !sgi_label && !sun_label) {
4492 printf(_("Type 0 means free space to many systems\n"
4493 "(but not to Linux). Having partitions of\n"
4494 "type 0 is probably unwise. You can delete\n"
4495 "a partition using the `d' command.\n"));
4499 if (!sun_label && !sgi_label) {
4500 if (IS_EXTENDED (sys) != IS_EXTENDED (p->sys_ind)) {
4501 printf(_("You cannot change a partition into"
4502 " an extended one or vice versa\n"
4503 "Delete it first.\n"));
4509 #ifdef CONFIG_FEATURE_SUN_LABEL
4510 if (sun_label && i == 2 && sys != WHOLE_DISK)
4511 printf(_("Consider leaving partition 3 "
4512 "as Whole disk (5),\n"
4513 "as SunOS/Solaris expects it and "
4514 "even Linux likes it.\n\n"));
4516 #ifdef CONFIG_FEATURE_SGI_LABEL
4517 if (sgi_label && ((i == 10 && sys != ENTIRE_DISK)
4518 || (i == 8 && sys != 0)))
4519 printf(_("Consider leaving partition 9 "
4520 "as volume header (0),\nand "
4521 "partition 11 as entire volume (6)"
4522 "as IRIX expects it.\n\n"));
4526 #ifdef CONFIG_FEATURE_SUN_LABEL
4528 sun_change_sysid(i, sys);
4531 #ifdef CONFIG_FEATURE_SGI_LABEL
4533 sgi_change_sysid(i, sys);
4537 printf (_("Changed system type of partition %d "
4538 "to %x (%s)\n"), i + 1, sys,
4539 partition_type(sys));
4540 ptes[i].changed = 1;
4541 if (is_dos_partition(origsys) ||
4542 is_dos_partition(sys))
4548 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
4551 /* check_consistency() and long2chs() added Sat Mar 6 12:28:16 1993,
4552 * faith@cs.unc.edu, based on code fragments from pfdisk by Gordon W. Ross,
4553 * Jan. 1990 (version 1.2.1 by Gordon W. Ross Aug. 1990; Modified by S.
4554 * Lubkin Oct. 1991). */
4556 static void long2chs(ulong ls, uint *c, uint *h, uint *s) {
4557 int spc = heads * sectors;
4562 *s = ls % sectors + 1; /* sectors count from 1 */
4565 static void check_consistency(const struct partition *p, int partition) {
4566 uint pbc, pbh, pbs; /* physical beginning c, h, s */
4567 uint pec, peh, pes; /* physical ending c, h, s */
4568 uint lbc, lbh, lbs; /* logical beginning c, h, s */
4569 uint lec, leh, les; /* logical ending c, h, s */
4571 if (!heads || !sectors || (partition >= 4))
4572 return; /* do not check extended partitions */
4574 /* physical beginning c, h, s */
4575 pbc = (p->cyl & 0xff) | ((p->sector << 2) & 0x300);
4577 pbs = p->sector & 0x3f;
4579 /* physical ending c, h, s */
4580 pec = (p->end_cyl & 0xff) | ((p->end_sector << 2) & 0x300);
4582 pes = p->end_sector & 0x3f;
4584 /* compute logical beginning (c, h, s) */
4585 long2chs(get_start_sect(p), &lbc, &lbh, &lbs);
4587 /* compute logical ending (c, h, s) */
4588 long2chs(get_start_sect(p) + get_nr_sects(p) - 1, &lec, &leh, &les);
4590 /* Same physical / logical beginning? */
4591 if (cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) {
4592 printf(_("Partition %d has different physical/logical "
4593 "beginnings (non-Linux?):\n"), partition + 1);
4594 printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs);
4595 printf(_("logical=(%d, %d, %d)\n"),lbc, lbh, lbs);
4598 /* Same physical / logical ending? */
4599 if (cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) {
4600 printf(_("Partition %d has different physical/logical "
4601 "endings:\n"), partition + 1);
4602 printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
4603 printf(_("logical=(%d, %d, %d)\n"),lec, leh, les);
4607 /* Beginning on cylinder boundary? */
4608 if (pbh != !pbc || pbs != 1) {
4609 printf(_("Partition %i does not start on cylinder "
4610 "boundary:\n"), partition + 1);
4611 printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs);
4612 printf(_("should be (%d, %d, 1)\n"), pbc, !pbc);
4616 /* Ending on cylinder boundary? */
4617 if (peh != (heads - 1) || pes != sectors) {
4618 printf(_("Partition %i does not end on cylinder boundary.\n"),
4621 printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
4622 printf(_("should be (%d, %d, %d)\n"),
4623 pec, heads - 1, sectors);
4629 list_disk_geometry(void) {
4630 long long bytes = (total_number_of_sectors << 9);
4631 long megabytes = bytes/1000000;
4633 if (megabytes < 10000)
4634 printf(_("\nDisk %s: %ld MB, %lld bytes\n"),
4635 disk_device, megabytes, bytes);
4637 printf(_("\nDisk %s: %ld.%ld GB, %lld bytes\n"),
4638 disk_device, megabytes/1000, (megabytes/100)%10, bytes);
4639 printf(_("%d heads, %d sectors/track, %d cylinders"),
4640 heads, sectors, cylinders);
4641 if (units_per_sector == 1)
4642 printf(_(", total %llu sectors"),
4643 total_number_of_sectors / (sector_size/512));
4644 printf(_("\nUnits = %s of %d * %d = %d bytes\n\n"),
4646 units_per_sector, sector_size, units_per_sector * sector_size);
4650 * Check whether partition entries are ordered by their starting positions.
4651 * Return 0 if OK. Return i if partition i should have been earlier.
4652 * Two separate checks: primary and logical partitions.
4655 wrong_p_order(int *prev) {
4656 const struct pte *pe;
4657 const struct partition *p;
4658 uint last_p_start_pos = 0, p_start_pos;
4661 for (i = 0 ; i < partitions; i++) {
4664 last_p_start_pos = 0;
4667 if ((p = pe->part_table)->sys_ind) {
4668 p_start_pos = get_partition_start(pe);
4670 if (last_p_start_pos > p_start_pos) {
4676 last_p_start_pos = p_start_pos;
4683 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
4685 * Fix the chain of logicals.
4686 * extended_offset is unchanged, the set of sectors used is unchanged
4687 * The chain is sorted so that sectors increase, and so that
4688 * starting sectors increase.
4690 * After this it may still be that cfdisk doesnt like the table.
4691 * (This is because cfdisk considers expanded parts, from link to
4692 * end of partition, and these may still overlap.)
4694 * sfdisk /dev/hda > ohda; sfdisk /dev/hda < ohda
4698 fix_chain_of_logicals(void) {
4699 int j, oj, ojj, sj, sjj;
4700 struct partition *pj,*pjj,tmp;
4702 /* Stage 1: sort sectors but leave sector of part 4 */
4703 /* (Its sector is the global extended_offset.) */
4705 for (j = 5; j < partitions-1; j++) {
4706 oj = ptes[j].offset;
4707 ojj = ptes[j+1].offset;
4709 ptes[j].offset = ojj;
4710 ptes[j+1].offset = oj;
4711 pj = ptes[j].part_table;
4712 set_start_sect(pj, get_start_sect(pj)+oj-ojj);
4713 pjj = ptes[j+1].part_table;
4714 set_start_sect(pjj, get_start_sect(pjj)+ojj-oj);
4715 set_start_sect(ptes[j-1].ext_pointer,
4716 ojj-extended_offset);
4717 set_start_sect(ptes[j].ext_pointer,
4718 oj-extended_offset);
4723 /* Stage 2: sort starting sectors */
4725 for (j = 4; j < partitions-1; j++) {
4726 pj = ptes[j].part_table;
4727 pjj = ptes[j+1].part_table;
4728 sj = get_start_sect(pj);
4729 sjj = get_start_sect(pjj);
4730 oj = ptes[j].offset;
4731 ojj = ptes[j+1].offset;
4732 if (oj+sj > ojj+sjj) {
4736 set_start_sect(pj, ojj+sjj-oj);
4737 set_start_sect(pjj, oj+sj-ojj);
4742 /* Probably something was changed */
4743 for (j = 4; j < partitions; j++)
4744 ptes[j].changed = 1;
4749 fix_partition_table_order(void) {
4750 struct pte *pei, *pek;
4753 if (!wrong_p_order(NULL)) {
4754 printf(_("Nothing to do. Ordering is correct already.\n\n"));
4758 while ((i = wrong_p_order(&k)) != 0 && i < 4) {
4759 /* partition i should have come earlier, move it */
4760 /* We have to move data in the MBR */
4761 struct partition *pi, *pk, *pe, pbuf;
4765 pe = pei->ext_pointer;
4766 pei->ext_pointer = pek->ext_pointer;
4767 pek->ext_pointer = pe;
4769 pi = pei->part_table;
4770 pk = pek->part_table;
4772 memmove(&pbuf, pi, sizeof(struct partition));
4773 memmove(pi, pk, sizeof(struct partition));
4774 memmove(pk, &pbuf, sizeof(struct partition));
4776 pei->changed = pek->changed = 1;
4780 fix_chain_of_logicals();
4788 list_table(int xtra) {
4789 const struct partition *p;
4792 #ifdef CONFIG_FEATURE_SUN_LABEL
4794 sun_list_table(xtra);
4799 #ifdef CONFIG_FEATURE_SGI_LABEL
4801 sgi_list_table(xtra);
4806 list_disk_geometry();
4808 #ifdef CONFIG_FEATURE_OSF_LABEL
4810 xbsd_print_disklabel(xtra);
4815 /* Heuristic: we list partition 3 of /dev/foo as /dev/foo3,
4816 but if the device name ends in a digit, say /dev/foo1,
4817 then the partition is called /dev/foo1p3. */
4818 w = strlen(disk_device);
4819 if (w && isdigit(disk_device[w-1]))
4824 printf(_("%*s Boot Start End Blocks Id System\n"),
4827 for (i = 0; i < partitions; i++) {
4828 const struct pte *pe = &ptes[i];
4831 if (p && !is_cleared_partition(p)) {
4832 unsigned int psects = get_nr_sects(p);
4833 unsigned int pblocks = psects;
4834 unsigned int podd = 0;
4836 if (sector_size < 1024) {
4837 pblocks /= (1024 / sector_size);
4838 podd = psects % (1024 / sector_size);
4840 if (sector_size > 1024)
4841 pblocks *= (sector_size / 1024);
4843 "%s %c %11lu %11lu %11lu%c %2x %s\n",
4844 partname(disk_device, i+1, w+2),
4845 /* boot flag */ !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG
4847 /* start */ (unsigned long) cround(get_partition_start(pe)),
4848 /* end */ (unsigned long) cround(get_partition_start(pe) + psects
4849 - (psects ? 1 : 0)),
4850 /* odd flag on end */ (unsigned long) pblocks, podd ? '+' : ' ',
4851 /* type id */ p->sys_ind,
4852 /* type name */ partition_type(p->sys_ind));
4853 check_consistency(p, i);
4857 /* Is partition table in disk order? It need not be, but... */
4858 /* partition table entries are not checked for correct order if this
4859 is a sgi, sun or aix labeled disk... */
4860 if (dos_label && wrong_p_order(NULL)) {
4861 printf(_("\nPartition table entries are not in disk order\n"));
4865 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
4867 x_list_table(int extend) {
4868 const struct pte *pe;
4869 const struct partition *p;
4872 printf(_("\nDisk %s: %d heads, %d sectors, %d cylinders\n\n"),
4873 disk_device, heads, sectors, cylinders);
4874 printf(_("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n"));
4875 for (i = 0 ; i < partitions; i++) {
4877 p = (extend ? pe->ext_pointer : pe->part_table);
4879 printf("%2d %02x%4d%4d%5d%4d%4d%5d%11u%11u %02x\n",
4880 i + 1, p->boot_ind, p->head,
4882 cylinder(p->sector, p->cyl), p->end_head,
4883 sector(p->end_sector),
4884 cylinder(p->end_sector, p->end_cyl),
4885 get_start_sect(p), get_nr_sects(p), p->sys_ind);
4887 check_consistency(p, i);
4893 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4895 fill_bounds(uint *first, uint *last) {
4897 const struct pte *pe = &ptes[0];
4898 const struct partition *p;
4900 for (i = 0; i < partitions; pe++,i++) {
4902 if (!p->sys_ind || IS_EXTENDED (p->sys_ind)) {
4903 first[i] = 0xffffffff;
4906 first[i] = get_partition_start(pe);
4907 last[i] = first[i] + get_nr_sects(p) - 1;
4913 check(int n, uint h, uint s, uint c, uint start) {
4914 uint total, real_s, real_c;
4916 real_s = sector(s) - 1;
4917 real_c = cylinder(s, c);
4918 total = (real_c * sectors + real_s) * heads + h;
4920 fprintf(stderr, _("Warning: partition %d contains sector 0\n"), n);
4923 _("Partition %d: head %d greater than maximum %d\n"),
4925 if (real_s >= sectors)
4926 fprintf(stderr, _("Partition %d: sector %d greater than "
4927 "maximum %d\n"), n, s, sectors);
4928 if (real_c >= cylinders)
4929 fprintf(stderr, _("Partitions %d: cylinder %d greater than "
4930 "maximum %d\n"), n, real_c + 1, cylinders);
4931 if (cylinders <= 1024 && start != total)
4933 _("Partition %d: previous sectors %d disagrees with "
4934 "total %d\n"), n, start, total);
4941 uint first[partitions], last[partitions];
4942 struct partition *p;
4944 if (warn_geometry())
4947 #ifdef CONFIG_FEATURE_SUN_LABEL
4953 #ifdef CONFIG_FEATURE_SGI_LABEL
4960 fill_bounds(first, last);
4961 for (i = 0; i < partitions; i++) {
4962 struct pte *pe = &ptes[i];
4965 if (p->sys_ind && !IS_EXTENDED (p->sys_ind)) {
4966 check_consistency(p, i);
4967 if (get_partition_start(pe) < first[i])
4968 printf(_("Warning: bad start-of-data in "
4969 "partition %d\n"), i + 1);
4970 check(i + 1, p->end_head, p->end_sector, p->end_cyl,
4972 total += last[i] + 1 - first[i];
4973 for (j = 0; j < i; j++)
4974 if ((first[i] >= first[j] && first[i] <= last[j])
4975 || ((last[i] <= last[j] && last[i] >= first[j]))) {
4976 printf(_("Warning: partition %d overlaps "
4977 "partition %d.\n"), j + 1, i + 1);
4978 total += first[i] >= first[j] ?
4979 first[i] : first[j];
4980 total -= last[i] <= last[j] ?
4986 if (extended_offset) {
4987 struct pte *pex = &ptes[ext_index];
4988 uint e_last = get_start_sect(pex->part_table) +
4989 get_nr_sects(pex->part_table) - 1;
4991 for (i = 4; i < partitions; i++) {
4993 p = ptes[i].part_table;
4995 if (i != 4 || i + 1 < partitions)
4996 printf(_("Warning: partition %d "
4997 "is empty\n"), i + 1);
4999 else if (first[i] < extended_offset ||
5001 printf(_("Logical partition %d not entirely in "
5002 "partition %d\n"), i + 1, ext_index + 1);
5006 if (total > heads * sectors * cylinders)
5007 printf(_("Total allocated sectors %d greater than the maximum "
5008 "%d\n"), total, heads * sectors * cylinders);
5009 else if ((total = heads * sectors * cylinders - total) != 0)
5010 printf(_("%d unallocated sectors\n"), total);
5014 add_partition(int n, int sys) {
5015 char mesg[256]; /* 48 does not suffice in Japanese */
5017 struct partition *p = ptes[n].part_table;
5018 struct partition *q = ptes[ext_index].part_table;
5020 uint start, stop = 0, limit, temp,
5021 first[partitions], last[partitions];
5023 if (p && p->sys_ind) {
5024 printf(_("Partition %d is already defined. Delete "
5025 "it before re-adding it.\n"), n + 1);
5028 fill_bounds(first, last);
5030 start = sector_offset;
5031 if (display_in_cyl_units || !total_number_of_sectors)
5032 llimit = heads * sectors * cylinders - 1;
5034 llimit = total_number_of_sectors - 1;
5036 if (limit != llimit)
5038 if (extended_offset) {
5039 first[ext_index] = extended_offset;
5040 last[ext_index] = get_start_sect(q) +
5041 get_nr_sects(q) - 1;
5044 start = extended_offset + sector_offset;
5045 limit = get_start_sect(q) + get_nr_sects(q) - 1;
5047 if (display_in_cyl_units)
5048 for (i = 0; i < partitions; i++)
5049 first[i] = (cround(first[i]) - 1) * units_per_sector;
5051 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
5054 for (i = 0; i < partitions; i++) {
5057 if (start == ptes[i].offset)
5058 start += sector_offset;
5059 lastplusoff = last[i] + ((n<4) ? 0 : sector_offset);
5060 if (start >= first[i] && start <= lastplusoff)
5061 start = lastplusoff + 1;
5065 if (start >= temp+units_per_sector && readed) {
5066 printf(_("Sector %d is already allocated\n"), temp);
5070 if (!readed && start == temp) {
5073 saved_start = start;
5074 start = read_int(cround(saved_start), cround(saved_start), cround(limit),
5076 if (display_in_cyl_units) {
5077 start = (start - 1) * units_per_sector;
5078 if (start < saved_start) start = saved_start;
5082 } while (start != temp || !readed);
5083 if (n > 4) { /* NOT for fifth partition */
5084 struct pte *pe = &ptes[n];
5086 pe->offset = start - sector_offset;
5087 if (pe->offset == extended_offset) { /* must be corrected */
5089 if (sector_offset == 1)
5094 for (i = 0; i < partitions; i++) {
5095 struct pte *pe = &ptes[i];
5097 if (start < pe->offset && limit >= pe->offset)
5098 limit = pe->offset - 1;
5099 if (start < first[i] && limit >= first[i])
5100 limit = first[i] - 1;
5102 if (start > limit) {
5103 printf(_("No free sectors available\n"));
5108 if (cround(start) == cround(limit)) {
5111 snprintf(mesg, sizeof(mesg),
5112 _("Last %s or +size or +sizeM or +sizeK"),
5113 str_units(SINGULAR));
5114 stop = read_int(cround(start), cround(limit), cround(limit),
5115 cround(start), mesg);
5116 if (display_in_cyl_units) {
5117 stop = stop * units_per_sector - 1;
5123 set_partition(n, 0, start, stop, sys);
5125 set_partition(n - 1, 1, ptes[n].offset, stop, EXTENDED);
5127 if (IS_EXTENDED (sys)) {
5128 struct pte *pe4 = &ptes[4];
5129 struct pte *pen = &ptes[n];
5132 pen->ext_pointer = p;
5133 pe4->offset = extended_offset = start;
5134 pe4->sectorbuffer = xcalloc(1, sector_size);
5135 pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
5136 pe4->ext_pointer = pe4->part_table + 1;
5144 if (partitions > 5 || ptes[4].part_table->sys_ind) {
5145 struct pte *pe = &ptes[partitions];
5147 pe->sectorbuffer = xcalloc(1, sector_size);
5148 pe->part_table = pt_offset(pe->sectorbuffer, 0);
5149 pe->ext_pointer = pe->part_table + 1;
5154 add_partition(partitions - 1, LINUX_NATIVE);
5158 new_partition(void) {
5159 int i, free_primary = 0;
5161 if (warn_geometry())
5164 #ifdef CONFIG_FEATURE_SUN_LABEL
5166 add_sun_partition(get_partition(0, partitions), LINUX_NATIVE);
5170 #ifdef CONFIG_FEATURE_SGI_LABEL
5172 sgi_add_partition(get_partition(0, partitions), LINUX_NATIVE);
5176 #ifdef CONFIG_FEATURE_AIX_LABEL
5178 printf(_("\tSorry - this fdisk cannot handle AIX disk labels."
5179 "\n\tIf you want to add DOS-type partitions, create"
5180 "\n\ta new empty DOS partition table first. (Use o.)"
5182 "This will destroy the present disk contents.\n"));
5187 for (i = 0; i < 4; i++)
5188 free_primary += !ptes[i].part_table->sys_ind;
5190 if (!free_primary && partitions >= MAXIMUM_PARTS) {
5191 printf(_("The maximum number of partitions has been created\n"));
5195 if (!free_primary) {
5196 if (extended_offset)
5199 printf(_("You must delete some partition and add "
5200 "an extended partition first\n"));
5202 char c, line[LINE_LENGTH];
5203 snprintf(line, sizeof(line), "%s\n %s\n p primary "
5204 "partition (1-4)\n",
5205 "Command action", (extended_offset ?
5206 "l logical (5 or over)" : "e extended"));
5208 if ((c = read_char(line)) == 'p' || c == 'P') {
5209 i = get_nonexisting_partition(0, 4);
5211 add_partition(i, LINUX_NATIVE);
5214 else if (c == 'l' && extended_offset) {
5218 else if (c == 'e' && !extended_offset) {
5219 i = get_nonexisting_partition(0, 4);
5221 add_partition(i, EXTENDED);
5225 printf(_("Invalid partition number "
5226 "for type `%c'\n"), c);
5237 if (ptes[i].changed)
5238 ptes[3].changed = 1;
5239 for (i = 3; i < partitions; i++) {
5240 struct pte *pe = &ptes[i];
5243 write_part_table_flag(pe->sectorbuffer);
5244 write_sector(pe->offset, pe->sectorbuffer);
5248 #ifdef CONFIG_FEATURE_SGI_LABEL
5249 else if (sgi_label) {
5250 /* no test on change? the printf below might be mistaken */
5254 #ifdef CONFIG_FEATURE_SUN_LABEL
5255 else if (sun_label) {
5259 if (ptes[i].changed)
5266 printf(_("The partition table has been altered!\n\n"));
5267 reread_partition_table(1);
5271 reread_partition_table(int leave) {
5275 printf(_("Calling ioctl() to re-read partition table.\n"));
5278 if ((i = ioctl(fd, BLKRRPART)) != 0) {
5281 /* some kernel versions (1.2.x) seem to have trouble
5282 rereading the partition table, but if asked to do it
5283 twice, the second time works. - biro@yggdrasil.com */
5286 if ((i = ioctl(fd, BLKRRPART)) != 0)
5291 printf(_("\nWARNING: Re-reading the partition table "
5292 "failed with error %d: %s.\n"
5293 "The kernel still uses the old table.\n"
5294 "The new table will be used "
5295 "at the next reboot.\n"),
5296 error, strerror(error));
5301 _("\nWARNING: If you have created or modified any DOS 6.x\n"
5302 "partitions, please see the fdisk manual page for additional\n"
5308 printf(_("Syncing disks.\n"));
5310 sleep(4); /* for sync() */
5314 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
5316 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
5317 #define MAX_PER_LINE 16
5319 print_buffer(char pbuffer[]) {
5323 for (i = 0, l = 0; i < sector_size; i++, l++) {
5325 printf("0x%03X:", i);
5326 printf(" %02X", (unsigned char) pbuffer[i]);
5327 if (l == MAX_PER_LINE - 1) {
5342 printf(_("Device: %s\n"), disk_device);
5343 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
5344 if (sun_label || sgi_label)
5345 print_buffer(MBRbuffer);
5348 for (i = 3; i < partitions; i++)
5349 print_buffer(ptes[i].sectorbuffer);
5354 struct pte *pe = &ptes[i];
5355 struct partition *p = pe->part_table;
5358 if (warn_geometry())
5360 if (!p->sys_ind || !get_nr_sects(p) || IS_EXTENDED (p->sys_ind)) {
5361 printf(_("Partition %d has no data area\n"), i + 1);
5364 first = get_partition_start(pe);
5365 new = read_int(first, first, first + get_nr_sects(p) - 1, first,
5366 _("New beginning of data")) - pe->offset;
5368 if (new != get_nr_sects(p)) {
5369 first = get_nr_sects(p) + get_start_sect(p) - new;
5370 set_nr_sects(p, first);
5371 set_start_sect(p, new);
5382 c = tolower(read_char(_("Expert command (m for help): ")));
5385 #ifdef CONFIG_FEATURE_SUN_LABEL
5392 move_begin(get_partition(0, partitions));
5395 user_cylinders = cylinders =
5396 read_int(1, cylinders, 1048576, 0,
5397 _("Number of cylinders"));
5398 #ifdef CONFIG_FEATURE_SUN_LABEL
5400 sun_set_ncyl(cylinders);
5409 #ifdef CONFIG_FEATURE_SGI_LABEL
5414 #ifdef CONFIG_FEATURE_SUN_LABEL
5424 fix_partition_table_order();
5427 #ifdef CONFIG_FEATURE_SGI_LABEL
5432 user_heads = heads = read_int(1, heads, 256, 0,
5433 _("Number of heads"));
5437 #ifdef CONFIG_FEATURE_SUN_LABEL
5443 #ifdef CONFIG_FEATURE_SUN_LABEL
5449 #ifdef CONFIG_FEATURE_SUN_LABEL
5463 user_sectors = sectors = read_int(1, sectors, 63, 0,
5464 _("Number of sectors"));
5465 if (dos_compatible_flag) {
5466 sector_offset = sectors;
5467 fprintf(stderr, _("Warning: setting "
5468 "sector offset for DOS "
5477 write_table(); /* does not return */
5480 #ifdef CONFIG_FEATURE_SUN_LABEL
5482 sun_set_pcylcount();
5490 #endif /* ADVANCED mode */
5493 is_ide_cdrom_or_tape(const char *device) {
5496 struct stat statbuf;
5499 /* No device was given explicitly, and we are trying some
5500 likely things. But opening /dev/hdc may produce errors like
5501 "hdc: tray open or drive not ready"
5502 if it happens to be a CD-ROM drive. It even happens that
5503 the process hangs on the attempt to read a music CD.
5504 So try to be careful. This only works since 2.1.73. */
5506 if (strncmp("/dev/hd", device, 7))
5509 snprintf(buf, sizeof(buf), "/proc/ide/%s/media", device+5);
5510 procf = fopen(buf, "r");
5511 if (procf != NULL && fgets(buf, sizeof(buf), procf))
5512 is_ide = (!strncmp(buf, "cdrom", 5) ||
5513 !strncmp(buf, "tape", 4));
5515 /* Now when this proc file does not exist, skip the
5516 device when it is read-only. */
5517 if (stat(device, &statbuf) == 0)
5518 is_ide = ((statbuf.st_mode & 0222) == 0);
5526 try(const char *device, int user_specified) {
5529 disk_device = device;
5530 if (setjmp(listingbuf))
5532 if (!user_specified)
5533 if (is_ide_cdrom_or_tape(device))
5535 if ((fd = open(disk_device, type_open)) >= 0) {
5536 gb = get_boot(try_only);
5537 if (gb > 0) { /* I/O error */
5539 } else if (gb < 0) { /* no DOS signature */
5540 list_disk_geometry();
5543 #ifdef CONFIG_FEATURE_OSF_LABEL
5544 if (btrydev(device) < 0)
5547 _("Disk %s doesn't contain a valid "
5548 "partition table\n"), device);
5553 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5554 if (!sun_label && partitions > 4)
5555 delete_partition(ext_index);
5559 /* Ignore other errors, since we try IDE
5560 and SCSI hard disks which may not be
5561 installed on the system. */
5562 if (errno == EACCES) {
5563 fprintf(stderr, _("Cannot open %s\n"), device);
5569 /* for fdisk -l: try all things in /proc/partitions
5570 that look like a partition name (do not end in a digit) */
5574 char line[100], ptname[100], devname[120], *s;
5577 procpt = bb_wfopen(PROC_PARTITIONS, "r");
5579 while (fgets(line, sizeof(line), procpt)) {
5580 if (sscanf (line, " %d %d %d %[^\n ]",
5581 &ma, &mi, &sz, ptname) != 4)
5583 for (s = ptname; *s; s++);
5586 sprintf(devname, "/dev/%s", ptname);
5589 #ifdef CONFIG_FEATURE_CLEAN_UP
5594 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5596 unknown_command(int c) {
5597 printf(_("%c: unknown command\n"), c);
5601 int fdisk_main(int argc, char **argv) {
5603 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5606 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5612 * fdisk -l [-b sectorsize] [-u] device ...
5613 * fdisk -s [partition] ...
5614 * fdisk [-b sectorsize] [-u] device
5616 * Options -C, -H, -S set the geometry.
5619 while ((c = getopt(argc, argv, "b:C:H:lS:uvV"
5620 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5626 /* Ugly: this sector size is really per device,
5627 so cannot be combined with multiple disks,
5628 and te same goes for the C/H/S options.
5630 sector_size = atoi(optarg);
5631 if (sector_size != 512 && sector_size != 1024 &&
5632 sector_size != 2048)
5635 user_set_sector_size = 1;
5638 user_cylinders = atoi(optarg);
5641 user_heads = atoi(optarg);
5642 if (user_heads <= 0 || user_heads >= 256)
5646 user_sectors = atoi(optarg);
5647 if (user_sectors <= 0 || user_sectors >= 64)
5651 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5655 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5661 display_in_cyl_units = 0;
5665 printf("fdisk v" UTIL_LINUX_VERSION "\n");
5673 printf(_("This kernel finds the sector size itself - "
5674 "-b option ignored\n"));
5676 if (user_set_sector_size && argc-optind != 1)
5677 printf(_("Warning: the -b (set sector size) option should"
5678 " be used with one specified device\n"));
5681 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5685 type_open = O_RDONLY;
5686 if (argc > optind) {
5689 /* avoid gcc warning:
5690 variable `k' might be clobbered by `longjmp' */
5694 for (k=optind; k<argc; k++)
5697 /* we no longer have default device names */
5698 /* but, we can use /proc/partitions instead */
5702 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5706 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5712 type_open = O_RDONLY;
5714 opts = argc - optind;
5718 for (j = optind; j < argc; j++) {
5719 disk_device = argv[j];
5720 if ((fd = open(disk_device, type_open)) < 0)
5721 fdisk_fatal(unable_to_open);
5722 if (ioctl(fd, BLKGETSIZE, &size))
5723 fdisk_fatal(ioctl_error);
5726 printf("%ld\n", size/2);
5728 printf("%s: %ld\n", argv[j], size/2);
5734 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5735 if (argc-optind == 1)
5736 disk_device = argv[optind];
5742 #ifdef CONFIG_FEATURE_OSF_LABEL
5744 /* OSF label, and no DOS label */
5745 printf(_("Detected an OSF/1 disklabel on %s, entering "
5746 "disklabel mode.\n"),
5750 /* If we return we may want to make an empty DOS label? */
5756 c = tolower(read_char(_("Command (m for help): ")));
5760 toggle_active(get_partition(1, partitions));
5761 #ifdef CONFIG_FEATURE_SUN_LABEL
5763 toggle_sunflags(get_partition(1, partitions),
5766 #ifdef CONFIG_FEATURE_SGI_LABEL
5768 sgi_set_bootpartition(
5769 get_partition(1, partitions));
5775 #ifdef CONFIG_FEATURE_SGI_LABEL
5777 printf(_("\nThe current boot file is: %s\n"),
5778 sgi_get_bootfile());
5779 if (read_chars(_("Please enter the name of the "
5780 "new boot file: ")) == '\n')
5781 printf(_("Boot file unchanged\n"));
5783 sgi_set_bootfile(line_ptr);
5786 #ifdef CONFIG_FEATURE_OSF_LABEL
5792 toggle_dos_compatibility_flag();
5793 #ifdef CONFIG_FEATURE_SUN_LABEL
5795 toggle_sunflags(get_partition(1, partitions),
5798 #ifdef CONFIG_FEATURE_SGI_LABEL
5800 sgi_set_swappartition(
5801 get_partition(1, partitions));
5809 #ifdef CONFIG_FEATURE_SGI_LABEL
5810 /* If sgi_label then don't use get_existing_partition,
5811 let the user select a partition, since
5812 get_existing_partition() only works for Linux-like
5815 j = get_existing_partition(1, partitions);
5817 j = get_partition(1, partitions);
5820 j = get_existing_partition(1, partitions);
5823 delete_partition(j);
5827 #ifdef CONFIG_FEATURE_SGI_LABEL
5834 list_types(get_sys_types());
5853 #ifdef CONFIG_FEATURE_SUN_LABEL
5867 write_table(); /* does not return */
5869 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
5871 #ifdef CONFIG_FEATURE_SGI_LABEL
5874 _("\n\tSorry, no experts menu for SGI "
5875 "partition tables available.\n\n"));
5888 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */