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"
17 #include <sys/types.h>
18 #include <sys/stat.h> /* stat */
27 #include <assert.h> /* assert */
31 #define u_char unsigned char
32 #include <scsi/scsi.h> /* SCSI_IOCTL_GET_IDLUN */
35 #include <sys/ioctl.h>
36 #include <sys/param.h>
37 #include <sys/sysmacros.h> /* major */
39 #include <stdint.h> /* for uint32_t, uint16_t, uint8_t, int16_t, etc */
41 /* Copied from linux/major.h */
42 #define FLOPPY_MAJOR 2
44 #include <sys/utsname.h>
48 #define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r))
54 #define BLKRRPART _IO(0x12,95) /* re-read partition table */
55 #define BLKGETSIZE _IO(0x12,96) /* return device size */
56 #define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */
57 #define BLKSSZGET _IO(0x12,104) /* get block device sector size */
59 /* Avoid conflicts with the 2.6 kernel headers, which define
60 * _IOR rather differently */
62 #define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size))
63 #define BLKGETSIZE64 _IOR(0x12,114,8) /* 8 = sizeof(u64) */
69 #define DEFAULT_SECTOR_SIZE 512
70 #define MAX_SECTOR_SIZE 2048
71 #define SECTOR_SIZE 512 /* still used in BSD code */
72 #define MAXIMUM_PARTS 60
74 #define ACTIVE_FLAG 0x80
77 #define WIN98_EXTENDED 0x0f
78 #define LINUX_PARTITION 0x81
79 #define LINUX_SWAP 0x82
80 #define LINUX_NATIVE 0x83
81 #define LINUX_EXTENDED 0x85
82 #define LINUX_LVM 0x8e
83 #define LINUX_RAID 0xfd
88 #define IS_EXTENDED(i) \
89 ((i) == EXTENDED || (i) == WIN98_EXTENDED || (i) == LINUX_EXTENDED)
91 #define SIZE(a) (sizeof(a)/sizeof((a)[0]))
93 #define cround(n) (display_in_cyl_units ? ((n)/units_per_sector)+1 : (n))
94 #define scround(x) (((x)+units_per_sector-1)/units_per_sector)
97 #if defined(CONFIG_LFS) || defined(FDISK_SUPPORT_LARGE_DISKS) || defined(__alpha__) || defined(__ia64__) || defined(__s390x__)
98 typedef long long fdisk_loff_t;
100 typedef long fdisk_loff_t;
104 /* including <linux/hdreg.h> also fails */
107 unsigned char sectors;
108 unsigned short cylinders;
112 #define HDIO_GETGEO 0x0301 /* get device geometry */
116 const unsigned char *name;
119 static uint sector_size = DEFAULT_SECTOR_SIZE,
120 user_set_sector_size,
124 * Raw disk label. For DOS-type partition tables the MBR,
125 * with descriptions of the primary partitions.
127 static char MBRbuffer[MAX_SECTOR_SIZE];
129 #ifdef CONFIG_FEATURE_SUN_LABEL
130 static int sun_label; /* looking at sun disklabel */
134 #ifdef CONFIG_FEATURE_SGI_LABEL
135 static int sgi_label; /* looking at sgi disklabel */
139 #ifdef CONFIG_FEATURE_AIX_LABEL
140 static int aix_label; /* looking at aix disklabel */
144 #ifdef CONFIG_FEATURE_OSF_LABEL
145 static int osf_label; /* looking at OSF/1 disklabel */
146 static int possibly_osf_label;
151 #define dos_label (!sun_label && !sgi_label && !aix_label && !osf_label)
153 static uint heads, sectors, cylinders;
154 static void update_units(void);
158 * return partition name - uses static storage unless buf is supplied
161 partname(const char *dev, int pno, int lth) {
162 static char buffer[80];
169 bufsiz = sizeof(buffer);
174 if (isdigit(dev[w-1]))
177 /* devfs kludge - note: fdisk partition names are not supposed
178 to equal kernel names, so there is no reason to do this */
179 if (strcmp (dev + w - 4, "disc") == 0) {
187 snprintf(bufp, bufsiz, "%*.*s%s%-2u",
188 lth-wp-2, w, dev, p, pno);
190 snprintf(bufp, bufsiz, "%.*s%s%-2u", w, dev, p, pno);
196 unsigned char boot_ind; /* 0x80 - active */
197 unsigned char head; /* starting head */
198 unsigned char sector; /* starting sector */
199 unsigned char cyl; /* starting cylinder */
200 unsigned char sys_ind; /* What partition type */
201 unsigned char end_head; /* end head */
202 unsigned char end_sector; /* end sector */
203 unsigned char end_cyl; /* end cylinder */
204 unsigned char start4[4]; /* starting sector counting from 0 */
205 unsigned char size4[4]; /* nr of sectors in partition */
209 ioctl_error, unable_to_open, unable_to_read, unable_to_seek,
213 enum action {fdisk, require, try_only, create_empty_dos, create_empty_sun};
215 static const char *disk_device;
216 static int fd; /* the disk */
217 static int partitions = 4; /* maximum partition + 1 */
218 static uint display_in_cyl_units = 1;
219 static uint units_per_sector = 1;
220 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
221 static char *line_ptr;
222 static void change_units(void);
223 static void reread_partition_table(int leave);
224 static void delete_partition(int i);
225 static int get_partition(int warn, int max);
226 static void list_types(const struct systypes *sys);
227 static uint read_int(uint low, uint dflt, uint high, uint base, char *mesg);
229 static const char *partition_type(unsigned char type);
230 static void fdisk_fatal(enum failure why) __attribute__ ((noreturn));
231 static void get_geometry(void);
232 static int get_boot(enum action what);
237 #define hex_val(c) ({ \
239 isdigit(_c) ? _c - '0' : \
240 tolower(_c) + 10 - 'a'; \
244 #define LINE_LENGTH 800
245 #define pt_offset(b, n) ((struct partition *)((b) + 0x1be + \
246 (n) * sizeof(struct partition)))
247 #define sector(s) ((s) & 0x3f)
248 #define cylinder(s, c) ((c) | (((s) & 0xc0) << 2))
250 #define hsc2sector(h,s,c) (sector(s) - 1 + sectors * \
251 ((h) + heads * cylinder(s,c)))
252 #define set_hsc(h,s,c,sector) { \
253 s = sector % sectors + 1; \
255 h = sector % heads; \
258 s |= (sector >> 2) & 0xc0; \
262 static unsigned int get_start_sect(const struct partition *p);
263 static unsigned int get_nr_sects(const struct partition *p);
266 * per partition table entry data
268 * The four primary partitions have the same sectorbuffer (MBRbuffer)
269 * and have NULL ext_pointer.
270 * Each logical partition table entry has two pointers, one for the
271 * partition and one link to the next one.
274 struct partition *part_table; /* points into sectorbuffer */
275 struct partition *ext_pointer; /* points into sectorbuffer */
276 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
277 char changed; /* boolean */
279 uint offset; /* disk sector number */
280 char *sectorbuffer; /* disk sector contents */
281 } ptes[MAXIMUM_PARTS];
284 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
286 set_all_unchanged(void) {
289 for (i = 0; i < MAXIMUM_PARTS; i++)
297 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
299 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_OSF_LABEL)
300 static struct partition *
301 get_part_table(int i) {
302 return ptes[i].part_table;
307 str_units(int n) { /* n==1: use singular */
309 return display_in_cyl_units ? _("cylinder") : _("sector");
311 return display_in_cyl_units ? _("cylinders") : _("sectors");
315 valid_part_table_flag(const unsigned char *b) {
316 return (b[510] == 0x55 && b[511] == 0xaa);
319 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
320 static char line_buffer[LINE_LENGTH];
322 /* read line; return 0 or first char */
326 static int got_eof = 0;
328 fflush (stdout); /* requested by niles@scyld.com */
329 line_ptr = line_buffer;
330 if (!fgets(line_buffer, LINE_LENGTH, stdin)) {
332 got_eof++; /* user typed ^D ? */
334 fprintf(stderr, _("\ngot EOF thrice - exiting..\n"));
339 while (*line_ptr && !isgraph(*line_ptr))
345 read_char(const char *mesg)
349 } while (!read_line());
354 read_chars(const char *mesg)
365 read_hex(const struct systypes *sys)
371 read_char(_("Hex code (type L to list codes): "));
372 if (*line_ptr == 'l' || *line_ptr == 'L')
374 else if (isxdigit (*line_ptr))
378 hex = hex << 4 | hex_val(*line_ptr++);
379 while (isxdigit(*line_ptr));
384 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
386 #ifdef CONFIG_FEATURE_AIX_LABEL
388 * Copyright (C) Andreas Neuper, Sep 1998.
389 * This file may be redistributed under
390 * the terms of the GNU Public License.
394 unsigned int magic; /* expect AIX_LABEL_MAGIC */
395 unsigned int fillbytes1[124];
396 unsigned int physical_volume_id;
397 unsigned int fillbytes2[124];
400 #define AIX_LABEL_MAGIC 0xc9c2d4c1
401 #define AIX_LABEL_MAGIC_SWAPPED 0xc1d4c2c9
402 #define AIX_INFO_MAGIC 0x00072959
403 #define AIX_INFO_MAGIC_SWAPPED 0x59290700
405 #define aixlabel ((aix_partition *)MBRbuffer)
410 * 1999-03-20 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
411 * Internationalization
413 * 2003-03-20 Phillip Kesling <pkesling@sgi.com>
417 static int aix_other_endian;
418 static short aix_volumes=1;
421 * only dealing with free blocks here
427 _("\n\tThere is a valid AIX label on this disk.\n"
428 "\tUnfortunately Linux cannot handle these\n"
429 "\tdisks at the moment. Nevertheless some\n"
431 "\t1. fdisk will destroy its contents on write.\n"
432 "\t2. Be sure that this disk is NOT a still vital\n"
433 "\t part of a volume group. (Otherwise you may\n"
434 "\t erase the other disks as well, if unmirrored.)\n"
435 "\t3. Before deleting this physical volume be sure\n"
436 "\t to remove the disk logically from your AIX\n"
437 "\t machine. (Otherwise you become an AIXpert).")
447 memset( MBRbuffer, 0, sizeof(MBRbuffer) ); /* avoid fdisk cores */
452 check_aix_label( void )
454 if (aixlabel->magic != AIX_LABEL_MAGIC &&
455 aixlabel->magic != AIX_LABEL_MAGIC_SWAPPED) {
457 aix_other_endian = 0;
460 aix_other_endian = (aixlabel->magic == AIX_LABEL_MAGIC_SWAPPED);
466 aix_nolabel(); /* %% */
467 aix_label = 1; /* %% */
470 #endif /* AIX_LABEL */
472 #ifdef CONFIG_FEATURE_OSF_LABEL
474 * Copyright (c) 1987, 1988 Regents of the University of California.
475 * All rights reserved.
477 * Redistribution and use in source and binary forms, with or without
478 * modification, are permitted provided that the following conditions
480 * 1. Redistributions of source code must retain the above copyright
481 * notice, this list of conditions and the following disclaimer.
482 * 2. Redistributions in binary form must reproduce the above copyright
483 * notice, this list of conditions and the following disclaimer in the
484 * documentation and/or other materials provided with the distribution.
485 * 3. All advertising materials mentioning features or use of this software
486 * must display the following acknowledgement:
487 * This product includes software developed by the University of
488 * California, Berkeley and its contributors.
489 * 4. Neither the name of the University nor the names of its contributors
490 * may be used to endorse or promote products derived from this software
491 * without specific prior written permission.
493 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
494 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
495 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
496 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
497 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
498 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
499 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
500 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
501 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
502 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
507 #ifndef BSD_DISKMAGIC
508 #define BSD_DISKMAGIC ((uint32_t) 0x82564557)
511 #ifndef BSD_MAXPARTITIONS
512 #define BSD_MAXPARTITIONS 16
515 #define BSD_LINUX_BOOTDIR "/usr/ucb/mdec"
517 #if defined (i386) || defined (__sparc__) || defined (__arm__) || defined (__mips__) || defined (__s390__) || defined (__sh__) || defined(__x86_64__)
518 #define BSD_LABELSECTOR 1
519 #define BSD_LABELOFFSET 0
520 #elif defined (__alpha__) || defined (__powerpc__) || defined (__ia64__) || defined (__hppa__)
521 #define BSD_LABELSECTOR 0
522 #define BSD_LABELOFFSET 64
523 #elif defined (__s390__) || defined (__s390x__)
524 #define BSD_LABELSECTOR 1
525 #define BSD_LABELOFFSET 0
527 #error unknown architecture
530 #define BSD_BBSIZE 8192 /* size of boot area, with label */
531 #define BSD_SBSIZE 8192 /* max size of fs superblock */
533 struct xbsd_disklabel {
534 uint32_t d_magic; /* the magic number */
535 int16_t d_type; /* drive type */
536 int16_t d_subtype; /* controller/d_type specific */
537 char d_typename[16]; /* type name, e.g. "eagle" */
538 char d_packname[16]; /* pack identifier */
540 uint32_t d_secsize; /* # of bytes per sector */
541 uint32_t d_nsectors; /* # of data sectors per track */
542 uint32_t d_ntracks; /* # of tracks per cylinder */
543 uint32_t d_ncylinders; /* # of data cylinders per unit */
544 uint32_t d_secpercyl; /* # of data sectors per cylinder */
545 uint32_t d_secperunit; /* # of data sectors per unit */
547 * Spares (bad sector replacements) below
548 * are not counted in d_nsectors or d_secpercyl.
549 * Spare sectors are assumed to be physical sectors
550 * which occupy space at the end of each track and/or cylinder.
552 uint16_t d_sparespertrack; /* # of spare sectors per track */
553 uint16_t d_sparespercyl; /* # of spare sectors per cylinder */
555 * Alternate cylinders include maintenance, replacement,
556 * configuration description areas, etc.
558 uint32_t d_acylinders; /* # of alt. cylinders per unit */
560 /* hardware characteristics: */
562 * d_interleave, d_trackskew and d_cylskew describe perturbations
563 * in the media format used to compensate for a slow controller.
564 * Interleave is physical sector interleave, set up by the formatter
565 * or controller when formatting. When interleaving is in use,
566 * logically adjacent sectors are not physically contiguous,
567 * but instead are separated by some number of sectors.
568 * It is specified as the ratio of physical sectors traversed
569 * per logical sector. Thus an interleave of 1:1 implies contiguous
570 * layout, while 2:1 implies that logical sector 0 is separated
571 * by one sector from logical sector 1.
572 * d_trackskew is the offset of sector 0 on track N
573 * relative to sector 0 on track N-1 on the same cylinder.
574 * Finally, d_cylskew is the offset of sector 0 on cylinder N
575 * relative to sector 0 on cylinder N-1.
577 uint16_t d_rpm; /* rotational speed */
578 uint16_t d_interleave; /* hardware sector interleave */
579 uint16_t d_trackskew; /* sector 0 skew, per track */
580 uint16_t d_cylskew; /* sector 0 skew, per cylinder */
581 uint32_t d_headswitch; /* head switch time, usec */
582 uint32_t d_trkseek; /* track-to-track seek, usec */
583 uint32_t d_flags; /* generic flags */
585 uint32_t d_drivedata[NDDATA]; /* drive-type specific information */
587 uint32_t d_spare[NSPARE]; /* reserved for future use */
588 uint32_t d_magic2; /* the magic number (again) */
589 uint16_t d_checksum; /* xor of data incl. partitions */
590 /* filesystem and partition information: */
591 uint16_t d_npartitions; /* number of partitions in following */
592 uint32_t d_bbsize; /* size of boot area at sn0, bytes */
593 uint32_t d_sbsize; /* max size of fs superblock, bytes */
594 struct xbsd_partition { /* the partition table */
595 uint32_t p_size; /* number of sectors in partition */
596 uint32_t p_offset; /* starting sector */
597 uint32_t p_fsize; /* filesystem basic fragment size */
598 uint8_t p_fstype; /* filesystem type, see below */
599 uint8_t p_frag; /* filesystem fragments per block */
600 uint16_t p_cpg; /* filesystem cylinders per group */
601 } d_partitions[BSD_MAXPARTITIONS]; /* actually may be more */
605 #define BSD_DTYPE_SMD 1 /* SMD, XSMD; VAX hp/up */
606 #define BSD_DTYPE_MSCP 2 /* MSCP */
607 #define BSD_DTYPE_DEC 3 /* other DEC (rk, rl) */
608 #define BSD_DTYPE_SCSI 4 /* SCSI */
609 #define BSD_DTYPE_ESDI 5 /* ESDI interface */
610 #define BSD_DTYPE_ST506 6 /* ST506 etc. */
611 #define BSD_DTYPE_HPIB 7 /* CS/80 on HP-IB */
612 #define BSD_DTYPE_HPFL 8 /* HP Fiber-link */
613 #define BSD_DTYPE_FLOPPY 10 /* floppy */
615 /* d_subtype values: */
616 #define BSD_DSTYPE_INDOSPART 0x8 /* is inside dos partition */
617 #define BSD_DSTYPE_DOSPART(s) ((s) & 3) /* dos partition number */
618 #define BSD_DSTYPE_GEOMETRY 0x10 /* drive params in label */
621 static const char * const xbsd_dktypenames[] = {
635 #define BSD_DKMAXTYPES (sizeof(xbsd_dktypenames) / sizeof(xbsd_dktypenames[0]) - 1)
639 * Filesystem type and version.
640 * Used to interpret other filesystem-specific
641 * per-partition information.
643 #define BSD_FS_UNUSED 0 /* unused */
644 #define BSD_FS_SWAP 1 /* swap */
645 #define BSD_FS_V6 2 /* Sixth Edition */
646 #define BSD_FS_V7 3 /* Seventh Edition */
647 #define BSD_FS_SYSV 4 /* System V */
648 #define BSD_FS_V71K 5 /* V7 with 1K blocks (4.1, 2.9) */
649 #define BSD_FS_V8 6 /* Eighth Edition, 4K blocks */
650 #define BSD_FS_BSDFFS 7 /* 4.2BSD fast file system */
651 #define BSD_FS_BSDLFS 9 /* 4.4BSD log-structured file system */
652 #define BSD_FS_OTHER 10 /* in use, but unknown/unsupported */
653 #define BSD_FS_HPFS 11 /* OS/2 high-performance file system */
654 #define BSD_FS_ISO9660 12 /* ISO-9660 filesystem (cdrom) */
655 #define BSD_FS_ISOFS BSD_FS_ISO9660
656 #define BSD_FS_BOOT 13 /* partition contains bootstrap */
657 #define BSD_FS_ADOS 14 /* AmigaDOS fast file system */
658 #define BSD_FS_HFS 15 /* Macintosh HFS */
659 #define BSD_FS_ADVFS 16 /* Digital Unix AdvFS */
661 /* this is annoying, but it's also the way it is :-( */
663 #define BSD_FS_EXT2 8 /* ext2 file system */
665 #define BSD_FS_MSDOS 8 /* MS-DOS file system */
669 static const struct systypes xbsd_fstypes[] = {
670 /* BSD_FS_UNUSED */ {"\x00" "unused"},
671 /* BSD_FS_SWAP */ {"\x01" "swap"},
672 /* BSD_FS_V6 */ {"\x02" "Version 6"},
673 /* BSD_FS_V7 */ {"\x03" "Version 7"},
674 /* BSD_FS_SYSV */ {"\x04" "System V"},
675 /* BSD_FS_V71K */ {"\x05" "4.1BSD"},
676 /* BSD_FS_V8 */ {"\x06" "Eighth Edition"},
677 /* BSD_FS_BSDFFS */ {"\x07" "4.2BSD"},
679 /* BSD_FS_EXT2 */ {"\x08" "ext2"},
681 /* BSD_FS_MSDOS */ {"\x08" "MS-DOS"},
683 /* BSD_FS_BSDLFS */ {"\x09" "4.4LFS"},
684 /* BSD_FS_OTHER */ {"\x0a" "unknown"},
685 /* BSD_FS_HPFS */ {"\x0b" "HPFS"},
686 /* BSD_FS_ISO9660 */ {"\x0c" "ISO-9660"},
687 /* BSD_FS_BOOT */ {"\x0d" "boot"},
688 /* BSD_FS_ADOS */ {"\x0e" "ADOS"},
689 /* BSD_FS_HFS */ {"\x0f" "HFS"},
690 /* BSD_FS_ADVFS */ {"\x10" "AdvFS"},
693 #define BSD_FSMAXTYPES (SIZE(xbsd_fstypes)-1)
698 * flags shared by various drives:
700 #define BSD_D_REMOVABLE 0x01 /* removable media */
701 #define BSD_D_ECC 0x02 /* supports ECC */
702 #define BSD_D_BADSECT 0x04 /* supports bad sector forw. */
703 #define BSD_D_RAMDISK 0x08 /* disk emulator */
704 #define BSD_D_CHAIN 0x10 /* can do back-back transfers */
705 #define BSD_D_DOSPART 0x20 /* within MSDOS partition */
707 #endif /* OSF_LABEL */
710 * Copyright (C) Andreas Neuper, Sep 1998.
711 * This file may be modified and redistributed under
712 * the terms of the GNU Public License.
715 struct device_parameter { /* 48 bytes */
719 unsigned char sparecyl;
720 unsigned short pcylcount;
721 unsigned short head_vol0;
722 unsigned short ntrks; /* tracks in cyl 0 or vol 0 */
723 unsigned char cmd_tag_queue_depth;
724 unsigned char unused0;
725 unsigned short unused1;
726 unsigned short nsect; /* sectors/tracks in cyl 0 or vol 0 */
727 unsigned short bytes;
728 unsigned short ilfact;
729 unsigned int flags; /* controller flags */
730 unsigned int datarate;
731 unsigned int retries_on_error;
732 unsigned int ms_per_word;
733 unsigned short xylogics_gap1;
734 unsigned short xylogics_syncdelay;
735 unsigned short xylogics_readdelay;
736 unsigned short xylogics_gap2;
737 unsigned short xylogics_readgate;
738 unsigned short xylogics_writecont;
741 #define SGI_VOLHDR 0x00
742 /* 1 and 2 were used for drive types no longer supported by SGI */
743 #define SGI_SWAP 0x03
744 /* 4 and 5 were for filesystem types SGI haven't ever supported on MIPS CPUs */
745 #define SGI_VOLUME 0x06
747 #define SGI_LVOL 0x08
748 #define SGI_RLVOL 0x09
750 #define SGI_XFSLOG 0x0b
753 #define ENTIRE_DISK SGI_VOLUME
757 #define SECTOR_SLIP 0x01
758 #define SECTOR_FWD 0x02
759 #define TRACK_FWD 0x04
760 #define TRACK_MULTIVOL 0x08
761 #define IGNORE_ERRORS 0x10
763 #define ENABLE_CMDTAGQ 0x40
766 unsigned int magic; /* expect SGI_LABEL_MAGIC */
767 unsigned short boot_part; /* active boot partition */
768 unsigned short swap_part; /* active swap partition */
769 unsigned char boot_file[16]; /* name of the bootfile */
770 struct device_parameter devparam; /* 1 * 48 bytes */
771 struct volume_directory { /* 15 * 16 bytes */
772 unsigned char vol_file_name[8]; /* a character array */
773 unsigned int vol_file_start; /* number of logical block */
774 unsigned int vol_file_size; /* number of bytes */
776 struct sgi_partition { /* 16 * 12 bytes */
777 unsigned int num_sectors; /* number of blocks */
778 unsigned int start_sector; /* must be cylinder aligned */
782 unsigned int fillbytes;
786 unsigned int magic; /* looks like a magic number */
795 unsigned char scsi_string[50];
796 unsigned char serial[137];
797 unsigned short check1816;
798 unsigned char installer[225];
801 #define SGI_LABEL_MAGIC 0x0be5a941
802 #define SGI_LABEL_MAGIC_SWAPPED 0x41a9e50b
803 #define SGI_INFO_MAGIC 0x00072959
804 #define SGI_INFO_MAGIC_SWAPPED 0x59290700
805 #define SGI_SSWAP16(x) (sgi_other_endian ? __swap16(x) \
807 #define SGI_SSWAP32(x) (sgi_other_endian ? __swap32(x) \
810 #define sgilabel ((sgi_partition *)MBRbuffer)
811 #define sgiparam (sgilabel->devparam)
814 unsigned char info[128]; /* Informative text string */
815 unsigned char spare0[14];
817 unsigned char spare1;
819 unsigned char spare2;
822 unsigned char spare1[246]; /* Boot information etc. */
823 unsigned short rspeed; /* Disk rotational speed */
824 unsigned short pcylcount; /* Physical cylinder count */
825 unsigned short sparecyl; /* extra sects per cylinder */
826 unsigned char spare2[4]; /* More magic... */
827 unsigned short ilfact; /* Interleave factor */
828 unsigned short ncyl; /* Data cylinder count */
829 unsigned short nacyl; /* Alt. cylinder count */
830 unsigned short ntrks; /* Tracks per cylinder */
831 unsigned short nsect; /* Sectors per track */
832 unsigned char spare3[4]; /* Even more magic... */
833 struct sun_partition {
834 uint32_t start_cylinder;
835 uint32_t num_sectors;
837 unsigned short magic; /* Magic number */
838 unsigned short csum; /* Label xor'd checksum */
842 #define SUN_LABEL_MAGIC 0xDABE
843 #define SUN_LABEL_MAGIC_SWAPPED 0xBEDA
844 #define sunlabel ((sun_partition *)MBRbuffer)
845 #define SUN_SSWAP16(x) (sun_other_endian ? __swap16(x) \
847 #define SUN_SSWAP32(x) (sun_other_endian ? __swap32(x) \
850 #if defined(FDISK_SUPPORT_LARGE_DISKS)
852 * llseek.c -- stub calling the llseek system call
854 * Copyright (C) 1994 Remy Card. This file may be redistributed
855 * under the terms of the GNU Public License.
862 #if defined(__alpha__) || defined(__ia64__) || defined(__s390x__)
864 #define my_llseek lseek
868 static int _llseek (unsigned int, unsigned long,
869 unsigned long, fdisk_loff_t *, unsigned int);
871 static _syscall5(int,_llseek,unsigned int,f_d,unsigned long,offset_high,
872 unsigned long, offset_low,fdisk_loff_t *,result,
873 unsigned int, origin);
875 static fdisk_loff_t my_llseek (unsigned int f_d, fdisk_loff_t offset,
881 retval = _llseek (f_d, ((unsigned long long) offset) >> 32,
882 ((unsigned long long) offset) & 0xffffffff,
884 return (retval == -1 ? (fdisk_loff_t) retval : result);
887 #endif /* __alpha__ */
890 static fdisk_loff_t fdisk_llseek (unsigned int f_d, fdisk_loff_t offset,
894 static int do_compat = 0;
897 result = my_llseek (f_d, offset, origin);
898 if (!(result == -1 && errno == ENOSYS))
902 * Just in case this code runs on top of an old kernel
903 * which does not support the llseek system call
907 * Now try ordinary lseek.
911 if ((sizeof(off_t) >= sizeof(fdisk_loff_t)) ||
912 (offset < ((fdisk_loff_t) 1 << ((sizeof(off_t)*8) -1))))
913 return lseek(f_d, (off_t) offset, origin);
919 # define fdisk_llseek lseek
920 #endif /* FDISK_SUPPORT_LARGE_DISKS */
924 #ifdef CONFIG_FEATURE_OSF_LABEL
927 19990319 - Arnaldo Carvalho de Melo <acme@conectiva.com.br> - i18n/nls
929 20000101 - David Huggins-Daines <dhuggins@linuxcare.com> - Better
930 support for OSF/1 disklabels on Alpha.
931 Also fixed unaligned accesses in alpha_bootblock_checksum()
934 #define FREEBSD_PARTITION 0xa5
935 #define NETBSD_PARTITION 0xa9
937 static void xbsd_delete_part (void);
938 static void xbsd_new_part (void);
939 static void xbsd_write_disklabel (void);
940 static int xbsd_create_disklabel (void);
941 static void xbsd_edit_disklabel (void);
942 static void xbsd_write_bootstrap (void);
943 static void xbsd_change_fstype (void);
944 static int xbsd_get_part_index (int max);
945 static int xbsd_check_new_partition (int *i);
946 static void xbsd_list_types (void);
947 static u_short xbsd_dkcksum (struct xbsd_disklabel *lp);
948 static int xbsd_initlabel (struct partition *p, struct xbsd_disklabel *d,
950 static int xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d);
951 static int xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d);
953 #if defined (__alpha__)
954 static void alpha_bootblock_checksum (char *boot);
957 #if !defined (__alpha__)
958 static int xbsd_translate_fstype (int linux_type);
959 static void xbsd_link_part (void);
960 static struct partition *xbsd_part;
961 static int xbsd_part_index;
964 #if defined (__alpha__)
965 /* We access this through a u_int64_t * when checksumming */
966 static char disklabelbuffer[BSD_BBSIZE] __attribute__((aligned(8)));
968 static char disklabelbuffer[BSD_BBSIZE];
971 static struct xbsd_disklabel xbsd_dlabel;
973 #define bsd_cround(n) \
974 (display_in_cyl_units ? ((n)/xbsd_dlabel.d_secpercyl) + 1 : (n))
977 * Test whether the whole disk has BSD disk label magic.
979 * Note: often reformatting with DOS-type label leaves the BSD magic,
980 * so this does not mean that there is a BSD disk label.
983 check_osf_label(void) {
984 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
989 static void xbsd_print_disklabel(int);
992 btrydev (const char * dev) {
993 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
995 printf(_("\nBSD label for device: %s\n"), dev);
996 xbsd_print_disklabel (0);
1002 puts (_("Command action"));
1003 puts (_("\td\tdelete a BSD partition"));
1004 puts (_("\te\tedit drive data"));
1005 puts (_("\ti\tinstall bootstrap"));
1006 puts (_("\tl\tlist known filesystem types"));
1007 puts (_("\tm\tprint this menu"));
1008 puts (_("\tn\tadd a new BSD partition"));
1009 puts (_("\tp\tprint BSD partition table"));
1010 puts (_("\tq\tquit without saving changes"));
1011 puts (_("\tr\treturn to main menu"));
1012 puts (_("\ts\tshow complete disklabel"));
1013 puts (_("\tt\tchange a partition's filesystem id"));
1014 puts (_("\tu\tchange units (cylinders/sectors)"));
1015 puts (_("\tw\twrite disklabel to disk"));
1016 #if !defined (__alpha__)
1017 puts (_("\tx\tlink BSD partition to non-BSD partition"));
1021 #if !defined (__alpha__)
1028 is_bsd_partition_type(int type) {
1029 return (type == FREEBSD_PARTITION ||
1030 type == hidden(FREEBSD_PARTITION) ||
1031 type == NETBSD_PARTITION ||
1032 type == hidden(NETBSD_PARTITION));
1038 #if !defined (__alpha__)
1040 struct partition *p;
1042 for (t=0; t<4; t++) {
1043 p = get_part_table(t);
1044 if (p && is_bsd_partition_type(p->sys_ind)) {
1046 xbsd_part_index = t;
1047 ss = get_start_sect(xbsd_part);
1049 fprintf (stderr, _("Partition %s has invalid starting sector 0.\n"),
1050 partname(disk_device, t+1, 0));
1053 printf (_("Reading disklabel of %s at sector %d.\n"),
1054 partname(disk_device, t+1, 0), ss + BSD_LABELSECTOR);
1055 if (xbsd_readlabel (xbsd_part, &xbsd_dlabel) == 0)
1056 if (xbsd_create_disklabel () == 0)
1063 printf (_("There is no *BSD partition on %s.\n"), disk_device);
1067 #elif defined (__alpha__)
1069 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
1070 if (xbsd_create_disklabel () == 0)
1071 exit ( EXIT_SUCCESS );
1077 switch (tolower (read_char (_("BSD disklabel command (m for help): ")))) {
1079 xbsd_delete_part ();
1082 xbsd_edit_disklabel ();
1085 xbsd_write_bootstrap ();
1094 xbsd_print_disklabel (0);
1098 exit ( EXIT_SUCCESS );
1102 xbsd_print_disklabel (1);
1105 xbsd_change_fstype ();
1111 xbsd_write_disklabel ();
1113 #if !defined (__alpha__)
1126 xbsd_delete_part (void)
1130 i = xbsd_get_part_index (xbsd_dlabel.d_npartitions);
1131 xbsd_dlabel.d_partitions[i].p_size = 0;
1132 xbsd_dlabel.d_partitions[i].p_offset = 0;
1133 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
1134 if (xbsd_dlabel.d_npartitions == i + 1)
1135 while (xbsd_dlabel.d_partitions[xbsd_dlabel.d_npartitions-1].p_size == 0)
1136 xbsd_dlabel.d_npartitions--;
1140 xbsd_new_part (void)
1146 if (!xbsd_check_new_partition (&i))
1149 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
1150 begin = get_start_sect(xbsd_part);
1151 end = begin + get_nr_sects(xbsd_part) - 1;
1154 end = xbsd_dlabel.d_secperunit - 1;
1157 snprintf (mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
1158 begin = read_int (bsd_cround (begin), bsd_cround (begin), bsd_cround (end),
1161 if (display_in_cyl_units)
1162 begin = (begin - 1) * xbsd_dlabel.d_secpercyl;
1164 snprintf (mesg, sizeof(mesg), _("Last %s or +size or +sizeM or +sizeK"),
1165 str_units(SINGULAR));
1166 end = read_int (bsd_cround (begin), bsd_cround (end), bsd_cround (end),
1167 bsd_cround (begin), mesg);
1169 if (display_in_cyl_units)
1170 end = end * xbsd_dlabel.d_secpercyl - 1;
1172 xbsd_dlabel.d_partitions[i].p_size = end - begin + 1;
1173 xbsd_dlabel.d_partitions[i].p_offset = begin;
1174 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
1178 xbsd_print_disklabel (int show_all) {
1179 struct xbsd_disklabel *lp = &xbsd_dlabel;
1180 struct xbsd_partition *pp;
1184 #if defined (__alpha__)
1185 printf("# %s:\n", disk_device);
1187 printf("# %s:\n", partname(disk_device, xbsd_part_index+1, 0));
1189 if ((unsigned) lp->d_type < BSD_DKMAXTYPES)
1190 printf(_("type: %s\n"), xbsd_dktypenames[lp->d_type]);
1192 printf(_("type: %d\n"), lp->d_type);
1193 printf(_("disk: %.*s\n"), (int) sizeof(lp->d_typename), lp->d_typename);
1194 printf(_("label: %.*s\n"), (int) sizeof(lp->d_packname), lp->d_packname);
1195 printf(_("flags:"));
1196 if (lp->d_flags & BSD_D_REMOVABLE)
1197 printf(_(" removable"));
1198 if (lp->d_flags & BSD_D_ECC)
1200 if (lp->d_flags & BSD_D_BADSECT)
1201 printf(_(" badsect"));
1203 /* On various machines the fields of *lp are short/int/long */
1204 /* In order to avoid problems, we cast them all to long. */
1205 printf(_("bytes/sector: %ld\n"), (long) lp->d_secsize);
1206 printf(_("sectors/track: %ld\n"), (long) lp->d_nsectors);
1207 printf(_("tracks/cylinder: %ld\n"), (long) lp->d_ntracks);
1208 printf(_("sectors/cylinder: %ld\n"), (long) lp->d_secpercyl);
1209 printf(_("cylinders: %ld\n"), (long) lp->d_ncylinders);
1210 printf(_("rpm: %d\n"), lp->d_rpm);
1211 printf(_("interleave: %d\n"), lp->d_interleave);
1212 printf(_("trackskew: %d\n"), lp->d_trackskew);
1213 printf(_("cylinderskew: %d\n"), lp->d_cylskew);
1214 printf(_("headswitch: %ld\t\t# milliseconds\n"),
1215 (long) lp->d_headswitch);
1216 printf(_("track-to-track seek: %ld\t# milliseconds\n"),
1217 (long) lp->d_trkseek);
1218 printf(_("drivedata: "));
1219 for (i = NDDATA - 1; i >= 0; i--)
1220 if (lp->d_drivedata[i])
1224 for (j = 0; j <= i; j++)
1225 printf("%ld ", (long) lp->d_drivedata[j]);
1227 printf(_("\n%d partitions:\n"), lp->d_npartitions);
1228 printf(_("# start end size fstype [fsize bsize cpg]\n"));
1229 pp = lp->d_partitions;
1230 for (i = 0; i < lp->d_npartitions; i++, pp++) {
1232 if (display_in_cyl_units && lp->d_secpercyl) {
1233 printf(" %c: %8ld%c %8ld%c %8ld%c ",
1235 (long) pp->p_offset / lp->d_secpercyl + 1,
1236 (pp->p_offset % lp->d_secpercyl) ? '*' : ' ',
1237 (long) (pp->p_offset + pp->p_size + lp->d_secpercyl - 1)
1239 ((pp->p_offset + pp->p_size) % lp->d_secpercyl) ? '*' : ' ',
1240 (long) pp->p_size / lp->d_secpercyl,
1241 (pp->p_size % lp->d_secpercyl) ? '*' : ' ');
1243 printf(" %c: %8ld %8ld %8ld ",
1245 (long) pp->p_offset,
1246 (long) pp->p_offset + pp->p_size - 1,
1249 if ((unsigned) pp->p_fstype < BSD_FSMAXTYPES)
1250 printf("%8.8s", xbsd_fstypes[pp->p_fstype].name);
1252 printf("%8x", pp->p_fstype);
1253 switch (pp->p_fstype) {
1255 printf(" %5ld %5ld %5.5s ",
1256 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, "");
1260 printf(" %5ld %5ld %5d ",
1261 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag,
1266 printf("%22.22s", "");
1275 xbsd_write_disklabel (void) {
1276 #if defined (__alpha__)
1277 printf (_("Writing disklabel to %s.\n"), disk_device);
1278 xbsd_writelabel (NULL, &xbsd_dlabel);
1280 printf (_("Writing disklabel to %s.\n"),
1281 partname(disk_device, xbsd_part_index+1, 0));
1282 xbsd_writelabel (xbsd_part, &xbsd_dlabel);
1284 reread_partition_table(0); /* no exit yet */
1288 xbsd_create_disklabel (void) {
1291 #if defined (__alpha__)
1292 fprintf (stderr, _("%s contains no disklabel.\n"), disk_device);
1294 fprintf (stderr, _("%s contains no disklabel.\n"),
1295 partname(disk_device, xbsd_part_index+1, 0));
1299 c = read_char (_("Do you want to create a disklabel? (y/n) "));
1300 if (c == 'y' || c == 'Y') {
1301 if (xbsd_initlabel (
1302 #if defined (__alpha__) || defined (__powerpc__) || defined (__hppa__) || \
1303 defined (__s390__) || defined (__s390x__)
1304 NULL, &xbsd_dlabel, 0
1306 xbsd_part, &xbsd_dlabel, xbsd_part_index
1309 xbsd_print_disklabel (1);
1313 } else if (c == 'n')
1319 edit_int (int def, char *mesg)
1322 fputs (mesg, stdout);
1323 printf (" (%d): ", def);
1327 while (!isdigit (*line_ptr));
1328 return atoi (line_ptr);
1332 xbsd_edit_disklabel (void)
1334 struct xbsd_disklabel *d;
1338 #if defined (__alpha__) || defined (__ia64__)
1339 d -> d_secsize = (u_long) edit_int ((u_long) d -> d_secsize ,_("bytes/sector"));
1340 d -> d_nsectors = (u_long) edit_int ((u_long) d -> d_nsectors ,_("sectors/track"));
1341 d -> d_ntracks = (u_long) edit_int ((u_long) d -> d_ntracks ,_("tracks/cylinder"));
1342 d -> d_ncylinders = (u_long) edit_int ((u_long) d -> d_ncylinders ,_("cylinders"));
1345 /* d -> d_secpercyl can be != d -> d_nsectors * d -> d_ntracks */
1348 d -> d_secpercyl = (u_long) edit_int ((u_long) d -> d_nsectors * d -> d_ntracks,
1349 _("sectors/cylinder"));
1350 if (d -> d_secpercyl <= d -> d_nsectors * d -> d_ntracks)
1353 printf (_("Must be <= sectors/track * tracks/cylinder (default).\n"));
1355 d -> d_rpm = (u_short) edit_int ((u_short) d -> d_rpm ,_("rpm"));
1356 d -> d_interleave = (u_short) edit_int ((u_short) d -> d_interleave,_("interleave"));
1357 d -> d_trackskew = (u_short) edit_int ((u_short) d -> d_trackskew ,_("trackskew"));
1358 d -> d_cylskew = (u_short) edit_int ((u_short) d -> d_cylskew ,_("cylinderskew"));
1359 d -> d_headswitch = (u_long) edit_int ((u_long) d -> d_headswitch ,_("headswitch"));
1360 d -> d_trkseek = (u_long) edit_int ((u_long) d -> d_trkseek ,_("track-to-track seek"));
1362 d -> d_secperunit = d -> d_secpercyl * d -> d_ncylinders;
1366 xbsd_get_bootstrap (char *path, void *ptr, int size)
1370 if ((fdb = open (path, O_RDONLY)) < 0)
1375 if (read (fdb, ptr, size) < 0)
1381 printf (" ... %s\n", path);
1389 printf (_("\nSyncing disks.\n"));
1395 xbsd_write_bootstrap (void)
1397 char *bootdir = BSD_LINUX_BOOTDIR;
1398 char path[MAXPATHLEN];
1400 struct xbsd_disklabel dl;
1404 if (xbsd_dlabel.d_type == BSD_DTYPE_SCSI)
1409 printf (_("Bootstrap: %sboot -> boot%s (%s): "),
1410 dkbasename, dkbasename, dkbasename);
1412 line_ptr[strlen (line_ptr)-1] = '\0';
1413 dkbasename = line_ptr;
1415 snprintf (path, sizeof(path), "%s/%sboot", bootdir, dkbasename);
1416 if (!xbsd_get_bootstrap (path, disklabelbuffer, (int) xbsd_dlabel.d_secsize))
1419 /* We need a backup of the disklabel (xbsd_dlabel might have changed). */
1420 d = &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE];
1421 bcopy (d, &dl, sizeof (struct xbsd_disklabel));
1423 /* The disklabel will be overwritten by 0's from bootxx anyway */
1424 bzero (d, sizeof (struct xbsd_disklabel));
1426 snprintf (path, sizeof(path), "%s/boot%s", bootdir, dkbasename);
1427 if (!xbsd_get_bootstrap (path, &disklabelbuffer[xbsd_dlabel.d_secsize],
1428 (int) xbsd_dlabel.d_bbsize - xbsd_dlabel.d_secsize))
1431 e = d + sizeof (struct xbsd_disklabel);
1432 for (p=d; p < e; p++)
1434 fprintf (stderr, _("Bootstrap overlaps with disk label!\n"));
1435 exit ( EXIT_FAILURE );
1438 bcopy (&dl, d, sizeof (struct xbsd_disklabel));
1440 #if defined (__powerpc__) || defined (__hppa__)
1442 #elif defined (__alpha__)
1444 alpha_bootblock_checksum (disklabelbuffer);
1446 sector = get_start_sect(xbsd_part);
1449 if (fdisk_llseek (fd, (fdisk_loff_t) sector * SECTOR_SIZE, SEEK_SET) == -1)
1450 fdisk_fatal (unable_to_seek);
1451 if (BSD_BBSIZE != write (fd, disklabelbuffer, BSD_BBSIZE))
1452 fdisk_fatal (unable_to_write);
1454 #if defined (__alpha__)
1455 printf (_("Bootstrap installed on %s.\n"), disk_device);
1457 printf (_("Bootstrap installed on %s.\n"),
1458 partname (disk_device, xbsd_part_index+1, 0));
1465 xbsd_change_fstype (void)
1469 i = xbsd_get_part_index (xbsd_dlabel.d_npartitions);
1470 xbsd_dlabel.d_partitions[i].p_fstype = read_hex (xbsd_fstypes);
1474 xbsd_get_part_index (int max)
1479 snprintf (prompt, sizeof(prompt), _("Partition (a-%c): "), 'a' + max - 1);
1481 l = tolower (read_char (prompt));
1482 while (l < 'a' || l > 'a' + max - 1);
1487 xbsd_check_new_partition (int *i) {
1489 /* room for more? various BSD flavours have different maxima */
1490 if (xbsd_dlabel.d_npartitions == BSD_MAXPARTITIONS) {
1493 for (t = 0; t < BSD_MAXPARTITIONS; t++)
1494 if (xbsd_dlabel.d_partitions[t].p_size == 0)
1497 if (t == BSD_MAXPARTITIONS) {
1498 fprintf (stderr, _("The maximum number of partitions "
1499 "has been created\n"));
1504 *i = xbsd_get_part_index (BSD_MAXPARTITIONS);
1506 if (*i >= xbsd_dlabel.d_npartitions)
1507 xbsd_dlabel.d_npartitions = (*i) + 1;
1509 if (xbsd_dlabel.d_partitions[*i].p_size != 0) {
1510 fprintf (stderr, _("This partition already exists.\n"));
1518 xbsd_list_types (void) {
1519 list_types (xbsd_fstypes);
1523 xbsd_dkcksum (struct xbsd_disklabel *lp) {
1524 u_short *start, *end;
1527 start = (u_short *) lp;
1528 end = (u_short *) &lp->d_partitions[lp->d_npartitions];
1535 xbsd_initlabel (struct partition *p, struct xbsd_disklabel *d, int pindex) {
1536 struct xbsd_partition *pp;
1539 bzero (d, sizeof (struct xbsd_disklabel));
1541 d -> d_magic = BSD_DISKMAGIC;
1543 if (strncmp (disk_device, "/dev/sd", 7) == 0)
1544 d -> d_type = BSD_DTYPE_SCSI;
1546 d -> d_type = BSD_DTYPE_ST506;
1548 #if 0 /* not used (at least not written to disk) by NetBSD/i386 1.0 */
1549 d -> d_subtype = BSD_DSTYPE_INDOSPART & pindex;
1552 #if !defined (__alpha__)
1553 d -> d_flags = BSD_D_DOSPART;
1557 d -> d_secsize = SECTOR_SIZE; /* bytes/sector */
1558 d -> d_nsectors = sectors; /* sectors/track */
1559 d -> d_ntracks = heads; /* tracks/cylinder (heads) */
1560 d -> d_ncylinders = cylinders;
1561 d -> d_secpercyl = sectors * heads;/* sectors/cylinder */
1562 if (d -> d_secpercyl == 0)
1563 d -> d_secpercyl = 1; /* avoid segfaults */
1564 d -> d_secperunit = d -> d_secpercyl * d -> d_ncylinders;
1567 d -> d_interleave = 1;
1568 d -> d_trackskew = 0;
1570 d -> d_headswitch = 0;
1573 d -> d_magic2 = BSD_DISKMAGIC;
1574 d -> d_bbsize = BSD_BBSIZE;
1575 d -> d_sbsize = BSD_SBSIZE;
1577 #if !defined (__alpha__)
1578 d -> d_npartitions = 4;
1579 pp = &d -> d_partitions[2]; /* Partition C should be
1580 the NetBSD partition */
1581 pp -> p_offset = get_start_sect(p);
1582 pp -> p_size = get_nr_sects(p);
1583 pp -> p_fstype = BSD_FS_UNUSED;
1584 pp = &d -> d_partitions[3]; /* Partition D should be
1587 pp -> p_size = d -> d_secperunit;
1588 pp -> p_fstype = BSD_FS_UNUSED;
1589 #elif defined (__alpha__)
1590 d -> d_npartitions = 3;
1591 pp = &d -> d_partitions[2]; /* Partition C should be
1594 pp -> p_size = d -> d_secperunit;
1595 pp -> p_fstype = BSD_FS_UNUSED;
1602 * Read a xbsd_disklabel from sector 0 or from the starting sector of p.
1603 * If it has the right magic, return 1.
1606 xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d)
1610 /* p is used only to get the starting sector */
1611 #if !defined (__alpha__)
1612 sector = (p ? get_start_sect(p) : 0);
1613 #elif defined (__alpha__)
1617 if (fdisk_llseek (fd, (fdisk_loff_t) sector * SECTOR_SIZE, SEEK_SET) == -1)
1618 fdisk_fatal (unable_to_seek);
1619 if (BSD_BBSIZE != read (fd, disklabelbuffer, BSD_BBSIZE))
1620 fdisk_fatal (unable_to_read);
1622 bcopy (&disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
1623 d, sizeof (struct xbsd_disklabel));
1625 if (d -> d_magic != BSD_DISKMAGIC || d -> d_magic2 != BSD_DISKMAGIC)
1628 for (t = d -> d_npartitions; t < BSD_MAXPARTITIONS; t++) {
1629 d -> d_partitions[t].p_size = 0;
1630 d -> d_partitions[t].p_offset = 0;
1631 d -> d_partitions[t].p_fstype = BSD_FS_UNUSED;
1634 if (d -> d_npartitions > BSD_MAXPARTITIONS)
1635 fprintf (stderr, _("Warning: too many partitions "
1636 "(%d, maximum is %d).\n"),
1637 d -> d_npartitions, BSD_MAXPARTITIONS);
1642 xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d)
1644 unsigned int sector;
1646 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
1647 sector = get_start_sect(p) + BSD_LABELSECTOR;
1649 sector = BSD_LABELSECTOR;
1652 d -> d_checksum = 0;
1653 d -> d_checksum = xbsd_dkcksum (d);
1655 /* This is necessary if we want to write the bootstrap later,
1656 otherwise we'd write the old disklabel with the bootstrap.
1658 bcopy (d, &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
1659 sizeof (struct xbsd_disklabel));
1661 #if defined (__alpha__) && BSD_LABELSECTOR == 0
1662 alpha_bootblock_checksum (disklabelbuffer);
1663 if (fdisk_llseek (fd, (fdisk_loff_t) 0, SEEK_SET) == -1)
1664 fdisk_fatal (unable_to_seek);
1665 if (BSD_BBSIZE != write (fd, disklabelbuffer, BSD_BBSIZE))
1666 fdisk_fatal (unable_to_write);
1668 if (fdisk_llseek (fd, (fdisk_loff_t) sector * SECTOR_SIZE + BSD_LABELOFFSET,
1670 fdisk_fatal (unable_to_seek);
1671 if (sizeof (struct xbsd_disklabel) != write (fd, d, sizeof (struct xbsd_disklabel)))
1672 fdisk_fatal (unable_to_write);
1681 #if !defined (__alpha__)
1683 xbsd_translate_fstype (int linux_type)
1687 case 0x01: /* DOS 12-bit FAT */
1688 case 0x04: /* DOS 16-bit <32M */
1689 case 0x06: /* DOS 16-bit >=32M */
1690 case 0xe1: /* DOS access */
1691 case 0xe3: /* DOS R/O */
1692 case 0xf2: /* DOS secondary */
1693 return BSD_FS_MSDOS;
1694 case 0x07: /* OS/2 HPFS */
1697 return BSD_FS_OTHER;
1702 xbsd_link_part (void)
1705 struct partition *p;
1707 k = get_partition (1, partitions);
1709 if (!xbsd_check_new_partition (&i))
1712 p = get_part_table(k);
1714 xbsd_dlabel.d_partitions[i].p_size = get_nr_sects(p);
1715 xbsd_dlabel.d_partitions[i].p_offset = get_start_sect(p);
1716 xbsd_dlabel.d_partitions[i].p_fstype = xbsd_translate_fstype(p->sys_ind);
1720 #if defined (__alpha__)
1722 #if !defined(__GLIBC__)
1723 typedef unsigned long long u_int64_t;
1727 alpha_bootblock_checksum (char *boot)
1732 dp = (u_int64_t *)boot;
1734 for (i = 0; i < 63; i++)
1738 #endif /* __alpha__ */
1740 #endif /* OSF_LABEL */
1742 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
1743 static inline unsigned short
1744 __swap16(unsigned short x) {
1745 return (((uint16_t)(x) & 0xFF) << 8) | (((uint16_t)(x) & 0xFF00) >> 8);
1748 static inline uint32_t
1749 __swap32(uint32_t x) {
1750 return (((x & 0xFF) << 24) |
1751 ((x & 0xFF00) << 8) |
1752 ((x & 0xFF0000) >> 8) |
1753 ((x & 0xFF000000) >> 24));
1757 #ifdef CONFIG_FEATURE_SGI_LABEL
1762 * Copyright (C) Andreas Neuper, Sep 1998.
1763 * This file may be modified and redistributed under
1764 * the terms of the GNU Public License.
1766 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
1767 * Internationalization
1771 static int sgi_other_endian;
1773 static short sgi_volumes=1;
1776 * only dealing with free blocks here
1779 typedef struct { unsigned int first; unsigned int last; } freeblocks;
1780 static freeblocks freelist[17]; /* 16 partitions can produce 17 vacant slots */
1783 setfreelist(int i, unsigned int f, unsigned int l) {
1784 freelist[i].first = f;
1785 freelist[i].last = l;
1789 add2freelist(unsigned int f, unsigned int l) {
1791 for ( ; i < 17 ; i++)
1792 if (freelist[i].last == 0)
1794 setfreelist(i, f, l);
1798 clearfreelist(void) {
1801 for (i = 0; i < 17 ; i++)
1802 setfreelist(i, 0, 0);
1806 isinfreelist(unsigned int b) {
1809 for (i = 0; i < 17 ; i++)
1810 if (freelist[i].first <= b && freelist[i].last >= b)
1811 return freelist[i].last;
1814 /* return last vacant block of this stride (never 0). */
1815 /* the '>=' is not quite correct, but simplifies the code */
1817 * end of free blocks section
1820 static const struct systypes sgi_sys_types[] = {
1821 /* SGI_VOLHDR */ {"\x00" "SGI volhdr" },
1822 /* 0x01 */ {"\x01" "SGI trkrepl" },
1823 /* 0x02 */ {"\x02" "SGI secrepl" },
1824 /* SGI_SWAP */ {"\x03" "SGI raw" },
1825 /* 0x04 */ {"\x04" "SGI bsd" },
1826 /* 0x05 */ {"\x05" "SGI sysv" },
1827 /* ENTIRE_DISK */ {"\x06" "SGI volume" },
1828 /* SGI_EFS */ {"\x07" "SGI efs" },
1829 /* 0x08 */ {"\x08" "SGI lvol" },
1830 /* 0x09 */ {"\x09" "SGI rlvol" },
1831 /* SGI_XFS */ {"\x0a" "SGI xfs" },
1832 /* SGI_XFSLOG */ {"\x0b" "SGI xfslog" },
1833 /* SGI_XLV */ {"\x0c" "SGI xlv" },
1834 /* SGI_XVM */ {"\x0d" "SGI xvm" },
1835 /* LINUX_SWAP */ {"\x82" "Linux swap" },
1836 /* LINUX_NATIVE */ {"\x83" "Linux native" },
1837 /* LINUX_LVM */ {"\x8d" "Linux LVM" },
1838 /* LINUX_RAID */ {"\xfd" "Linux RAID" },
1844 sgi_get_nsect(void) {
1845 return SGI_SSWAP16(sgilabel->devparam.nsect);
1849 sgi_get_ntrks(void) {
1850 return SGI_SSWAP16(sgilabel->devparam.ntrks);
1855 sgilabel->magic = 0;
1861 two_s_complement_32bit_sum(unsigned int* base, int size /* in bytes */) {
1865 size /= sizeof(unsigned int);
1866 for (i = 0; i < size; i++)
1867 sum -= SGI_SSWAP32(base[i]);
1872 check_sgi_label(void) {
1873 if (sizeof(sgilabel) > 512) {
1875 _("According to MIPS Computer Systems, Inc the "
1876 "Label must not contain more than 512 bytes\n"));
1880 if (sgilabel->magic != SGI_LABEL_MAGIC &&
1881 sgilabel->magic != SGI_LABEL_MAGIC_SWAPPED) {
1883 sgi_other_endian = 0;
1887 sgi_other_endian = (sgilabel->magic == SGI_LABEL_MAGIC_SWAPPED);
1889 * test for correct checksum
1891 if (two_s_complement_32bit_sum((unsigned int*)sgilabel,
1892 sizeof(*sgilabel))) {
1894 _("Detected sgi disklabel with wrong checksum.\n"));
1904 sgi_get_start_sector(int i) {
1905 return SGI_SSWAP32(sgilabel->partitions[i].start_sector);
1909 sgi_get_num_sectors(int i) {
1910 return SGI_SSWAP32(sgilabel->partitions[i].num_sectors);
1914 sgi_get_sysid(int i)
1916 return SGI_SSWAP32(sgilabel->partitions[i].id);
1920 sgi_get_bootpartition(void)
1922 return SGI_SSWAP16(sgilabel->boot_part);
1926 sgi_get_swappartition(void)
1928 return SGI_SSWAP16(sgilabel->swap_part);
1932 sgi_list_table(int xtra) {
1934 int kpi = 0; /* kernel partition ID */
1937 printf(_("\nDisk %s (SGI disk label): %d heads, %d sectors\n"
1938 "%d cylinders, %d physical cylinders\n"
1939 "%d extra sects/cyl, interleave %d:1\n"
1941 "Units = %s of %d * 512 bytes\n\n"),
1942 disk_device, heads, sectors, cylinders,
1943 SGI_SSWAP16(sgiparam.pcylcount),
1944 SGI_SSWAP16(sgiparam.sparecyl),
1945 SGI_SSWAP16(sgiparam.ilfact),
1947 str_units(PLURAL), units_per_sector);
1949 printf( _("\nDisk %s (SGI disk label): "
1950 "%d heads, %d sectors, %d cylinders\n"
1951 "Units = %s of %d * 512 bytes\n\n"),
1952 disk_device, heads, sectors, cylinders,
1953 str_units(PLURAL), units_per_sector );
1956 w = strlen(disk_device);
1957 wd = strlen(_("Device"));
1961 printf(_("----- partitions -----\n"
1962 "Pt# %*s Info Start End Sectors Id System\n"),
1963 w + 2, _("Device"));
1964 for (i = 0 ; i < partitions; i++) {
1965 if( sgi_get_num_sectors(i) || debug ) {
1966 uint32_t start = sgi_get_start_sector(i);
1967 uint32_t len = sgi_get_num_sectors(i);
1968 kpi++; /* only count nonempty partitions */
1970 "%2d: %s %4s %9ld %9ld %9ld %2x %s\n",
1971 /* fdisk part number */ i+1,
1972 /* device */ partname(disk_device, kpi, w+3),
1973 /* flags */ (sgi_get_swappartition() == i) ? "swap" :
1974 /* flags */ (sgi_get_bootpartition() == i) ? "boot" : " ",
1975 /* start */ (long) scround(start),
1976 /* end */ (long) scround(start+len)-1,
1977 /* no odd flag on end */ (long) len,
1978 /* type id */ sgi_get_sysid(i),
1979 /* type name */ partition_type(sgi_get_sysid(i)));
1982 printf(_("----- Bootinfo -----\nBootfile: %s\n"
1983 "----- Directory Entries -----\n"),
1984 sgilabel->boot_file);
1985 for (i = 0 ; i < sgi_volumes; i++) {
1986 if (sgilabel->directory[i].vol_file_size) {
1987 uint32_t start = SGI_SSWAP32(sgilabel->directory[i].vol_file_start);
1988 uint32_t len = SGI_SSWAP32(sgilabel->directory[i].vol_file_size);
1989 char*name = sgilabel->directory[i].vol_file_name;
1991 printf(_("%2d: %-10s sector%5u size%8u\n"),
1992 i, name, (unsigned int) start, (unsigned int) len);
1998 sgi_set_bootpartition( int i )
2000 sgilabel->boot_part = SGI_SSWAP16(((short)i));
2004 sgi_get_lastblock(void) {
2005 return heads * sectors * cylinders;
2009 sgi_set_swappartition( int i ) {
2010 sgilabel->swap_part = SGI_SSWAP16(((short)i));
2014 sgi_check_bootfile(const char* aFile) {
2016 if (strlen(aFile) < 3) /* "/a\n" is minimum */ {
2017 printf(_("\nInvalid Bootfile!\n"
2018 "\tThe bootfile must be an absolute non-zero pathname,\n"
2019 "\te.g. \"/unix\" or \"/unix.save\".\n"));
2022 if (strlen(aFile) > 16) {
2023 printf(_("\n\tName of Bootfile too long: "
2024 "16 bytes maximum.\n"));
2027 if (aFile[0] != '/') {
2028 printf(_("\n\tBootfile must have a "
2029 "fully qualified pathname.\n"));
2034 if (strncmp(aFile, sgilabel->boot_file, 16)) {
2035 printf(_("\n\tBe aware, that the bootfile is not checked for existence.\n\t"
2036 "SGI's default is \"/unix\" and for backup \"/unix.save\".\n"));
2037 /* filename is correct and did change */
2040 return 0; /* filename did not change */
2044 sgi_get_bootfile(void) {
2045 return sgilabel->boot_file;
2049 sgi_set_bootfile(const char* aFile) {
2052 if (sgi_check_bootfile(aFile)) {
2054 if ((aFile[i] != '\n') /* in principle caught again by next line */
2055 && (strlen(aFile) > i))
2056 sgilabel->boot_file[i] = aFile[i];
2058 sgilabel->boot_file[i] = 0;
2061 printf(_("\n\tBootfile is changed to \"%s\".\n"), sgilabel->boot_file);
2066 create_sgiinfo(void)
2068 /* I keep SGI's habit to write the sgilabel to the second block */
2069 sgilabel->directory[0].vol_file_start = SGI_SSWAP32(2);
2070 sgilabel->directory[0].vol_file_size = SGI_SSWAP32(sizeof(sgiinfo));
2071 strncpy(sgilabel->directory[0].vol_file_name, "sgilabel", 8);
2074 static sgiinfo *fill_sgiinfo(void);
2077 sgi_write_table(void) {
2079 sgilabel->csum = SGI_SSWAP32(two_s_complement_32bit_sum(
2080 (unsigned int*)sgilabel,
2081 sizeof(*sgilabel)));
2082 assert(two_s_complement_32bit_sum(
2083 (unsigned int*)sgilabel, sizeof(*sgilabel)) == 0);
2084 if (lseek(fd, 0, SEEK_SET) < 0)
2085 fdisk_fatal(unable_to_seek);
2086 if (write(fd, sgilabel, SECTOR_SIZE) != SECTOR_SIZE)
2087 fdisk_fatal(unable_to_write);
2088 if (! strncmp(sgilabel->directory[0].vol_file_name, "sgilabel", 8)) {
2090 * keep this habit of first writing the "sgilabel".
2091 * I never tested whether it works without (AN 981002).
2093 sgiinfo *info = fill_sgiinfo();
2094 int infostartblock = SGI_SSWAP32(sgilabel->directory[0].vol_file_start);
2095 if (fdisk_llseek(fd, (long long)infostartblock*
2096 SECTOR_SIZE, SEEK_SET) < 0)
2097 fdisk_fatal(unable_to_seek);
2098 if (write(fd, info, SECTOR_SIZE) != SECTOR_SIZE)
2099 fdisk_fatal(unable_to_write);
2105 compare_start(int *x, int *y) {
2107 * sort according to start sectors
2108 * and prefers largest partition:
2109 * entry zero is entire disk entry
2111 unsigned int i = *x;
2112 unsigned int j = *y;
2113 unsigned int a = sgi_get_start_sector(i);
2114 unsigned int b = sgi_get_start_sector(j);
2115 unsigned int c = sgi_get_num_sectors(i);
2116 unsigned int d = sgi_get_num_sectors(j);
2119 return (d > c) ? 1 : (d == c) ? 0 : -1;
2120 return (a > b) ? 1 : -1;
2125 verify_sgi(int verbose)
2127 int Index[16]; /* list of valid partitions */
2128 int sortcount = 0; /* number of used partitions, i.e. non-zero lengths */
2129 int entire = 0, i = 0;
2130 unsigned int start = 0;
2131 long long gap = 0; /* count unused blocks */
2132 unsigned int lastblock = sgi_get_lastblock();
2135 for (i=0; i<16; i++) {
2136 if (sgi_get_num_sectors(i) != 0) {
2137 Index[sortcount++]=i;
2138 if (sgi_get_sysid(i) == ENTIRE_DISK) {
2139 if (entire++ == 1) {
2141 printf(_("More than one entire disk entry present.\n"));
2146 if (sortcount == 0) {
2148 printf(_("No partitions defined\n"));
2149 return (lastblock > 0) ? 1 : (lastblock == 0) ? 0 : -1;
2151 qsort(Index, sortcount, sizeof(Index[0]), (void*)compare_start);
2152 if (sgi_get_sysid(Index[0]) == ENTIRE_DISK) {
2153 if ((Index[0] != 10) && verbose)
2154 printf(_("IRIX likes when Partition 11 covers the entire disk.\n"));
2155 if ((sgi_get_start_sector(Index[0]) != 0) && verbose)
2156 printf(_("The entire disk partition should start "
2158 "not at diskblock %d.\n"),
2159 sgi_get_start_sector(Index[0]));
2160 if (debug) /* I do not understand how some disks fulfil it */
2161 if ((sgi_get_num_sectors(Index[0]) != lastblock) && verbose)
2162 printf(_("The entire disk partition is only %d diskblock large,\n"
2163 "but the disk is %d diskblocks long.\n"),
2164 sgi_get_num_sectors(Index[0]), lastblock);
2165 lastblock = sgi_get_num_sectors(Index[0]);
2168 printf(_("One Partition (#11) should cover the entire disk.\n"));
2170 printf("sysid=%d\tpartition=%d\n",
2171 sgi_get_sysid(Index[0]), Index[0]+1);
2173 for (i=1, start=0; i<sortcount; i++) {
2174 int cylsize = sgi_get_nsect() * sgi_get_ntrks();
2176 if ((sgi_get_start_sector(Index[i]) % cylsize) != 0) {
2177 if (debug) /* I do not understand how some disks fulfil it */
2179 printf(_("Partition %d does not start on cylinder boundary.\n"),
2182 if (sgi_get_num_sectors(Index[i]) % cylsize != 0) {
2183 if (debug) /* I do not understand how some disks fulfil it */
2185 printf(_("Partition %d does not end on cylinder boundary.\n"),
2188 /* We cannot handle several "entire disk" entries. */
2189 if (sgi_get_sysid(Index[i]) == ENTIRE_DISK) continue;
2190 if (start > sgi_get_start_sector(Index[i])) {
2192 printf(_("The Partition %d and %d overlap by %d sectors.\n"),
2193 Index[i-1]+1, Index[i]+1,
2194 start - sgi_get_start_sector(Index[i]));
2195 if (gap > 0) gap = -gap;
2196 if (gap == 0) gap = -1;
2198 if (start < sgi_get_start_sector(Index[i])) {
2200 printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"),
2201 sgi_get_start_sector(Index[i]) - start,
2202 start, sgi_get_start_sector(Index[i])-1);
2203 gap += sgi_get_start_sector(Index[i]) - start;
2204 add2freelist(start, sgi_get_start_sector(Index[i]));
2206 start = sgi_get_start_sector(Index[i])
2207 + sgi_get_num_sectors(Index[i]);
2210 printf("%2d:%12d\t%12d\t%12d\n", Index[i],
2211 sgi_get_start_sector(Index[i]),
2212 sgi_get_num_sectors(Index[i]),
2213 sgi_get_sysid(Index[i]));
2216 if (start < lastblock) {
2218 printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"),
2219 lastblock - start, start, lastblock-1);
2220 gap += lastblock - start;
2221 add2freelist(start, lastblock);
2224 * Done with arithmetics
2225 * Go for details now
2228 if (!sgi_get_num_sectors(sgi_get_bootpartition())) {
2229 printf(_("\nThe boot partition does not exist.\n"));
2231 if (!sgi_get_num_sectors(sgi_get_swappartition())) {
2232 printf(_("\nThe swap partition does not exist.\n"));
2234 if ((sgi_get_sysid(sgi_get_swappartition()) != SGI_SWAP)
2235 && (sgi_get_sysid(sgi_get_swappartition()) != LINUX_SWAP))
2236 printf(_("\nThe swap partition has no swap type.\n"));
2238 if (sgi_check_bootfile("/unix"))
2239 printf(_("\tYou have chosen an unusual boot file name.\n"));
2241 return (gap > 0) ? 1 : (gap == 0) ? 0 : -1;
2247 * returned value is:
2248 * = 0 : disk is properly filled to the rim
2249 * < 0 : there is an overlap
2250 * > 0 : there is still some vacant space
2252 return verify_sgi(0);
2256 sgi_change_sysid( int i, int sys )
2258 if( sgi_get_num_sectors(i) == 0 ) /* caught already before, ... */
2260 printf(_("Sorry You may change the Tag of non-empty partitions.\n"));
2263 if( ((sys != ENTIRE_DISK ) && (sys != SGI_VOLHDR))
2264 && (sgi_get_start_sector(i)<1) )
2267 _("It is highly recommended that the partition at offset 0\n"
2268 "is of type \"SGI volhdr\", the IRIX system will rely on it to\n"
2269 "retrieve from its directory standalone tools like sash and fx.\n"
2270 "Only the \"SGI volume\" entire disk section may violate this.\n"
2271 "Type YES if you are sure about tagging this partition differently.\n"));
2272 if (strcmp (line_ptr, _("YES\n")))
2275 sgilabel->partitions[i].id = SGI_SSWAP32(sys);
2278 /* returns partition index of first entry marked as entire disk */
2284 if(sgi_get_sysid(i) == SGI_VOLUME)
2290 sgi_set_partition(int i, unsigned int start, unsigned int length, int sys) {
2292 sgilabel->partitions[i].id = SGI_SSWAP32(sys);
2293 sgilabel->partitions[i].num_sectors = SGI_SSWAP32(length);
2294 sgilabel->partitions[i].start_sector = SGI_SSWAP32(start);
2296 if (sgi_gaps() < 0) /* rebuild freelist */
2297 printf(_("Do You know, You got a partition overlap on the disk?\n"));
2301 sgi_set_entire(void) {
2304 for(n=10; n < partitions; n++) {
2305 if(!sgi_get_num_sectors(n) ) {
2306 sgi_set_partition(n, 0, sgi_get_lastblock(), SGI_VOLUME);
2313 sgi_set_volhdr(void)
2316 for( n=8; n<partitions; n++ )
2318 if(!sgi_get_num_sectors( n ) )
2321 * 5 cylinders is an arbitrary value I like
2322 * IRIX 5.3 stored files in the volume header
2323 * (like sash, symmon, fx, ide) with ca. 3200
2326 if( heads * sectors * 5 < sgi_get_lastblock() )
2327 sgi_set_partition( n, 0, heads * sectors * 5, SGI_VOLHDR );
2334 sgi_delete_partition( int i )
2336 sgi_set_partition( i, 0, 0, 0 );
2340 sgi_add_partition( int n, int sys )
2343 unsigned int first=0, last=0;
2347 } else if ( n == 8 ) {
2350 if(sgi_get_num_sectors(n)) {
2351 printf(_("Partition %d is already defined. Delete "
2352 "it before re-adding it.\n"), n + 1);
2355 if( (sgi_entire() == -1) && (sys != SGI_VOLUME) ) {
2356 printf(_("Attempting to generate entire disk entry automatically.\n"));
2360 if( (sgi_gaps() == 0) && (sys != SGI_VOLUME) ) {
2361 printf(_("The entire disk is already covered with partitions.\n"));
2364 if(sgi_gaps() < 0) {
2365 printf(_("You got a partition overlap on the disk. Fix it first!\n"));
2368 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
2370 if(sys == SGI_VOLUME) {
2371 last = sgi_get_lastblock();
2372 first = read_int(0, 0, last-1, 0, mesg);
2374 printf(_("It is highly recommended that eleventh partition\n"
2375 "covers the entire disk and is of type `SGI volume'\n"));
2378 first = freelist[0].first;
2379 last = freelist[0].last;
2380 first = read_int(scround(first), scround(first), scround(last)-1,
2383 if (display_in_cyl_units)
2384 first *= units_per_sector;
2386 first = first; /* align to cylinder if you know how ... */
2388 last = isinfreelist(first);
2390 printf(_("You will get a partition overlap on the disk. "
2391 "Fix it first!\n"));
2395 snprintf(mesg, sizeof(mesg), _(" Last %s"), str_units(SINGULAR));
2396 last = read_int(scround(first), scround(last)-1, scround(last)-1,
2397 scround(first), mesg)+1;
2398 if (display_in_cyl_units)
2399 last *= units_per_sector;
2401 last = last; /* align to cylinder if You know how ... */
2402 if( (sys == SGI_VOLUME) && ( first != 0 || last != sgi_get_lastblock() ) )
2403 printf(_("It is highly recommended that eleventh partition\n"
2404 "covers the entire disk and is of type `SGI volume'\n"));
2405 sgi_set_partition( n, first, last-first, sys );
2408 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
2410 create_sgilabel(void)
2412 struct hd_geometry geometry;
2419 long longsectors; /* the number of sectors on the device */
2420 int res; /* the result from the ioctl */
2421 int sec_fac; /* the sector factor */
2423 sec_fac = sector_size / 512; /* determine the sector factor */
2426 _("Building a new SGI disklabel. Changes will remain in memory only,\n"
2427 "until you decide to write them. After that, of course, the previous\n"
2428 "content will be unrecoverably lost.\n\n"));
2430 sgi_other_endian = (BYTE_ORDER == LITTLE_ENDIAN);
2431 res = ioctl(fd, BLKGETSIZE, &longsectors);
2432 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
2433 heads = geometry.heads;
2434 sectors = geometry.sectors;
2436 /* the get device size ioctl was successful */
2437 cylinders = longsectors / (heads * sectors);
2438 cylinders /= sec_fac;
2440 /* otherwise print error and use truncated version */
2441 cylinders = geometry.cylinders;
2443 _("Warning: BLKGETSIZE ioctl failed on %s. "
2444 "Using geometry cylinder value of %d.\n"
2445 "This value may be truncated for devices"
2446 " > 33.8 GB.\n"), disk_device, cylinders);
2449 for (i = 0; i < 4; i++) {
2451 if(valid_part_table_flag(MBRbuffer)) {
2452 if(get_part_table(i)->sys_ind) {
2453 old[i].sysid = get_part_table(i)->sys_ind;
2454 old[i].start = get_start_sect(get_part_table(i));
2455 old[i].nsect = get_nr_sects(get_part_table(i));
2456 printf(_("Trying to keep parameters of partition %d.\n"), i);
2458 printf(_("ID=%02x\tSTART=%d\tLENGTH=%d\n"),
2459 old[i].sysid, old[i].start, old[i].nsect);
2464 memset(MBRbuffer, 0, sizeof(MBRbuffer));
2465 sgilabel->magic = SGI_SSWAP32(SGI_LABEL_MAGIC);
2466 sgilabel->boot_part = SGI_SSWAP16(0);
2467 sgilabel->swap_part = SGI_SSWAP16(1);
2469 /* sizeof(sgilabel->boot_file) = 16 > 6 */
2470 memset(sgilabel->boot_file, 0, 16);
2471 strcpy(sgilabel->boot_file, "/unix");
2473 sgilabel->devparam.skew = (0);
2474 sgilabel->devparam.gap1 = (0);
2475 sgilabel->devparam.gap2 = (0);
2476 sgilabel->devparam.sparecyl = (0);
2477 sgilabel->devparam.pcylcount = SGI_SSWAP16(geometry.cylinders);
2478 sgilabel->devparam.head_vol0 = SGI_SSWAP16(0);
2479 sgilabel->devparam.ntrks = SGI_SSWAP16(geometry.heads);
2480 /* tracks/cylinder (heads) */
2481 sgilabel->devparam.cmd_tag_queue_depth = (0);
2482 sgilabel->devparam.unused0 = (0);
2483 sgilabel->devparam.unused1 = SGI_SSWAP16(0);
2484 sgilabel->devparam.nsect = SGI_SSWAP16(geometry.sectors);
2486 sgilabel->devparam.bytes = SGI_SSWAP16(512);
2487 sgilabel->devparam.ilfact = SGI_SSWAP16(1);
2488 sgilabel->devparam.flags = SGI_SSWAP32(TRACK_FWD|
2489 IGNORE_ERRORS|RESEEK);
2490 sgilabel->devparam.datarate = SGI_SSWAP32(0);
2491 sgilabel->devparam.retries_on_error = SGI_SSWAP32(1);
2492 sgilabel->devparam.ms_per_word = SGI_SSWAP32(0);
2493 sgilabel->devparam.xylogics_gap1 = SGI_SSWAP16(0);
2494 sgilabel->devparam.xylogics_syncdelay = SGI_SSWAP16(0);
2495 sgilabel->devparam.xylogics_readdelay = SGI_SSWAP16(0);
2496 sgilabel->devparam.xylogics_gap2 = SGI_SSWAP16(0);
2497 sgilabel->devparam.xylogics_readgate = SGI_SSWAP16(0);
2498 sgilabel->devparam.xylogics_writecont = SGI_SSWAP16(0);
2499 memset( &(sgilabel->directory), 0, sizeof(struct volume_directory)*15 );
2500 memset( &(sgilabel->partitions), 0, sizeof(struct sgi_partition)*16 );
2506 for (i = 0; i < 4; i++) {
2508 sgi_set_partition(i, old[i].start, old[i].nsect, old[i].sysid);
2516 /* do nothing in the beginning */
2518 #endif /* CONFIG_FEATURE_FDISK_ADVANCED */
2520 /* _____________________________________________________________
2526 sgiinfo *info = calloc(1, sizeof(sgiinfo));
2528 info->magic=SGI_SSWAP32(SGI_INFO_MAGIC);
2529 info->b1=SGI_SSWAP32(-1);
2530 info->b2=SGI_SSWAP16(-1);
2531 info->b3=SGI_SSWAP16(1);
2532 /* You may want to replace this string !!!!!!! */
2533 strcpy( info->scsi_string, "IBM OEM 0662S12 3 30" );
2534 strcpy( info->serial, "0000" );
2535 info->check1816 = SGI_SSWAP16(18*256 +16 );
2536 strcpy( info->installer, "Sfx version 5.3, Oct 18, 1994" );
2539 #endif /* SGI_LABEL */
2542 #ifdef CONFIG_FEATURE_SUN_LABEL
2546 * I think this is mostly, or entirely, due to
2547 * Jakub Jelinek (jj@sunsite.mff.cuni.cz), July 1996
2549 * Merged with fdisk for other architectures, aeb, June 1998.
2551 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
2552 * Internationalization
2556 static int sun_other_endian;
2557 static int scsi_disk;
2561 #define IDE0_MAJOR 3
2564 #define IDE1_MAJOR 22
2567 static void guess_device_type(void) {
2568 struct stat bootstat;
2570 if (fstat (fd, &bootstat) < 0) {
2573 } else if (S_ISBLK(bootstat.st_mode)
2574 && (major(bootstat.st_rdev) == IDE0_MAJOR ||
2575 major(bootstat.st_rdev) == IDE1_MAJOR)) {
2578 } else if (S_ISBLK(bootstat.st_mode)
2579 && major(bootstat.st_rdev) == FLOPPY_MAJOR) {
2588 static const struct systypes sun_sys_types[] = {
2589 /* 0 */ {"\x00" "Empty" },
2590 /* 1 */ {"\x01" "Boot" },
2591 /* 2 */ {"\x02" "SunOS root" },
2592 /* SUNOS_SWAP */ {"\x03" "SunOS swap" },
2593 /* 4 */ {"\x04" "SunOS usr" },
2594 /* WHOLE_DISK */ {"\x05" "Whole disk" },
2595 /* 6 */ {"\x06" "SunOS stand" },
2596 /* 7 */ {"\x07" "SunOS var" },
2597 /* 8 */ {"\x08" "SunOS home" },
2598 /* LINUX_SWAP */ {"\x82" "Linux swap" },
2599 /* LINUX_NATIVE */ {"\x83" "Linux native" },
2600 /* 0x8e */ {"\x8e" "Linux LVM" },
2601 /* New (2.2.x) raid partition with autodetect using persistent superblock */
2602 /* 0xfd */ {"\xfd" "Linux raid autodetect" },
2608 set_sun_partition(int i, uint start, uint stop, int sysid) {
2609 sunlabel->infos[i].id = sysid;
2610 sunlabel->partitions[i].start_cylinder =
2611 SUN_SSWAP32(start / (heads * sectors));
2612 sunlabel->partitions[i].num_sectors =
2613 SUN_SSWAP32(stop - start);
2620 sunlabel->magic = 0;
2625 check_sun_label(void) {
2626 unsigned short *ush;
2629 if (sunlabel->magic != SUN_LABEL_MAGIC &&
2630 sunlabel->magic != SUN_LABEL_MAGIC_SWAPPED) {
2632 sun_other_endian = 0;
2635 sun_other_endian = (sunlabel->magic == SUN_LABEL_MAGIC_SWAPPED);
2636 ush = ((unsigned short *) (sunlabel + 1)) - 1;
2637 for (csum = 0; ush >= (unsigned short *)sunlabel;) csum ^= *ush--;
2639 fprintf(stderr,_("Detected sun disklabel with wrong checksum.\n"
2640 "Probably you'll have to set all the values,\n"
2641 "e.g. heads, sectors, cylinders and partitions\n"
2642 "or force a fresh label (s command in main menu)\n"));
2644 heads = SUN_SSWAP16(sunlabel->ntrks);
2645 cylinders = SUN_SSWAP16(sunlabel->ncyl);
2646 sectors = SUN_SSWAP16(sunlabel->nsect);
2654 static const struct sun_predefined_drives {
2657 unsigned short sparecyl;
2658 unsigned short ncyl;
2659 unsigned short nacyl;
2660 unsigned short pcylcount;
2661 unsigned short ntrks;
2662 unsigned short nsect;
2663 unsigned short rspeed;
2665 {"Quantum","ProDrive 80S",1,832,2,834,6,34,3662},
2666 {"Quantum","ProDrive 105S",1,974,2,1019,6,35,3662},
2667 {"CDC","Wren IV 94171-344",3,1545,2,1549,9,46,3600},
2668 {"IBM","DPES-31080",0,4901,2,4903,4,108,5400},
2669 {"IBM","DORS-32160",0,1015,2,1017,67,62,5400},
2670 {"IBM","DNES-318350",0,11199,2,11474,10,320,7200},
2671 {"SEAGATE","ST34371",0,3880,2,3882,16,135,7228},
2672 {"","SUN0104",1,974,2,1019,6,35,3662},
2673 {"","SUN0207",4,1254,2,1272,9,36,3600},
2674 {"","SUN0327",3,1545,2,1549,9,46,3600},
2675 {"","SUN0340",0,1538,2,1544,6,72,4200},
2676 {"","SUN0424",2,1151,2,2500,9,80,4400},
2677 {"","SUN0535",0,1866,2,2500,7,80,5400},
2678 {"","SUN0669",5,1614,2,1632,15,54,3600},
2679 {"","SUN1.0G",5,1703,2,1931,15,80,3597},
2680 {"","SUN1.05",0,2036,2,2038,14,72,5400},
2681 {"","SUN1.3G",6,1965,2,3500,17,80,5400},
2682 {"","SUN2.1G",0,2733,2,3500,19,80,5400},
2683 {"IOMEGA","Jaz",0,1019,2,1021,64,32,5394},
2686 static const struct sun_predefined_drives *
2687 sun_autoconfigure_scsi(void) {
2688 const struct sun_predefined_drives *p = NULL;
2690 #ifdef SCSI_IOCTL_GET_IDLUN
2700 if (!ioctl(fd, SCSI_IOCTL_GET_IDLUN, &id)) {
2702 "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n",
2704 ((id[0]>>24)&0xff)-/*PROC_SCSI_SCSI+PROC_SCSI_FILE*/33,
2706 /* This is very wrong (works only if you have one HBA),
2707 but I haven't found a way how to get hostno
2708 from the current kernel */
2714 pfd = fopen("/proc/scsi/scsi","r");
2716 while (fgets(buffer2,2048,pfd)) {
2717 if (!strcmp(buffer, buffer2)) {
2718 if (fgets(buffer2,2048,pfd)) {
2719 q = strstr(buffer2,"Vendor: ");
2724 *q++ = 0; /* truncate vendor name */
2725 q = strstr(q,"Model: ");
2730 q = strstr(q," Rev: ");
2733 for (i = 0; i < SIZE(sun_drives); i++) {
2734 if (*sun_drives[i].vendor && strcasecmp(sun_drives[i].vendor, vendor))
2736 if (!strstr(model, sun_drives[i].model))
2738 printf(_("Autoconfigure found a %s%s%s\n"),sun_drives[i].vendor,(*sun_drives[i].vendor) ? " " : "",sun_drives[i].model);
2756 static void create_sunlabel(void)
2758 struct hd_geometry geometry;
2762 const struct sun_predefined_drives *p = NULL;
2765 _("Building a new sun disklabel. Changes will remain in memory only,\n"
2766 "until you decide to write them. After that, of course, the previous\n"
2767 "content won't be recoverable.\n\n"));
2768 #if BYTE_ORDER == LITTLE_ENDIAN
2769 sun_other_endian = 1;
2771 sun_other_endian = 0;
2773 memset(MBRbuffer, 0, sizeof(MBRbuffer));
2774 sunlabel->magic = SUN_SSWAP16(SUN_LABEL_MAGIC);
2776 puts(_("Drive type\n"
2777 " ? auto configure\n"
2778 " 0 custom (with hardware detected defaults)"));
2779 for (i = 0; i < SIZE(sun_drives); i++) {
2780 printf(" %c %s%s%s\n",
2781 i + 'a', sun_drives[i].vendor,
2782 (*sun_drives[i].vendor) ? " " : "",
2783 sun_drives[i].model);
2786 c = read_char(_("Select type (? for auto, 0 for custom): "));
2787 if (c >= 'a' && c < 'a' + SIZE(sun_drives)) {
2788 p = sun_drives + c - 'a';
2790 } else if (c >= 'A' && c < 'A' + SIZE(sun_drives)) {
2791 p = sun_drives + c - 'A';
2793 } else if (c == '0') {
2795 } else if (c == '?' && scsi_disk) {
2796 p = sun_autoconfigure_scsi();
2798 printf(_("Autoconfigure failed.\n"));
2805 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
2806 heads = geometry.heads;
2807 sectors = geometry.sectors;
2808 cylinders = geometry.cylinders;
2815 sunlabel->nacyl = 0;
2816 sunlabel->pcylcount = SUN_SSWAP16(cylinders);
2817 sunlabel->rspeed = SUN_SSWAP16(300);
2818 sunlabel->ilfact = SUN_SSWAP16(1);
2819 sunlabel->sparecyl = 0;
2821 heads = read_int(1,heads,1024,0,_("Heads"));
2822 sectors = read_int(1,sectors,1024,0,_("Sectors/track"));
2824 cylinders = read_int(1,cylinders-2,65535,0,_("Cylinders"));
2826 cylinders = read_int(1,0,65535,0,_("Cylinders"));
2828 SUN_SSWAP16(read_int(0,2,65535,0,
2829 _("Alternate cylinders")));
2830 sunlabel->pcylcount =
2831 SUN_SSWAP16(read_int(0,cylinders+SUN_SSWAP16(sunlabel->nacyl),
2832 65535,0,_("Physical cylinders")));
2834 SUN_SSWAP16(read_int(1,5400,100000,0,
2835 _("Rotation speed (rpm)")));
2837 SUN_SSWAP16(read_int(1,1,32,0,_("Interleave factor")));
2838 sunlabel->sparecyl =
2839 SUN_SSWAP16(read_int(0,0,sectors,0,
2840 _("Extra sectors per cylinder")));
2843 sunlabel->sparecyl = SUN_SSWAP16(p->sparecyl);
2844 sunlabel->ncyl = SUN_SSWAP16(p->ncyl);
2845 sunlabel->nacyl = SUN_SSWAP16(p->nacyl);
2846 sunlabel->pcylcount = SUN_SSWAP16(p->pcylcount);
2847 sunlabel->ntrks = SUN_SSWAP16(p->ntrks);
2848 sunlabel->nsect = SUN_SSWAP16(p->nsect);
2849 sunlabel->rspeed = SUN_SSWAP16(p->rspeed);
2850 sunlabel->ilfact = SUN_SSWAP16(1);
2851 cylinders = p->ncyl;
2854 puts(_("You may change all the disk params from the x menu"));
2857 snprintf(sunlabel->info, sizeof(sunlabel->info),
2858 "%s%s%s cyl %d alt %d hd %d sec %d",
2859 p ? p->vendor : "", (p && *p->vendor) ? " " : "",
2861 : (floppy ? _("3,5\" floppy") : _("Linux custom")),
2862 cylinders, SUN_SSWAP16(sunlabel->nacyl), heads, sectors);
2864 sunlabel->ntrks = SUN_SSWAP16(heads);
2865 sunlabel->nsect = SUN_SSWAP16(sectors);
2866 sunlabel->ncyl = SUN_SSWAP16(cylinders);
2868 set_sun_partition(0, 0, cylinders * heads * sectors, LINUX_NATIVE);
2870 if (cylinders * heads * sectors >= 150 * 2048) {
2871 ndiv = cylinders - (50 * 2048 / (heads * sectors)); /* 50M swap */
2873 ndiv = cylinders * 2 / 3;
2874 set_sun_partition(0, 0, ndiv * heads * sectors, LINUX_NATIVE);
2875 set_sun_partition(1, ndiv * heads * sectors, cylinders * heads * sectors, LINUX_SWAP);
2876 sunlabel->infos[1].flags |= 0x01; /* Not mountable */
2878 set_sun_partition(2, 0, cylinders * heads * sectors, WHOLE_DISK);
2880 unsigned short *ush = (unsigned short *)sunlabel;
2881 unsigned short csum = 0;
2882 while(ush < (unsigned short *)(&sunlabel->csum))
2884 sunlabel->csum = csum;
2887 set_all_unchanged();
2889 get_boot(create_empty_sun);
2893 toggle_sunflags(int i, unsigned char mask) {
2894 if (sunlabel->infos[i].flags & mask)
2895 sunlabel->infos[i].flags &= ~mask;
2896 else sunlabel->infos[i].flags |= mask;
2901 fetch_sun(uint *starts, uint *lens, uint *start, uint *stop) {
2902 int i, continuous = 1;
2903 *start = 0; *stop = cylinders * heads * sectors;
2904 for (i = 0; i < partitions; i++) {
2905 if (sunlabel->partitions[i].num_sectors
2906 && sunlabel->infos[i].id
2907 && sunlabel->infos[i].id != WHOLE_DISK) {
2908 starts[i] = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
2909 lens[i] = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
2911 if (starts[i] == *start)
2913 else if (starts[i] + lens[i] >= *stop)
2917 /* There will be probably more gaps
2918 than one, so lets check afterwards */
2927 static uint *verify_sun_starts;
2930 verify_sun_cmp(int *a, int *b) {
2931 if (*a == -1) return 1;
2932 if (*b == -1) return -1;
2933 if (verify_sun_starts[*a] > verify_sun_starts[*b]) return 1;
2939 uint starts[8], lens[8], start, stop;
2940 int i,j,k,starto,endo;
2943 verify_sun_starts = starts;
2944 fetch_sun(starts,lens,&start,&stop);
2945 for (k = 0; k < 7; k++) {
2946 for (i = 0; i < 8; i++) {
2947 if (k && (lens[i] % (heads * sectors))) {
2948 printf(_("Partition %d doesn't end on cylinder boundary\n"), i+1);
2951 for (j = 0; j < i; j++)
2953 if (starts[j] == starts[i]+lens[i]) {
2954 starts[j] = starts[i]; lens[j] += lens[i];
2956 } else if (starts[i] == starts[j]+lens[j]){
2960 if (starts[i] < starts[j]+lens[j] &&
2961 starts[j] < starts[i]+lens[i]) {
2963 if (starts[j] > starto)
2965 endo = starts[i]+lens[i];
2966 if (starts[j]+lens[j] < endo)
2967 endo = starts[j]+lens[j];
2968 printf(_("Partition %d overlaps with others in "
2969 "sectors %d-%d\n"), i+1, starto, endo);
2976 for (i = 0; i < 8; i++) {
2982 qsort(array,SIZE(array),sizeof(array[0]),
2983 (int (*)(const void *,const void *)) verify_sun_cmp);
2984 if (array[0] == -1) {
2985 printf(_("No partitions defined\n"));
2988 stop = cylinders * heads * sectors;
2989 if (starts[array[0]])
2990 printf(_("Unused gap - sectors 0-%d\n"),starts[array[0]]);
2991 for (i = 0; i < 7 && array[i+1] != -1; i++) {
2992 printf(_("Unused gap - sectors %d-%d\n"),starts[array[i]]+lens[array[i]],starts[array[i+1]]);
2994 start = starts[array[i]]+lens[array[i]];
2996 printf(_("Unused gap - sectors %d-%d\n"),start,stop);
3000 add_sun_partition(int n, int sys) {
3001 uint start, stop, stop2;
3002 uint starts[8], lens[8];
3008 if (sunlabel->partitions[n].num_sectors && sunlabel->infos[n].id) {
3009 printf(_("Partition %d is already defined. Delete "
3010 "it before re-adding it.\n"), n + 1);
3014 fetch_sun(starts,lens,&start,&stop);
3015 if (stop <= start) {
3019 printf(_("Other partitions already cover the whole disk.\nDelete "
3020 "some/shrink them before retry.\n"));
3024 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
3027 first = read_int(0, 0, 0, 0, mesg);
3029 first = read_int(scround(start), scround(stop)+1,
3030 scround(stop), 0, mesg);
3031 if (display_in_cyl_units)
3032 first *= units_per_sector;
3034 /* Starting sector has to be properly aligned */
3035 first = (first + heads * sectors - 1) / (heads * sectors);
3036 if (n == 2 && first != 0)
3038 It is highly recommended that the third partition covers the whole disk\n\
3039 and is of type `Whole disk'\n");
3040 /* ewt asks to add: "don't start a partition at cyl 0"
3041 However, edmundo@rano.demon.co.uk writes:
3042 "In addition to having a Sun partition table, to be able to
3043 boot from the disc, the first partition, /dev/sdX1, must
3044 start at cylinder 0. This means that /dev/sdX1 contains
3045 the partition table and the boot block, as these are the
3046 first two sectors of the disc. Therefore you must be
3047 careful what you use /dev/sdX1 for. In particular, you must
3048 not use a partition starting at cylinder 0 for Linux swap,
3049 as that would overwrite the partition table and the boot
3050 block. You may, however, use such a partition for a UFS
3051 or EXT2 file system, as these file systems leave the first
3052 1024 bytes undisturbed. */
3053 /* On the other hand, one should not use partitions
3054 starting at block 0 in an md, or the label will
3056 for (i = 0; i < partitions; i++)
3057 if (lens[i] && starts[i] <= first
3058 && starts[i] + lens[i] > first)
3060 if (i < partitions && !whole_disk) {
3061 if (n == 2 && !first) {
3065 printf(_("Sector %d is already allocated\n"), first);
3069 stop = cylinders * heads * sectors;
3071 for (i = 0; i < partitions; i++) {
3072 if (starts[i] > first && starts[i] < stop)
3075 snprintf(mesg, sizeof(mesg),
3076 _("Last %s or +size or +sizeM or +sizeK"),
3077 str_units(SINGULAR));
3079 last = read_int(scround(stop2), scround(stop2), scround(stop2),
3081 else if (n == 2 && !first)
3082 last = read_int(scround(first), scround(stop2), scround(stop2),
3083 scround(first), mesg);
3085 last = read_int(scround(first), scround(stop), scround(stop),
3086 scround(first), mesg);
3087 if (display_in_cyl_units)
3088 last *= units_per_sector;
3089 if (n == 2 && !first) {
3090 if (last >= stop2) {
3093 } else if (last > stop) {
3095 _("You haven't covered the whole disk with the 3rd partition, but your value\n"
3096 "%d %s covers some other partition. Your entry has been changed\n"
3098 scround(last), str_units(SINGULAR),
3099 scround(stop), str_units(SINGULAR));
3102 } else if (!whole_disk && last > stop)
3105 if (whole_disk) sys = WHOLE_DISK;
3106 set_sun_partition(n, first, last, sys);
3110 sun_delete_partition(int i) {
3113 if (i == 2 && sunlabel->infos[i].id == WHOLE_DISK &&
3114 !sunlabel->partitions[i].start_cylinder &&
3115 (nsec = SUN_SSWAP32(sunlabel->partitions[i].num_sectors))
3116 == heads * sectors * cylinders)
3117 printf(_("If you want to maintain SunOS/Solaris compatibility, "
3118 "consider leaving this\n"
3119 "partition as Whole disk (5), starting at 0, with %u "
3120 "sectors\n"), nsec);
3121 sunlabel->infos[i].id = 0;
3122 sunlabel->partitions[i].num_sectors = 0;
3126 sun_change_sysid(int i, int sys) {
3127 if (sys == LINUX_SWAP && !sunlabel->partitions[i].start_cylinder) {
3129 _("It is highly recommended that the partition at offset 0\n"
3130 "is UFS, EXT2FS filesystem or SunOS swap. Putting Linux swap\n"
3131 "there may destroy your partition table and bootblock.\n"
3132 "Type YES if you're very sure you would like that partition\n"
3133 "tagged with 82 (Linux swap): "));
3134 if (strcmp (line_ptr, _("YES\n")))
3140 /* swaps are not mountable by default */
3141 sunlabel->infos[i].flags |= 0x01;
3144 /* assume other types are mountable;
3145 user can change it anyway */
3146 sunlabel->infos[i].flags &= ~0x01;
3149 sunlabel->infos[i].id = sys;
3153 sun_list_table(int xtra) {
3156 w = strlen(disk_device);
3159 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d rpm\n"
3160 "%d cylinders, %d alternate cylinders, %d physical cylinders\n"
3161 "%d extra sects/cyl, interleave %d:1\n"
3163 "Units = %s of %d * 512 bytes\n\n"),
3164 disk_device, heads, sectors, SUN_SSWAP16(sunlabel->rspeed),
3165 cylinders, SUN_SSWAP16(sunlabel->nacyl),
3166 SUN_SSWAP16(sunlabel->pcylcount),
3167 SUN_SSWAP16(sunlabel->sparecyl),
3168 SUN_SSWAP16(sunlabel->ilfact),
3170 str_units(PLURAL), units_per_sector);
3173 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d cylinders\n"
3174 "Units = %s of %d * 512 bytes\n\n"),
3175 disk_device, heads, sectors, cylinders,
3176 str_units(PLURAL), units_per_sector);
3178 printf(_("%*s Flag Start End Blocks Id System\n"),
3179 w + 1, _("Device"));
3180 for (i = 0 ; i < partitions; i++) {
3181 if (sunlabel->partitions[i].num_sectors) {
3182 uint32_t start = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
3183 uint32_t len = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
3185 "%s %c%c %9ld %9ld %9ld%c %2x %s\n",
3186 /* device */ partname(disk_device, i+1, w),
3187 /* flags */ (sunlabel->infos[i].flags & 0x01) ? 'u' : ' ',
3188 (sunlabel->infos[i].flags & 0x10) ? 'r' : ' ',
3189 /* start */ (long) scround(start),
3190 /* end */ (long) scround(start+len),
3191 /* odd flag on end */ (long) len / 2, len & 1 ? '+' : ' ',
3192 /* type id */ sunlabel->infos[i].id,
3193 /* type name */ partition_type(sunlabel->infos[i].id));
3198 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3201 sun_set_alt_cyl(void) {
3203 SUN_SSWAP16(read_int(0,SUN_SSWAP16(sunlabel->nacyl), 65535, 0,
3204 _("Number of alternate cylinders")));
3208 sun_set_ncyl(int cyl) {
3209 sunlabel->ncyl = SUN_SSWAP16(cyl);
3213 sun_set_xcyl(void) {
3214 sunlabel->sparecyl =
3215 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->sparecyl), sectors, 0,
3216 _("Extra sectors per cylinder")));
3220 sun_set_ilfact(void) {
3222 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->ilfact), 32, 0,
3223 _("Interleave factor")));
3227 sun_set_rspeed(void) {
3229 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->rspeed), 100000, 0,
3230 _("Rotation speed (rpm)")));
3234 sun_set_pcylcount(void) {
3235 sunlabel->pcylcount =
3236 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->pcylcount), 65535, 0,
3237 _("Number of physical cylinders")));
3239 #endif /* CONFIG_FEATURE_FDISK_ADVANCED */
3242 sun_write_table(void) {
3243 unsigned short *ush = (unsigned short *)sunlabel;
3244 unsigned short csum = 0;
3246 while(ush < (unsigned short *)(&sunlabel->csum))
3248 sunlabel->csum = csum;
3249 if (lseek(fd, 0, SEEK_SET) < 0)
3250 fdisk_fatal(unable_to_seek);
3251 if (write(fd, sunlabel, SECTOR_SIZE) != SECTOR_SIZE)
3252 fdisk_fatal(unable_to_write);
3254 #endif /* SUN_LABEL */
3256 /* DOS partition types */
3258 static const struct systypes i386_sys_types[] = {
3261 {"\x04" "FAT16 <32M"},
3262 {"\x05" "Extended"}, /* DOS 3.3+ extended partition */
3263 {"\x06" "FAT16"}, /* DOS 16-bit >=32M */
3264 {"\x07" "HPFS/NTFS"}, /* OS/2 IFS, eg, HPFS or NTFS or QNX */
3265 {"\x0a" "OS/2 Boot Manager"},/* OS/2 Boot Manager */
3266 {"\x0b" "Win95 FAT32"},
3267 {"\x0c" "Win95 FAT32 (LBA)"},/* LBA really is `Extended Int 13h' */
3268 {"\x0e" "Win95 FAT16 (LBA)"},
3269 {"\x0f" "Win95 Ext'd (LBA)"},
3270 {"\x11" "Hidden FAT12"},
3271 {"\x12" "Compaq diagnostics"},
3272 {"\x14" "Hidden FAT16 <32M"},
3273 {"\x16" "Hidden FAT16"},
3274 {"\x17" "Hidden HPFS/NTFS"},
3275 {"\x1b" "Hidden Win95 FAT32"},
3276 {"\x1c" "Hidden Win95 FAT32 (LBA)"},
3277 {"\x1e" "Hidden Win95 FAT16 (LBA)"},
3278 {"\x3c" "PartitionMagic recovery"},
3279 {"\x41" "PPC PReP Boot"},
3281 {"\x63" "GNU HURD or SysV"}, /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */
3282 {"\x80" "Old Minix"}, /* Minix 1.4a and earlier */
3283 {"\x81" "Minix / old Linux"},/* Minix 1.4b and later */
3284 {"\x82" "Linux swap"}, /* also Solaris */
3286 {"\x84" "OS/2 hidden C: drive"},
3287 {"\x85" "Linux extended"},
3288 {"\x86" "NTFS volume set"},
3289 {"\x87" "NTFS volume set"},
3290 {"\x8e" "Linux LVM"},
3291 {"\x9f" "BSD/OS"}, /* BSDI */
3292 {"\xa0" "IBM Thinkpad hibernation"},
3293 {"\xa5" "FreeBSD"}, /* various BSD flavours */
3295 {"\xa8" "Darwin UFS"},
3297 {"\xab" "Darwin boot"},
3299 {"\xb8" "BSDI swap"},
3300 {"\xbe" "Solaris boot"},
3302 {"\xee" "EFI GPT"}, /* Intel EFI GUID Partition Table */
3303 {"\xef" "EFI (FAT-12/16/32)"},/* Intel EFI System Partition */
3304 {"\xf0" "Linux/PA-RISC boot"},/* Linux/PA-RISC boot loader */
3305 {"\xf2" "DOS secondary"}, /* DOS 3.3+ secondary */
3306 {"\xfd" "Linux raid autodetect"},/* New (2.2.x) raid partition with
3307 autodetect using persistent
3309 #ifdef CONFIG_WEIRD_PARTITION_TYPES
3310 {"\x02" "XENIX root"},
3311 {"\x03" "XENIX usr"},
3312 {"\x08" "AIX"}, /* AIX boot (AIX -- PS/2 port) or SplitDrive */
3313 {"\x09" "AIX bootable"}, /* AIX data or Coherent */
3315 {"\x18" "AST SmartSleep"},
3318 {"\x40" "Venix 80286"},
3320 {"\x4e" "QNX4.x 2nd part"},
3321 {"\x4f" "QNX4.x 3rd part"},
3322 {"\x50" "OnTrack DM"},
3323 {"\x51" "OnTrack DM6 Aux1"}, /* (or Novell) */
3324 {"\x52" "CP/M"}, /* CP/M or Microport SysV/AT */
3325 {"\x53" "OnTrack DM6 Aux3"},
3326 {"\x54" "OnTrackDM6"},
3327 {"\x55" "EZ-Drive"},
3328 {"\x56" "Golden Bow"},
3329 {"\x5c" "Priam Edisk"},
3330 {"\x61" "SpeedStor"},
3331 {"\x64" "Novell Netware 286"},
3332 {"\x65" "Novell Netware 386"},
3333 {"\x70" "DiskSecure Multi-Boot"},
3336 {"\x94" "Amoeba BBT"}, /* (bad block table) */
3337 {"\xa7" "NeXTSTEP"},
3338 {"\xbb" "Boot Wizard hidden"},
3339 {"\xc1" "DRDOS/sec (FAT-12)"},
3340 {"\xc4" "DRDOS/sec (FAT-16 < 32M)"},
3341 {"\xc6" "DRDOS/sec (FAT-16)"},
3343 {"\xda" "Non-FS data"},
3344 {"\xdb" "CP/M / CTOS / ..."},/* CP/M or Concurrent CP/M or
3345 Concurrent DOS or CTOS */
3346 {"\xde" "Dell Utility"}, /* Dell PowerEdge Server utilities */
3347 {"\xdf" "BootIt"}, /* BootIt EMBRM */
3348 {"\xe1" "DOS access"}, /* DOS access or SpeedStor 12-bit FAT
3349 extended partition */
3350 {"\xe3" "DOS R/O"}, /* DOS R/O or SpeedStor */
3351 {"\xe4" "SpeedStor"}, /* SpeedStor 16-bit FAT extended
3352 partition < 1024 cyl. */
3353 {"\xf1" "SpeedStor"},
3354 {"\xf4" "SpeedStor"}, /* SpeedStor large partition */
3355 {"\xfe" "LANstep"}, /* SpeedStor >1024 cyl. or LANstep */
3356 {"\xff" "BBT"}, /* Xenix Bad Block Table */
3363 /* A valid partition table sector ends in 0x55 0xaa */
3365 part_table_flag(const char *b) {
3366 return ((uint) b[510]) + (((uint) b[511]) << 8);
3370 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3372 write_part_table_flag(char *b) {
3377 /* start_sect and nr_sects are stored little endian on all machines */
3378 /* moreover, they are not aligned correctly */
3380 store4_little_endian(unsigned char *cp, unsigned int val) {
3381 cp[0] = (val & 0xff);
3382 cp[1] = ((val >> 8) & 0xff);
3383 cp[2] = ((val >> 16) & 0xff);
3384 cp[3] = ((val >> 24) & 0xff);
3386 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3389 read4_little_endian(const unsigned char *cp) {
3390 return (uint)(cp[0]) + ((uint)(cp[1]) << 8)
3391 + ((uint)(cp[2]) << 16) + ((uint)(cp[3]) << 24);
3394 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3396 set_start_sect(struct partition *p, unsigned int start_sect) {
3397 store4_little_endian(p->start4, start_sect);
3402 get_start_sect(const struct partition *p) {
3403 return read4_little_endian(p->start4);
3406 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3408 set_nr_sects(struct partition *p, unsigned int nr_sects) {
3409 store4_little_endian(p->size4, nr_sects);
3414 get_nr_sects(const struct partition *p) {
3415 return read4_little_endian(p->size4);
3418 /* normally O_RDWR, -l option gives O_RDONLY */
3419 static int type_open = O_RDWR;
3422 static int ext_index, /* the prime extended partition */
3423 listing, /* no aborts for fdisk -l */
3424 dos_compatible_flag = ~0;
3425 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3426 static int dos_changed;
3427 static int nowarn; /* no warnings for fdisk -l/-s */
3432 static uint user_cylinders, user_heads, user_sectors;
3433 static uint pt_heads, pt_sectors;
3434 static uint kern_heads, kern_sectors;
3436 static uint extended_offset; /* offset of link pointers */
3438 static unsigned long long total_number_of_sectors;
3441 static jmp_buf listingbuf;
3443 static void fdisk_fatal(enum failure why) {
3444 const char *message;
3448 longjmp(listingbuf, 1);
3452 case unable_to_open:
3453 message = "Unable to open %s\n";
3455 case unable_to_read:
3456 message = "Unable to read %s\n";
3458 case unable_to_seek:
3459 message = "Unable to seek on %s\n";
3461 case unable_to_write:
3462 message = "Unable to write %s\n";
3465 message = "BLKGETSIZE ioctl failed on %s\n";
3468 message = "Fatal error\n";
3471 fputc('\n', stderr);
3472 fprintf(stderr, message, disk_device);
3477 seek_sector(uint secno) {
3478 fdisk_loff_t offset = (fdisk_loff_t) secno * sector_size;
3479 if (fdisk_llseek(fd, offset, SEEK_SET) == (fdisk_loff_t) -1)
3480 fdisk_fatal(unable_to_seek);
3483 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3485 write_sector(uint secno, char *buf) {
3487 if (write(fd, buf, sector_size) != sector_size)
3488 fdisk_fatal(unable_to_write);
3492 /* Allocate a buffer and read a partition table sector */
3494 read_pte(struct pte *pe, uint offset) {
3496 pe->offset = offset;
3497 pe->sectorbuffer = (char *) xmalloc(sector_size);
3498 seek_sector(offset);
3499 if (read(fd, pe->sectorbuffer, sector_size) != sector_size)
3500 fdisk_fatal(unable_to_read);
3501 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3504 pe->part_table = pe->ext_pointer = NULL;
3508 get_partition_start(const struct pte *pe) {
3509 return pe->offset + get_start_sect(pe->part_table);
3512 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3514 * Avoid warning about DOS partitions when no DOS partition was changed.
3515 * Here a heuristic "is probably dos partition".
3516 * We might also do the opposite and warn in all cases except
3517 * for "is probably nondos partition".
3520 is_dos_partition(int t) {
3521 return (t == 1 || t == 4 || t == 6 ||
3522 t == 0x0b || t == 0x0c || t == 0x0e ||
3523 t == 0x11 || t == 0x12 || t == 0x14 || t == 0x16 ||
3524 t == 0x1b || t == 0x1c || t == 0x1e || t == 0x24 ||
3525 t == 0xc1 || t == 0xc4 || t == 0xc6);
3530 #ifdef CONFIG_FEATURE_SUN_LABEL
3532 puts(_("Command action"));
3533 puts(_("\ta\ttoggle a read only flag")); /* sun */
3534 puts(_("\tb\tedit bsd disklabel"));
3535 puts(_("\tc\ttoggle the mountable flag")); /* sun */
3536 puts(_("\td\tdelete a partition"));
3537 puts(_("\tl\tlist known partition types"));
3538 puts(_("\tm\tprint this menu"));
3539 puts(_("\tn\tadd a new partition"));
3540 puts(_("\to\tcreate a new empty DOS partition table"));
3541 puts(_("\tp\tprint the partition table"));
3542 puts(_("\tq\tquit without saving changes"));
3543 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3544 puts(_("\tt\tchange a partition's system id"));
3545 puts(_("\tu\tchange display/entry units"));
3546 puts(_("\tv\tverify the partition table"));
3547 puts(_("\tw\twrite table to disk and exit"));
3548 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3549 puts(_("\tx\textra functionality (experts only)"));
3553 #ifdef CONFIG_FEATURE_SGI_LABEL
3555 puts(_("Command action"));
3556 puts(_("\ta\tselect bootable partition")); /* sgi flavour */
3557 puts(_("\tb\tedit bootfile entry")); /* sgi */
3558 puts(_("\tc\tselect sgi swap partition")); /* sgi flavour */
3559 puts(_("\td\tdelete a partition"));
3560 puts(_("\tl\tlist known partition types"));
3561 puts(_("\tm\tprint this menu"));
3562 puts(_("\tn\tadd a new partition"));
3563 puts(_("\to\tcreate a new empty DOS partition table"));
3564 puts(_("\tp\tprint the partition table"));
3565 puts(_("\tq\tquit without saving changes"));
3566 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3567 puts(_("\tt\tchange a partition's system id"));
3568 puts(_("\tu\tchange display/entry units"));
3569 puts(_("\tv\tverify the partition table"));
3570 puts(_("\tw\twrite table to disk and exit"));
3573 #ifdef CONFIG_FEATURE_AIX_LABEL
3575 puts(_("Command action"));
3576 puts(_("\tm\tprint this menu"));
3577 puts(_("\to\tcreate a new empty DOS partition table"));
3578 puts(_("\tq\tquit without saving changes"));
3579 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3583 puts(_("Command action"));
3584 puts(_("\ta\ttoggle a bootable flag"));
3585 puts(_("\tb\tedit bsd disklabel"));
3586 puts(_("\tc\ttoggle the dos compatibility flag"));
3587 puts(_("\td\tdelete a partition"));
3588 puts(_("\tl\tlist known partition types"));
3589 puts(_("\tm\tprint this menu"));
3590 puts(_("\tn\tadd a new partition"));
3591 puts(_("\to\tcreate a new empty DOS partition table"));
3592 puts(_("\tp\tprint the partition table"));
3593 puts(_("\tq\tquit without saving changes"));
3594 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3595 puts(_("\tt\tchange a partition's system id"));
3596 puts(_("\tu\tchange display/entry units"));
3597 puts(_("\tv\tverify the partition table"));
3598 puts(_("\tw\twrite table to disk and exit"));
3599 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3600 puts(_("\tx\textra functionality (experts only)"));
3604 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3607 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3610 #ifdef CONFIG_FEATURE_SUN_LABEL
3612 puts(_("Command action"));
3613 puts(_("\ta\tchange number of alternate cylinders")); /*sun*/
3614 puts(_("\tc\tchange number of cylinders"));
3615 puts(_("\td\tprint the raw data in the partition table"));
3616 puts(_("\te\tchange number of extra sectors per cylinder"));/*sun*/
3617 puts(_("\th\tchange number of heads"));
3618 puts(_("\ti\tchange interleave factor")); /*sun*/
3619 puts(_("\to\tchange rotation speed (rpm)")); /*sun*/
3620 puts(_("\tm\tprint this menu"));
3621 puts(_("\tp\tprint the partition table"));
3622 puts(_("\tq\tquit without saving changes"));
3623 puts(_("\tr\treturn to main menu"));
3624 puts(_("\ts\tchange number of sectors/track"));
3625 puts(_("\tv\tverify the partition table"));
3626 puts(_("\tw\twrite table to disk and exit"));
3627 puts(_("\ty\tchange number of physical cylinders")); /*sun*/
3630 #ifdef CONFIG_FEATURE_SGI_LABEL
3632 puts(_("Command action"));
3633 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3634 puts(_("\tc\tchange number of cylinders"));
3635 puts(_("\td\tprint the raw data in the partition table"));
3636 puts(_("\te\tlist extended partitions")); /* !sun */
3637 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3638 puts(_("\th\tchange number of heads"));
3639 puts(_("\tm\tprint this menu"));
3640 puts(_("\tp\tprint the partition table"));
3641 puts(_("\tq\tquit without saving changes"));
3642 puts(_("\tr\treturn to main menu"));
3643 puts(_("\ts\tchange number of sectors/track"));
3644 puts(_("\tv\tverify the partition table"));
3645 puts(_("\tw\twrite table to disk and exit"));
3648 #ifdef CONFIG_FEATURE_AIX_LABEL
3650 puts(_("Command action"));
3651 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3652 puts(_("\tc\tchange number of cylinders"));
3653 puts(_("\td\tprint the raw data in the partition table"));
3654 puts(_("\te\tlist extended partitions")); /* !sun */
3655 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3656 puts(_("\th\tchange number of heads"));
3657 puts(_("\tm\tprint this menu"));
3658 puts(_("\tp\tprint the partition table"));
3659 puts(_("\tq\tquit without saving changes"));
3660 puts(_("\tr\treturn to main menu"));
3661 puts(_("\ts\tchange number of sectors/track"));
3662 puts(_("\tv\tverify the partition table"));
3663 puts(_("\tw\twrite table to disk and exit"));
3667 puts(_("Command action"));
3668 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3669 puts(_("\tc\tchange number of cylinders"));
3670 puts(_("\td\tprint the raw data in the partition table"));
3671 puts(_("\te\tlist extended partitions")); /* !sun */
3672 puts(_("\tf\tfix partition order")); /* !sun, !aix, !sgi */
3673 #ifdef CONFIG_FEATURE_SGI_LABEL
3674 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3676 puts(_("\th\tchange number of heads"));
3677 puts(_("\tm\tprint this menu"));
3678 puts(_("\tp\tprint the partition table"));
3679 puts(_("\tq\tquit without saving changes"));
3680 puts(_("\tr\treturn to main menu"));
3681 puts(_("\ts\tchange number of sectors/track"));
3682 puts(_("\tv\tverify the partition table"));
3683 puts(_("\tw\twrite table to disk and exit"));
3686 #endif /* ADVANCED mode */
3688 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3689 static const struct systypes *
3690 get_sys_types(void) {
3692 #ifdef CONFIG_FEATURE_SUN_LABEL
3693 sun_label ? sun_sys_types :
3695 #ifdef CONFIG_FEATURE_SGI_LABEL
3696 sgi_label ? sgi_sys_types :
3701 #define get_sys_types() i386_sys_types
3702 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3704 static const char *partition_type(unsigned char type)
3707 const struct systypes *types = get_sys_types();
3709 for (i=0; types[i].name; i++)
3710 if (types[i].name[0] == type)
3711 return types[i].name + 1;
3713 return _("Unknown");
3717 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3721 #ifdef CONFIG_FEATURE_SUN_LABEL
3722 sun_label ? sunlabel->infos[i].id :
3724 #ifdef CONFIG_FEATURE_SGI_LABEL
3725 sgi_label ? sgi_get_sysid(i) :
3727 ptes[i].part_table->sys_ind);
3730 void list_types(const struct systypes *sys)
3732 uint last[4], done = 0, next = 0, size;
3735 for (i = 0; sys[i].name; i++);
3738 for (i = 3; i >= 0; i--)
3739 last[3 - i] = done += (size + i - done) / (i + 1);
3743 printf("%c%2x %-15.15s", i ? ' ' : '\n',
3744 sys[next].name[0], partition_type(sys[next].name[0]));
3745 next = last[i++] + done;
3746 if (i > 3 || next >= last[i]) {
3750 } while (done < last[0]);
3753 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3756 is_cleared_partition(const struct partition *p) {
3757 return !(!p || p->boot_ind || p->head || p->sector || p->cyl ||
3758 p->sys_ind || p->end_head || p->end_sector || p->end_cyl ||
3759 get_start_sect(p) || get_nr_sects(p));
3763 clear_partition(struct partition *p) {
3766 memset(p, 0, sizeof(struct partition));
3769 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3771 set_partition(int i, int doext, uint start, uint stop, int sysid) {
3772 struct partition *p;
3776 p = ptes[i].ext_pointer;
3777 offset = extended_offset;
3779 p = ptes[i].part_table;
3780 offset = ptes[i].offset;
3784 set_start_sect(p, start - offset);
3785 set_nr_sects(p, stop - start + 1);
3786 if (dos_compatible_flag && (start/(sectors*heads) > 1023))
3787 start = heads*sectors*1024 - 1;
3788 set_hsc(p->head, p->sector, p->cyl, start);
3789 if (dos_compatible_flag && (stop/(sectors*heads) > 1023))
3790 stop = heads*sectors*1024 - 1;
3791 set_hsc(p->end_head, p->end_sector, p->end_cyl, stop);
3792 ptes[i].changed = 1;
3797 test_c(const char **m, const char *mesg) {
3800 fprintf(stderr, _("You must set"));
3802 fprintf(stderr, " %s", *m);
3810 warn_geometry(void) {
3811 const char *m = NULL;
3815 prev = test_c(&m, _("heads"));
3817 prev = test_c(&m, _("sectors"));
3819 prev = test_c(&m, _("cylinders"));
3823 fprintf(stderr, "%s%s.\n"
3824 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3825 "You can do this from the extra functions menu.\n"
3827 , prev ? _(" and ") : " ", m);
3832 static void update_units(void)
3834 int cyl_units = heads * sectors;
3836 if (display_in_cyl_units && cyl_units)
3837 units_per_sector = cyl_units;
3839 units_per_sector = 1; /* in sectors */
3842 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3844 warn_cylinders(void) {
3845 if (dos_label && cylinders > 1024 && !nowarn)
3846 fprintf(stderr, _("\n"
3847 "The number of cylinders for this disk is set to %d.\n"
3848 "There is nothing wrong with that, but this is larger than 1024,\n"
3849 "and could in certain setups cause problems with:\n"
3850 "1) software that runs at boot time (e.g., old versions of LILO)\n"
3851 "2) booting and partitioning software from other OSs\n"
3852 " (e.g., DOS FDISK, OS/2 FDISK)\n"),
3858 read_extended(int ext) {
3861 struct partition *p, *q;
3865 pex->ext_pointer = pex->part_table;
3867 p = pex->part_table;
3868 if (!get_start_sect(p)) {
3870 _("Bad offset in primary extended partition\n"));
3874 while (IS_EXTENDED (p->sys_ind)) {
3875 struct pte *pe = &ptes[partitions];
3877 if (partitions >= MAXIMUM_PARTS) {
3878 /* This is not a Linux restriction, but
3879 this program uses arrays of size MAXIMUM_PARTS.
3880 Do not try to `improve' this test. */
3881 struct pte *pre = &ptes[partitions-1];
3882 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3884 _("Warning: deleting partitions after %d\n"),
3888 clear_partition(pre->ext_pointer);
3892 read_pte(pe, extended_offset + get_start_sect(p));
3894 if (!extended_offset)
3895 extended_offset = get_start_sect(p);
3897 q = p = pt_offset(pe->sectorbuffer, 0);
3898 for (i = 0; i < 4; i++, p++) if (get_nr_sects(p)) {
3899 if (IS_EXTENDED (p->sys_ind)) {
3900 if (pe->ext_pointer)
3902 _("Warning: extra link "
3903 "pointer in partition table"
3904 " %d\n"), partitions + 1);
3906 pe->ext_pointer = p;
3907 } else if (p->sys_ind) {
3910 _("Warning: ignoring extra "
3911 "data in partition table"
3912 " %d\n"), partitions + 1);
3918 /* very strange code here... */
3919 if (!pe->part_table) {
3920 if (q != pe->ext_pointer)
3923 pe->part_table = q + 1;
3925 if (!pe->ext_pointer) {
3926 if (q != pe->part_table)
3927 pe->ext_pointer = q;
3929 pe->ext_pointer = q + 1;
3932 p = pe->ext_pointer;
3936 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3937 /* remove empty links */
3939 for (i = 4; i < partitions; i++) {
3940 struct pte *pe = &ptes[i];
3942 if (!get_nr_sects(pe->part_table) &&
3943 (partitions > 5 || ptes[4].part_table->sys_ind)) {
3944 printf("omitting empty partition (%d)\n", i+1);
3945 delete_partition(i);
3946 goto remove; /* numbering changed */
3952 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3954 create_doslabel(void) {
3958 _("Building a new DOS disklabel. Changes will remain in memory only,\n"
3959 "until you decide to write them. After that, of course, the previous\n"
3960 "content won't be recoverable.\n\n"));
3961 #ifdef CONFIG_FEATURE_SUN_LABEL
3962 sun_nolabel(); /* otherwise always recognised as sun */
3964 #ifdef CONFIG_FEATURE_SGI_LABEL
3965 sgi_nolabel(); /* otherwise always recognised as sgi */
3967 #ifdef CONFIG_FEATURE_AIX_LABEL
3970 #ifdef CONFIG_FEATURE_OSF_LABEL
3972 possibly_osf_label = 0;
3976 for (i = 510-64; i < 510; i++)
3978 write_part_table_flag(MBRbuffer);
3979 extended_offset = 0;
3980 set_all_unchanged();
3982 get_boot(create_empty_dos);
3984 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3987 get_sectorsize(void) {
3988 if (!user_set_sector_size &&
3989 get_kernel_revision() >= MAKE_VERSION(2,3,3)) {
3991 if (ioctl(fd, BLKSSZGET, &arg) == 0)
3993 if (sector_size != DEFAULT_SECTOR_SIZE)
3994 printf(_("Note: sector size is %d (not %d)\n"),
3995 sector_size, DEFAULT_SECTOR_SIZE);
4000 get_kernel_geometry(void) {
4001 struct hd_geometry geometry;
4003 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
4004 kern_heads = geometry.heads;
4005 kern_sectors = geometry.sectors;
4006 /* never use geometry.cylinders - it is truncated */
4011 get_partition_table_geometry(void) {
4012 const unsigned char *bufp = MBRbuffer;
4013 struct partition *p;
4014 int i, h, s, hh, ss;
4018 if (!(valid_part_table_flag(bufp)))
4022 for (i=0; i<4; i++) {
4023 p = pt_offset(bufp, i);
4024 if (p->sys_ind != 0) {
4025 h = p->end_head + 1;
4026 s = (p->end_sector & 077);
4031 } else if (hh != h || ss != s)
4036 if (!first && !bad) {
4043 get_geometry(void) {
4045 unsigned long long bytes; /* really u64 */
4048 sec_fac = sector_size / 512;
4049 #ifdef CONFIG_FEATURE_SUN_LABEL
4050 guess_device_type();
4052 heads = cylinders = sectors = 0;
4053 kern_heads = kern_sectors = 0;
4054 pt_heads = pt_sectors = 0;
4056 get_kernel_geometry();
4057 get_partition_table_geometry();
4059 heads = user_heads ? user_heads :
4060 pt_heads ? pt_heads :
4061 kern_heads ? kern_heads : 255;
4062 sectors = user_sectors ? user_sectors :
4063 pt_sectors ? pt_sectors :
4064 kern_sectors ? kern_sectors : 63;
4065 if (ioctl(fd, BLKGETSIZE64, &bytes) == 0) {
4068 unsigned long longsectors;
4070 if (ioctl(fd, BLKGETSIZE, &longsectors))
4072 bytes = ((unsigned long long) longsectors) << 9;
4075 total_number_of_sectors = (bytes >> 9);
4078 if (dos_compatible_flag)
4079 sector_offset = sectors;
4081 cylinders = total_number_of_sectors / (heads * sectors * sec_fac);
4083 cylinders = user_cylinders;
4087 * Read MBR. Returns:
4088 * -1: no 0xaa55 flag present (possibly entire disk BSD)
4089 * 0: found or created label
4093 get_boot(enum action what) {
4098 for (i = 0; i < 4; i++) {
4099 struct pte *pe = &ptes[i];
4101 pe->part_table = pt_offset(MBRbuffer, i);
4102 pe->ext_pointer = NULL;
4104 pe->sectorbuffer = MBRbuffer;
4105 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4106 pe->changed = (what == create_empty_dos);
4110 #ifdef CONFIG_FEATURE_SUN_LABEL
4111 if (what == create_empty_sun && check_sun_label())
4115 memset(MBRbuffer, 0, 512);
4117 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4118 if (what == create_empty_dos)
4119 goto got_dos_table; /* skip reading disk */
4121 if ((fd = open(disk_device, type_open)) < 0) {
4122 if ((fd = open(disk_device, O_RDONLY)) < 0) {
4123 if (what == try_only)
4125 fdisk_fatal(unable_to_open);
4127 printf(_("You will not be able to write "
4128 "the partition table.\n"));
4131 if (512 != read(fd, MBRbuffer, 512)) {
4132 if (what == try_only)
4134 fdisk_fatal(unable_to_read);
4137 if ((fd = open(disk_device, O_RDONLY)) < 0)
4139 if (512 != read(fd, MBRbuffer, 512))
4147 #ifdef CONFIG_FEATURE_SUN_LABEL
4148 if (check_sun_label())
4152 #ifdef CONFIG_FEATURE_SGI_LABEL
4153 if (check_sgi_label())
4157 #ifdef CONFIG_FEATURE_AIX_LABEL
4158 if (check_aix_label())
4162 #ifdef CONFIG_FEATURE_OSF_LABEL
4163 if (check_osf_label()) {
4164 possibly_osf_label = 1;
4165 if (!valid_part_table_flag(MBRbuffer)) {
4169 printf(_("This disk has both DOS and BSD magic.\n"
4170 "Give the 'b' command to go to BSD mode.\n"));
4174 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4178 if (!valid_part_table_flag(MBRbuffer)) {
4179 #ifndef CONFIG_FEATURE_FDISK_WRITABLE
4185 _("Device contains neither a valid DOS "
4186 "partition table, nor Sun, SGI or OSF "
4189 #ifdef CONFIG_FEATURE_SUN_LABEL
4198 case create_empty_dos:
4199 #ifdef CONFIG_FEATURE_SUN_LABEL
4200 case create_empty_sun:
4204 fprintf(stderr, _("Internal error\n"));
4207 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
4210 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4215 for (i = 0; i < 4; i++) {
4216 struct pte *pe = &ptes[i];
4218 if (IS_EXTENDED (pe->part_table->sys_ind)) {
4219 if (partitions != 4)
4220 fprintf(stderr, _("Ignoring extra extended "
4221 "partition %d\n"), i + 1);
4227 for (i = 3; i < partitions; i++) {
4228 struct pte *pe = &ptes[i];
4230 if (!valid_part_table_flag(pe->sectorbuffer)) {
4232 _("Warning: invalid flag 0x%04x of partition "
4233 "table %d will be corrected by w(rite)\n"),
4234 part_table_flag(pe->sectorbuffer), i + 1);
4235 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4244 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4246 * Print the message MESG, then read an integer between LOW and HIGH (inclusive).
4247 * If the user hits Enter, DFLT is returned.
4248 * Answers like +10 are interpreted as offsets from BASE.
4250 * There is no default if DFLT is not between LOW and HIGH.
4253 read_int(uint low, uint dflt, uint high, uint base, char *mesg)
4257 static char *ms = NULL;
4258 static int mslen = 0;
4260 if (!ms || strlen(mesg)+100 > mslen) {
4261 mslen = strlen(mesg)+200;
4262 ms = xrealloc(ms,mslen);
4265 if (dflt < low || dflt > high)
4269 snprintf(ms, mslen, _("%s (%u-%u, default %u): "),
4270 mesg, low, high, dflt);
4272 snprintf(ms, mslen, "%s (%u-%u): ",
4276 int use_default = default_ok;
4278 /* ask question and read answer */
4279 while (read_chars(ms) != '\n' && !isdigit(*line_ptr)
4280 && *line_ptr != '-' && *line_ptr != '+')
4283 if (*line_ptr == '+' || *line_ptr == '-') {
4284 int minus = (*line_ptr == '-');
4287 i = atoi(line_ptr+1);
4289 while (isdigit(*++line_ptr))
4292 switch (*line_ptr) {
4295 if (!display_in_cyl_units)
4296 i *= heads * sectors;
4310 absolute = 1000000000;
4316 unsigned long long bytes;
4319 bytes = (unsigned long long) i * absolute;
4320 unit = sector_size * units_per_sector;
4321 bytes += unit/2; /* round */
4330 while (isdigit(*line_ptr)) {
4336 printf(_("Using default value %u\n"), i = dflt);
4337 if (i >= low && i <= high)
4340 printf(_("Value out of range.\n"));
4346 get_partition(int warn, int max) {
4350 i = read_int(1, 0, max, 0, _("Partition number")) - 1;
4354 if ((!sun_label && !sgi_label && !pe->part_table->sys_ind)
4355 #ifdef CONFIG_FEATURE_SUN_LABEL
4357 (!sunlabel->partitions[i].num_sectors ||
4358 !sunlabel->infos[i].id))
4360 #ifdef CONFIG_FEATURE_SGI_LABEL
4361 || (sgi_label && (!sgi_get_num_sectors(i)))
4365 _("Warning: partition %d has empty type\n"),
4372 get_existing_partition(int warn, int max) {
4376 for (i = 0; i < max; i++) {
4377 struct pte *pe = &ptes[i];
4378 struct partition *p = pe->part_table;
4380 if (p && !is_cleared_partition(p)) {
4387 printf(_("Selected partition %d\n"), pno+1);
4390 printf(_("No partition is defined yet!\n"));
4394 return get_partition(warn, max);
4398 get_nonexisting_partition(int warn, int max) {
4402 for (i = 0; i < max; i++) {
4403 struct pte *pe = &ptes[i];
4404 struct partition *p = pe->part_table;
4406 if (p && is_cleared_partition(p)) {
4413 printf(_("Selected partition %d\n"), pno+1);
4416 printf(_("All primary partitions have been defined already!\n"));
4420 return get_partition(warn, max);
4424 void change_units(void)
4426 display_in_cyl_units = !display_in_cyl_units;
4428 printf(_("Changing display/entry units to %s\n"),
4433 toggle_active(int i) {
4434 struct pte *pe = &ptes[i];
4435 struct partition *p = pe->part_table;
4437 if (IS_EXTENDED (p->sys_ind) && !p->boot_ind)
4439 _("WARNING: Partition %d is an extended partition\n"),
4441 p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG);
4446 toggle_dos_compatibility_flag(void) {
4447 dos_compatible_flag = ~dos_compatible_flag;
4448 if (dos_compatible_flag) {
4449 sector_offset = sectors;
4450 printf(_("DOS Compatibility flag is set\n"));
4454 printf(_("DOS Compatibility flag is not set\n"));
4459 delete_partition(int i) {
4460 struct pte *pe = &ptes[i];
4461 struct partition *p = pe->part_table;
4462 struct partition *q = pe->ext_pointer;
4464 /* Note that for the fifth partition (i == 4) we don't actually
4465 * decrement partitions.
4468 if (warn_geometry())
4469 return; /* C/H/S not set */
4472 #ifdef CONFIG_FEATURE_SUN_LABEL
4474 sun_delete_partition(i);
4478 #ifdef CONFIG_FEATURE_SGI_LABEL
4480 sgi_delete_partition(i);
4486 if (IS_EXTENDED (p->sys_ind) && i == ext_index) {
4488 ptes[ext_index].ext_pointer = NULL;
4489 extended_offset = 0;
4495 if (!q->sys_ind && i > 4) {
4496 /* the last one in the chain - just delete */
4499 clear_partition(ptes[i].ext_pointer);
4500 ptes[i].changed = 1;
4502 /* not the last one - further ones will be moved down */
4504 /* delete this link in the chain */
4505 p = ptes[i-1].ext_pointer;
4507 set_start_sect(p, get_start_sect(q));
4508 set_nr_sects(p, get_nr_sects(q));
4509 ptes[i-1].changed = 1;
4510 } else if (partitions > 5) { /* 5 will be moved to 4 */
4511 /* the first logical in a longer chain */
4514 if (pe->part_table) /* prevent SEGFAULT */
4515 set_start_sect(pe->part_table,
4516 get_partition_start(pe) -
4518 pe->offset = extended_offset;
4522 if (partitions > 5) {
4524 while (i < partitions) {
4525 ptes[i] = ptes[i+1];
4529 /* the only logical: clear only */
4530 clear_partition(ptes[i].part_table);
4535 change_sysid(void) {
4536 int i, sys, origsys;
4537 struct partition *p;
4539 #ifdef CONFIG_FEATURE_SGI_LABEL
4540 /* If sgi_label then don't use get_existing_partition,
4541 let the user select a partition, since get_existing_partition()
4542 only works for Linux like partition tables. */
4544 i = get_existing_partition(0, partitions);
4546 i = get_partition(0, partitions);
4549 i = get_existing_partition(0, partitions);
4553 p = ptes[i].part_table;
4554 origsys = sys = get_sysid(i);
4556 /* if changing types T to 0 is allowed, then
4557 the reverse change must be allowed, too */
4558 if (!sys && !sgi_label && !sun_label && !get_nr_sects(p))
4559 printf(_("Partition %d does not exist yet!\n"), i + 1);
4561 sys = read_hex (get_sys_types());
4563 if (!sys && !sgi_label && !sun_label) {
4564 printf(_("Type 0 means free space to many systems\n"
4565 "(but not to Linux). Having partitions of\n"
4566 "type 0 is probably unwise. You can delete\n"
4567 "a partition using the `d' command.\n"));
4571 if (!sun_label && !sgi_label) {
4572 if (IS_EXTENDED (sys) != IS_EXTENDED (p->sys_ind)) {
4573 printf(_("You cannot change a partition into"
4574 " an extended one or vice versa\n"
4575 "Delete it first.\n"));
4581 #ifdef CONFIG_FEATURE_SUN_LABEL
4582 if (sun_label && i == 2 && sys != WHOLE_DISK)
4583 printf(_("Consider leaving partition 3 "
4584 "as Whole disk (5),\n"
4585 "as SunOS/Solaris expects it and "
4586 "even Linux likes it.\n\n"));
4588 #ifdef CONFIG_FEATURE_SGI_LABEL
4589 if (sgi_label && ((i == 10 && sys != ENTIRE_DISK)
4590 || (i == 8 && sys != 0)))
4591 printf(_("Consider leaving partition 9 "
4592 "as volume header (0),\nand "
4593 "partition 11 as entire volume (6)"
4594 "as IRIX expects it.\n\n"));
4598 #ifdef CONFIG_FEATURE_SUN_LABEL
4600 sun_change_sysid(i, sys);
4603 #ifdef CONFIG_FEATURE_SGI_LABEL
4605 sgi_change_sysid(i, sys);
4609 printf (_("Changed system type of partition %d "
4610 "to %x (%s)\n"), i + 1, sys,
4611 partition_type(sys));
4612 ptes[i].changed = 1;
4613 if (is_dos_partition(origsys) ||
4614 is_dos_partition(sys))
4620 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
4623 /* check_consistency() and long2chs() added Sat Mar 6 12:28:16 1993,
4624 * faith@cs.unc.edu, based on code fragments from pfdisk by Gordon W. Ross,
4625 * Jan. 1990 (version 1.2.1 by Gordon W. Ross Aug. 1990; Modified by S.
4626 * Lubkin Oct. 1991). */
4628 static void long2chs(ulong ls, uint *c, uint *h, uint *s) {
4629 int spc = heads * sectors;
4634 *s = ls % sectors + 1; /* sectors count from 1 */
4637 static void check_consistency(const struct partition *p, int partition) {
4638 uint pbc, pbh, pbs; /* physical beginning c, h, s */
4639 uint pec, peh, pes; /* physical ending c, h, s */
4640 uint lbc, lbh, lbs; /* logical beginning c, h, s */
4641 uint lec, leh, les; /* logical ending c, h, s */
4643 if (!heads || !sectors || (partition >= 4))
4644 return; /* do not check extended partitions */
4646 /* physical beginning c, h, s */
4647 pbc = (p->cyl & 0xff) | ((p->sector << 2) & 0x300);
4649 pbs = p->sector & 0x3f;
4651 /* physical ending c, h, s */
4652 pec = (p->end_cyl & 0xff) | ((p->end_sector << 2) & 0x300);
4654 pes = p->end_sector & 0x3f;
4656 /* compute logical beginning (c, h, s) */
4657 long2chs(get_start_sect(p), &lbc, &lbh, &lbs);
4659 /* compute logical ending (c, h, s) */
4660 long2chs(get_start_sect(p) + get_nr_sects(p) - 1, &lec, &leh, &les);
4662 /* Same physical / logical beginning? */
4663 if (cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) {
4664 printf(_("Partition %d has different physical/logical "
4665 "beginnings (non-Linux?):\n"), partition + 1);
4666 printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs);
4667 printf(_("logical=(%d, %d, %d)\n"),lbc, lbh, lbs);
4670 /* Same physical / logical ending? */
4671 if (cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) {
4672 printf(_("Partition %d has different physical/logical "
4673 "endings:\n"), partition + 1);
4674 printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
4675 printf(_("logical=(%d, %d, %d)\n"),lec, leh, les);
4679 /* Beginning on cylinder boundary? */
4680 if (pbh != !pbc || pbs != 1) {
4681 printf(_("Partition %i does not start on cylinder "
4682 "boundary:\n"), partition + 1);
4683 printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs);
4684 printf(_("should be (%d, %d, 1)\n"), pbc, !pbc);
4688 /* Ending on cylinder boundary? */
4689 if (peh != (heads - 1) || pes != sectors) {
4690 printf(_("Partition %i does not end on cylinder boundary.\n"),
4693 printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
4694 printf(_("should be (%d, %d, %d)\n"),
4695 pec, heads - 1, sectors);
4701 list_disk_geometry(void) {
4702 long long bytes = (total_number_of_sectors << 9);
4703 long megabytes = bytes/1000000;
4705 if (megabytes < 10000)
4706 printf(_("\nDisk %s: %ld MB, %lld bytes\n"),
4707 disk_device, megabytes, bytes);
4709 printf(_("\nDisk %s: %ld.%ld GB, %lld bytes\n"),
4710 disk_device, megabytes/1000, (megabytes/100)%10, bytes);
4711 printf(_("%d heads, %d sectors/track, %d cylinders"),
4712 heads, sectors, cylinders);
4713 if (units_per_sector == 1)
4714 printf(_(", total %llu sectors"),
4715 total_number_of_sectors / (sector_size/512));
4716 printf(_("\nUnits = %s of %d * %d = %d bytes\n\n"),
4718 units_per_sector, sector_size, units_per_sector * sector_size);
4722 * Check whether partition entries are ordered by their starting positions.
4723 * Return 0 if OK. Return i if partition i should have been earlier.
4724 * Two separate checks: primary and logical partitions.
4727 wrong_p_order(int *prev) {
4728 const struct pte *pe;
4729 const struct partition *p;
4730 uint last_p_start_pos = 0, p_start_pos;
4733 for (i = 0 ; i < partitions; i++) {
4736 last_p_start_pos = 0;
4739 if ((p = pe->part_table)->sys_ind) {
4740 p_start_pos = get_partition_start(pe);
4742 if (last_p_start_pos > p_start_pos) {
4748 last_p_start_pos = p_start_pos;
4755 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
4757 * Fix the chain of logicals.
4758 * extended_offset is unchanged, the set of sectors used is unchanged
4759 * The chain is sorted so that sectors increase, and so that
4760 * starting sectors increase.
4762 * After this it may still be that cfdisk doesnt like the table.
4763 * (This is because cfdisk considers expanded parts, from link to
4764 * end of partition, and these may still overlap.)
4766 * sfdisk /dev/hda > ohda; sfdisk /dev/hda < ohda
4770 fix_chain_of_logicals(void) {
4771 int j, oj, ojj, sj, sjj;
4772 struct partition *pj,*pjj,tmp;
4774 /* Stage 1: sort sectors but leave sector of part 4 */
4775 /* (Its sector is the global extended_offset.) */
4777 for (j = 5; j < partitions-1; j++) {
4778 oj = ptes[j].offset;
4779 ojj = ptes[j+1].offset;
4781 ptes[j].offset = ojj;
4782 ptes[j+1].offset = oj;
4783 pj = ptes[j].part_table;
4784 set_start_sect(pj, get_start_sect(pj)+oj-ojj);
4785 pjj = ptes[j+1].part_table;
4786 set_start_sect(pjj, get_start_sect(pjj)+ojj-oj);
4787 set_start_sect(ptes[j-1].ext_pointer,
4788 ojj-extended_offset);
4789 set_start_sect(ptes[j].ext_pointer,
4790 oj-extended_offset);
4795 /* Stage 2: sort starting sectors */
4797 for (j = 4; j < partitions-1; j++) {
4798 pj = ptes[j].part_table;
4799 pjj = ptes[j+1].part_table;
4800 sj = get_start_sect(pj);
4801 sjj = get_start_sect(pjj);
4802 oj = ptes[j].offset;
4803 ojj = ptes[j+1].offset;
4804 if (oj+sj > ojj+sjj) {
4808 set_start_sect(pj, ojj+sjj-oj);
4809 set_start_sect(pjj, oj+sj-ojj);
4814 /* Probably something was changed */
4815 for (j = 4; j < partitions; j++)
4816 ptes[j].changed = 1;
4821 fix_partition_table_order(void) {
4822 struct pte *pei, *pek;
4825 if (!wrong_p_order(NULL)) {
4826 printf(_("Nothing to do. Ordering is correct already.\n\n"));
4830 while ((i = wrong_p_order(&k)) != 0 && i < 4) {
4831 /* partition i should have come earlier, move it */
4832 /* We have to move data in the MBR */
4833 struct partition *pi, *pk, *pe, pbuf;
4837 pe = pei->ext_pointer;
4838 pei->ext_pointer = pek->ext_pointer;
4839 pek->ext_pointer = pe;
4841 pi = pei->part_table;
4842 pk = pek->part_table;
4844 memmove(&pbuf, pi, sizeof(struct partition));
4845 memmove(pi, pk, sizeof(struct partition));
4846 memmove(pk, &pbuf, sizeof(struct partition));
4848 pei->changed = pek->changed = 1;
4852 fix_chain_of_logicals();
4860 list_table(int xtra) {
4861 const struct partition *p;
4864 #ifdef CONFIG_FEATURE_SUN_LABEL
4866 sun_list_table(xtra);
4871 #ifdef CONFIG_FEATURE_SGI_LABEL
4873 sgi_list_table(xtra);
4878 list_disk_geometry();
4880 #ifdef CONFIG_FEATURE_OSF_LABEL
4882 xbsd_print_disklabel(xtra);
4887 /* Heuristic: we list partition 3 of /dev/foo as /dev/foo3,
4888 but if the device name ends in a digit, say /dev/foo1,
4889 then the partition is called /dev/foo1p3. */
4890 w = strlen(disk_device);
4891 if (w && isdigit(disk_device[w-1]))
4896 printf(_("%*s Boot Start End Blocks Id System\n"),
4899 for (i = 0; i < partitions; i++) {
4900 const struct pte *pe = &ptes[i];
4903 if (p && !is_cleared_partition(p)) {
4904 unsigned int psects = get_nr_sects(p);
4905 unsigned int pblocks = psects;
4906 unsigned int podd = 0;
4908 if (sector_size < 1024) {
4909 pblocks /= (1024 / sector_size);
4910 podd = psects % (1024 / sector_size);
4912 if (sector_size > 1024)
4913 pblocks *= (sector_size / 1024);
4915 "%s %c %11lu %11lu %11lu%c %2x %s\n",
4916 partname(disk_device, i+1, w+2),
4917 /* boot flag */ !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG
4919 /* start */ (unsigned long) cround(get_partition_start(pe)),
4920 /* end */ (unsigned long) cround(get_partition_start(pe) + psects
4921 - (psects ? 1 : 0)),
4922 /* odd flag on end */ (unsigned long) pblocks, podd ? '+' : ' ',
4923 /* type id */ p->sys_ind,
4924 /* type name */ partition_type(p->sys_ind));
4925 check_consistency(p, i);
4929 /* Is partition table in disk order? It need not be, but... */
4930 /* partition table entries are not checked for correct order if this
4931 is a sgi, sun or aix labeled disk... */
4932 if (dos_label && wrong_p_order(NULL)) {
4933 printf(_("\nPartition table entries are not in disk order\n"));
4937 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
4939 x_list_table(int extend) {
4940 const struct pte *pe;
4941 const struct partition *p;
4944 printf(_("\nDisk %s: %d heads, %d sectors, %d cylinders\n\n"),
4945 disk_device, heads, sectors, cylinders);
4946 printf(_("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n"));
4947 for (i = 0 ; i < partitions; i++) {
4949 p = (extend ? pe->ext_pointer : pe->part_table);
4951 printf("%2d %02x%4d%4d%5d%4d%4d%5d%11u%11u %02x\n",
4952 i + 1, p->boot_ind, p->head,
4954 cylinder(p->sector, p->cyl), p->end_head,
4955 sector(p->end_sector),
4956 cylinder(p->end_sector, p->end_cyl),
4957 get_start_sect(p), get_nr_sects(p), p->sys_ind);
4959 check_consistency(p, i);
4965 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4967 fill_bounds(uint *first, uint *last) {
4969 const struct pte *pe = &ptes[0];
4970 const struct partition *p;
4972 for (i = 0; i < partitions; pe++,i++) {
4974 if (!p->sys_ind || IS_EXTENDED (p->sys_ind)) {
4975 first[i] = 0xffffffff;
4978 first[i] = get_partition_start(pe);
4979 last[i] = first[i] + get_nr_sects(p) - 1;
4985 check(int n, uint h, uint s, uint c, uint start) {
4986 uint total, real_s, real_c;
4988 real_s = sector(s) - 1;
4989 real_c = cylinder(s, c);
4990 total = (real_c * sectors + real_s) * heads + h;
4992 fprintf(stderr, _("Warning: partition %d contains sector 0\n"), n);
4995 _("Partition %d: head %d greater than maximum %d\n"),
4997 if (real_s >= sectors)
4998 fprintf(stderr, _("Partition %d: sector %d greater than "
4999 "maximum %d\n"), n, s, sectors);
5000 if (real_c >= cylinders)
5001 fprintf(stderr, _("Partitions %d: cylinder %d greater than "
5002 "maximum %d\n"), n, real_c + 1, cylinders);
5003 if (cylinders <= 1024 && start != total)
5005 _("Partition %d: previous sectors %d disagrees with "
5006 "total %d\n"), n, start, total);
5013 uint first[partitions], last[partitions];
5014 struct partition *p;
5016 if (warn_geometry())
5019 #ifdef CONFIG_FEATURE_SUN_LABEL
5025 #ifdef CONFIG_FEATURE_SGI_LABEL
5032 fill_bounds(first, last);
5033 for (i = 0; i < partitions; i++) {
5034 struct pte *pe = &ptes[i];
5037 if (p->sys_ind && !IS_EXTENDED (p->sys_ind)) {
5038 check_consistency(p, i);
5039 if (get_partition_start(pe) < first[i])
5040 printf(_("Warning: bad start-of-data in "
5041 "partition %d\n"), i + 1);
5042 check(i + 1, p->end_head, p->end_sector, p->end_cyl,
5044 total += last[i] + 1 - first[i];
5045 for (j = 0; j < i; j++)
5046 if ((first[i] >= first[j] && first[i] <= last[j])
5047 || ((last[i] <= last[j] && last[i] >= first[j]))) {
5048 printf(_("Warning: partition %d overlaps "
5049 "partition %d.\n"), j + 1, i + 1);
5050 total += first[i] >= first[j] ?
5051 first[i] : first[j];
5052 total -= last[i] <= last[j] ?
5058 if (extended_offset) {
5059 struct pte *pex = &ptes[ext_index];
5060 uint e_last = get_start_sect(pex->part_table) +
5061 get_nr_sects(pex->part_table) - 1;
5063 for (i = 4; i < partitions; i++) {
5065 p = ptes[i].part_table;
5067 if (i != 4 || i + 1 < partitions)
5068 printf(_("Warning: partition %d "
5069 "is empty\n"), i + 1);
5071 else if (first[i] < extended_offset ||
5073 printf(_("Logical partition %d not entirely in "
5074 "partition %d\n"), i + 1, ext_index + 1);
5078 if (total > heads * sectors * cylinders)
5079 printf(_("Total allocated sectors %d greater than the maximum "
5080 "%d\n"), total, heads * sectors * cylinders);
5081 else if ((total = heads * sectors * cylinders - total) != 0)
5082 printf(_("%d unallocated sectors\n"), total);
5086 add_partition(int n, int sys) {
5087 char mesg[256]; /* 48 does not suffice in Japanese */
5089 struct partition *p = ptes[n].part_table;
5090 struct partition *q = ptes[ext_index].part_table;
5092 uint start, stop = 0, limit, temp,
5093 first[partitions], last[partitions];
5095 if (p && p->sys_ind) {
5096 printf(_("Partition %d is already defined. Delete "
5097 "it before re-adding it.\n"), n + 1);
5100 fill_bounds(first, last);
5102 start = sector_offset;
5103 if (display_in_cyl_units || !total_number_of_sectors)
5104 llimit = heads * sectors * cylinders - 1;
5106 llimit = total_number_of_sectors - 1;
5108 if (limit != llimit)
5110 if (extended_offset) {
5111 first[ext_index] = extended_offset;
5112 last[ext_index] = get_start_sect(q) +
5113 get_nr_sects(q) - 1;
5116 start = extended_offset + sector_offset;
5117 limit = get_start_sect(q) + get_nr_sects(q) - 1;
5119 if (display_in_cyl_units)
5120 for (i = 0; i < partitions; i++)
5121 first[i] = (cround(first[i]) - 1) * units_per_sector;
5123 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
5126 for (i = 0; i < partitions; i++) {
5129 if (start == ptes[i].offset)
5130 start += sector_offset;
5131 lastplusoff = last[i] + ((n<4) ? 0 : sector_offset);
5132 if (start >= first[i] && start <= lastplusoff)
5133 start = lastplusoff + 1;
5137 if (start >= temp+units_per_sector && readed) {
5138 printf(_("Sector %d is already allocated\n"), temp);
5142 if (!readed && start == temp) {
5145 saved_start = start;
5146 start = read_int(cround(saved_start), cround(saved_start), cround(limit),
5148 if (display_in_cyl_units) {
5149 start = (start - 1) * units_per_sector;
5150 if (start < saved_start) start = saved_start;
5154 } while (start != temp || !readed);
5155 if (n > 4) { /* NOT for fifth partition */
5156 struct pte *pe = &ptes[n];
5158 pe->offset = start - sector_offset;
5159 if (pe->offset == extended_offset) { /* must be corrected */
5161 if (sector_offset == 1)
5166 for (i = 0; i < partitions; i++) {
5167 struct pte *pe = &ptes[i];
5169 if (start < pe->offset && limit >= pe->offset)
5170 limit = pe->offset - 1;
5171 if (start < first[i] && limit >= first[i])
5172 limit = first[i] - 1;
5174 if (start > limit) {
5175 printf(_("No free sectors available\n"));
5180 if (cround(start) == cround(limit)) {
5183 snprintf(mesg, sizeof(mesg),
5184 _("Last %s or +size or +sizeM or +sizeK"),
5185 str_units(SINGULAR));
5186 stop = read_int(cround(start), cround(limit), cround(limit),
5187 cround(start), mesg);
5188 if (display_in_cyl_units) {
5189 stop = stop * units_per_sector - 1;
5195 set_partition(n, 0, start, stop, sys);
5197 set_partition(n - 1, 1, ptes[n].offset, stop, EXTENDED);
5199 if (IS_EXTENDED (sys)) {
5200 struct pte *pe4 = &ptes[4];
5201 struct pte *pen = &ptes[n];
5204 pen->ext_pointer = p;
5205 pe4->offset = extended_offset = start;
5206 pe4->sectorbuffer = xcalloc(1, sector_size);
5207 pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
5208 pe4->ext_pointer = pe4->part_table + 1;
5216 if (partitions > 5 || ptes[4].part_table->sys_ind) {
5217 struct pte *pe = &ptes[partitions];
5219 pe->sectorbuffer = xcalloc(1, sector_size);
5220 pe->part_table = pt_offset(pe->sectorbuffer, 0);
5221 pe->ext_pointer = pe->part_table + 1;
5226 add_partition(partitions - 1, LINUX_NATIVE);
5230 new_partition(void) {
5231 int i, free_primary = 0;
5233 if (warn_geometry())
5236 #ifdef CONFIG_FEATURE_SUN_LABEL
5238 add_sun_partition(get_partition(0, partitions), LINUX_NATIVE);
5242 #ifdef CONFIG_FEATURE_SGI_LABEL
5244 sgi_add_partition(get_partition(0, partitions), LINUX_NATIVE);
5248 #ifdef CONFIG_FEATURE_AIX_LABEL
5250 printf(_("\tSorry - this fdisk cannot handle AIX disk labels."
5251 "\n\tIf you want to add DOS-type partitions, create"
5252 "\n\ta new empty DOS partition table first. (Use o.)"
5254 "This will destroy the present disk contents.\n"));
5259 for (i = 0; i < 4; i++)
5260 free_primary += !ptes[i].part_table->sys_ind;
5262 if (!free_primary && partitions >= MAXIMUM_PARTS) {
5263 printf(_("The maximum number of partitions has been created\n"));
5267 if (!free_primary) {
5268 if (extended_offset)
5271 printf(_("You must delete some partition and add "
5272 "an extended partition first\n"));
5274 char c, line[LINE_LENGTH];
5275 snprintf(line, sizeof(line), "%s\n %s\n p primary "
5276 "partition (1-4)\n",
5277 "Command action", (extended_offset ?
5278 "l logical (5 or over)" : "e extended"));
5280 if ((c = read_char(line)) == 'p' || c == 'P') {
5281 i = get_nonexisting_partition(0, 4);
5283 add_partition(i, LINUX_NATIVE);
5286 else if (c == 'l' && extended_offset) {
5290 else if (c == 'e' && !extended_offset) {
5291 i = get_nonexisting_partition(0, 4);
5293 add_partition(i, EXTENDED);
5297 printf(_("Invalid partition number "
5298 "for type `%c'\n"), c);
5309 if (ptes[i].changed)
5310 ptes[3].changed = 1;
5311 for (i = 3; i < partitions; i++) {
5312 struct pte *pe = &ptes[i];
5315 write_part_table_flag(pe->sectorbuffer);
5316 write_sector(pe->offset, pe->sectorbuffer);
5320 #ifdef CONFIG_FEATURE_SGI_LABEL
5321 else if (sgi_label) {
5322 /* no test on change? the printf below might be mistaken */
5326 #ifdef CONFIG_FEATURE_SUN_LABEL
5327 else if (sun_label) {
5331 if (ptes[i].changed)
5338 printf(_("The partition table has been altered!\n\n"));
5339 reread_partition_table(1);
5343 reread_partition_table(int leave) {
5347 printf(_("Calling ioctl() to re-read partition table.\n"));
5350 if ((i = ioctl(fd, BLKRRPART)) != 0) {
5353 /* some kernel versions (1.2.x) seem to have trouble
5354 rereading the partition table, but if asked to do it
5355 twice, the second time works. - biro@yggdrasil.com */
5358 if ((i = ioctl(fd, BLKRRPART)) != 0)
5363 printf(_("\nWARNING: Re-reading the partition table "
5364 "failed with error %d: %s.\n"
5365 "The kernel still uses the old table.\n"
5366 "The new table will be used "
5367 "at the next reboot.\n"),
5368 error, strerror(error));
5373 _("\nWARNING: If you have created or modified any DOS 6.x\n"
5374 "partitions, please see the fdisk manual page for additional\n"
5380 printf(_("Syncing disks.\n"));
5382 sleep(4); /* for sync() */
5386 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
5388 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
5389 #define MAX_PER_LINE 16
5391 print_buffer(char pbuffer[]) {
5395 for (i = 0, l = 0; i < sector_size; i++, l++) {
5397 printf("0x%03X:", i);
5398 printf(" %02X", (unsigned char) pbuffer[i]);
5399 if (l == MAX_PER_LINE - 1) {
5414 printf(_("Device: %s\n"), disk_device);
5415 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
5416 if (sun_label || sgi_label)
5417 print_buffer(MBRbuffer);
5420 for (i = 3; i < partitions; i++)
5421 print_buffer(ptes[i].sectorbuffer);
5426 struct pte *pe = &ptes[i];
5427 struct partition *p = pe->part_table;
5430 if (warn_geometry())
5432 if (!p->sys_ind || !get_nr_sects(p) || IS_EXTENDED (p->sys_ind)) {
5433 printf(_("Partition %d has no data area\n"), i + 1);
5436 first = get_partition_start(pe);
5437 new = read_int(first, first, first + get_nr_sects(p) - 1, first,
5438 _("New beginning of data")) - pe->offset;
5440 if (new != get_nr_sects(p)) {
5441 first = get_nr_sects(p) + get_start_sect(p) - new;
5442 set_nr_sects(p, first);
5443 set_start_sect(p, new);
5454 c = tolower(read_char(_("Expert command (m for help): ")));
5457 #ifdef CONFIG_FEATURE_SUN_LABEL
5464 move_begin(get_partition(0, partitions));
5467 user_cylinders = cylinders =
5468 read_int(1, cylinders, 1048576, 0,
5469 _("Number of cylinders"));
5470 #ifdef CONFIG_FEATURE_SUN_LABEL
5472 sun_set_ncyl(cylinders);
5481 #ifdef CONFIG_FEATURE_SGI_LABEL
5486 #ifdef CONFIG_FEATURE_SUN_LABEL
5496 fix_partition_table_order();
5499 #ifdef CONFIG_FEATURE_SGI_LABEL
5504 user_heads = heads = read_int(1, heads, 256, 0,
5505 _("Number of heads"));
5509 #ifdef CONFIG_FEATURE_SUN_LABEL
5515 #ifdef CONFIG_FEATURE_SUN_LABEL
5521 #ifdef CONFIG_FEATURE_SUN_LABEL
5535 user_sectors = sectors = read_int(1, sectors, 63, 0,
5536 _("Number of sectors"));
5537 if (dos_compatible_flag) {
5538 sector_offset = sectors;
5539 fprintf(stderr, _("Warning: setting "
5540 "sector offset for DOS "
5549 write_table(); /* does not return */
5552 #ifdef CONFIG_FEATURE_SUN_LABEL
5554 sun_set_pcylcount();
5562 #endif /* ADVANCED mode */
5565 is_ide_cdrom_or_tape(const char *device) {
5568 struct stat statbuf;
5571 /* No device was given explicitly, and we are trying some
5572 likely things. But opening /dev/hdc may produce errors like
5573 "hdc: tray open or drive not ready"
5574 if it happens to be a CD-ROM drive. It even happens that
5575 the process hangs on the attempt to read a music CD.
5576 So try to be careful. This only works since 2.1.73. */
5578 if (strncmp("/dev/hd", device, 7))
5581 snprintf(buf, sizeof(buf), "/proc/ide/%s/media", device+5);
5582 procf = fopen(buf, "r");
5583 if (procf != NULL && fgets(buf, sizeof(buf), procf))
5584 is_ide = (!strncmp(buf, "cdrom", 5) ||
5585 !strncmp(buf, "tape", 4));
5587 /* Now when this proc file does not exist, skip the
5588 device when it is read-only. */
5589 if (stat(device, &statbuf) == 0)
5590 is_ide = ((statbuf.st_mode & 0222) == 0);
5598 try(const char *device, int user_specified) {
5601 disk_device = device;
5602 if (setjmp(listingbuf))
5604 if (!user_specified)
5605 if (is_ide_cdrom_or_tape(device))
5607 if ((fd = open(disk_device, type_open)) >= 0) {
5608 gb = get_boot(try_only);
5609 if (gb > 0) { /* I/O error */
5611 } else if (gb < 0) { /* no DOS signature */
5612 list_disk_geometry();
5615 #ifdef CONFIG_FEATURE_OSF_LABEL
5616 if (btrydev(device) < 0)
5619 _("Disk %s doesn't contain a valid "
5620 "partition table\n"), device);
5625 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5626 if (!sun_label && partitions > 4)
5627 delete_partition(ext_index);
5631 /* Ignore other errors, since we try IDE
5632 and SCSI hard disks which may not be
5633 installed on the system. */
5634 if (errno == EACCES) {
5635 fprintf(stderr, _("Cannot open %s\n"), device);
5641 /* for fdisk -l: try all things in /proc/partitions
5642 that look like a partition name (do not end in a digit) */
5646 char line[100], ptname[100], devname[120], *s;
5649 procpt = bb_wfopen(PROC_PARTITIONS, "r");
5651 while (fgets(line, sizeof(line), procpt)) {
5652 if (sscanf (line, " %d %d %d %[^\n ]",
5653 &ma, &mi, &sz, ptname) != 4)
5655 for (s = ptname; *s; s++);
5658 sprintf(devname, "/dev/%s", ptname);
5661 #ifdef CONFIG_FEATURE_CLEAN_UP
5666 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5668 unknown_command(int c) {
5669 printf(_("%c: unknown command\n"), c);
5673 int fdisk_main(int argc, char **argv) {
5675 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5678 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5684 * fdisk -l [-b sectorsize] [-u] device ...
5685 * fdisk -s [partition] ...
5686 * fdisk [-b sectorsize] [-u] device
5688 * Options -C, -H, -S set the geometry.
5691 while ((c = getopt(argc, argv, "b:C:H:lS:uvV"
5692 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5698 /* Ugly: this sector size is really per device,
5699 so cannot be combined with multiple disks,
5700 and te same goes for the C/H/S options.
5702 sector_size = atoi(optarg);
5703 if (sector_size != 512 && sector_size != 1024 &&
5704 sector_size != 2048)
5707 user_set_sector_size = 1;
5710 user_cylinders = atoi(optarg);
5713 user_heads = atoi(optarg);
5714 if (user_heads <= 0 || user_heads >= 256)
5718 user_sectors = atoi(optarg);
5719 if (user_sectors <= 0 || user_sectors >= 64)
5723 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5727 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5733 display_in_cyl_units = 0;
5737 printf("fdisk v" UTIL_LINUX_VERSION "\n");
5745 printf(_("This kernel finds the sector size itself - "
5746 "-b option ignored\n"));
5748 if (user_set_sector_size && argc-optind != 1)
5749 printf(_("Warning: the -b (set sector size) option should"
5750 " be used with one specified device\n"));
5753 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5757 type_open = O_RDONLY;
5758 if (argc > optind) {
5761 /* avoid gcc warning:
5762 variable `k' might be clobbered by `longjmp' */
5766 for (k=optind; k<argc; k++)
5769 /* we no longer have default device names */
5770 /* but, we can use /proc/partitions instead */
5774 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5778 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5784 type_open = O_RDONLY;
5786 opts = argc - optind;
5790 for (j = optind; j < argc; j++) {
5791 disk_device = argv[j];
5792 if ((fd = open(disk_device, type_open)) < 0)
5793 fdisk_fatal(unable_to_open);
5794 if (ioctl(fd, BLKGETSIZE, &size))
5795 fdisk_fatal(ioctl_error);
5798 printf("%ld\n", size/2);
5800 printf("%s: %ld\n", argv[j], size/2);
5806 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5807 if (argc-optind == 1)
5808 disk_device = argv[optind];
5814 #ifdef CONFIG_FEATURE_OSF_LABEL
5816 /* OSF label, and no DOS label */
5817 printf(_("Detected an OSF/1 disklabel on %s, entering "
5818 "disklabel mode.\n"),
5822 /* If we return we may want to make an empty DOS label? */
5828 c = tolower(read_char(_("Command (m for help): ")));
5832 toggle_active(get_partition(1, partitions));
5833 #ifdef CONFIG_FEATURE_SUN_LABEL
5835 toggle_sunflags(get_partition(1, partitions),
5838 #ifdef CONFIG_FEATURE_SGI_LABEL
5840 sgi_set_bootpartition(
5841 get_partition(1, partitions));
5847 #ifdef CONFIG_FEATURE_SGI_LABEL
5849 printf(_("\nThe current boot file is: %s\n"),
5850 sgi_get_bootfile());
5851 if (read_chars(_("Please enter the name of the "
5852 "new boot file: ")) == '\n')
5853 printf(_("Boot file unchanged\n"));
5855 sgi_set_bootfile(line_ptr);
5858 #ifdef CONFIG_FEATURE_OSF_LABEL
5864 toggle_dos_compatibility_flag();
5865 #ifdef CONFIG_FEATURE_SUN_LABEL
5867 toggle_sunflags(get_partition(1, partitions),
5870 #ifdef CONFIG_FEATURE_SGI_LABEL
5872 sgi_set_swappartition(
5873 get_partition(1, partitions));
5881 #ifdef CONFIG_FEATURE_SGI_LABEL
5882 /* If sgi_label then don't use get_existing_partition,
5883 let the user select a partition, since
5884 get_existing_partition() only works for Linux-like
5887 j = get_existing_partition(1, partitions);
5889 j = get_partition(1, partitions);
5892 j = get_existing_partition(1, partitions);
5895 delete_partition(j);
5899 #ifdef CONFIG_FEATURE_SGI_LABEL
5906 list_types(get_sys_types());
5925 #ifdef CONFIG_FEATURE_SUN_LABEL
5939 write_table(); /* does not return */
5941 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
5943 #ifdef CONFIG_FEATURE_SGI_LABEL
5946 _("\n\tSorry, no experts menu for SGI "
5947 "partition tables available.\n\n"));
5960 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */