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 * For detailed old history, see older versions.
11 * Contributions before 2001 by faith@cs.unc.edu, Michael Bischoff,
12 * LeBlanc@mcc.ac.uk, martin@cs.unc.edu, leisner@sdsp.mc.xerox.com,
13 * esr@snark.thyrsus.com, aeb@cwi.nl, quinlan@yggdrasil.com,
14 * fasten@cs.bonn.edu, orschaer@cip.informatik.uni-erlangen.de,
15 * jj@sunsite.mff.cuni.cz, fasten@shw.com, ANeuper@GUUG.de,
16 * kgw@suse.de, kalium@gmx.de, dhuggins@linuxcare.com,
17 * michal@ellpspace.math.ualberta.ca and probably others.
19 * Vladimir Oleynik <dzo@simtreas.ru> 2001,2002 Busybox port
22 #define UTIL_LINUX_VERSION "2.11w"
24 #define PROC_PARTITIONS "/proc/partitions"
26 #include <sys/types.h>
27 #include <sys/stat.h> /* stat */
36 #include <assert.h> /* assert */
40 #define u_char unsigned char
41 #include <scsi/scsi.h> /* SCSI_IOCTL_GET_IDLUN */
44 #include <sys/ioctl.h>
45 #include <sys/param.h>
47 #include <stdint.h> /* for uint32_t, uint16_t, uint8_t, int16_t, etc */
49 /* Copied from linux/major.h */
50 #define FLOPPY_MAJOR 2
52 #include <sys/utsname.h>
56 #define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r))
62 #define BLKRRPART _IO(0x12,95) /* re-read partition table */
63 #define BLKGETSIZE _IO(0x12,96) /* return device size */
64 #define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */
65 #define BLKSSZGET _IO(0x12,104) /* get block device sector size */
72 #define DEFAULT_SECTOR_SIZE 512
73 #define MAX_SECTOR_SIZE 2048
74 #define SECTOR_SIZE 512 /* still used in BSD code */
75 #define MAXIMUM_PARTS 60
77 #define ACTIVE_FLAG 0x80
80 #define WIN98_EXTENDED 0x0f
81 #define LINUX_PARTITION 0x81
82 #define LINUX_SWAP 0x82
83 #define LINUX_NATIVE 0x83
84 #define LINUX_EXTENDED 0x85
85 #define LINUX_LVM 0x8e
86 #define LINUX_RAID 0xfd
91 #define IS_EXTENDED(i) \
92 ((i) == EXTENDED || (i) == WIN98_EXTENDED || (i) == LINUX_EXTENDED)
94 #define SIZE(a) (sizeof(a)/sizeof((a)[0]))
96 #define cround(n) (display_in_cyl_units ? ((n)/units_per_sector)+1 : (n))
97 #define scround(x) (((x)+units_per_sector-1)/units_per_sector)
99 #if defined(__GNUC__) || defined(HAS_LONG_LONG)
100 typedef long long ext2_loff_t;
102 typedef long ext2_loff_t;
105 /* including <linux/hdreg.h> also fails */
108 unsigned char sectors;
109 unsigned short cylinders;
113 #define HDIO_GETGEO 0x0301 /* get device geometry */
117 const unsigned char *name;
122 * Raw disk label. For DOS-type partition tables the MBR,
123 * with descriptions of the primary partitions.
125 static char MBRbuffer[MAX_SECTOR_SIZE];
127 #ifdef CONFIG_FEATURE_SUN_LABEL
128 static int sun_label; /* looking at sun disklabel */
131 #define check_sun_label() 0
133 #ifdef CONFIG_FEATURE_SGI_LABEL
134 static int sgi_label; /* looking at sgi disklabel */
138 #ifdef CONFIG_FEATURE_AIX_LABEL
139 static int aix_label; /* looking at aix disklabel */
143 #ifdef CONFIG_FEATURE_OSF_LABEL
144 static int osf_label; /* looking at OSF/1 disklabel */
145 static int possibly_osf_label;
150 #define dos_label (!sun_label && !sgi_label && !aix_label && !osf_label)
152 static uint heads, sectors, cylinders;
153 static void update_units(void);
155 static const char *partition_type(unsigned char type);
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};
217 unsigned int sectors;
218 unsigned int cylinders;
221 static const char *disk_device;
222 static char *line_ptr;
223 static int fd; /* the disk */
224 static int partitions = 4; /* maximum partition + 1 */
225 static uint display_in_cyl_units = 1;
226 static uint units_per_sector = 1;
227 static void change_units(void);
228 static void fdisk_fatal(enum failure why) __attribute__ ((noreturn));
229 static void get_geometry(struct geom *);
230 static int get_boot(enum action what);
231 static int get_partition(int warn, int max);
232 static void list_types(const struct systypes *sys);
233 static void reread_partition_table(int leave);
234 static int valid_part_table_flag(const unsigned char *b);
235 static uint read_int(uint low, uint dflt, uint high, uint base, char *mesg);
240 #define hex_val(c) ({ \
242 isdigit(_c) ? _c - '0' : \
243 tolower(_c) + 10 - 'a'; \
247 #define LINE_LENGTH 800
248 #define pt_offset(b, n) ((struct partition *)((b) + 0x1be + \
249 (n) * sizeof(struct partition)))
250 #define sector(s) ((s) & 0x3f)
251 #define cylinder(s, c) ((c) | (((s) & 0xc0) << 2))
253 #define hsc2sector(h,s,c) (sector(s) - 1 + sectors * \
254 ((h) + heads * cylinder(s,c)))
255 #define set_hsc(h,s,c,sector) { \
256 s = sector % sectors + 1; \
258 h = sector % heads; \
261 s |= (sector >> 2) & 0xc0; \
265 static unsigned int get_start_sect(const struct partition *p);
266 static unsigned int get_nr_sects(const struct partition *p);
269 * per partition table entry data
271 * The four primary partitions have the same sectorbuffer (MBRbuffer)
272 * and have NULL ext_pointer.
273 * Each logical partition table entry has two pointers, one for the
274 * partition and one link to the next one.
277 struct partition *part_table; /* points into sectorbuffer */
278 struct partition *ext_pointer; /* points into sectorbuffer */
279 char changed; /* boolean */
280 uint offset; /* disk sector number */
281 char *sectorbuffer; /* disk sector contents */
282 } ptes[MAXIMUM_PARTS];
284 static char line_buffer[LINE_LENGTH];
287 set_all_unchanged(void) {
290 for (i = 0; i < MAXIMUM_PARTS; i++)
300 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_OSF_LABEL)
301 static struct partition *
302 get_part_table(int i) {
303 return ptes[i].part_table;
308 str_units(int n) { /* n==1: use singular */
310 return display_in_cyl_units ? _("cylinder") : _("sector");
312 return display_in_cyl_units ? _("cylinders") : _("sectors");
315 /* read line; return 0 or first char */
319 static int got_eof = 0;
321 fflush (stdout); /* requested by niles@scyld.com */
322 line_ptr = line_buffer;
323 if (!fgets(line_buffer, LINE_LENGTH, stdin)) {
325 got_eof++; /* user typed ^D ? */
328 fprintf(stderr, _("\ngot EOF thrice - exiting..\n"));
333 while (*line_ptr && !isgraph(*line_ptr))
339 read_char(const char *mesg)
343 } while (!read_line());
348 read_chars(const char *mesg)
359 read_hex(const struct systypes *sys)
365 read_char(_("Hex code (type L to list codes): "));
366 if (*line_ptr == 'l' || *line_ptr == 'L')
368 else if (isxdigit (*line_ptr))
372 hex = hex << 4 | hex_val(*line_ptr++);
373 while (isxdigit(*line_ptr));
379 #ifdef CONFIG_FEATURE_AIX_LABEL
381 * Copyright (C) Andreas Neuper, Sep 1998.
382 * This file may be redistributed under
383 * the terms of the GNU Public License.
387 unsigned int magic; /* expect AIX_LABEL_MAGIC */
388 unsigned int fillbytes1[124];
389 unsigned int physical_volume_id;
390 unsigned int fillbytes2[124];
393 #define AIX_LABEL_MAGIC 0xc9c2d4c1
394 #define AIX_LABEL_MAGIC_SWAPPED 0xc1d4c2c9
395 #define AIX_INFO_MAGIC 0x00072959
396 #define AIX_INFO_MAGIC_SWAPPED 0x59290700
398 #define aixlabel ((aix_partition *)MBRbuffer)
403 Sat Mar 20 09:51:38 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
407 static int aix_other_endian;
408 static short aix_volumes=1;
411 * only dealing with free blocks here
417 _("\n\tThere is a valid AIX label on this disk.\n"
418 "\tUnfortunately Linux cannot handle these\n"
419 "\tdisks at the moment. Nevertheless some\n"
421 "\t1. fdisk will destroy its contents on write.\n"
422 "\t2. Be sure that this disk is NOT a still vital\n"
423 "\t part of a volume group. (Otherwise you may\n"
424 "\t erase the other disks as well, if unmirrored.)\n"
425 "\t3. Before deleting this physical volume be sure\n"
426 "\t to remove the disk logically from your AIX\n"
427 "\t machine. (Otherwise you become an AIXpert).")
437 memset( MBRbuffer, 0, sizeof(MBRbuffer) ); /* avoid fdisk cores */
442 check_aix_label( void )
444 if (aixlabel->magic != AIX_LABEL_MAGIC &&
445 aixlabel->magic != AIX_LABEL_MAGIC_SWAPPED) {
447 aix_other_endian = 0;
450 aix_other_endian = (aixlabel->magic == AIX_LABEL_MAGIC_SWAPPED);
456 aix_nolabel(); /* %% */
457 aix_label = 1; /* %% */
460 #endif /* AIX_LABEL */
462 #ifdef CONFIG_FEATURE_OSF_LABEL
464 * Copyright (c) 1987, 1988 Regents of the University of California.
465 * All rights reserved.
467 * Redistribution and use in source and binary forms, with or without
468 * modification, are permitted provided that the following conditions
470 * 1. Redistributions of source code must retain the above copyright
471 * notice, this list of conditions and the following disclaimer.
472 * 2. Redistributions in binary form must reproduce the above copyright
473 * notice, this list of conditions and the following disclaimer in the
474 * documentation and/or other materials provided with the distribution.
475 * 3. All advertising materials mentioning features or use of this software
476 * must display the following acknowledgement:
477 * This product includes software developed by the University of
478 * California, Berkeley and its contributors.
479 * 4. Neither the name of the University nor the names of its contributors
480 * may be used to endorse or promote products derived from this software
481 * without specific prior written permission.
483 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
484 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
485 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
486 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
487 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
488 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
489 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
490 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
491 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
492 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
497 #ifndef BSD_DISKMAGIC
498 #define BSD_DISKMAGIC ((uint32_t) 0x82564557)
501 #ifndef BSD_MAXPARTITIONS
502 #define BSD_MAXPARTITIONS 16
505 #define BSD_LINUX_BOOTDIR "/usr/ucb/mdec"
507 #if defined (i386) || defined (__sparc__) || defined (__arm__) || defined (__mips__) || defined (__s390__) || defined (__sh__) || defined(__x86_64__)
508 #define BSD_LABELSECTOR 1
509 #define BSD_LABELOFFSET 0
510 #elif defined (__alpha__) || defined (__powerpc__) || defined (__ia64__) || defined (__hppa__)
511 #define BSD_LABELSECTOR 0
512 #define BSD_LABELOFFSET 64
514 #error unknown architecture
517 #define BSD_BBSIZE 8192 /* size of boot area, with label */
518 #define BSD_SBSIZE 8192 /* max size of fs superblock */
520 struct xbsd_disklabel {
521 uint32_t d_magic; /* the magic number */
522 int16_t d_type; /* drive type */
523 int16_t d_subtype; /* controller/d_type specific */
524 char d_typename[16]; /* type name, e.g. "eagle" */
525 char d_packname[16]; /* pack identifier */
527 uint32_t d_secsize; /* # of bytes per sector */
528 uint32_t d_nsectors; /* # of data sectors per track */
529 uint32_t d_ntracks; /* # of tracks per cylinder */
530 uint32_t d_ncylinders; /* # of data cylinders per unit */
531 uint32_t d_secpercyl; /* # of data sectors per cylinder */
532 uint32_t d_secperunit; /* # of data sectors per unit */
534 * Spares (bad sector replacements) below
535 * are not counted in d_nsectors or d_secpercyl.
536 * Spare sectors are assumed to be physical sectors
537 * which occupy space at the end of each track and/or cylinder.
539 uint16_t d_sparespertrack; /* # of spare sectors per track */
540 uint16_t d_sparespercyl; /* # of spare sectors per cylinder */
542 * Alternate cylinders include maintenance, replacement,
543 * configuration description areas, etc.
545 uint32_t d_acylinders; /* # of alt. cylinders per unit */
547 /* hardware characteristics: */
549 * d_interleave, d_trackskew and d_cylskew describe perturbations
550 * in the media format used to compensate for a slow controller.
551 * Interleave is physical sector interleave, set up by the formatter
552 * or controller when formatting. When interleaving is in use,
553 * logically adjacent sectors are not physically contiguous,
554 * but instead are separated by some number of sectors.
555 * It is specified as the ratio of physical sectors traversed
556 * per logical sector. Thus an interleave of 1:1 implies contiguous
557 * layout, while 2:1 implies that logical sector 0 is separated
558 * by one sector from logical sector 1.
559 * d_trackskew is the offset of sector 0 on track N
560 * relative to sector 0 on track N-1 on the same cylinder.
561 * Finally, d_cylskew is the offset of sector 0 on cylinder N
562 * relative to sector 0 on cylinder N-1.
564 uint16_t d_rpm; /* rotational speed */
565 uint16_t d_interleave; /* hardware sector interleave */
566 uint16_t d_trackskew; /* sector 0 skew, per track */
567 uint16_t d_cylskew; /* sector 0 skew, per cylinder */
568 uint32_t d_headswitch; /* head switch time, usec */
569 uint32_t d_trkseek; /* track-to-track seek, usec */
570 uint32_t d_flags; /* generic flags */
572 uint32_t d_drivedata[NDDATA]; /* drive-type specific information */
574 uint32_t d_spare[NSPARE]; /* reserved for future use */
575 uint32_t d_magic2; /* the magic number (again) */
576 uint16_t d_checksum; /* xor of data incl. partitions */
577 /* filesystem and partition information: */
578 uint16_t d_npartitions; /* number of partitions in following */
579 uint32_t d_bbsize; /* size of boot area at sn0, bytes */
580 uint32_t d_sbsize; /* max size of fs superblock, bytes */
581 struct xbsd_partition { /* the partition table */
582 uint32_t p_size; /* number of sectors in partition */
583 uint32_t p_offset; /* starting sector */
584 uint32_t p_fsize; /* filesystem basic fragment size */
585 uint8_t p_fstype; /* filesystem type, see below */
586 uint8_t p_frag; /* filesystem fragments per block */
587 uint16_t p_cpg; /* filesystem cylinders per group */
588 } d_partitions[BSD_MAXPARTITIONS]; /* actually may be more */
592 #define BSD_DTYPE_SMD 1 /* SMD, XSMD; VAX hp/up */
593 #define BSD_DTYPE_MSCP 2 /* MSCP */
594 #define BSD_DTYPE_DEC 3 /* other DEC (rk, rl) */
595 #define BSD_DTYPE_SCSI 4 /* SCSI */
596 #define BSD_DTYPE_ESDI 5 /* ESDI interface */
597 #define BSD_DTYPE_ST506 6 /* ST506 etc. */
598 #define BSD_DTYPE_HPIB 7 /* CS/80 on HP-IB */
599 #define BSD_DTYPE_HPFL 8 /* HP Fiber-link */
600 #define BSD_DTYPE_FLOPPY 10 /* floppy */
602 /* d_subtype values: */
603 #define BSD_DSTYPE_INDOSPART 0x8 /* is inside dos partition */
604 #define BSD_DSTYPE_DOSPART(s) ((s) & 3) /* dos partition number */
605 #define BSD_DSTYPE_GEOMETRY 0x10 /* drive params in label */
608 static const char * const xbsd_dktypenames[] = {
622 #define BSD_DKMAXTYPES (sizeof(xbsd_dktypenames) / sizeof(xbsd_dktypenames[0]) - 1)
626 * Filesystem type and version.
627 * Used to interpret other filesystem-specific
628 * per-partition information.
630 #define BSD_FS_UNUSED 0 /* unused */
631 #define BSD_FS_SWAP 1 /* swap */
632 #define BSD_FS_V6 2 /* Sixth Edition */
633 #define BSD_FS_V7 3 /* Seventh Edition */
634 #define BSD_FS_SYSV 4 /* System V */
635 #define BSD_FS_V71K 5 /* V7 with 1K blocks (4.1, 2.9) */
636 #define BSD_FS_V8 6 /* Eighth Edition, 4K blocks */
637 #define BSD_FS_BSDFFS 7 /* 4.2BSD fast file system */
638 #define BSD_FS_BSDLFS 9 /* 4.4BSD log-structured file system */
639 #define BSD_FS_OTHER 10 /* in use, but unknown/unsupported */
640 #define BSD_FS_HPFS 11 /* OS/2 high-performance file system */
641 #define BSD_FS_ISO9660 12 /* ISO-9660 filesystem (cdrom) */
642 #define BSD_FS_ISOFS BSD_FS_ISO9660
643 #define BSD_FS_BOOT 13 /* partition contains bootstrap */
644 #define BSD_FS_ADOS 14 /* AmigaDOS fast file system */
645 #define BSD_FS_HFS 15 /* Macintosh HFS */
646 #define BSD_FS_ADVFS 16 /* Digital Unix AdvFS */
648 /* this is annoying, but it's also the way it is :-( */
650 #define BSD_FS_EXT2 8 /* ext2 file system */
652 #define BSD_FS_MSDOS 8 /* MS-DOS file system */
656 static const struct systypes xbsd_fstypes[] = {
657 /* BSD_FS_UNUSED */ {"\x00" "unused"},
658 /* BSD_FS_SWAP */ {"\x01" "swap"},
659 /* BSD_FS_V6 */ {"\x02" "Version 6"},
660 /* BSD_FS_V7 */ {"\x03" "Version 7"},
661 /* BSD_FS_SYSV */ {"\x04" "System V"},
662 /* BSD_FS_V71K */ {"\x05" "4.1BSD"},
663 /* BSD_FS_V8 */ {"\x06" "Eighth Edition"},
664 /* BSD_FS_BSDFFS */ {"\x07" "4.2BSD"},
666 /* BSD_FS_EXT2 */ {"\x08" "ext2"},
668 /* BSD_FS_MSDOS */ {"\x08" "MS-DOS"},
670 /* BSD_FS_BSDLFS */ {"\x09" "4.4LFS"},
671 /* BSD_FS_OTHER */ {"\x0a" "unknown"},
672 /* BSD_FS_HPFS */ {"\x0b" "HPFS"},
673 /* BSD_FS_ISO9660 */ {"\x0c" "ISO-9660"},
674 /* BSD_FS_BOOT */ {"\x0d" "boot"},
675 /* BSD_FS_ADOS */ {"\x0e" "ADOS"},
676 /* BSD_FS_HFS */ {"\x0f" "HFS"},
677 /* BSD_FS_ADVFS */ {"\x10" "AdvFS"},
680 #define BSD_FSMAXTYPES (SIZE(xbsd_fstypes)-1)
685 * flags shared by various drives:
687 #define BSD_D_REMOVABLE 0x01 /* removable media */
688 #define BSD_D_ECC 0x02 /* supports ECC */
689 #define BSD_D_BADSECT 0x04 /* supports bad sector forw. */
690 #define BSD_D_RAMDISK 0x08 /* disk emulator */
691 #define BSD_D_CHAIN 0x10 /* can do back-back transfers */
692 #define BSD_D_DOSPART 0x20 /* within MSDOS partition */
694 #endif /* OSF_LABEL */
697 * Copyright (C) Andreas Neuper, Sep 1998.
698 * This file may be modified and redistributed under
699 * the terms of the GNU Public License.
702 struct device_parameter { /* 48 bytes */
706 unsigned char sparecyl;
707 unsigned short pcylcount;
708 unsigned short head_vol0;
709 unsigned short ntrks; /* tracks in cyl 0 or vol 0 */
710 unsigned char cmd_tag_queue_depth;
711 unsigned char unused0;
712 unsigned short unused1;
713 unsigned short nsect; /* sectors/tracks in cyl 0 or vol 0 */
714 unsigned short bytes;
715 unsigned short ilfact;
716 unsigned int flags; /* controller flags */
717 unsigned int datarate;
718 unsigned int retries_on_error;
719 unsigned int ms_per_word;
720 unsigned short xylogics_gap1;
721 unsigned short xylogics_syncdelay;
722 unsigned short xylogics_readdelay;
723 unsigned short xylogics_gap2;
724 unsigned short xylogics_readgate;
725 unsigned short xylogics_writecont;
728 #define SGI_VOLHDR 0x00
729 /* 1 and 2 were used for drive types no longer supported by SGI */
730 #define SGI_SWAP 0x03
731 /* 4 and 5 were for filesystem types SGI haven't ever supported on MIPS CPUs */
732 #define SGI_VOLUME 0x06
734 #define SGI_LVOL 0x08
735 #define SGI_RLVOL 0x09
737 #define SGI_XFSLOG 0x0b
740 #define ENTIRE_DISK SGI_VOLUME
744 #define SECTOR_SLIP 0x01
745 #define SECTOR_FWD 0x02
746 #define TRACK_FWD 0x04
747 #define TRACK_MULTIVOL 0x08
748 #define IGNORE_ERRORS 0x10
750 #define ENABLE_CMDTAGQ 0x40
753 unsigned int magic; /* expect SGI_LABEL_MAGIC */
754 unsigned short boot_part; /* active boot partition */
755 unsigned short swap_part; /* active swap partition */
756 unsigned char boot_file[16]; /* name of the bootfile */
757 struct device_parameter devparam; /* 1 * 48 bytes */
758 struct volume_directory { /* 15 * 16 bytes */
759 unsigned char vol_file_name[8]; /* a character array */
760 unsigned int vol_file_start; /* number of logical block */
761 unsigned int vol_file_size; /* number of bytes */
763 struct sgi_partition { /* 16 * 12 bytes */
764 unsigned int num_sectors; /* number of blocks */
765 unsigned int start_sector; /* must be cylinder aligned */
769 unsigned int fillbytes;
773 unsigned int magic; /* looks like a magic number */
782 unsigned char scsi_string[50];
783 unsigned char serial[137];
784 unsigned short check1816;
785 unsigned char installer[225];
788 #define SGI_LABEL_MAGIC 0x0be5a941
789 #define SGI_LABEL_MAGIC_SWAPPED 0x41a9e50b
790 #define SGI_INFO_MAGIC 0x00072959
791 #define SGI_INFO_MAGIC_SWAPPED 0x59290700
792 #define SGI_SSWAP16(x) (sgi_other_endian ? __swap16(x) \
794 #define SGI_SSWAP32(x) (sgi_other_endian ? __swap32(x) \
797 #define sgilabel ((sgi_partition *)MBRbuffer)
798 #define sgiparam (sgilabel->devparam)
801 unsigned char info[128]; /* Informative text string */
802 unsigned char spare0[14];
804 unsigned char spare1;
806 unsigned char spare2;
809 unsigned char spare1[246]; /* Boot information etc. */
810 unsigned short rspeed; /* Disk rotational speed */
811 unsigned short pcylcount; /* Physical cylinder count */
812 unsigned short sparecyl; /* extra sects per cylinder */
813 unsigned char spare2[4]; /* More magic... */
814 unsigned short ilfact; /* Interleave factor */
815 unsigned short ncyl; /* Data cylinder count */
816 unsigned short nacyl; /* Alt. cylinder count */
817 unsigned short ntrks; /* Tracks per cylinder */
818 unsigned short nsect; /* Sectors per track */
819 unsigned char spare3[4]; /* Even more magic... */
820 struct sun_partition {
821 uint32_t start_cylinder;
822 uint32_t num_sectors;
824 unsigned short magic; /* Magic number */
825 unsigned short csum; /* Label xor'd checksum */
828 #define SUN_LABEL_MAGIC 0xDABE
829 #define SUN_LABEL_MAGIC_SWAPPED 0xBEDA
830 #define sunlabel ((sun_partition *)MBRbuffer)
831 #define SUN_SSWAP16(x) (sun_other_endian ? __swap16(x) \
833 #define SUN_SSWAP32(x) (sun_other_endian ? __swap32(x) \
837 * llseek.c -- stub calling the llseek system call
839 * Copyright (C) 1994 Remy Card. This file may be redistributed
840 * under the terms of the GNU Public License.
849 #else /* HAVE_LLSEEK */
851 #if defined(__alpha__) || defined(__ia64__)
853 #define my_llseek lseek
856 #include <asm/unistd.h> /* for __NR__llseek */
858 static int _llseek (unsigned int, unsigned long,
859 unsigned long, ext2_loff_t *, unsigned int);
863 static _syscall5(int,_llseek,unsigned int,f_d,unsigned long,offset_high,
864 unsigned long, offset_low,ext2_loff_t *,result,
865 unsigned int, origin)
869 /* no __NR__llseek on compilation machine - might give it explicitly */
870 static int _llseek (unsigned int f_d, unsigned long oh,
871 unsigned long ol, ext2_loff_t *result,
872 unsigned int origin) {
879 static ext2_loff_t my_llseek (unsigned int f_d, ext2_loff_t offset,
885 retval = _llseek (f_d, ((unsigned long long) offset) >> 32,
886 ((unsigned long long) offset) & 0xffffffff,
888 return (retval == -1 ? (ext2_loff_t) retval : result);
891 #endif /* __alpha__ */
893 #endif /* HAVE_LLSEEK */
895 static ext2_loff_t ext2_llseek (unsigned int f_d, ext2_loff_t offset,
899 static int do_compat = 0;
902 result = my_llseek (f_d, offset, origin);
903 if (!(result == -1 && errno == ENOSYS))
907 * Just in case this code runs on top of an old kernel
908 * which does not support the llseek system call
912 * Now try ordinary lseek.
916 if ((sizeof(off_t) >= sizeof(ext2_loff_t)) ||
917 (offset < ((ext2_loff_t) 1 << ((sizeof(off_t)*8) -1))))
918 return lseek(f_d, (off_t) offset, origin);
926 static ext2_loff_t ext2_llseek (unsigned int f_d, ext2_loff_t offset,
929 if ((sizeof(off_t) < sizeof(ext2_loff_t)) &&
930 (offset >= ((ext2_loff_t) 1 << ((sizeof(off_t)*8) -1)))) {
934 return lseek (f_d, (off_t) offset, origin);
940 #ifdef CONFIG_FEATURE_OSF_LABEL
943 19990319 - Arnaldo Carvalho de Melo <acme@conectiva.com.br> - i18n/nls
945 20000101 - David Huggins-Daines <dhuggins@linuxcare.com> - Better
946 support for OSF/1 disklabels on Alpha.
947 Also fixed unaligned accesses in alpha_bootblock_checksum()
950 #define FREEBSD_PARTITION 0xa5
951 #define NETBSD_PARTITION 0xa9
953 static void xbsd_delete_part (void);
954 static void xbsd_new_part (void);
955 static void xbsd_write_disklabel (void);
956 static int xbsd_create_disklabel (void);
957 static void xbsd_edit_disklabel (void);
958 static void xbsd_write_bootstrap (void);
959 static void xbsd_change_fstype (void);
960 static int xbsd_get_part_index (int max);
961 static int xbsd_check_new_partition (int *i);
962 static void xbsd_list_types (void);
963 static u_short xbsd_dkcksum (struct xbsd_disklabel *lp);
964 static int xbsd_initlabel (struct partition *p, struct xbsd_disklabel *d,
966 static int xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d);
967 static int xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d);
969 #if defined (__alpha__)
970 static void alpha_bootblock_checksum (char *boot);
973 #if !defined (__alpha__)
974 static int xbsd_translate_fstype (int linux_type);
975 static void xbsd_link_part (void);
976 static struct partition *xbsd_part;
977 static int xbsd_part_index;
980 #if defined (__alpha__)
981 /* We access this through a u_int64_t * when checksumming */
982 static char disklabelbuffer[BSD_BBSIZE] __attribute__((aligned(8)));
984 static char disklabelbuffer[BSD_BBSIZE];
987 static struct xbsd_disklabel xbsd_dlabel;
989 #define bsd_cround(n) \
990 (display_in_cyl_units ? ((n)/xbsd_dlabel.d_secpercyl) + 1 : (n))
993 * Test whether the whole disk has BSD disk label magic.
995 * Note: often reformatting with DOS-type label leaves the BSD magic,
996 * so this does not mean that there is a BSD disk label.
999 check_osf_label(void) {
1000 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
1005 static void xbsd_print_disklabel(int);
1008 btrydev (const char * dev) {
1009 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
1011 printf(_("\nBSD label for device: %s\n"), dev);
1012 xbsd_print_disklabel (0);
1018 puts (_("Command action"));
1019 puts (_("\td\tdelete a BSD partition"));
1020 puts (_("\te\tedit drive data"));
1021 puts (_("\ti\tinstall bootstrap"));
1022 puts (_("\tl\tlist known filesystem types"));
1023 puts (_("\tm\tprint this menu"));
1024 puts (_("\tn\tadd a new BSD partition"));
1025 puts (_("\tp\tprint BSD partition table"));
1026 puts (_("\tq\tquit without saving changes"));
1027 puts (_("\tr\treturn to main menu"));
1028 puts (_("\ts\tshow complete disklabel"));
1029 puts (_("\tt\tchange a partition's filesystem id"));
1030 puts (_("\tu\tchange units (cylinders/sectors)"));
1031 puts (_("\tw\twrite disklabel to disk"));
1032 #if !defined (__alpha__)
1033 puts (_("\tx\tlink BSD partition to non-BSD partition"));
1037 #if !defined (__alpha__)
1044 is_bsd_partition_type(int type) {
1045 return (type == FREEBSD_PARTITION ||
1046 type == hidden(FREEBSD_PARTITION) ||
1047 type == NETBSD_PARTITION ||
1048 type == hidden(NETBSD_PARTITION));
1054 #if !defined (__alpha__)
1056 struct partition *p;
1058 for (t=0; t<4; t++) {
1059 p = get_part_table(t);
1060 if (p && is_bsd_partition_type(p->sys_ind)) {
1062 xbsd_part_index = t;
1063 ss = get_start_sect(xbsd_part);
1065 fprintf (stderr, _("Partition %s has invalid starting sector 0.\n"),
1066 partname(disk_device, t+1, 0));
1069 printf (_("Reading disklabel of %s at sector %d.\n"),
1070 partname(disk_device, t+1, 0), ss + BSD_LABELSECTOR);
1071 if (xbsd_readlabel (xbsd_part, &xbsd_dlabel) == 0)
1072 if (xbsd_create_disklabel () == 0)
1079 printf (_("There is no *BSD partition on %s.\n"), disk_device);
1083 #elif defined (__alpha__)
1085 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
1086 if (xbsd_create_disklabel () == 0)
1087 exit ( EXIT_SUCCESS );
1093 switch (tolower (read_char (_("BSD disklabel command (m for help): ")))) {
1095 xbsd_delete_part ();
1098 xbsd_edit_disklabel ();
1101 xbsd_write_bootstrap ();
1110 xbsd_print_disklabel (0);
1114 exit ( EXIT_SUCCESS );
1118 xbsd_print_disklabel (1);
1121 xbsd_change_fstype ();
1127 xbsd_write_disklabel ();
1129 #if !defined (__alpha__)
1142 xbsd_delete_part (void)
1146 i = xbsd_get_part_index (xbsd_dlabel.d_npartitions);
1147 xbsd_dlabel.d_partitions[i].p_size = 0;
1148 xbsd_dlabel.d_partitions[i].p_offset = 0;
1149 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
1150 if (xbsd_dlabel.d_npartitions == i + 1)
1151 while (xbsd_dlabel.d_partitions[xbsd_dlabel.d_npartitions-1].p_size == 0)
1152 xbsd_dlabel.d_npartitions--;
1156 xbsd_new_part (void)
1162 if (!xbsd_check_new_partition (&i))
1165 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
1166 begin = get_start_sect(xbsd_part);
1167 end = begin + get_nr_sects(xbsd_part) - 1;
1170 end = xbsd_dlabel.d_secperunit - 1;
1173 snprintf (mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
1174 begin = read_int (bsd_cround (begin), bsd_cround (begin), bsd_cround (end),
1177 if (display_in_cyl_units)
1178 begin = (begin - 1) * xbsd_dlabel.d_secpercyl;
1180 snprintf (mesg, sizeof(mesg), _("Last %s or +size or +sizeM or +sizeK"),
1181 str_units(SINGULAR));
1182 end = read_int (bsd_cround (begin), bsd_cround (end), bsd_cround (end),
1183 bsd_cround (begin), mesg);
1185 if (display_in_cyl_units)
1186 end = end * xbsd_dlabel.d_secpercyl - 1;
1188 xbsd_dlabel.d_partitions[i].p_size = end - begin + 1;
1189 xbsd_dlabel.d_partitions[i].p_offset = begin;
1190 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
1194 xbsd_print_disklabel (int show_all) {
1195 struct xbsd_disklabel *lp = &xbsd_dlabel;
1196 struct xbsd_partition *pp;
1201 #if defined (__alpha__)
1202 fprintf(f, "# %s:\n", disk_device);
1204 fprintf(f, "# %s:\n", partname(disk_device, xbsd_part_index+1, 0));
1206 if ((unsigned) lp->d_type < BSD_DKMAXTYPES)
1207 fprintf(f, _("type: %s\n"), xbsd_dktypenames[lp->d_type]);
1209 fprintf(f, _("type: %d\n"), lp->d_type);
1210 fprintf(f, _("disk: %.*s\n"), (int) sizeof(lp->d_typename), lp->d_typename);
1211 fprintf(f, _("label: %.*s\n"), (int) sizeof(lp->d_packname), lp->d_packname);
1212 fprintf(f, _("flags:"));
1213 if (lp->d_flags & BSD_D_REMOVABLE)
1214 fprintf(f, _(" removable"));
1215 if (lp->d_flags & BSD_D_ECC)
1216 fprintf(f, _(" ecc"));
1217 if (lp->d_flags & BSD_D_BADSECT)
1218 fprintf(f, _(" badsect"));
1220 /* On various machines the fields of *lp are short/int/long */
1221 /* In order to avoid problems, we cast them all to long. */
1222 fprintf(f, _("bytes/sector: %ld\n"), (long) lp->d_secsize);
1223 fprintf(f, _("sectors/track: %ld\n"), (long) lp->d_nsectors);
1224 fprintf(f, _("tracks/cylinder: %ld\n"), (long) lp->d_ntracks);
1225 fprintf(f, _("sectors/cylinder: %ld\n"), (long) lp->d_secpercyl);
1226 fprintf(f, _("cylinders: %ld\n"), (long) lp->d_ncylinders);
1227 fprintf(f, _("rpm: %d\n"), lp->d_rpm);
1228 fprintf(f, _("interleave: %d\n"), lp->d_interleave);
1229 fprintf(f, _("trackskew: %d\n"), lp->d_trackskew);
1230 fprintf(f, _("cylinderskew: %d\n"), lp->d_cylskew);
1231 fprintf(f, _("headswitch: %ld\t\t# milliseconds\n"),
1232 (long) lp->d_headswitch);
1233 fprintf(f, _("track-to-track seek: %ld\t# milliseconds\n"),
1234 (long) lp->d_trkseek);
1235 fprintf(f, _("drivedata: "));
1236 for (i = NDDATA - 1; i >= 0; i--)
1237 if (lp->d_drivedata[i])
1241 for (j = 0; j <= i; j++)
1242 fprintf(f, "%ld ", (long) lp->d_drivedata[j]);
1244 fprintf (f, _("\n%d partitions:\n"), lp->d_npartitions);
1245 fprintf (f, _("# start end size fstype [fsize bsize cpg]\n"));
1246 pp = lp->d_partitions;
1247 for (i = 0; i < lp->d_npartitions; i++, pp++) {
1249 if (display_in_cyl_units && lp->d_secpercyl) {
1250 fprintf(f, " %c: %8ld%c %8ld%c %8ld%c ",
1252 (long) pp->p_offset / lp->d_secpercyl + 1,
1253 (pp->p_offset % lp->d_secpercyl) ? '*' : ' ',
1254 (long) (pp->p_offset + pp->p_size + lp->d_secpercyl - 1)
1256 ((pp->p_offset + pp->p_size) % lp->d_secpercyl) ? '*' : ' ',
1257 (long) pp->p_size / lp->d_secpercyl,
1258 (pp->p_size % lp->d_secpercyl) ? '*' : ' ');
1260 fprintf(f, " %c: %8ld %8ld %8ld ",
1262 (long) pp->p_offset,
1263 (long) pp->p_offset + pp->p_size - 1,
1266 if ((unsigned) pp->p_fstype < BSD_FSMAXTYPES)
1267 fprintf(f, "%8.8s", xbsd_fstypes[pp->p_fstype].name);
1269 fprintf(f, "%8x", pp->p_fstype);
1270 switch (pp->p_fstype) {
1272 fprintf(f, " %5ld %5ld %5.5s ",
1273 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, "");
1277 fprintf(f, " %5ld %5ld %5d ",
1278 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag,
1283 fprintf(f, "%22.22s", "");
1292 xbsd_write_disklabel (void) {
1293 #if defined (__alpha__)
1294 printf (_("Writing disklabel to %s.\n"), disk_device);
1295 xbsd_writelabel (NULL, &xbsd_dlabel);
1297 printf (_("Writing disklabel to %s.\n"),
1298 partname(disk_device, xbsd_part_index+1, 0));
1299 xbsd_writelabel (xbsd_part, &xbsd_dlabel);
1301 reread_partition_table(0); /* no exit yet */
1305 xbsd_create_disklabel (void) {
1308 #if defined (__alpha__)
1309 fprintf (stderr, _("%s contains no disklabel.\n"), disk_device);
1311 fprintf (stderr, _("%s contains no disklabel.\n"),
1312 partname(disk_device, xbsd_part_index+1, 0));
1316 c = read_char (_("Do you want to create a disklabel? (y/n) "));
1317 if (c == 'y' || c == 'Y') {
1318 if (xbsd_initlabel (
1319 #if defined (__alpha__) || defined (__powerpc__) || defined (__hppa__)
1320 NULL, &xbsd_dlabel, 0
1322 xbsd_part, &xbsd_dlabel, xbsd_part_index
1325 xbsd_print_disklabel (1);
1329 } else if (c == 'n')
1335 edit_int (int def, char *mesg)
1338 fputs (mesg, stdout);
1339 printf (" (%d): ", def);
1343 while (!isdigit (*line_ptr));
1344 return atoi (line_ptr);
1348 xbsd_edit_disklabel (void)
1350 struct xbsd_disklabel *d;
1354 #if defined (__alpha__) || defined (__ia64__)
1355 d -> d_secsize = (u_long) edit_int ((u_long) d -> d_secsize ,_("bytes/sector"));
1356 d -> d_nsectors = (u_long) edit_int ((u_long) d -> d_nsectors ,_("sectors/track"));
1357 d -> d_ntracks = (u_long) edit_int ((u_long) d -> d_ntracks ,_("tracks/cylinder"));
1358 d -> d_ncylinders = (u_long) edit_int ((u_long) d -> d_ncylinders ,_("cylinders"));
1361 /* d -> d_secpercyl can be != d -> d_nsectors * d -> d_ntracks */
1364 d -> d_secpercyl = (u_long) edit_int ((u_long) d -> d_nsectors * d -> d_ntracks,
1365 _("sectors/cylinder"));
1366 if (d -> d_secpercyl <= d -> d_nsectors * d -> d_ntracks)
1369 printf (_("Must be <= sectors/track * tracks/cylinder (default).\n"));
1371 d -> d_rpm = (u_short) edit_int ((u_short) d -> d_rpm ,_("rpm"));
1372 d -> d_interleave = (u_short) edit_int ((u_short) d -> d_interleave,_("interleave"));
1373 d -> d_trackskew = (u_short) edit_int ((u_short) d -> d_trackskew ,_("trackskew"));
1374 d -> d_cylskew = (u_short) edit_int ((u_short) d -> d_cylskew ,_("cylinderskew"));
1375 d -> d_headswitch = (u_long) edit_int ((u_long) d -> d_headswitch ,_("headswitch"));
1376 d -> d_trkseek = (u_long) edit_int ((u_long) d -> d_trkseek ,_("track-to-track seek"));
1378 d -> d_secperunit = d -> d_secpercyl * d -> d_ncylinders;
1382 xbsd_get_bootstrap (char *path, void *ptr, int size)
1386 if ((fdb = open (path, O_RDONLY)) < 0)
1391 if (read (fdb, ptr, size) < 0)
1397 printf (" ... %s\n", path);
1405 printf (_("\nSyncing disks.\n"));
1411 xbsd_write_bootstrap (void)
1413 char *bootdir = BSD_LINUX_BOOTDIR;
1414 char path[MAXPATHLEN];
1416 struct xbsd_disklabel dl;
1420 if (xbsd_dlabel.d_type == BSD_DTYPE_SCSI)
1425 printf (_("Bootstrap: %sboot -> boot%s (%s): "),
1426 dkbasename, dkbasename, dkbasename);
1428 line_ptr[strlen (line_ptr)-1] = '\0';
1429 dkbasename = line_ptr;
1431 snprintf (path, sizeof(path), "%s/%sboot", bootdir, dkbasename);
1432 if (!xbsd_get_bootstrap (path, disklabelbuffer, (int) xbsd_dlabel.d_secsize))
1435 /* We need a backup of the disklabel (xbsd_dlabel might have changed). */
1436 d = &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE];
1437 bcopy (d, &dl, sizeof (struct xbsd_disklabel));
1439 /* The disklabel will be overwritten by 0's from bootxx anyway */
1440 bzero (d, sizeof (struct xbsd_disklabel));
1442 snprintf (path, sizeof(path), "%s/boot%s", bootdir, dkbasename);
1443 if (!xbsd_get_bootstrap (path, &disklabelbuffer[xbsd_dlabel.d_secsize],
1444 (int) xbsd_dlabel.d_bbsize - xbsd_dlabel.d_secsize))
1447 e = d + sizeof (struct xbsd_disklabel);
1448 for (p=d; p < e; p++)
1450 fprintf (stderr, _("Bootstrap overlaps with disk label!\n"));
1451 exit ( EXIT_FAILURE );
1454 bcopy (&dl, d, sizeof (struct xbsd_disklabel));
1456 #if defined (__powerpc__) || defined (__hppa__)
1458 #elif defined (__alpha__)
1460 alpha_bootblock_checksum (disklabelbuffer);
1462 sector = get_start_sect(xbsd_part);
1465 if (ext2_llseek (fd, (ext2_loff_t) sector * SECTOR_SIZE, SEEK_SET) == -1)
1466 fdisk_fatal (unable_to_seek);
1467 if (BSD_BBSIZE != write (fd, disklabelbuffer, BSD_BBSIZE))
1468 fdisk_fatal (unable_to_write);
1470 #if defined (__alpha__)
1471 printf (_("Bootstrap installed on %s.\n"), disk_device);
1473 printf (_("Bootstrap installed on %s.\n"),
1474 partname (disk_device, xbsd_part_index+1, 0));
1481 xbsd_change_fstype (void)
1485 i = xbsd_get_part_index (xbsd_dlabel.d_npartitions);
1486 xbsd_dlabel.d_partitions[i].p_fstype = read_hex (xbsd_fstypes);
1490 xbsd_get_part_index (int max)
1495 snprintf (prompt, sizeof(prompt), _("Partition (a-%c): "), 'a' + max - 1);
1497 l = tolower (read_char (prompt));
1498 while (l < 'a' || l > 'a' + max - 1);
1503 xbsd_check_new_partition (int *i) {
1505 /* room for more? various BSD flavours have different maxima */
1506 if (xbsd_dlabel.d_npartitions == BSD_MAXPARTITIONS) {
1509 for (t = 0; t < BSD_MAXPARTITIONS; t++)
1510 if (xbsd_dlabel.d_partitions[t].p_size == 0)
1513 if (t == BSD_MAXPARTITIONS) {
1514 fprintf (stderr, _("The maximum number of partitions "
1515 "has been created\n"));
1520 *i = xbsd_get_part_index (BSD_MAXPARTITIONS);
1522 if (*i >= xbsd_dlabel.d_npartitions)
1523 xbsd_dlabel.d_npartitions = (*i) + 1;
1525 if (xbsd_dlabel.d_partitions[*i].p_size != 0) {
1526 fprintf (stderr, _("This partition already exists.\n"));
1534 xbsd_list_types (void) {
1535 list_types (xbsd_fstypes);
1539 xbsd_dkcksum (struct xbsd_disklabel *lp) {
1540 u_short *start, *end;
1543 start = (u_short *) lp;
1544 end = (u_short *) &lp->d_partitions[lp->d_npartitions];
1551 xbsd_initlabel (struct partition *p, struct xbsd_disklabel *d, int pindex) {
1552 struct xbsd_partition *pp;
1556 bzero (d, sizeof (struct xbsd_disklabel));
1558 d -> d_magic = BSD_DISKMAGIC;
1560 if (strncmp (disk_device, "/dev/sd", 7) == 0)
1561 d -> d_type = BSD_DTYPE_SCSI;
1563 d -> d_type = BSD_DTYPE_ST506;
1565 #if 0 /* not used (at least not written to disk) by NetBSD/i386 1.0 */
1566 d -> d_subtype = BSD_DSTYPE_INDOSPART & pindex;
1569 #if !defined (__alpha__)
1570 d -> d_flags = BSD_D_DOSPART;
1574 d -> d_secsize = SECTOR_SIZE; /* bytes/sector */
1575 d -> d_nsectors = g.sectors; /* sectors/track */
1576 d -> d_ntracks = g.heads; /* tracks/cylinder (heads) */
1577 d -> d_ncylinders = g.cylinders;
1578 d -> d_secpercyl = g.sectors * g.heads;/* sectors/cylinder */
1579 if (d -> d_secpercyl == 0)
1580 d -> d_secpercyl = 1; /* avoid segfaults */
1581 d -> d_secperunit = d -> d_secpercyl * d -> d_ncylinders;
1584 d -> d_interleave = 1;
1585 d -> d_trackskew = 0;
1587 d -> d_headswitch = 0;
1590 d -> d_magic2 = BSD_DISKMAGIC;
1591 d -> d_bbsize = BSD_BBSIZE;
1592 d -> d_sbsize = BSD_SBSIZE;
1594 #if !defined (__alpha__)
1595 d -> d_npartitions = 4;
1596 pp = &d -> d_partitions[2]; /* Partition C should be
1597 the NetBSD partition */
1598 pp -> p_offset = get_start_sect(p);
1599 pp -> p_size = get_nr_sects(p);
1600 pp -> p_fstype = BSD_FS_UNUSED;
1601 pp = &d -> d_partitions[3]; /* Partition D should be
1604 pp -> p_size = d -> d_secperunit;
1605 pp -> p_fstype = BSD_FS_UNUSED;
1606 #elif defined (__alpha__)
1607 d -> d_npartitions = 3;
1608 pp = &d -> d_partitions[2]; /* Partition C should be
1611 pp -> p_size = d -> d_secperunit;
1612 pp -> p_fstype = BSD_FS_UNUSED;
1619 * Read a xbsd_disklabel from sector 0 or from the starting sector of p.
1620 * If it has the right magic, return 1.
1623 xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d)
1627 /* p is used only to get the starting sector */
1628 #if !defined (__alpha__)
1629 sector = (p ? get_start_sect(p) : 0);
1630 #elif defined (__alpha__)
1634 if (ext2_llseek (fd, (ext2_loff_t) sector * SECTOR_SIZE, SEEK_SET) == -1)
1635 fdisk_fatal (unable_to_seek);
1636 if (BSD_BBSIZE != read (fd, disklabelbuffer, BSD_BBSIZE))
1637 fdisk_fatal (unable_to_read);
1639 bcopy (&disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
1640 d, sizeof (struct xbsd_disklabel));
1642 if (d -> d_magic != BSD_DISKMAGIC || d -> d_magic2 != BSD_DISKMAGIC)
1645 for (t = d -> d_npartitions; t < BSD_MAXPARTITIONS; t++) {
1646 d -> d_partitions[t].p_size = 0;
1647 d -> d_partitions[t].p_offset = 0;
1648 d -> d_partitions[t].p_fstype = BSD_FS_UNUSED;
1651 if (d -> d_npartitions > BSD_MAXPARTITIONS)
1652 fprintf (stderr, _("Warning: too many partitions "
1653 "(%d, maximum is %d).\n"),
1654 d -> d_npartitions, BSD_MAXPARTITIONS);
1659 xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d)
1663 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
1664 sector = get_start_sect(p) + BSD_LABELSECTOR;
1666 sector = BSD_LABELSECTOR;
1669 d -> d_checksum = 0;
1670 d -> d_checksum = xbsd_dkcksum (d);
1672 /* This is necessary if we want to write the bootstrap later,
1673 otherwise we'd write the old disklabel with the bootstrap.
1675 bcopy (d, &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
1676 sizeof (struct xbsd_disklabel));
1678 #if defined (__alpha__) && BSD_LABELSECTOR == 0
1679 alpha_bootblock_checksum (disklabelbuffer);
1680 if (ext2_llseek (fd, (ext2_loff_t) 0, SEEK_SET) == -1)
1681 fdisk_fatal (unable_to_seek);
1682 if (BSD_BBSIZE != write (fd, disklabelbuffer, BSD_BBSIZE))
1683 fdisk_fatal (unable_to_write);
1685 if (ext2_llseek (fd, (ext2_loff_t) sector * SECTOR_SIZE + BSD_LABELOFFSET,
1687 fdisk_fatal (unable_to_seek);
1688 if (sizeof (struct xbsd_disklabel) != write (fd, d, sizeof (struct xbsd_disklabel)))
1689 fdisk_fatal (unable_to_write);
1698 #if !defined (__alpha__)
1700 xbsd_translate_fstype (int linux_type)
1704 case 0x01: /* DOS 12-bit FAT */
1705 case 0x04: /* DOS 16-bit <32M */
1706 case 0x06: /* DOS 16-bit >=32M */
1707 case 0xe1: /* DOS access */
1708 case 0xe3: /* DOS R/O */
1709 case 0xf2: /* DOS secondary */
1710 return BSD_FS_MSDOS;
1711 case 0x07: /* OS/2 HPFS */
1714 return BSD_FS_OTHER;
1719 xbsd_link_part (void)
1722 struct partition *p;
1724 k = get_partition (1, partitions);
1726 if (!xbsd_check_new_partition (&i))
1729 p = get_part_table(k);
1731 xbsd_dlabel.d_partitions[i].p_size = get_nr_sects(p);
1732 xbsd_dlabel.d_partitions[i].p_offset = get_start_sect(p);
1733 xbsd_dlabel.d_partitions[i].p_fstype = xbsd_translate_fstype(p->sys_ind);
1737 #if defined (__alpha__)
1739 #if !defined(__GLIBC__)
1740 typedef unsigned long long u_int64_t;
1744 alpha_bootblock_checksum (char *boot)
1749 dp = (u_int64_t *)boot;
1751 for (i = 0; i < 63; i++)
1755 #endif /* __alpha__ */
1757 #endif /* OSF_LABEL */
1759 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
1760 static inline unsigned short
1761 __swap16(unsigned short x) {
1762 return (((uint16_t)(x) & 0xFF) << 8) | (((uint16_t)(x) & 0xFF00) >> 8);
1765 static inline uint32_t
1766 __swap32(uint32_t x) {
1767 return (((uint32_t)(x) & 0xFF) << 24) | (((uint32_t)(x) & 0xFF00) << 8) | (((uint32_t)(x) & 0xFF0000) >> 8) | (((uint32_t)(x) & 0xFF000000) >> 24);
1771 #ifdef CONFIG_FEATURE_SGI_LABEL
1776 * Copyright (C) Andreas Neuper, Sep 1998.
1777 * This file may be modified and redistributed under
1778 * the terms of the GNU Public License.
1780 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
1781 * Internationalization
1785 static int sgi_other_endian;
1787 static short sgi_volumes=1;
1790 * only dealing with free blocks here
1793 typedef struct { int first; int last; } freeblocks;
1794 static freeblocks freelist[17]; /* 16 partitions can produce 17 vacant slots */
1797 setfreelist( int i, int f, int l ) {
1798 freelist[i].first = f;
1799 freelist[i].last = l;
1803 add2freelist( int f, int l ) {
1805 for( ; i<17 ; i++ ) {
1806 if(freelist[i].last==0) break;
1808 setfreelist( i, f, l );
1812 clearfreelist(void) {
1814 for( ; i<17 ; i++ ) {
1815 setfreelist( i, 0, 0 );
1820 isinfreelist( int b ) {
1822 for( ; i<17 ; i++ ) {
1823 if (freelist[i].first <= b && freelist[i].last >= b) {
1824 return freelist[i].last;
1829 /* return last vacant block of this stride (never 0). */
1830 /* the '>=' is not quite correct, but simplifies the code */
1832 * end of free blocks section
1835 static const struct systypes sgi_sys_types[] = {
1836 /* SGI_VOLHDR */ {"\x00" "SGI volhdr" },
1837 /* 0x01 */ {"\x01" "SGI trkrepl" },
1838 /* 0x02 */ {"\x02" "SGI secrepl" },
1839 /* SGI_SWAP */ {"\x03" "SGI raw" },
1840 /* 0x04 */ {"\x04" "SGI bsd" },
1841 /* 0x05 */ {"\x05" "SGI sysv" },
1842 /* ENTIRE_DISK */ {"\x06" "SGI volume" },
1843 /* SGI_EFS */ {"\x07" "SGI efs" },
1844 /* 0x08 */ {"\x08" "SGI lvol" },
1845 /* 0x09 */ {"\x09" "SGI rlvol" },
1846 /* SGI_XFS */ {"\x0a" "SGI xfs" },
1847 /* SGI_XFSLOG */ {"\x0b" "SGI xfslog" },
1848 /* SGI_XLV */ {"\x0c" "SGI xlv" },
1849 /* SGI_XVM */ {"\x0d" "SGI xvm" },
1850 /* LINUX_SWAP */ {"\x82" "Linux swap" },
1851 /* LINUX_NATIVE */ {"\x83" "Linux native" },
1852 /* LINUX_LVM */ {"\x8d" "Linux LVM" },
1853 /* LINUX_RAID */ {"\xfd" "Linux RAID" },
1859 sgi_get_nsect(void) {
1860 return SGI_SSWAP16(sgilabel->devparam.nsect);
1864 sgi_get_ntrks(void) {
1865 return SGI_SSWAP16(sgilabel->devparam.ntrks);
1869 sgi_get_pcylcount(void) {
1870 return SGI_SSWAP16(sgilabel->devparam.pcylcount);
1875 sgilabel->magic = 0;
1881 two_s_complement_32bit_sum(unsigned int* base, int size /* in bytes */ ) {
1885 size = size / sizeof( unsigned int );
1886 for( i=0; i<size; i++ )
1887 sum = sum - SGI_SSWAP32(base[i]);
1892 check_sgi_label(void) {
1893 if (sizeof(sgilabel) > 512) {
1895 _("According to MIPS Computer Systems, Inc the "
1896 "Label must not contain more than 512 bytes\n"));
1900 if (sgilabel->magic != SGI_LABEL_MAGIC &&
1901 sgilabel->magic != SGI_LABEL_MAGIC_SWAPPED) {
1903 sgi_other_endian = 0;
1907 sgi_other_endian = (sgilabel->magic == SGI_LABEL_MAGIC_SWAPPED);
1909 * test for correct checksum
1911 if( two_s_complement_32bit_sum( (unsigned int*)sgilabel,
1912 sizeof(*sgilabel) ) )
1914 fprintf( stderr, _("Detected sgi disklabel with wrong checksum.\n"));
1917 heads = sgi_get_ntrks();
1918 cylinders = sgi_get_pcylcount();
1919 sectors = sgi_get_nsect();
1929 sgi_get_start_sector( int i ) {
1930 return SGI_SSWAP32(sgilabel->partitions[i].start_sector);
1934 sgi_get_num_sectors( int i ) {
1935 return SGI_SSWAP32(sgilabel->partitions[i].num_sectors);
1939 sgi_get_sysid( int i )
1941 return SGI_SSWAP32(sgilabel->partitions[i].id);
1945 sgi_get_bootpartition(void)
1947 return SGI_SSWAP16(sgilabel->boot_part);
1951 sgi_get_swappartition(void)
1953 return SGI_SSWAP16(sgilabel->swap_part);
1957 sgi_list_table( int xtra ) {
1959 int kpi = 0; /* kernel partition ID */
1962 w = strlen( disk_device );
1965 printf(_("\nDisk %s (SGI disk label): %d heads, %d sectors\n"
1966 "%d cylinders, %d physical cylinders\n"
1967 "%d extra sects/cyl, interleave %d:1\n"
1969 "Units = %s of %d * 512 bytes\n\n"),
1970 disk_device, heads, sectors, cylinders,
1971 SGI_SSWAP16(sgiparam.pcylcount),
1972 SGI_SSWAP16(sgiparam.sparecyl),
1973 SGI_SSWAP16(sgiparam.ilfact),
1975 str_units(PLURAL), units_per_sector);
1977 printf( _("\nDisk %s (SGI disk label): "
1978 "%d heads, %d sectors, %d cylinders\n"
1979 "Units = %s of %d * 512 bytes\n\n"),
1980 disk_device, heads, sectors, cylinders,
1981 str_units(PLURAL), units_per_sector );
1983 printf(_("----- partitions -----\n"
1984 "Pt# %*s Info Start End Sectors Id System\n"),
1985 w + 1, _("Device"));
1986 for (i = 0 ; i < partitions; i++) {
1987 if( sgi_get_num_sectors(i) || debug ) {
1988 uint32_t start = sgi_get_start_sector(i);
1989 uint32_t len = sgi_get_num_sectors(i);
1990 kpi++; /* only count nonempty partitions */
1992 "%2d: %s %4s %9ld %9ld %9ld %2x %s\n",
1993 /* fdisk part number */ i+1,
1994 /* device */ partname(disk_device, kpi, w+2),
1995 /* flags */ (sgi_get_swappartition() == i) ? "swap" :
1996 /* flags */ (sgi_get_bootpartition() == i) ? "boot" : " ",
1997 /* start */ (long) scround(start),
1998 /* end */ (long) scround(start+len)-1,
1999 /* no odd flag on end */ (long) len,
2000 /* type id */ sgi_get_sysid(i),
2001 /* type name */ (type = partition_type(sgi_get_sysid(i)))
2002 ? type : _("Unknown"));
2005 printf(_("----- Bootinfo -----\nBootfile: %s\n"
2006 "----- Directory Entries -----\n"),
2007 sgilabel->boot_file );
2008 for (i = 0 ; i < sgi_volumes; i++)
2010 if (sgilabel->directory[i].vol_file_size)
2012 uint32_t start = SGI_SSWAP32(sgilabel->directory[i].vol_file_start);
2013 uint32_t len = SGI_SSWAP32(sgilabel->directory[i].vol_file_size);
2014 char*name = sgilabel->directory[i].vol_file_name;
2015 printf(_("%2d: %-10s sector%5u size%8u\n"),
2016 i, name, (unsigned int) start, (unsigned int) len);
2022 sgi_set_bootpartition( int i )
2024 sgilabel->boot_part = SGI_SSWAP16(((short)i));
2028 sgi_get_lastblock(void) {
2029 return heads * sectors * cylinders;
2033 sgi_set_swappartition( int i ) {
2034 sgilabel->swap_part = SGI_SSWAP16(((short)i));
2038 sgi_check_bootfile( const char* aFile ) {
2039 if( strlen( aFile ) < 3 ) /* "/a\n" is minimum */
2041 printf( _("\nInvalid Bootfile!\n"
2042 "\tThe bootfile must be an absolute non-zero pathname,\n"
2043 "\te.g. \"/unix\" or \"/unix.save\".\n") );
2046 if( strlen( aFile ) > 16 )
2048 printf( _("\n\tName of Bootfile too long: 16 bytes maximum.\n") );
2051 if( aFile[0] != '/' )
2053 printf( _("\n\tBootfile must have a fully qualified pathname.\n") );
2056 if( strncmp( aFile, sgilabel->boot_file, 16 ) )
2058 printf( _("\n\tBe aware, that the bootfile is not checked for existence.\n\t"
2059 "SGI's default is \"/unix\" and for backup \"/unix.save\".\n") );
2060 /* filename is correct and did change */
2063 return 0; /* filename did not change */
2067 sgi_get_bootfile(void) {
2068 return sgilabel->boot_file;
2072 sgi_set_bootfile( const char* aFile )
2075 if( sgi_check_bootfile( aFile ) )
2079 if( (aFile[i] != '\n') /* in principle caught again by next line */
2080 && (strlen( aFile ) > i ) )
2081 sgilabel->boot_file[i] = aFile[i];
2083 sgilabel->boot_file[i] = 0;
2086 printf( _("\n\tBootfile is changed to \"%s\".\n"), sgilabel->boot_file );
2091 create_sgiinfo(void)
2093 /* I keep SGI's habit to write the sgilabel to the second block */
2094 sgilabel->directory[0].vol_file_start = SGI_SSWAP32( 2 );
2095 sgilabel->directory[0].vol_file_size = SGI_SSWAP32( sizeof( sgiinfo ) );
2096 strncpy( sgilabel->directory[0].vol_file_name, "sgilabel", 8 );
2099 static sgiinfo * fill_sgiinfo(void);
2102 sgi_write_table(void)
2105 sgilabel->csum = SGI_SSWAP32( two_s_complement_32bit_sum(
2106 (unsigned int*)sgilabel,
2107 sizeof(*sgilabel) ) );
2108 assert( two_s_complement_32bit_sum(
2109 (unsigned int*)sgilabel, sizeof(*sgilabel) ) == 0 );
2110 if( lseek(fd, 0, SEEK_SET) < 0 )
2111 fdisk_fatal(unable_to_seek);
2112 if( write(fd, sgilabel, SECTOR_SIZE) != SECTOR_SIZE )
2113 fdisk_fatal(unable_to_write);
2114 if( ! strncmp( sgilabel->directory[0].vol_file_name, "sgilabel",8 ) )
2117 * keep this habbit of first writing the "sgilabel".
2118 * I never tested whether it works without (AN 981002).
2120 sgiinfo*info = fill_sgiinfo(); /* fills the block appropriately */
2121 int infostartblock = SGI_SSWAP32( sgilabel->directory[0].vol_file_start );
2122 if( ext2_llseek(fd, (ext2_loff_t)infostartblock*
2123 SECTOR_SIZE, SEEK_SET) < 0 )
2124 fdisk_fatal(unable_to_seek);
2125 if( write(fd, info, SECTOR_SIZE) != SECTOR_SIZE )
2126 fdisk_fatal(unable_to_write);
2132 compare_start( int *x, int *y ) {
2134 * sort according to start sectors
2135 * and prefers largest partition:
2136 * entry zero is entire disk entry
2140 int a = sgi_get_start_sector(i);
2141 int b = sgi_get_start_sector(j);
2142 int c = sgi_get_num_sectors(i);
2143 int d = sgi_get_num_sectors(j);
2153 verify_sgi( int verbose )
2155 int Index[16]; /* list of valid partitions */
2156 int sortcount = 0; /* number of used partitions, i.e. non-zero lengths */
2157 int entire = 0, i = 0; /* local counters */
2159 int gap = 0; /* count unused blocks */
2160 int lastblock = sgi_get_lastblock();
2164 for( i=0; i<16; i++ )
2166 if( sgi_get_num_sectors(i)!=0 )
2168 Index[sortcount++]=i;
2169 if( sgi_get_sysid(i) == ENTIRE_DISK )
2174 printf(_("More than one entire disk entry present.\n"));
2179 if( sortcount == 0 )
2182 printf(_("No partitions defined\n"));
2185 qsort( Index, sortcount, sizeof(Index[0]), (void*)compare_start );
2186 if( sgi_get_sysid( Index[0] ) == ENTIRE_DISK )
2188 if( ( Index[0] != 10 ) && verbose )
2189 printf( _("IRIX likes when Partition 11 covers the entire disk.\n") );
2190 if( ( sgi_get_start_sector( Index[0] ) != 0 ) && verbose )
2191 printf( _("The entire disk partition should start at block 0,\nnot "
2192 "at diskblock %d.\n"), sgi_get_start_sector(Index[0] ) );
2193 if(debug) /* I do not understand how some disks fulfil it */
2194 if( ( sgi_get_num_sectors( Index[0] ) != lastblock ) && verbose )
2195 printf( _("The entire disk partition is only %d diskblock large,\n"
2196 "but the disk is %d diskblocks long.\n"),
2197 sgi_get_num_sectors( Index[0] ), lastblock );
2198 lastblock = sgi_get_num_sectors( Index[0] );
2202 printf( _("One Partition (#11) should cover the entire disk.\n") );
2204 printf( "sysid=%d\tpartition=%d\n",
2205 sgi_get_sysid( Index[0] ), Index[0]+1 );
2207 for( i=1, start=0; i<sortcount; i++ )
2209 int cylsize = sgi_get_nsect() * sgi_get_ntrks();
2210 if( (sgi_get_start_sector( Index[i] ) % cylsize) != 0 )
2212 if(debug) /* I do not understand how some disks fulfil it */
2214 printf( _("Partition %d does not start on cylinder boundary.\n"),
2217 if( sgi_get_num_sectors( Index[i] ) % cylsize != 0 )
2219 if(debug) /* I do not understand how some disks fulfil it */
2221 printf( _("Partition %d does not end on cylinder boundary.\n"),
2224 /* We cannot handle several "entire disk" entries. */
2225 if( sgi_get_sysid( Index[i] ) == ENTIRE_DISK ) continue;
2226 if( start > sgi_get_start_sector( Index[i] ) )
2229 printf( _("The Partition %d and %d overlap by %d sectors.\n"),
2230 Index[i-1]+1, Index[i]+1,
2231 start - sgi_get_start_sector( Index[i] ) );
2232 if( gap > 0 ) gap = -gap;
2233 if( gap == 0 ) gap = -1;
2235 if( start < sgi_get_start_sector( Index[i] ) )
2238 printf( _("Unused gap of %8d sectors - sectors %8d-%d\n"),
2239 sgi_get_start_sector( Index[i] ) - start,
2240 start, sgi_get_start_sector( Index[i] )-1 );
2241 gap += sgi_get_start_sector( Index[i] ) - start;
2242 add2freelist( start, sgi_get_start_sector( Index[i] ) );
2244 start = sgi_get_start_sector( Index[i] )
2245 + sgi_get_num_sectors( Index[i] );
2249 printf( "%2d:%12d\t%12d\t%12d\n", Index[i],
2250 sgi_get_start_sector(Index[i]),
2251 sgi_get_num_sectors(Index[i]),
2252 sgi_get_sysid(Index[i]) );
2255 if( ( start < lastblock ) )
2258 printf( _("Unused gap of %8d sectors - sectors %8d-%d\n"),
2259 lastblock - start, start, lastblock-1 );
2260 gap += lastblock - start;
2261 add2freelist( start, lastblock );
2264 * Done with arithmetics
2265 * Go for details now
2269 if( !sgi_get_num_sectors( sgi_get_bootpartition() ) )
2271 printf( _("\nThe boot partition does not exist.\n") );
2273 if( !sgi_get_num_sectors( sgi_get_swappartition() ) )
2275 printf( _("\nThe swap partition does not exist.\n") );
2277 if( ( sgi_get_sysid( sgi_get_swappartition() ) != SGI_SWAP )
2278 && ( sgi_get_sysid( sgi_get_swappartition() ) != LINUX_SWAP ) )
2280 printf( _("\nThe swap partition has no swap type.\n") );
2282 if( sgi_check_bootfile( "/unix" ) )
2284 printf( _("\tYou have chosen an unusual boot file name.\n") );
2293 * returned value is:
2294 * = 0 : disk is properly filled to the rim
2295 * < 0 : there is an overlap
2296 * > 0 : there is still some vacant space
2298 return verify_sgi(0);
2302 sgi_change_sysid( int i, int sys )
2304 if( sgi_get_num_sectors(i) == 0 ) /* caught already before, ... */
2306 printf(_("Sorry You may change the Tag of non-empty partitions.\n"));
2309 if( ((sys != ENTIRE_DISK ) && (sys != SGI_VOLHDR))
2310 && (sgi_get_start_sector(i)<1) )
2313 _("It is highly recommended that the partition at offset 0\n"
2314 "is of type \"SGI volhdr\", the IRIX system will rely on it to\n"
2315 "retrieve from its directory standalone tools like sash and fx.\n"
2316 "Only the \"SGI volume\" entire disk section may violate this.\n"
2317 "Type YES if you are sure about tagging this partition differently.\n"));
2318 if (strcmp (line_ptr, _("YES\n")))
2321 sgilabel->partitions[i].id = SGI_SSWAP32(sys);
2324 /* returns partition index of first entry marked as entire disk */
2328 for( i=0; i<16; i++ )
2329 if( sgi_get_sysid(i) == SGI_VOLUME )
2335 sgi_set_partition( int i, uint start, uint length, int sys ) {
2336 sgilabel->partitions[i].id =
2338 sgilabel->partitions[i].num_sectors =
2339 SGI_SSWAP32( length );
2340 sgilabel->partitions[i].start_sector =
2341 SGI_SSWAP32( start );
2343 if( sgi_gaps() < 0 ) /* rebuild freelist */
2344 printf(_("Do You know, You got a partition overlap on the disk?\n"));
2348 sgi_set_entire(void) {
2350 for( n=10; n<partitions; n++ ) {
2351 if(!sgi_get_num_sectors( n ) ) {
2352 sgi_set_partition( n, 0, sgi_get_lastblock(), SGI_VOLUME );
2359 sgi_set_volhdr(void)
2362 for( n=8; n<partitions; n++ )
2364 if(!sgi_get_num_sectors( n ) )
2367 * 5 cylinders is an arbitrary value I like
2368 * IRIX 5.3 stored files in the volume header
2369 * (like sash, symmon, fx, ide) with ca. 3200
2372 if( heads * sectors * 5 < sgi_get_lastblock() )
2373 sgi_set_partition( n, 0, heads * sectors * 5, SGI_VOLHDR );
2380 sgi_delete_partition( int i )
2382 sgi_set_partition( i, 0, 0, 0 );
2386 sgi_add_partition( int n, int sys )
2389 int first=0, last=0;
2393 } else if ( n == 8 ) {
2396 if( sgi_get_num_sectors(n) )
2398 printf(_("Partition %d is already defined. Delete "
2399 "it before re-adding it.\n"), n + 1);
2402 if( (sgi_entire() == -1)
2403 && (sys != SGI_VOLUME) )
2405 printf(_("Attempting to generate entire disk entry automatically.\n"));
2409 if( (sgi_gaps() == 0)
2410 && (sys != SGI_VOLUME) )
2412 printf(_("The entire disk is already covered with partitions.\n"));
2415 if( sgi_gaps() < 0 )
2417 printf(_("You got a partition overlap on the disk. Fix it first!\n"));
2420 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
2422 if(sys == SGI_VOLUME) {
2423 last = sgi_get_lastblock();
2424 first = read_int(0, 0, last-1, 0, mesg);
2426 printf(_("It is highly recommended that eleventh partition\n"
2427 "covers the entire disk and is of type `SGI volume'\n"));
2430 first = freelist[0].first;
2431 last = freelist[0].last;
2432 first = read_int(scround(first), scround(first), scround(last)-1,
2435 if (display_in_cyl_units)
2436 first *= units_per_sector;
2438 first = first; /* align to cylinder if you know how ... */
2440 last = isinfreelist(first);
2442 printf(_("You will get a partition overlap on the disk. "
2443 "Fix it first!\n"));
2447 snprintf(mesg, sizeof(mesg), _(" Last %s"), str_units(SINGULAR));
2448 last = read_int(scround(first), scround(last)-1, scround(last)-1,
2449 scround(first), mesg)+1;
2450 if (display_in_cyl_units)
2451 last *= units_per_sector;
2453 last = last; /* align to cylinder if You know how ... */
2454 if( (sys == SGI_VOLUME) && ( first != 0 || last != sgi_get_lastblock() ) )
2455 printf(_("It is highly recommended that eleventh partition\n"
2456 "covers the entire disk and is of type `SGI volume'\n"));
2457 sgi_set_partition( n, first, last-first, sys );
2461 create_sgilabel(void)
2463 struct hd_geometry geometry;
2466 int sysid; } old[4];
2469 _("Building a new SGI disklabel. Changes will remain in memory only,\n"
2470 "until you decide to write them. After that, of course, the previous\n"
2471 "content will be unrecoverably lost.\n\n"));
2473 sgi_other_endian = (BYTE_ORDER == LITTLE_ENDIAN);
2476 if (!ioctl(fd, HDIO_REQ, &geometry))
2478 if (!ioctl(fd, HDIO_GETGEO, &geometry))
2481 heads = geometry.heads;
2482 sectors = geometry.sectors;
2483 cylinders = geometry.cylinders;
2485 for (i = 0; i < 4; i++)
2488 if( valid_part_table_flag(MBRbuffer) )
2490 if( get_part_table(i)->sys_ind )
2492 old[i].sysid = get_part_table(i)->sys_ind;
2493 old[i].start = get_start_sect( get_part_table(i) );
2494 old[i].nsect = get_nr_sects( get_part_table(i) );
2495 printf( _("Trying to keep parameters of partition %d.\n"), i );
2497 printf( _("ID=%02x\tSTART=%d\tLENGTH=%d\n"),
2498 old[i].sysid, old[i].start, old[i].nsect );
2502 memset(MBRbuffer, 0, sizeof(MBRbuffer));
2503 sgilabel->magic = SGI_SSWAP32(SGI_LABEL_MAGIC);
2504 sgilabel->boot_part = SGI_SSWAP16(0);
2505 sgilabel->swap_part = SGI_SSWAP16(1);
2507 /* sizeof(sgilabel->boot_file) = 16 > 6 */
2508 memset(sgilabel->boot_file, 0, 16);
2509 strcpy(sgilabel->boot_file, "/unix");
2511 sgilabel->devparam.skew = (0);
2512 sgilabel->devparam.gap1 = (0);
2513 sgilabel->devparam.gap2 = (0);
2514 sgilabel->devparam.sparecyl = (0);
2515 sgilabel->devparam.pcylcount = SGI_SSWAP16(geometry.cylinders);
2516 sgilabel->devparam.head_vol0 = SGI_SSWAP16(0);
2517 sgilabel->devparam.ntrks = SGI_SSWAP16(geometry.heads);
2518 /* tracks/cylinder (heads) */
2519 sgilabel->devparam.cmd_tag_queue_depth = (0);
2520 sgilabel->devparam.unused0 = (0);
2521 sgilabel->devparam.unused1 = SGI_SSWAP16(0);
2522 sgilabel->devparam.nsect = SGI_SSWAP16(geometry.sectors);
2524 sgilabel->devparam.bytes = SGI_SSWAP16(512);
2525 sgilabel->devparam.ilfact = SGI_SSWAP16(1);
2526 sgilabel->devparam.flags = SGI_SSWAP32(TRACK_FWD|
2527 IGNORE_ERRORS|RESEEK);
2528 sgilabel->devparam.datarate = SGI_SSWAP32(0);
2529 sgilabel->devparam.retries_on_error = SGI_SSWAP32(1);
2530 sgilabel->devparam.ms_per_word = SGI_SSWAP32(0);
2531 sgilabel->devparam.xylogics_gap1 = SGI_SSWAP16(0);
2532 sgilabel->devparam.xylogics_syncdelay = SGI_SSWAP16(0);
2533 sgilabel->devparam.xylogics_readdelay = SGI_SSWAP16(0);
2534 sgilabel->devparam.xylogics_gap2 = SGI_SSWAP16(0);
2535 sgilabel->devparam.xylogics_readgate = SGI_SSWAP16(0);
2536 sgilabel->devparam.xylogics_writecont = SGI_SSWAP16(0);
2537 memset( &(sgilabel->directory), 0, sizeof(struct volume_directory)*15 );
2538 memset( &(sgilabel->partitions), 0, sizeof(struct sgi_partition)*16 );
2544 for (i = 0; i < 4; i++)
2548 sgi_set_partition( i, old[i].start, old[i].nsect, old[i].sysid );
2556 /* do nothing in the beginning */
2559 /* _____________________________________________________________
2565 sgiinfo*info=calloc( 1, sizeof(sgiinfo) );
2566 info->magic=SGI_SSWAP32(SGI_INFO_MAGIC);
2567 info->b1=SGI_SSWAP32(-1);
2568 info->b2=SGI_SSWAP16(-1);
2569 info->b3=SGI_SSWAP16(1);
2570 /* You may want to replace this string !!!!!!! */
2571 strcpy( info->scsi_string, "IBM OEM 0662S12 3 30" );
2572 strcpy( info->serial, "0000" );
2573 info->check1816 = SGI_SSWAP16(18*256 +16 );
2574 strcpy( info->installer, "Sfx version 5.3, Oct 18, 1994" );
2577 #endif /* SGI_LABEL */
2580 #ifdef CONFIG_FEATURE_SUN_LABEL
2584 * I think this is mostly, or entirely, due to
2585 * Jakub Jelinek (jj@sunsite.mff.cuni.cz), July 1996
2587 * Merged with fdisk for other architectures, aeb, June 1998.
2589 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
2590 * Internationalization
2594 static int sun_other_endian;
2595 static int scsi_disk;
2599 #define IDE0_MAJOR 3
2602 #define IDE1_MAJOR 22
2604 static void guess_device_type(void) {
2605 struct stat bootstat;
2607 if (fstat (fd, &bootstat) < 0) {
2610 } else if (S_ISBLK(bootstat.st_mode)
2611 && ((bootstat.st_rdev >> 8) == IDE0_MAJOR ||
2612 (bootstat.st_rdev >> 8) == IDE1_MAJOR)) {
2615 } else if (S_ISBLK(bootstat.st_mode)
2616 && (bootstat.st_rdev >> 8) == FLOPPY_MAJOR) {
2625 static const struct systypes sun_sys_types[] = {
2626 /* 0 */ {"\x00" "Empty" },
2627 /* 1 */ {"\x01" "Boot" },
2628 /* 2 */ {"\x02" "SunOS root" },
2629 /* SUNOS_SWAP */ {"\x03" "SunOS swap" },
2630 /* 4 */ {"\x04" "SunOS usr" },
2631 /* WHOLE_DISK */ {"\x05" "Whole disk" },
2632 /* 6 */ {"\x06" "SunOS stand" },
2633 /* 7 */ {"\x07" "SunOS var" },
2634 /* 8 */ {"\x08" "SunOS home" },
2635 /* LINUX_SWAP */ {"\x82" "Linux swap" },
2636 /* LINUX_NATIVE */ {"\x83" "Linux native" },
2637 /* 0x8e */ {"\x8e" "Linux LVM" },
2638 /* New (2.2.x) raid partition with autodetect using persistent superblock */
2639 /* 0xfd */ {"\xfd" "Linux raid autodetect" },
2645 set_sun_partition(int i, uint start, uint stop, int sysid) {
2646 sunlabel->infos[i].id = sysid;
2647 sunlabel->partitions[i].start_cylinder =
2648 SUN_SSWAP32(start / (heads * sectors));
2649 sunlabel->partitions[i].num_sectors =
2650 SUN_SSWAP32(stop - start);
2657 sunlabel->magic = 0;
2662 check_sun_label(void) {
2663 unsigned short *ush;
2666 if (sunlabel->magic != SUN_LABEL_MAGIC &&
2667 sunlabel->magic != SUN_LABEL_MAGIC_SWAPPED) {
2669 sun_other_endian = 0;
2672 sun_other_endian = (sunlabel->magic == SUN_LABEL_MAGIC_SWAPPED);
2673 ush = ((unsigned short *) (sunlabel + 1)) - 1;
2674 for (csum = 0; ush >= (unsigned short *)sunlabel;) csum ^= *ush--;
2676 fprintf(stderr,_("Detected sun disklabel with wrong checksum.\n"
2677 "Probably you'll have to set all the values,\n"
2678 "e.g. heads, sectors, cylinders and partitions\n"
2679 "or force a fresh label (s command in main menu)\n"));
2681 heads = SUN_SSWAP16(sunlabel->ntrks);
2682 cylinders = SUN_SSWAP16(sunlabel->ncyl);
2683 sectors = SUN_SSWAP16(sunlabel->nsect);
2691 static const struct sun_predefined_drives {
2694 unsigned short sparecyl;
2695 unsigned short ncyl;
2696 unsigned short nacyl;
2697 unsigned short pcylcount;
2698 unsigned short ntrks;
2699 unsigned short nsect;
2700 unsigned short rspeed;
2702 {"Quantum","ProDrive 80S",1,832,2,834,6,34,3662},
2703 {"Quantum","ProDrive 105S",1,974,2,1019,6,35,3662},
2704 {"CDC","Wren IV 94171-344",3,1545,2,1549,9,46,3600},
2705 {"IBM","DPES-31080",0,4901,2,4903,4,108,5400},
2706 {"IBM","DORS-32160",0,1015,2,1017,67,62,5400},
2707 {"IBM","DNES-318350",0,11199,2,11474,10,320,7200},
2708 {"SEAGATE","ST34371",0,3880,2,3882,16,135,7228},
2709 {"","SUN0104",1,974,2,1019,6,35,3662},
2710 {"","SUN0207",4,1254,2,1272,9,36,3600},
2711 {"","SUN0327",3,1545,2,1549,9,46,3600},
2712 {"","SUN0340",0,1538,2,1544,6,72,4200},
2713 {"","SUN0424",2,1151,2,2500,9,80,4400},
2714 {"","SUN0535",0,1866,2,2500,7,80,5400},
2715 {"","SUN0669",5,1614,2,1632,15,54,3600},
2716 {"","SUN1.0G",5,1703,2,1931,15,80,3597},
2717 {"","SUN1.05",0,2036,2,2038,14,72,5400},
2718 {"","SUN1.3G",6,1965,2,3500,17,80,5400},
2719 {"","SUN2.1G",0,2733,2,3500,19,80,5400},
2720 {"IOMEGA","Jaz",0,1019,2,1021,64,32,5394},
2723 static const struct sun_predefined_drives *
2724 sun_autoconfigure_scsi(void) {
2725 const struct sun_predefined_drives *p = NULL;
2727 #ifdef SCSI_IOCTL_GET_IDLUN
2737 if (!ioctl(fd, SCSI_IOCTL_GET_IDLUN, &id)) {
2739 "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n",
2741 ((id[0]>>24)&0xff)-/*PROC_SCSI_SCSI+PROC_SCSI_FILE*/33,
2743 /* This is very wrong (works only if you have one HBA),
2744 but I haven't found a way how to get hostno
2745 from the current kernel */
2751 pfd = fopen("/proc/scsi/scsi","r");
2753 while (fgets(buffer2,2048,pfd)) {
2754 if (!strcmp(buffer, buffer2)) {
2755 if (fgets(buffer2,2048,pfd)) {
2756 q = strstr(buffer2,"Vendor: ");
2761 *q++ = 0; /* truncate vendor name */
2762 q = strstr(q,"Model: ");
2767 q = strstr(q," Rev: ");
2770 for (i = 0; i < SIZE(sun_drives); i++) {
2771 if (*sun_drives[i].vendor && strcasecmp(sun_drives[i].vendor, vendor))
2773 if (!strstr(model, sun_drives[i].model))
2775 printf(_("Autoconfigure found a %s%s%s\n"),sun_drives[i].vendor,(*sun_drives[i].vendor) ? " " : "",sun_drives[i].model);
2793 static void create_sunlabel(void)
2795 struct hd_geometry geometry;
2799 const struct sun_predefined_drives *p = NULL;
2802 _("Building a new sun disklabel. Changes will remain in memory only,\n"
2803 "until you decide to write them. After that, of course, the previous\n"
2804 "content won't be recoverable.\n\n"));
2805 #if BYTE_ORDER == LITTLE_ENDIAN
2806 sun_other_endian = 1;
2808 sun_other_endian = 0;
2810 memset(MBRbuffer, 0, sizeof(MBRbuffer));
2811 sunlabel->magic = SUN_SSWAP16(SUN_LABEL_MAGIC);
2813 puts(_("Drive type\n"
2814 " ? auto configure\n"
2815 " 0 custom (with hardware detected defaults)"));
2816 for (i = 0; i < SIZE(sun_drives); i++) {
2817 printf(" %c %s%s%s\n",
2818 i + 'a', sun_drives[i].vendor,
2819 (*sun_drives[i].vendor) ? " " : "",
2820 sun_drives[i].model);
2823 c = read_char(_("Select type (? for auto, 0 for custom): "));
2824 if (c >= 'a' && c < 'a' + SIZE(sun_drives)) {
2825 p = sun_drives + c - 'a';
2827 } else if (c >= 'A' && c < 'A' + SIZE(sun_drives)) {
2828 p = sun_drives + c - 'A';
2830 } else if (c == '0') {
2832 } else if (c == '?' && scsi_disk) {
2833 p = sun_autoconfigure_scsi();
2835 printf(_("Autoconfigure failed.\n"));
2843 if (!ioctl(fd, HDIO_REQ, &geometry)) {
2845 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
2847 heads = geometry.heads;
2848 sectors = geometry.sectors;
2849 cylinders = geometry.cylinders;
2856 sunlabel->nacyl = 0;
2857 sunlabel->pcylcount = SUN_SSWAP16(cylinders);
2858 sunlabel->rspeed = SUN_SSWAP16(300);
2859 sunlabel->ilfact = SUN_SSWAP16(1);
2860 sunlabel->sparecyl = 0;
2862 heads = read_int(1,heads,1024,0,_("Heads"));
2863 sectors = read_int(1,sectors,1024,0,_("Sectors/track"));
2865 cylinders = read_int(1,cylinders-2,65535,0,_("Cylinders"));
2867 cylinders = read_int(1,0,65535,0,_("Cylinders"));
2869 SUN_SSWAP16(read_int(0,2,65535,0,
2870 _("Alternate cylinders")));
2871 sunlabel->pcylcount =
2872 SUN_SSWAP16(read_int(0,cylinders+SUN_SSWAP16(sunlabel->nacyl),
2873 65535,0,_("Physical cylinders")));
2875 SUN_SSWAP16(read_int(1,5400,100000,0,
2876 _("Rotation speed (rpm)")));
2878 SUN_SSWAP16(read_int(1,1,32,0,_("Interleave factor")));
2879 sunlabel->sparecyl =
2880 SUN_SSWAP16(read_int(0,0,sectors,0,
2881 _("Extra sectors per cylinder")));
2884 sunlabel->sparecyl = SUN_SSWAP16(p->sparecyl);
2885 sunlabel->ncyl = SUN_SSWAP16(p->ncyl);
2886 sunlabel->nacyl = SUN_SSWAP16(p->nacyl);
2887 sunlabel->pcylcount = SUN_SSWAP16(p->pcylcount);
2888 sunlabel->ntrks = SUN_SSWAP16(p->ntrks);
2889 sunlabel->nsect = SUN_SSWAP16(p->nsect);
2890 sunlabel->rspeed = SUN_SSWAP16(p->rspeed);
2891 sunlabel->ilfact = SUN_SSWAP16(1);
2892 cylinders = p->ncyl;
2895 puts(_("You may change all the disk params from the x menu"));
2898 snprintf(sunlabel->info, sizeof(sunlabel->info),
2899 "%s%s%s cyl %d alt %d hd %d sec %d",
2900 p ? p->vendor : "", (p && *p->vendor) ? " " : "",
2902 : (floppy ? _("3,5\" floppy") : _("Linux custom")),
2903 cylinders, SUN_SSWAP16(sunlabel->nacyl), heads, sectors);
2905 sunlabel->ntrks = SUN_SSWAP16(heads);
2906 sunlabel->nsect = SUN_SSWAP16(sectors);
2907 sunlabel->ncyl = SUN_SSWAP16(cylinders);
2909 set_sun_partition(0, 0, cylinders * heads * sectors, LINUX_NATIVE);
2911 if (cylinders * heads * sectors >= 150 * 2048) {
2912 ndiv = cylinders - (50 * 2048 / (heads * sectors)); /* 50M swap */
2914 ndiv = cylinders * 2 / 3;
2915 set_sun_partition(0, 0, ndiv * heads * sectors, LINUX_NATIVE);
2916 set_sun_partition(1, ndiv * heads * sectors, cylinders * heads * sectors, LINUX_SWAP);
2917 sunlabel->infos[1].flags |= 0x01; /* Not mountable */
2919 set_sun_partition(2, 0, cylinders * heads * sectors, WHOLE_DISK);
2921 unsigned short *ush = (unsigned short *)sunlabel;
2922 unsigned short csum = 0;
2923 while(ush < (unsigned short *)(&sunlabel->csum))
2925 sunlabel->csum = csum;
2928 set_all_unchanged();
2930 get_boot(create_empty_sun);
2934 toggle_sunflags(int i, unsigned char mask) {
2935 if (sunlabel->infos[i].flags & mask)
2936 sunlabel->infos[i].flags &= ~mask;
2937 else sunlabel->infos[i].flags |= mask;
2942 fetch_sun(uint *starts, uint *lens, uint *start, uint *stop) {
2943 int i, continuous = 1;
2944 *start = 0; *stop = cylinders * heads * sectors;
2945 for (i = 0; i < partitions; i++) {
2946 if (sunlabel->partitions[i].num_sectors
2947 && sunlabel->infos[i].id
2948 && sunlabel->infos[i].id != WHOLE_DISK) {
2949 starts[i] = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
2950 lens[i] = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
2952 if (starts[i] == *start)
2954 else if (starts[i] + lens[i] >= *stop)
2958 /* There will be probably more gaps
2959 than one, so lets check afterwards */
2968 static uint *verify_sun_starts;
2971 verify_sun_cmp(int *a, int *b) {
2972 if (*a == -1) return 1;
2973 if (*b == -1) return -1;
2974 if (verify_sun_starts[*a] > verify_sun_starts[*b]) return 1;
2980 uint starts[8], lens[8], start, stop;
2981 int i,j,k,starto,endo;
2984 verify_sun_starts = starts;
2985 fetch_sun(starts,lens,&start,&stop);
2986 for (k = 0; k < 7; k++) {
2987 for (i = 0; i < 8; i++) {
2988 if (k && (lens[i] % (heads * sectors))) {
2989 printf(_("Partition %d doesn't end on cylinder boundary\n"), i+1);
2992 for (j = 0; j < i; j++)
2994 if (starts[j] == starts[i]+lens[i]) {
2995 starts[j] = starts[i]; lens[j] += lens[i];
2997 } else if (starts[i] == starts[j]+lens[j]){
3001 if (starts[i] < starts[j]+lens[j] &&
3002 starts[j] < starts[i]+lens[i]) {
3004 if (starts[j] > starto)
3006 endo = starts[i]+lens[i];
3007 if (starts[j]+lens[j] < endo)
3008 endo = starts[j]+lens[j];
3009 printf(_("Partition %d overlaps with others in "
3010 "sectors %d-%d\n"), i+1, starto, endo);
3017 for (i = 0; i < 8; i++) {
3023 qsort(array,SIZE(array),sizeof(array[0]),
3024 (int (*)(const void *,const void *)) verify_sun_cmp);
3025 if (array[0] == -1) {
3026 printf(_("No partitions defined\n"));
3029 stop = cylinders * heads * sectors;
3030 if (starts[array[0]])
3031 printf(_("Unused gap - sectors 0-%d\n"),starts[array[0]]);
3032 for (i = 0; i < 7 && array[i+1] != -1; i++) {
3033 printf(_("Unused gap - sectors %d-%d\n"),starts[array[i]]+lens[array[i]],starts[array[i+1]]);
3035 start = starts[array[i]]+lens[array[i]];
3037 printf(_("Unused gap - sectors %d-%d\n"),start,stop);
3041 add_sun_partition(int n, int sys) {
3042 uint start, stop, stop2;
3043 uint starts[8], lens[8];
3049 if (sunlabel->partitions[n].num_sectors && sunlabel->infos[n].id) {
3050 printf(_("Partition %d is already defined. Delete "
3051 "it before re-adding it.\n"), n + 1);
3055 fetch_sun(starts,lens,&start,&stop);
3056 if (stop <= start) {
3060 printf(_("Other partitions already cover the whole disk.\nDelete "
3061 "some/shrink them before retry.\n"));
3065 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
3068 first = read_int(0, 0, 0, 0, mesg);
3070 first = read_int(scround(start), scround(stop)+1,
3071 scround(stop), 0, mesg);
3072 if (display_in_cyl_units)
3073 first *= units_per_sector;
3075 /* Starting sector has to be properly aligned */
3076 first = (first + heads * sectors - 1) / (heads * sectors);
3077 if (n == 2 && first != 0)
3079 It is highly recommended that the third partition covers the whole disk\n\
3080 and is of type `Whole disk'\n");
3081 /* ewt asks to add: "don't start a partition at cyl 0"
3082 However, edmundo@rano.demon.co.uk writes:
3083 "In addition to having a Sun partition table, to be able to
3084 boot from the disc, the first partition, /dev/sdX1, must
3085 start at cylinder 0. This means that /dev/sdX1 contains
3086 the partition table and the boot block, as these are the
3087 first two sectors of the disc. Therefore you must be
3088 careful what you use /dev/sdX1 for. In particular, you must
3089 not use a partition starting at cylinder 0 for Linux swap,
3090 as that would overwrite the partition table and the boot
3091 block. You may, however, use such a partition for a UFS
3092 or EXT2 file system, as these file systems leave the first
3093 1024 bytes undisturbed. */
3094 /* On the other hand, one should not use partitions
3095 starting at block 0 in an md, or the label will
3097 for (i = 0; i < partitions; i++)
3098 if (lens[i] && starts[i] <= first
3099 && starts[i] + lens[i] > first)
3101 if (i < partitions && !whole_disk) {
3102 if (n == 2 && !first) {
3106 printf(_("Sector %d is already allocated\n"), first);
3110 stop = cylinders * heads * sectors;
3112 for (i = 0; i < partitions; i++) {
3113 if (starts[i] > first && starts[i] < stop)
3116 snprintf(mesg, sizeof(mesg),
3117 _("Last %s or +size or +sizeM or +sizeK"),
3118 str_units(SINGULAR));
3120 last = read_int(scround(stop2), scround(stop2), scround(stop2),
3122 else if (n == 2 && !first)
3123 last = read_int(scround(first), scround(stop2), scround(stop2),
3124 scround(first), mesg);
3126 last = read_int(scround(first), scround(stop), scround(stop),
3127 scround(first), mesg);
3128 if (display_in_cyl_units)
3129 last *= units_per_sector;
3130 if (n == 2 && !first) {
3131 if (last >= stop2) {
3134 } else if (last > stop) {
3136 _("You haven't covered the whole disk with the 3rd partition, but your value\n"
3137 "%d %s covers some other partition. Your entry has been changed\n"
3139 scround(last), str_units(SINGULAR),
3140 scround(stop), str_units(SINGULAR));
3143 } else if (!whole_disk && last > stop)
3146 if (whole_disk) sys = WHOLE_DISK;
3147 set_sun_partition(n, first, last, sys);
3151 sun_delete_partition(int i) {
3152 if (i == 2 && sunlabel->infos[i].id == WHOLE_DISK &&
3153 !sunlabel->partitions[i].start_cylinder &&
3154 SUN_SSWAP32(sunlabel->partitions[i].num_sectors)
3155 == heads * sectors * cylinders)
3156 printf(_("If you want to maintain SunOS/Solaris compatibility, "
3157 "consider leaving this\n"
3158 "partition as Whole disk (5), starting at 0, with %u "
3160 (uint) SUN_SSWAP32(sunlabel->partitions[i].num_sectors));
3161 sunlabel->infos[i].id = 0;
3162 sunlabel->partitions[i].num_sectors = 0;
3166 sun_change_sysid(int i, int sys) {
3167 if (sys == LINUX_SWAP && !sunlabel->partitions[i].start_cylinder) {
3169 _("It is highly recommended that the partition at offset 0\n"
3170 "is UFS, EXT2FS filesystem or SunOS swap. Putting Linux swap\n"
3171 "there may destroy your partition table and bootblock.\n"
3172 "Type YES if you're very sure you would like that partition\n"
3173 "tagged with 82 (Linux swap): "));
3174 if (strcmp (line_ptr, _("YES\n")))
3180 /* swaps are not mountable by default */
3181 sunlabel->infos[i].flags |= 0x01;
3184 /* assume other types are mountable;
3185 user can change it anyway */
3186 sunlabel->infos[i].flags &= ~0x01;
3189 sunlabel->infos[i].id = sys;
3193 sun_list_table(int xtra) {
3197 w = strlen(disk_device);
3200 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d rpm\n"
3201 "%d cylinders, %d alternate cylinders, %d physical cylinders\n"
3202 "%d extra sects/cyl, interleave %d:1\n"
3204 "Units = %s of %d * 512 bytes\n\n"),
3205 disk_device, heads, sectors, SUN_SSWAP16(sunlabel->rspeed),
3206 cylinders, SUN_SSWAP16(sunlabel->nacyl),
3207 SUN_SSWAP16(sunlabel->pcylcount),
3208 SUN_SSWAP16(sunlabel->sparecyl),
3209 SUN_SSWAP16(sunlabel->ilfact),
3211 str_units(PLURAL), units_per_sector);
3214 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d cylinders\n"
3215 "Units = %s of %d * 512 bytes\n\n"),
3216 disk_device, heads, sectors, cylinders,
3217 str_units(PLURAL), units_per_sector);
3219 printf(_("%*s Flag Start End Blocks Id System\n"),
3220 w + 1, _("Device"));
3221 for (i = 0 ; i < partitions; i++) {
3222 if (sunlabel->partitions[i].num_sectors) {
3223 uint32_t start = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
3224 uint32_t len = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
3226 "%s %c%c %9ld %9ld %9ld%c %2x %s\n",
3227 /* device */ partname(disk_device, i+1, w),
3228 /* flags */ (sunlabel->infos[i].flags & 0x01) ? 'u' : ' ',
3229 (sunlabel->infos[i].flags & 0x10) ? 'r' : ' ',
3230 /* start */ (long) scround(start),
3231 /* end */ (long) scround(start+len),
3232 /* odd flag on end */ (long) len / 2, len & 1 ? '+' : ' ',
3233 /* type id */ sunlabel->infos[i].id,
3234 /* type name */ (type = partition_type(sunlabel->infos[i].id))
3235 ? type : _("Unknown"));
3241 sun_set_alt_cyl(void) {
3243 SUN_SSWAP16(read_int(0,SUN_SSWAP16(sunlabel->nacyl), 65535, 0,
3244 _("Number of alternate cylinders")));
3248 sun_set_ncyl(int cyl) {
3249 sunlabel->ncyl = SUN_SSWAP16(cyl);
3253 sun_set_xcyl(void) {
3254 sunlabel->sparecyl =
3255 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->sparecyl), sectors, 0,
3256 _("Extra sectors per cylinder")));
3260 sun_set_ilfact(void) {
3262 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->ilfact), 32, 0,
3263 _("Interleave factor")));
3267 sun_set_rspeed(void) {
3269 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->rspeed), 100000, 0,
3270 _("Rotation speed (rpm)")));
3274 sun_set_pcylcount(void) {
3275 sunlabel->pcylcount =
3276 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->pcylcount), 65535, 0,
3277 _("Number of physical cylinders")));
3281 sun_write_table(void) {
3282 unsigned short *ush = (unsigned short *)sunlabel;
3283 unsigned short csum = 0;
3285 while(ush < (unsigned short *)(&sunlabel->csum))
3287 sunlabel->csum = csum;
3288 if (lseek(fd, 0, SEEK_SET) < 0)
3289 fdisk_fatal(unable_to_seek);
3290 if (write(fd, sunlabel, SECTOR_SIZE) != SECTOR_SIZE)
3291 fdisk_fatal(unable_to_write);
3293 #endif /* SUN_LABEL */
3295 /* DOS partition types */
3297 static const struct systypes i386_sys_types[] = {
3300 {"\x02" "XENIX root"},
3301 {"\x03" "XENIX usr"},
3302 {"\x04" "FAT16 <32M"},
3303 {"\x05" "Extended"}, /* DOS 3.3+ extended partition */
3304 {"\x06" "FAT16"}, /* DOS 16-bit >=32M */
3305 {"\x07" "HPFS/NTFS"}, /* OS/2 IFS, eg, HPFS or NTFS or QNX */
3306 {"\x08" "AIX"}, /* AIX boot (AIX -- PS/2 port) or SplitDrive */
3307 {"\x09" "AIX bootable"}, /* AIX data or Coherent */
3308 {"\x0a" "OS/2 Boot Manager"},/* OS/2 Boot Manager */
3309 {"\x0b" "Win95 FAT32"},
3310 {"\x0c" "Win95 FAT32 (LBA)"},/* LBA really is `Extended Int 13h' */
3311 {"\x0e" "Win95 FAT16 (LBA)"},
3312 {"\x0f" "Win95 Ext'd (LBA)"},
3314 {"\x11" "Hidden FAT12"},
3315 {"\x12" "Compaq diagnostics"},
3316 {"\x14" "Hidden FAT16 <32M"},
3317 {"\x16" "Hidden FAT16"},
3318 {"\x17" "Hidden HPFS/NTFS"},
3319 {"\x18" "AST SmartSleep"},
3320 {"\x1b" "Hidden Win95 FAT32"},
3321 {"\x1c" "Hidden Win95 FAT32 (LBA)"},
3322 {"\x1e" "Hidden Win95 FAT16 (LBA)"},
3325 {"\x3c" "PartitionMagic recovery"},
3326 {"\x40" "Venix 80286"},
3327 {"\x41" "PPC PReP Boot"},
3330 {"\x4e" "QNX4.x 2nd part"},
3331 {"\x4f" "QNX4.x 3rd part"},
3332 {"\x50" "OnTrack DM"},
3333 {"\x51" "OnTrack DM6 Aux1"}, /* (or Novell) */
3334 {"\x52" "CP/M"}, /* CP/M or Microport SysV/AT */
3335 {"\x53" "OnTrack DM6 Aux3"},
3336 {"\x54" "OnTrackDM6"},
3337 {"\x55" "EZ-Drive"},
3338 {"\x56" "Golden Bow"},
3339 {"\x5c" "Priam Edisk"},
3340 {"\x61" "SpeedStor"},
3341 {"\x63" "GNU HURD or SysV"}, /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */
3342 {"\x64" "Novell Netware 286"},
3343 {"\x65" "Novell Netware 386"},
3344 {"\x70" "DiskSecure Multi-Boot"},
3346 {"\x80" "Old Minix"}, /* Minix 1.4a and earlier */
3347 {"\x81" "Minix / old Linux"},/* Minix 1.4b and later */
3348 {"\x82" "Linux swap"}, /* also Solaris */
3350 {"\x84" "OS/2 hidden C: drive"},
3351 {"\x85" "Linux extended"},
3352 {"\x86" "NTFS volume set"},
3353 {"\x87" "NTFS volume set"},
3354 {"\x8e" "Linux LVM"},
3356 {"\x94" "Amoeba BBT"}, /* (bad block table) */
3357 {"\x9f" "BSD/OS"}, /* BSDI */
3358 {"\xa0" "IBM Thinkpad hibernation"},
3359 {"\xa5" "FreeBSD"}, /* various BSD flavours */
3361 {"\xa7" "NeXTSTEP"},
3362 {"\xa8" "Darwin UFS"},
3364 {"\xab" "Darwin boot"},
3366 {"\xb8" "BSDI swap"},
3367 {"\xbb" "Boot Wizard hidden"},
3368 {"\xbe" "Solaris boot"},
3369 {"\xc1" "DRDOS/sec (FAT-12)"},
3370 {"\xc4" "DRDOS/sec (FAT-16 < 32M)"},
3371 {"\xc6" "DRDOS/sec (FAT-16)"},
3373 {"\xda" "Non-FS data"},
3374 {"\xdb" "CP/M / CTOS / ..."},/* CP/M or Concurrent CP/M or
3375 Concurrent DOS or CTOS */
3376 {"\xde" "Dell Utility"}, /* Dell PowerEdge Server utilities */
3377 {"\xdf" "BootIt"}, /* BootIt EMBRM */
3378 {"\xe1" "DOS access"}, /* DOS access or SpeedStor 12-bit FAT
3379 extended partition */
3380 {"\xe3" "DOS R/O"}, /* DOS R/O or SpeedStor */
3381 {"\xe4" "SpeedStor"}, /* SpeedStor 16-bit FAT extended
3382 partition < 1024 cyl. */
3384 {"\xee" "EFI GPT"}, /* Intel EFI GUID Partition Table */
3385 {"\xef" "EFI (FAT-12/16/32)"},/* Intel EFI System Partition */
3386 {"\xf0" "Linux/PA-RISC boot"},/* Linux/PA-RISC boot loader */
3387 {"\xf1" "SpeedStor"},
3388 {"\xf4" "SpeedStor"}, /* SpeedStor large partition */
3389 {"\xf2" "DOS secondary"}, /* DOS 3.3+ secondary */
3390 {"\xfd" "Linux raid autodetect"},/* New (2.2.x) raid partition with
3391 autodetect using persistent
3393 {"\xfe" "LANstep"}, /* SpeedStor >1024 cyl. or LANstep */
3394 {"\xff" "BBT"}, /* Xenix Bad Block Table */
3399 static void delete_partition(int i);
3401 /* A valid partition table sector ends in 0x55 0xaa */
3403 part_table_flag(const char *b) {
3404 return ((uint) b[510]) + (((uint) b[511]) << 8);
3408 valid_part_table_flag(const unsigned char *b) {
3409 return (b[510] == 0x55 && b[511] == 0xaa);
3413 write_part_table_flag(char *b) {
3418 /* start_sect and nr_sects are stored little endian on all machines */
3419 /* moreover, they are not aligned correctly */
3421 store4_little_endian(unsigned char *cp, unsigned int val) {
3422 cp[0] = (val & 0xff);
3423 cp[1] = ((val >> 8) & 0xff);
3424 cp[2] = ((val >> 16) & 0xff);
3425 cp[3] = ((val >> 24) & 0xff);
3429 read4_little_endian(const unsigned char *cp) {
3430 return (uint)(cp[0]) + ((uint)(cp[1]) << 8)
3431 + ((uint)(cp[2]) << 16) + ((uint)(cp[3]) << 24);
3435 set_start_sect(struct partition *p, unsigned int start_sect) {
3436 store4_little_endian(p->start4, start_sect);
3440 get_start_sect(const struct partition *p) {
3441 return read4_little_endian(p->start4);
3445 set_nr_sects(struct partition *p, unsigned int nr_sects) {
3446 store4_little_endian(p->size4, nr_sects);
3450 get_nr_sects(const struct partition *p) {
3451 return read4_little_endian(p->size4);
3454 /* normally O_RDWR, -l option gives O_RDONLY */
3455 static int type_open = O_RDWR;
3458 static int ext_index, /* the prime extended partition */
3459 listing, /* no aborts for fdisk -l */
3460 nowarn, /* no warnings for fdisk -l/-s */
3461 dos_compatible_flag = ~0,
3465 static uint user_cylinders, user_heads, user_sectors;
3466 static uint pt_heads, pt_sectors;
3467 static uint kern_heads, kern_sectors;
3469 static uint extended_offset; /* offset of link pointers */
3470 static uint sector_size = DEFAULT_SECTOR_SIZE,
3471 user_set_sector_size,
3474 static unsigned long total_number_of_sectors;
3477 static jmp_buf listingbuf;
3479 static void fdisk_fatal(enum failure why) {
3480 const char *message;
3484 longjmp(listingbuf, 1);
3488 case unable_to_open:
3489 message = "Unable to open %s\n";
3491 case unable_to_read:
3492 message = "Unable to read %s\n";
3494 case unable_to_seek:
3495 message = "Unable to seek on %s\n";
3497 case unable_to_write:
3498 message = "Unable to write %s\n";
3501 message = "BLKGETSIZE ioctl failed on %s\n";
3504 message = "Fatal error\n";
3507 fputc('\n', stderr);
3508 fprintf(stderr, message, disk_device);
3513 seek_sector(uint secno) {
3514 ext2_loff_t offset = (ext2_loff_t) secno * sector_size;
3515 if (ext2_llseek(fd, offset, SEEK_SET) == (ext2_loff_t) -1)
3516 fdisk_fatal(unable_to_seek);
3520 read_sector(uint secno, char *buf) {
3522 if (read(fd, buf, sector_size) != sector_size)
3523 fdisk_fatal(unable_to_read);
3527 write_sector(uint secno, char *buf) {
3529 if (write(fd, buf, sector_size) != sector_size)
3530 fdisk_fatal(unable_to_write);
3533 /* Allocate a buffer and read a partition table sector */
3535 read_pte(int pno, uint offset) {
3536 struct pte *pe = &ptes[pno];
3538 pe->offset = offset;
3539 pe->sectorbuffer = (char *) xmalloc(sector_size);
3540 read_sector(offset, pe->sectorbuffer);
3542 pe->part_table = pe->ext_pointer = NULL;
3546 get_partition_start(const struct pte *pe) {
3547 return pe->offset + get_start_sect(pe->part_table);
3551 * Avoid warning about DOS partitions when no DOS partition was changed.
3552 * Here a heuristic "is probably dos partition".
3553 * We might also do the opposite and warn in all cases except
3554 * for "is probably nondos partition".
3557 is_dos_partition(int t) {
3558 return (t == 1 || t == 4 || t == 6 ||
3559 t == 0x0b || t == 0x0c || t == 0x0e ||
3560 t == 0x11 || t == 0x12 || t == 0x14 || t == 0x16 ||
3561 t == 0x1b || t == 0x1c || t == 0x1e || t == 0x24 ||
3562 t == 0xc1 || t == 0xc4 || t == 0xc6);
3567 #ifdef CONFIG_FEATURE_SUN_LABEL
3569 puts(_("Command action"));
3570 puts(_("\ta\ttoggle a read only flag")); /* sun */
3571 puts(_("\tb\tedit bsd disklabel"));
3572 puts(_("\tc\ttoggle the mountable flag")); /* sun */
3573 puts(_("\td\tdelete a partition"));
3574 puts(_("\tl\tlist known partition types"));
3575 puts(_("\tm\tprint this menu"));
3576 puts(_("\tn\tadd a new partition"));
3577 puts(_("\to\tcreate a new empty DOS partition table"));
3578 puts(_("\tp\tprint the partition table"));
3579 puts(_("\tq\tquit without saving changes"));
3580 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3581 puts(_("\tt\tchange a partition's system id"));
3582 puts(_("\tu\tchange display/entry units"));
3583 puts(_("\tv\tverify the partition table"));
3584 puts(_("\tw\twrite table to disk and exit"));
3585 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3586 puts(_("\tx\textra functionality (experts only)"));
3590 #ifdef CONFIG_FEATURE_SGI_LABEL
3592 puts(_("Command action"));
3593 puts(_("\ta\tselect bootable partition")); /* sgi flavour */
3594 puts(_("\tb\tedit bootfile entry")); /* sgi */
3595 puts(_("\tc\tselect sgi swap partition")); /* sgi flavour */
3596 puts(_("\td\tdelete a partition"));
3597 puts(_("\tl\tlist known partition types"));
3598 puts(_("\tm\tprint this menu"));
3599 puts(_("\tn\tadd a new partition"));
3600 puts(_("\to\tcreate a new empty DOS partition table"));
3601 puts(_("\tp\tprint the partition table"));
3602 puts(_("\tq\tquit without saving changes"));
3603 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3604 puts(_("\tt\tchange a partition's system id"));
3605 puts(_("\tu\tchange display/entry units"));
3606 puts(_("\tv\tverify the partition table"));
3607 puts(_("\tw\twrite table to disk and exit"));
3610 #ifdef CONFIG_FEATURE_AIX_LABEL
3612 puts(_("Command action"));
3613 puts(_("\tm\tprint this menu"));
3614 puts(_("\to\tcreate a new empty DOS partition table"));
3615 puts(_("\tq\tquit without saving changes"));
3616 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3620 puts(_("Command action"));
3621 puts(_("\ta\ttoggle a bootable flag"));
3622 puts(_("\tb\tedit bsd disklabel"));
3623 puts(_("\tc\ttoggle the dos compatibility flag"));
3624 puts(_("\td\tdelete a partition"));
3625 puts(_("\tl\tlist known partition types"));
3626 puts(_("\tm\tprint this menu"));
3627 puts(_("\tn\tadd a new partition"));
3628 puts(_("\to\tcreate a new empty DOS partition table"));
3629 puts(_("\tp\tprint the partition table"));
3630 puts(_("\tq\tquit without saving changes"));
3631 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3632 puts(_("\tt\tchange a partition's system id"));
3633 puts(_("\tu\tchange display/entry units"));
3634 puts(_("\tv\tverify the partition table"));
3635 puts(_("\tw\twrite table to disk and exit"));
3636 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3637 puts(_("\tx\textra functionality (experts only)"));
3642 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3645 #ifdef CONFIG_FEATURE_SUN_LABEL
3647 puts(_("Command action"));
3648 puts(_("\ta\tchange number of alternate cylinders")); /*sun*/
3649 puts(_("\tc\tchange number of cylinders"));
3650 puts(_("\td\tprint the raw data in the partition table"));
3651 puts(_("\te\tchange number of extra sectors per cylinder"));/*sun*/
3652 puts(_("\th\tchange number of heads"));
3653 puts(_("\ti\tchange interleave factor")); /*sun*/
3654 puts(_("\to\tchange rotation speed (rpm)")); /*sun*/
3655 puts(_("\tm\tprint this menu"));
3656 puts(_("\tp\tprint the partition table"));
3657 puts(_("\tq\tquit without saving changes"));
3658 puts(_("\tr\treturn to main menu"));
3659 puts(_("\ts\tchange number of sectors/track"));
3660 puts(_("\tv\tverify the partition table"));
3661 puts(_("\tw\twrite table to disk and exit"));
3662 puts(_("\ty\tchange number of physical cylinders")); /*sun*/
3665 #ifdef CONFIG_FEATURE_SGI_LABEL
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(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3673 puts(_("\th\tchange number of heads"));
3674 puts(_("\tm\tprint this menu"));
3675 puts(_("\tp\tprint the partition table"));
3676 puts(_("\tq\tquit without saving changes"));
3677 puts(_("\tr\treturn to main menu"));
3678 puts(_("\ts\tchange number of sectors/track"));
3679 puts(_("\tv\tverify the partition table"));
3680 puts(_("\tw\twrite table to disk and exit"));
3683 #ifdef CONFIG_FEATURE_AIX_LABEL
3685 puts(_("Command action"));
3686 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3687 puts(_("\tc\tchange number of cylinders"));
3688 puts(_("\td\tprint the raw data in the partition table"));
3689 puts(_("\te\tlist extended partitions")); /* !sun */
3690 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3691 puts(_("\th\tchange number of heads"));
3692 puts(_("\tm\tprint this menu"));
3693 puts(_("\tp\tprint the partition table"));
3694 puts(_("\tq\tquit without saving changes"));
3695 puts(_("\tr\treturn to main menu"));
3696 puts(_("\ts\tchange number of sectors/track"));
3697 puts(_("\tv\tverify the partition table"));
3698 puts(_("\tw\twrite table to disk and exit"));
3702 puts(_("Command action"));
3703 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3704 puts(_("\tc\tchange number of cylinders"));
3705 puts(_("\td\tprint the raw data in the partition table"));
3706 puts(_("\te\tlist extended partitions")); /* !sun */
3707 puts(_("\tf\tfix partition order")); /* !sun, !aix, !sgi */
3708 #ifdef CONFIG_FEATURE_SGI_LABEL
3709 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3711 puts(_("\th\tchange number of heads"));
3712 puts(_("\tm\tprint this menu"));
3713 puts(_("\tp\tprint the partition table"));
3714 puts(_("\tq\tquit without saving changes"));
3715 puts(_("\tr\treturn to main menu"));
3716 puts(_("\ts\tchange number of sectors/track"));
3717 puts(_("\tv\tverify the partition table"));
3718 puts(_("\tw\twrite table to disk and exit"));
3721 #endif /* ADVANCED mode */
3727 #ifdef CONFIG_FEATURE_SUN_LABEL
3728 sun_label ? sunlabel->infos[i].id :
3730 #ifdef CONFIG_FEATURE_SGI_LABEL
3731 sgi_label ? sgi_get_sysid(i) :
3733 ptes[i].part_table->sys_ind);
3736 static const struct systypes *
3737 get_sys_types(void) {
3739 #ifdef CONFIG_FEATURE_SUN_LABEL
3740 sun_label ? sun_sys_types :
3742 #ifdef CONFIG_FEATURE_SGI_LABEL
3743 sgi_label ? sgi_sys_types :
3748 static const char *partition_type(unsigned char type)
3751 const struct systypes *types = get_sys_types();
3753 for (i=0; types[i].name; i++)
3754 if (types[i].name[0] == type)
3755 return types[i].name + 1;
3760 void list_types(const struct systypes *sys)
3762 uint last[4], done = 0, next = 0, size;
3765 for (i = 0; sys[i].name; i++);
3768 for (i = 3; i >= 0; i--)
3769 last[3 - i] = done += (size + i - done) / (i + 1);
3773 printf("%c%2x %-15.15s", i ? ' ' : '\n',
3774 sys[next].name[0], sys[next].name + 1);
3775 next = last[i++] + done;
3776 if (i > 3 || next >= last[i]) {
3780 } while (done < last[0]);
3785 is_cleared_partition(const struct partition *p) {
3786 return !(!p || p->boot_ind || p->head || p->sector || p->cyl ||
3787 p->sys_ind || p->end_head || p->end_sector || p->end_cyl ||
3788 get_start_sect(p) || get_nr_sects(p));
3792 clear_partition(struct partition *p) {
3803 set_start_sect(p,0);
3808 set_partition(int i, int doext, uint start, uint stop, int sysid) {
3809 struct partition *p;
3813 p = ptes[i].ext_pointer;
3814 offset = extended_offset;
3816 p = ptes[i].part_table;
3817 offset = ptes[i].offset;
3821 set_start_sect(p, start - offset);
3822 set_nr_sects(p, stop - start + 1);
3823 if (dos_compatible_flag && (start/(sectors*heads) > 1023))
3824 start = heads*sectors*1024 - 1;
3825 set_hsc(p->head, p->sector, p->cyl, start);
3826 if (dos_compatible_flag && (stop/(sectors*heads) > 1023))
3827 stop = heads*sectors*1024 - 1;
3828 set_hsc(p->end_head, p->end_sector, p->end_cyl, stop);
3829 ptes[i].changed = 1;
3833 test_c(const char **m, const char *mesg) {
3836 fprintf(stderr, _("You must set"));
3838 fprintf(stderr, " %s", *m);
3846 warn_geometry(void) {
3847 const char *m = NULL;
3851 prev = test_c(&m, _("heads"));
3853 prev = test_c(&m, _("sectors"));
3855 prev = test_c(&m, _("cylinders"));
3859 _("%s%s.\nYou can do this from the extra functions menu.\n"),
3860 prev ? _(" and ") : " ", m);
3864 static void update_units(void)
3866 int cyl_units = heads * sectors;
3868 if (display_in_cyl_units && cyl_units)
3869 units_per_sector = cyl_units;
3871 units_per_sector = 1; /* in sectors */
3875 warn_cylinders(void) {
3876 if (dos_label && cylinders > 1024 && !nowarn)
3877 fprintf(stderr, _("\n"
3878 "The number of cylinders for this disk is set to %d.\n"
3879 "There is nothing wrong with that, but this is larger than 1024,\n"
3880 "and could in certain setups cause problems with:\n"
3881 "1) software that runs at boot time (e.g., old versions of LILO)\n"
3882 "2) booting and partitioning software from other OSs\n"
3883 " (e.g., DOS FDISK, OS/2 FDISK)\n"),
3888 read_extended(int ext) {
3891 struct partition *p, *q;
3895 pex->ext_pointer = pex->part_table;
3897 p = pex->part_table;
3898 if (!get_start_sect(p)) {
3900 _("Bad offset in primary extended partition\n"));
3904 while (IS_EXTENDED (p->sys_ind)) {
3905 struct pte *pe = &ptes[partitions];
3907 if (partitions >= MAXIMUM_PARTS) {
3908 /* This is not a Linux restriction, but
3909 this program uses arrays of size MAXIMUM_PARTS.
3910 Do not try to `improve' this test. */
3911 struct pte *pre = &ptes[partitions-1];
3914 _("Warning: deleting partitions after %d\n"),
3916 clear_partition(pre->ext_pointer);
3921 read_pte(partitions, extended_offset + get_start_sect(p));
3923 if (!extended_offset)
3924 extended_offset = get_start_sect(p);
3926 q = p = pt_offset(pe->sectorbuffer, 0);
3927 for (i = 0; i < 4; i++, p++) if (get_nr_sects(p)) {
3928 if (IS_EXTENDED (p->sys_ind)) {
3929 if (pe->ext_pointer)
3931 _("Warning: extra link "
3932 "pointer in partition table"
3933 " %d\n"), partitions + 1);
3935 pe->ext_pointer = p;
3936 } else if (p->sys_ind) {
3939 _("Warning: ignoring extra "
3940 "data in partition table"
3941 " %d\n"), partitions + 1);
3947 /* very strange code here... */
3948 if (!pe->part_table) {
3949 if (q != pe->ext_pointer)
3952 pe->part_table = q + 1;
3954 if (!pe->ext_pointer) {
3955 if (q != pe->part_table)
3956 pe->ext_pointer = q;
3958 pe->ext_pointer = q + 1;
3961 p = pe->ext_pointer;
3965 /* remove empty links */
3967 for (i = 4; i < partitions; i++) {
3968 struct pte *pe = &ptes[i];
3970 if (!get_nr_sects(pe->part_table) &&
3971 (partitions > 5 || ptes[4].part_table->sys_ind)) {
3972 printf("omitting empty partition (%d)\n", i+1);
3973 delete_partition(i);
3974 goto remove; /* numbering changed */
3980 create_doslabel(void) {
3984 _("Building a new DOS disklabel. Changes will remain in memory only,\n"
3985 "until you decide to write them. After that, of course, the previous\n"
3986 "content won't be recoverable.\n\n"));
3987 #ifdef CONFIG_FEATURE_SUN_LABEL
3988 sun_nolabel(); /* otherwise always recognised as sun */
3990 #ifdef CONFIG_FEATURE_SGI_LABEL
3991 sgi_nolabel(); /* otherwise always recognised as sgi */
3993 #ifdef CONFIG_FEATURE_AIX_LABEL
3996 #ifdef CONFIG_FEATURE_OSF_LABEL
3998 possibly_osf_label = 0;
4002 for (i = 510-64; i < 510; i++)
4004 write_part_table_flag(MBRbuffer);
4005 extended_offset = 0;
4006 set_all_unchanged();
4008 get_boot(create_empty_dos);
4013 get_sectorsize(void) {
4014 if (!user_set_sector_size &&
4015 get_kernel_revision() >= MAKE_VERSION(2,3,3)) {
4017 if (ioctl(fd, BLKSSZGET, &arg) == 0)
4019 if (sector_size != DEFAULT_SECTOR_SIZE)
4020 printf(_("Note: sector size is %d (not %d)\n"),
4021 sector_size, DEFAULT_SECTOR_SIZE);
4026 get_kernel_geometry(void) {
4027 struct hd_geometry geometry;
4029 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
4030 kern_heads = geometry.heads;
4031 kern_sectors = geometry.sectors;
4032 /* never use geometry.cylinders - it is truncated */
4037 get_partition_table_geometry(void) {
4038 unsigned char *bufp = MBRbuffer;
4039 struct partition *p;
4040 int i, h, s, hh, ss;
4044 if (!(valid_part_table_flag(bufp)))
4048 for (i=0; i<4; i++) {
4049 p = pt_offset(bufp, i);
4050 if (p->sys_ind != 0) {
4051 h = p->end_head + 1;
4052 s = (p->end_sector & 077);
4057 } else if (hh != h || ss != s)
4062 if (!first && !bad) {
4069 get_geometry(struct geom *g) {
4071 unsigned long longsectors;
4074 sec_fac = sector_size / 512;
4075 #ifdef CONFIG_FEATURE_SUN_LABEL
4076 guess_device_type();
4078 heads = cylinders = sectors = 0;
4079 kern_heads = kern_sectors = 0;
4080 pt_heads = pt_sectors = 0;
4082 get_kernel_geometry();
4083 get_partition_table_geometry();
4085 heads = user_heads ? user_heads :
4086 pt_heads ? pt_heads :
4087 kern_heads ? kern_heads : 255;
4088 sectors = user_sectors ? user_sectors :
4089 pt_sectors ? pt_sectors :
4090 kern_sectors ? kern_sectors : 63;
4092 if (ioctl(fd, BLKGETSIZE, &longsectors))
4096 if (dos_compatible_flag)
4097 sector_offset = sectors;
4099 cylinders = longsectors / (heads * sectors);
4100 cylinders /= sec_fac;
4102 cylinders = user_cylinders;
4106 g->sectors = sectors;
4107 g->cylinders = cylinders;
4110 total_number_of_sectors = longsectors;
4114 * Read MBR. Returns:
4115 * -1: no 0xaa55 flag present (possibly entire disk BSD)
4116 * 0: found or created label
4120 get_boot(enum action what) {
4125 for (i = 0; i < 4; i++) {
4126 struct pte *pe = &ptes[i];
4128 pe->part_table = pt_offset(MBRbuffer, i);
4129 pe->ext_pointer = NULL;
4131 pe->sectorbuffer = MBRbuffer;
4132 pe->changed = (what == create_empty_dos);
4135 if (what == create_empty_sun && check_sun_label())
4138 memset(MBRbuffer, 0, 512);
4140 if (what == create_empty_dos)
4141 goto got_dos_table; /* skip reading disk */
4143 if ((fd = open(disk_device, type_open)) < 0) {
4144 if ((fd = open(disk_device, O_RDONLY)) < 0) {
4145 if (what == try_only)
4147 fdisk_fatal(unable_to_open);
4149 printf(_("You will not be able to write "
4150 "the partition table.\n"));
4153 if (512 != read(fd, MBRbuffer, 512)) {
4154 if (what == try_only)
4156 fdisk_fatal(unable_to_read);
4163 if (check_sun_label())
4166 #ifdef CONFIG_FEATURE_SGI_LABEL
4167 if (check_sgi_label())
4171 #ifdef CONFIG_FEATURE_AIX_LABEL
4172 if (check_aix_label())
4176 #ifdef CONFIG_FEATURE_OSF_LABEL
4177 if (check_osf_label()) {
4178 possibly_osf_label = 1;
4179 if (!valid_part_table_flag(MBRbuffer)) {
4183 printf(_("This disk has both DOS and BSD magic.\n"
4184 "Give the 'b' command to go to BSD mode.\n"));
4190 if (!valid_part_table_flag(MBRbuffer)) {
4194 _("Device contains neither a valid DOS "
4195 "partition table, nor Sun, SGI or OSF "
4198 #ifdef CONFIG_FEATURE_SUN_LABEL
4209 case create_empty_dos:
4210 case create_empty_sun:
4213 fprintf(stderr, _("Internal error\n"));
4221 for (i = 0; i < 4; i++) {
4222 struct pte *pe = &ptes[i];
4224 if (IS_EXTENDED (pe->part_table->sys_ind)) {
4225 if (partitions != 4)
4226 fprintf(stderr, _("Ignoring extra extended "
4227 "partition %d\n"), i + 1);
4233 for (i = 3; i < partitions; i++) {
4234 struct pte *pe = &ptes[i];
4236 if (!valid_part_table_flag(pe->sectorbuffer)) {
4238 _("Warning: invalid flag 0x%04x of partition "
4239 "table %d will be corrected by w(rite)\n"),
4240 part_table_flag(pe->sectorbuffer), i + 1);
4249 * Print the message MESG, then read an integer between LOW and HIGH (inclusive).
4250 * If the user hits Enter, DFLT is returned.
4251 * Answers like +10 are interpreted as offsets from BASE.
4253 * There is no default if DFLT is not between LOW and HIGH.
4256 read_int(uint low, uint dflt, uint high, uint base, char *mesg)
4260 static char *ms = NULL;
4261 static int mslen = 0;
4263 if (!ms || strlen(mesg)+100 > mslen) {
4264 mslen = strlen(mesg)+200;
4265 ms = xrealloc(ms,mslen);
4268 if (dflt < low || dflt > high)
4272 snprintf(ms, mslen, _("%s (%d-%d, default %d): "),
4273 mesg, low, high, dflt);
4275 snprintf(ms, mslen, "%s (%d-%d): ",
4279 int use_default = default_ok;
4281 /* ask question and read answer */
4282 while (read_chars(ms) != '\n' && !isdigit(*line_ptr)
4283 && *line_ptr != '-' && *line_ptr != '+')
4286 if (*line_ptr == '+' || *line_ptr == '-') {
4287 i = atoi(line_ptr+1);
4288 if (*line_ptr == '-')
4290 while (isdigit(*++line_ptr))
4292 switch (*line_ptr) {
4295 if (!display_in_cyl_units)
4296 i *= heads * sectors;
4301 i /= (sector_size / 512);
4302 i /= units_per_sector;
4307 i /= (sector_size / 512);
4308 i /= units_per_sector;
4313 i /= (sector_size / 512);
4314 i /= units_per_sector;
4322 while (isdigit(*line_ptr)) {
4328 printf(_("Using default value %d\n"), i = dflt);
4329 if (i >= low && i <= high)
4332 printf(_("Value out of range.\n"));
4338 get_partition(int warn, int max) {
4342 i = read_int(1, 0, max, 0, _("Partition number")) - 1;
4346 if ((!sun_label && !sgi_label && !pe->part_table->sys_ind)
4347 #ifdef CONFIG_FEATURE_SUN_LABEL
4349 (!sunlabel->partitions[i].num_sectors ||
4350 !sunlabel->infos[i].id))
4352 #ifdef CONFIG_FEATURE_SGI_LABEL
4353 || (sgi_label && (!sgi_get_num_sectors(i)))
4357 _("Warning: partition %d has empty type\n"),
4364 get_existing_partition(int warn, int max) {
4368 for (i = 0; i < max; i++) {
4369 struct pte *pe = &ptes[i];
4370 struct partition *p = pe->part_table;
4372 if (p && !is_cleared_partition(p)) {
4379 printf(_("Selected partition %d\n"), pno+1);
4382 printf(_("No partition is defined yet!\n"));
4386 return get_partition(warn, max);
4390 get_nonexisting_partition(int warn, int max) {
4394 for (i = 0; i < max; i++) {
4395 struct pte *pe = &ptes[i];
4396 struct partition *p = pe->part_table;
4398 if (p && is_cleared_partition(p)) {
4405 printf(_("Selected partition %d\n"), pno+1);
4408 printf(_("All primary partitions have been defined already!\n"));
4412 return get_partition(warn, max);
4416 void change_units(void)
4418 display_in_cyl_units = !display_in_cyl_units;
4420 printf(_("Changing display/entry units to %s\n"),
4425 toggle_active(int i) {
4426 struct pte *pe = &ptes[i];
4427 struct partition *p = pe->part_table;
4429 if (IS_EXTENDED (p->sys_ind) && !p->boot_ind)
4431 _("WARNING: Partition %d is an extended partition\n"),
4433 p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG);
4438 toggle_dos_compatibility_flag(void) {
4439 dos_compatible_flag = ~dos_compatible_flag;
4440 if (dos_compatible_flag) {
4441 sector_offset = sectors;
4442 printf(_("DOS Compatibility flag is set\n"));
4446 printf(_("DOS Compatibility flag is not set\n"));
4451 delete_partition(int i) {
4452 struct pte *pe = &ptes[i];
4453 struct partition *p = pe->part_table;
4454 struct partition *q = pe->ext_pointer;
4456 /* Note that for the fifth partition (i == 4) we don't actually
4457 * decrement partitions.
4460 if (warn_geometry())
4461 return; /* C/H/S not set */
4464 #ifdef CONFIG_FEATURE_SUN_LABEL
4466 sun_delete_partition(i);
4470 #ifdef CONFIG_FEATURE_SGI_LABEL
4472 sgi_delete_partition(i);
4478 if (IS_EXTENDED (p->sys_ind) && i == ext_index) {
4480 ptes[ext_index].ext_pointer = NULL;
4481 extended_offset = 0;
4487 if (!q->sys_ind && i > 4) {
4488 /* the last one in the chain - just delete */
4491 clear_partition(ptes[i].ext_pointer);
4492 ptes[i].changed = 1;
4494 /* not the last one - further ones will be moved down */
4496 /* delete this link in the chain */
4497 p = ptes[i-1].ext_pointer;
4499 set_start_sect(p, get_start_sect(q));
4500 set_nr_sects(p, get_nr_sects(q));
4501 ptes[i-1].changed = 1;
4502 } else if (partitions > 5) { /* 5 will be moved to 4 */
4503 /* the first logical in a longer chain */
4506 if (pe->part_table) /* prevent SEGFAULT */
4507 set_start_sect(pe->part_table,
4508 get_partition_start(pe) -
4510 pe->offset = extended_offset;
4514 if (partitions > 5) {
4516 while (i < partitions) {
4517 ptes[i] = ptes[i+1];
4521 /* the only logical: clear only */
4522 clear_partition(ptes[i].part_table);
4527 change_sysid(void) {
4529 int i, sys, origsys;
4530 struct partition *p;
4532 i = get_existing_partition(0, partitions);
4535 p = ptes[i].part_table;
4536 origsys = sys = get_sysid(i);
4538 /* if changing types T to 0 is allowed, then
4539 the reverse change must be allowed, too */
4540 if (!sys && !sgi_label && !sun_label && !get_nr_sects(p))
4541 printf(_("Partition %d does not exist yet!\n"), i + 1);
4543 sys = read_hex (get_sys_types());
4545 if (!sys && !sgi_label && !sun_label) {
4546 printf(_("Type 0 means free space to many systems\n"
4547 "(but not to Linux). Having partitions of\n"
4548 "type 0 is probably unwise. You can delete\n"
4549 "a partition using the `d' command.\n"));
4553 if (!sun_label && !sgi_label) {
4554 if (IS_EXTENDED (sys) != IS_EXTENDED (p->sys_ind)) {
4555 printf(_("You cannot change a partition into"
4556 " an extended one or vice versa\n"
4557 "Delete it first.\n"));
4563 #ifdef CONFIG_FEATURE_SUN_LABEL
4564 if (sun_label && i == 2 && sys != WHOLE_DISK)
4565 printf(_("Consider leaving partition 3 "
4566 "as Whole disk (5),\n"
4567 "as SunOS/Solaris expects it and "
4568 "even Linux likes it.\n\n"));
4570 #ifdef CONFIG_FEATURE_SGI_LABEL
4571 if (sgi_label && ((i == 10 && sys != ENTIRE_DISK)
4572 || (i == 8 && sys != 0)))
4573 printf(_("Consider leaving partition 9 "
4574 "as volume header (0),\nand "
4575 "partition 11 as entire volume (6)"
4576 "as IRIX expects it.\n\n"));
4580 #ifdef CONFIG_FEATURE_SUN_LABEL
4582 sun_change_sysid(i, sys);
4585 #ifdef CONFIG_FEATURE_SGI_LABEL
4587 sgi_change_sysid(i, sys);
4591 printf (_("Changed system type of partition %d "
4592 "to %x (%s)\n"), i + 1, sys,
4593 (temp = partition_type(sys)) ? temp :
4595 ptes[i].changed = 1;
4596 if (is_dos_partition(origsys) ||
4597 is_dos_partition(sys))
4604 /* check_consistency() and long2chs() added Sat Mar 6 12:28:16 1993,
4605 * faith@cs.unc.edu, based on code fragments from pfdisk by Gordon W. Ross,
4606 * Jan. 1990 (version 1.2.1 by Gordon W. Ross Aug. 1990; Modified by S.
4607 * Lubkin Oct. 1991). */
4609 static void long2chs(ulong ls, uint *c, uint *h, uint *s) {
4610 int spc = heads * sectors;
4615 *s = ls % sectors + 1; /* sectors count from 1 */
4618 static void check_consistency(const struct partition *p, int partition) {
4619 uint pbc, pbh, pbs; /* physical beginning c, h, s */
4620 uint pec, peh, pes; /* physical ending c, h, s */
4621 uint lbc, lbh, lbs; /* logical beginning c, h, s */
4622 uint lec, leh, les; /* logical ending c, h, s */
4624 if (!heads || !sectors || (partition >= 4))
4625 return; /* do not check extended partitions */
4627 /* physical beginning c, h, s */
4628 pbc = (p->cyl & 0xff) | ((p->sector << 2) & 0x300);
4630 pbs = p->sector & 0x3f;
4632 /* physical ending c, h, s */
4633 pec = (p->end_cyl & 0xff) | ((p->end_sector << 2) & 0x300);
4635 pes = p->end_sector & 0x3f;
4637 /* compute logical beginning (c, h, s) */
4638 long2chs(get_start_sect(p), &lbc, &lbh, &lbs);
4640 /* compute logical ending (c, h, s) */
4641 long2chs(get_start_sect(p) + get_nr_sects(p) - 1, &lec, &leh, &les);
4643 /* Same physical / logical beginning? */
4644 if (cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) {
4645 printf(_("Partition %d has different physical/logical "
4646 "beginnings (non-Linux?):\n"), partition + 1);
4647 printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs);
4648 printf(_("logical=(%d, %d, %d)\n"),lbc, lbh, lbs);
4651 /* Same physical / logical ending? */
4652 if (cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) {
4653 printf(_("Partition %d has different physical/logical "
4654 "endings:\n"), partition + 1);
4655 printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
4656 printf(_("logical=(%d, %d, %d)\n"),lec, leh, les);
4660 /* Beginning on cylinder boundary? */
4661 if (pbh != !pbc || pbs != 1) {
4662 printf(_("Partition %i does not start on cylinder "
4663 "boundary:\n"), partition + 1);
4664 printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs);
4665 printf(_("should be (%d, %d, 1)\n"), pbc, !pbc);
4669 /* Ending on cylinder boundary? */
4670 if (peh != (heads - 1) || pes != sectors) {
4671 printf(_("Partition %i does not end on cylinder boundary:\n"),
4674 printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
4675 printf(_("should be (%d, %d, %d)\n"),
4676 pec, heads - 1, sectors);
4682 list_disk_geometry(void) {
4683 long long bytes = (long long) total_number_of_sectors * 512;
4684 long megabytes = bytes/1000000;
4686 if (megabytes < 10000)
4687 printf(_("\nDisk %s: %ld MB, %lld bytes\n"),
4688 disk_device, megabytes, bytes);
4690 printf(_("\nDisk %s: %ld.%ld GB, %lld bytes\n"),
4691 disk_device, megabytes/1000, (megabytes/100)%10, bytes);
4692 printf(_("%d heads, %d sectors/track, %d cylinders"),
4693 heads, sectors, cylinders);
4694 if (units_per_sector == 1)
4695 printf(_(", total %lu sectors"),
4696 total_number_of_sectors / (sector_size/512));
4698 printf(_("Units = %s of %d * %d = %d bytes\n\n"),
4700 units_per_sector, sector_size, units_per_sector * sector_size);
4704 * Check whether partition entries are ordered by their starting positions.
4705 * Return 0 if OK. Return i if partition i should have been earlier.
4706 * Two separate checks: primary and logical partitions.
4709 wrong_p_order(int *prev) {
4710 const struct pte *pe;
4711 const struct partition *p;
4712 uint last_p_start_pos = 0, p_start_pos;
4715 for (i = 0 ; i < partitions; i++) {
4718 last_p_start_pos = 0;
4721 if ((p = pe->part_table)->sys_ind) {
4722 p_start_pos = get_partition_start(pe);
4724 if (last_p_start_pos > p_start_pos) {
4730 last_p_start_pos = p_start_pos;
4737 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
4739 * Fix the chain of logicals.
4740 * extended_offset is unchanged, the set of sectors used is unchanged
4741 * The chain is sorted so that sectors increase, and so that
4742 * starting sectors increase.
4744 * After this it may still be that cfdisk doesnt like the table.
4745 * (This is because cfdisk considers expanded parts, from link to
4746 * end of partition, and these may still overlap.)
4748 * sfdisk /dev/hda > ohda; sfdisk /dev/hda < ohda
4752 fix_chain_of_logicals(void) {
4753 int j, oj, ojj, sj, sjj;
4754 struct partition *pj,*pjj,tmp;
4756 /* Stage 1: sort sectors but leave sector of part 4 */
4757 /* (Its sector is the global extended_offset.) */
4759 for (j = 5; j < partitions-1; j++) {
4760 oj = ptes[j].offset;
4761 ojj = ptes[j+1].offset;
4763 ptes[j].offset = ojj;
4764 ptes[j+1].offset = oj;
4765 pj = ptes[j].part_table;
4766 set_start_sect(pj, get_start_sect(pj)+oj-ojj);
4767 pjj = ptes[j+1].part_table;
4768 set_start_sect(pjj, get_start_sect(pjj)+ojj-oj);
4769 set_start_sect(ptes[j-1].ext_pointer,
4770 ojj-extended_offset);
4771 set_start_sect(ptes[j].ext_pointer,
4772 oj-extended_offset);
4777 /* Stage 2: sort starting sectors */
4779 for (j = 4; j < partitions-1; j++) {
4780 pj = ptes[j].part_table;
4781 pjj = ptes[j+1].part_table;
4782 sj = get_start_sect(pj);
4783 sjj = get_start_sect(pjj);
4784 oj = ptes[j].offset;
4785 ojj = ptes[j+1].offset;
4786 if (oj+sj > ojj+sjj) {
4790 set_start_sect(pj, ojj+sjj-oj);
4791 set_start_sect(pjj, oj+sj-ojj);
4796 /* Probably something was changed */
4797 for (j = 4; j < partitions; j++)
4798 ptes[j].changed = 1;
4804 fix_partition_table_order(void) {
4805 struct pte *pei, *pek;
4808 if (!wrong_p_order(NULL)) {
4809 printf(_("Nothing to do. Ordering is correct already.\n\n"));
4813 while ((i = wrong_p_order(&k)) != 0 && i < 4) {
4814 /* partition i should have come earlier, move it */
4815 /* We have to move data in the MBR */
4816 struct partition *pi, *pk, *pe, pbuf;
4820 pe = pei->ext_pointer;
4821 pei->ext_pointer = pek->ext_pointer;
4822 pek->ext_pointer = pe;
4824 pi = pei->part_table;
4825 pk = pek->part_table;
4827 memmove(&pbuf, pi, sizeof(struct partition));
4828 memmove(pi, pk, sizeof(struct partition));
4829 memmove(pk, &pbuf, sizeof(struct partition));
4831 pei->changed = pek->changed = 1;
4835 fix_chain_of_logicals();
4843 list_table(int xtra) {
4844 const struct partition *p;
4848 #ifdef CONFIG_FEATURE_SUN_LABEL
4850 sun_list_table(xtra);
4855 #ifdef CONFIG_FEATURE_SGI_LABEL
4857 sgi_list_table(xtra);
4862 list_disk_geometry();
4864 #ifdef CONFIG_FEATURE_OSF_LABEL
4866 xbsd_print_disklabel(xtra);
4871 /* Heuristic: we list partition 3 of /dev/foo as /dev/foo3,
4872 but if the device name ends in a digit, say /dev/foo1,
4873 then the partition is called /dev/foo1p3. */
4874 w = strlen(disk_device);
4875 if (w && isdigit(disk_device[w-1]))
4880 printf(_("%*s Boot Start End Blocks Id System\n"),
4883 for (i = 0; i < partitions; i++) {
4884 const struct pte *pe = &ptes[i];
4887 if (p && !is_cleared_partition(p)) {
4888 unsigned int psects = get_nr_sects(p);
4889 unsigned int pblocks = psects;
4890 unsigned int podd = 0;
4892 if (sector_size < 1024) {
4893 pblocks /= (1024 / sector_size);
4894 podd = psects % (1024 / sector_size);
4896 if (sector_size > 1024)
4897 pblocks *= (sector_size / 1024);
4899 "%s %c %9ld %9ld %9ld%c %2x %s\n",
4900 partname(disk_device, i+1, w+2),
4901 /* boot flag */ !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG
4903 /* start */ (long) cround(get_partition_start(pe)),
4904 /* end */ (long) cround(get_partition_start(pe) + psects
4905 - (psects ? 1 : 0)),
4906 /* odd flag on end */ (long) pblocks, podd ? '+' : ' ',
4907 /* type id */ p->sys_ind,
4908 /* type name */ (type = partition_type(p->sys_ind)) ?
4909 type : _("Unknown"));
4910 check_consistency(p, i);
4914 /* Is partition table in disk order? It need not be, but... */
4915 /* partition table entries are not checked for correct order if this
4916 is a sgi, sun or aix labeled disk... */
4917 if (dos_label && wrong_p_order(NULL)) {
4918 printf(_("\nPartition table entries are not in disk order\n"));
4922 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
4924 x_list_table(int extend) {
4925 const struct pte *pe;
4926 const struct partition *p;
4929 printf(_("\nDisk %s: %d heads, %d sectors, %d cylinders\n\n"),
4930 disk_device, heads, sectors, cylinders);
4931 printf(_("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n"));
4932 for (i = 0 ; i < partitions; i++) {
4934 p = (extend ? pe->ext_pointer : pe->part_table);
4936 printf("%2d %02x%4d%4d%5d%4d%4d%5d%9d%9d %02x\n",
4937 i + 1, p->boot_ind, p->head,
4939 cylinder(p->sector, p->cyl), p->end_head,
4940 sector(p->end_sector),
4941 cylinder(p->end_sector, p->end_cyl),
4942 get_start_sect(p), get_nr_sects(p), p->sys_ind);
4944 check_consistency(p, i);
4951 fill_bounds(uint *first, uint *last) {
4953 const struct pte *pe = &ptes[0];
4954 const struct partition *p;
4956 for (i = 0; i < partitions; pe++,i++) {
4958 if (!p->sys_ind || IS_EXTENDED (p->sys_ind)) {
4959 first[i] = 0xffffffff;
4962 first[i] = get_partition_start(pe);
4963 last[i] = first[i] + get_nr_sects(p) - 1;
4969 check(int n, uint h, uint s, uint c, uint start) {
4970 uint total, real_s, real_c;
4972 real_s = sector(s) - 1;
4973 real_c = cylinder(s, c);
4974 total = (real_c * sectors + real_s) * heads + h;
4976 fprintf(stderr, _("Warning: partition %d contains sector 0\n"), n);
4979 _("Partition %d: head %d greater than maximum %d\n"),
4981 if (real_s >= sectors)
4982 fprintf(stderr, _("Partition %d: sector %d greater than "
4983 "maximum %d\n"), n, s, sectors);
4984 if (real_c >= cylinders)
4985 fprintf(stderr, _("Partitions %d: cylinder %d greater than "
4986 "maximum %d\n"), n, real_c + 1, cylinders);
4987 if (cylinders <= 1024 && start != total)
4989 _("Partition %d: previous sectors %d disagrees with "
4990 "total %d\n"), n, start, total);
4997 uint first[partitions], last[partitions];
4998 struct partition *p;
5000 if (warn_geometry())
5003 #ifdef CONFIG_FEATURE_SUN_LABEL
5009 #ifdef CONFIG_FEATURE_SGI_LABEL
5016 fill_bounds(first, last);
5017 for (i = 0; i < partitions; i++) {
5018 struct pte *pe = &ptes[i];
5021 if (p->sys_ind && !IS_EXTENDED (p->sys_ind)) {
5022 check_consistency(p, i);
5023 if (get_partition_start(pe) < first[i])
5024 printf(_("Warning: bad start-of-data in "
5025 "partition %d\n"), i + 1);
5026 check(i + 1, p->end_head, p->end_sector, p->end_cyl,
5028 total += last[i] + 1 - first[i];
5029 for (j = 0; j < i; j++)
5030 if ((first[i] >= first[j] && first[i] <= last[j])
5031 || ((last[i] <= last[j] && last[i] >= first[j]))) {
5032 printf(_("Warning: partition %d overlaps "
5033 "partition %d.\n"), j + 1, i + 1);
5034 total += first[i] >= first[j] ?
5035 first[i] : first[j];
5036 total -= last[i] <= last[j] ?
5042 if (extended_offset) {
5043 struct pte *pex = &ptes[ext_index];
5044 uint e_last = get_start_sect(pex->part_table) +
5045 get_nr_sects(pex->part_table) - 1;
5047 for (i = 4; i < partitions; i++) {
5049 p = ptes[i].part_table;
5051 if (i != 4 || i + 1 < partitions)
5052 printf(_("Warning: partition %d "
5053 "is empty\n"), i + 1);
5055 else if (first[i] < extended_offset ||
5057 printf(_("Logical partition %d not entirely in "
5058 "partition %d\n"), i + 1, ext_index + 1);
5062 if (total > heads * sectors * cylinders)
5063 printf(_("Total allocated sectors %d greater than the maximum "
5064 "%d\n"), total, heads * sectors * cylinders);
5065 else if ((total = heads * sectors * cylinders - total) != 0)
5066 printf(_("%d unallocated sectors\n"), total);
5070 add_partition(int n, int sys) {
5071 char mesg[256]; /* 48 does not suffice in Japanese */
5073 struct partition *p = ptes[n].part_table;
5074 struct partition *q = ptes[ext_index].part_table;
5075 uint start, stop = 0, limit, temp,
5076 first[partitions], last[partitions];
5078 if (p && p->sys_ind) {
5079 printf(_("Partition %d is already defined. Delete "
5080 "it before re-adding it.\n"), n + 1);
5083 fill_bounds(first, last);
5085 start = sector_offset;
5086 if (display_in_cyl_units)
5087 limit = heads * sectors * cylinders - 1;
5089 limit = total_number_of_sectors - 1;
5090 if (extended_offset) {
5091 first[ext_index] = extended_offset;
5092 last[ext_index] = get_start_sect(q) +
5093 get_nr_sects(q) - 1;
5096 start = extended_offset + sector_offset;
5097 limit = get_start_sect(q) + get_nr_sects(q) - 1;
5099 if (display_in_cyl_units)
5100 for (i = 0; i < partitions; i++)
5101 first[i] = (cround(first[i]) - 1) * units_per_sector;
5103 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
5106 for (i = 0; i < partitions; i++) {
5109 if (start == ptes[i].offset)
5110 start += sector_offset;
5111 lastplusoff = last[i] + ((n<4) ? 0 : sector_offset);
5112 if (start >= first[i] && start <= lastplusoff)
5113 start = lastplusoff + 1;
5117 if (start >= temp+units_per_sector && readed) {
5118 printf(_("Sector %d is already allocated\n"), temp);
5122 if (!readed && start == temp) {
5125 saved_start = start;
5126 start = read_int(cround(saved_start), cround(saved_start), cround(limit),
5128 if (display_in_cyl_units) {
5129 start = (start - 1) * units_per_sector;
5130 if (start < saved_start) start = saved_start;
5134 } while (start != temp || !readed);
5135 if (n > 4) { /* NOT for fifth partition */
5136 struct pte *pe = &ptes[n];
5138 pe->offset = start - sector_offset;
5139 if (pe->offset == extended_offset) { /* must be corrected */
5141 if (sector_offset == 1)
5146 for (i = 0; i < partitions; i++) {
5147 struct pte *pe = &ptes[i];
5149 if (start < pe->offset && limit >= pe->offset)
5150 limit = pe->offset - 1;
5151 if (start < first[i] && limit >= first[i])
5152 limit = first[i] - 1;
5154 if (start > limit) {
5155 printf(_("No free sectors available\n"));
5160 if (cround(start) == cround(limit)) {
5163 snprintf(mesg, sizeof(mesg),
5164 _("Last %s or +size or +sizeM or +sizeK"),
5165 str_units(SINGULAR));
5166 stop = read_int(cround(start), cround(limit), cround(limit),
5167 cround(start), mesg);
5168 if (display_in_cyl_units) {
5169 stop = stop * units_per_sector - 1;
5175 set_partition(n, 0, start, stop, sys);
5177 set_partition(n - 1, 1, ptes[n].offset, stop, EXTENDED);
5179 if (IS_EXTENDED (sys)) {
5180 struct pte *pe4 = &ptes[4];
5181 struct pte *pen = &ptes[n];
5184 pen->ext_pointer = p;
5185 pe4->offset = extended_offset = start;
5186 pe4->sectorbuffer = xcalloc(1, sector_size);
5187 pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
5188 pe4->ext_pointer = pe4->part_table + 1;
5196 if (partitions > 5 || ptes[4].part_table->sys_ind) {
5197 struct pte *pe = &ptes[partitions];
5199 pe->sectorbuffer = xcalloc(1, sector_size);
5200 pe->part_table = pt_offset(pe->sectorbuffer, 0);
5201 pe->ext_pointer = pe->part_table + 1;
5206 add_partition(partitions - 1, LINUX_NATIVE);
5210 new_partition(void) {
5211 int i, free_primary = 0;
5213 if (warn_geometry())
5216 #ifdef CONFIG_FEATURE_SUN_LABEL
5218 add_sun_partition(get_partition(0, partitions), LINUX_NATIVE);
5222 #ifdef CONFIG_FEATURE_SGI_LABEL
5224 sgi_add_partition(get_partition(0, partitions), LINUX_NATIVE);
5228 #ifdef CONFIG_FEATURE_AIX_LABEL
5230 printf(_("\tSorry - this fdisk cannot handle AIX disk labels."
5231 "\n\tIf you want to add DOS-type partitions, create"
5232 "\n\ta new empty DOS partition table first. (Use o.)"
5234 "This will destroy the present disk contents.\n"));
5239 if (partitions >= MAXIMUM_PARTS) {
5240 printf(_("The maximum number of partitions has been created\n"));
5244 for (i = 0; i < 4; i++)
5245 free_primary += !ptes[i].part_table->sys_ind;
5246 if (!free_primary) {
5247 if (extended_offset)
5250 printf(_("You must delete some partition and add "
5251 "an extended partition first\n"));
5253 char c, line[LINE_LENGTH];
5254 snprintf(line, sizeof(line), "%s\n %s\n p primary "
5255 "partition (1-4)\n",
5256 "Command action", (extended_offset ?
5257 "l logical (5 or over)" : "e extended"));
5259 if ((c = read_char(line)) == 'p' || c == 'P') {
5260 i = get_nonexisting_partition(0, 4);
5262 add_partition(i, LINUX_NATIVE);
5265 else if (c == 'l' && extended_offset) {
5269 else if (c == 'e' && !extended_offset) {
5270 i = get_nonexisting_partition(0, 4);
5272 add_partition(i, EXTENDED);
5276 printf(_("Invalid partition number "
5277 "for type `%c'\n"), c);
5288 if (ptes[i].changed)
5289 ptes[3].changed = 1;
5290 for (i = 3; i < partitions; i++) {
5291 struct pte *pe = &ptes[i];
5294 write_part_table_flag(pe->sectorbuffer);
5295 write_sector(pe->offset, pe->sectorbuffer);
5299 #ifdef CONFIG_FEATURE_SGI_LABEL
5300 else if (sgi_label) {
5301 /* no test on change? the printf below might be mistaken */
5305 #ifdef CONFIG_FEATURE_SUN_LABEL
5306 else if (sun_label) {
5310 if (ptes[i].changed)
5317 printf(_("The partition table has been altered!\n\n"));
5318 reread_partition_table(1);
5322 reread_partition_table(int leave) {
5326 printf(_("Calling ioctl() to re-read partition table.\n"));
5329 if ((i = ioctl(fd, BLKRRPART)) != 0) {
5332 /* some kernel versions (1.2.x) seem to have trouble
5333 rereading the partition table, but if asked to do it
5334 twice, the second time works. - biro@yggdrasil.com */
5337 if ((i = ioctl(fd, BLKRRPART)) != 0)
5342 printf(_("\nWARNING: Re-reading the partition table "
5343 "failed with error %d: %s.\n"
5344 "The kernel still uses the old table.\n"
5345 "The new table will be used "
5346 "at the next reboot.\n"),
5347 error, strerror(error));
5352 _("\nWARNING: If you have created or modified any DOS 6.x\n"
5353 "partitions, please see the fdisk manual page for additional\n"
5359 printf(_("Syncing disks.\n"));
5361 sleep(4); /* for sync() */
5366 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
5367 #define MAX_PER_LINE 16
5369 print_buffer(char pbuffer[]) {
5373 for (i = 0, l = 0; i < sector_size; i++, l++) {
5375 printf("0x%03X:", i);
5376 printf(" %02X", (unsigned char) pbuffer[i]);
5377 if (l == MAX_PER_LINE - 1) {
5392 printf(_("Device: %s\n"), disk_device);
5393 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
5394 if (sun_label || sgi_label)
5395 print_buffer(MBRbuffer);
5398 for (i = 3; i < partitions; i++)
5399 print_buffer(ptes[i].sectorbuffer);
5404 struct pte *pe = &ptes[i];
5405 struct partition *p = pe->part_table;
5408 if (warn_geometry())
5410 if (!p->sys_ind || !get_nr_sects(p) || IS_EXTENDED (p->sys_ind)) {
5411 printf(_("Partition %d has no data area\n"), i + 1);
5414 first = get_partition_start(pe);
5415 new = read_int(first, first, first + get_nr_sects(p) - 1, first,
5416 _("New beginning of data")) - pe->offset;
5418 if (new != get_nr_sects(p)) {
5419 first = get_nr_sects(p) + get_start_sect(p) - new;
5420 set_nr_sects(p, first);
5421 set_start_sect(p, new);
5432 c = tolower(read_char(_("Expert command (m for help): ")));
5435 #ifdef CONFIG_FEATURE_SUN_LABEL
5442 move_begin(get_partition(0, partitions));
5445 user_cylinders = cylinders =
5446 read_int(1, cylinders, 1048576, 0,
5447 _("Number of cylinders"));
5448 #ifdef CONFIG_FEATURE_SUN_LABEL
5450 sun_set_ncyl(cylinders);
5459 #ifdef CONFIG_FEATURE_SGI_LABEL
5464 #ifdef CONFIG_FEATURE_SUN_LABEL
5474 fix_partition_table_order();
5477 #ifdef CONFIG_FEATURE_SGI_LABEL
5482 user_heads = heads = read_int(1, heads, 256, 0,
5483 _("Number of heads"));
5487 #ifdef CONFIG_FEATURE_SUN_LABEL
5493 #ifdef CONFIG_FEATURE_SUN_LABEL
5499 #ifdef CONFIG_FEATURE_SUN_LABEL
5513 user_sectors = sectors = read_int(1, sectors, 63, 0,
5514 _("Number of sectors"));
5515 if (dos_compatible_flag) {
5516 sector_offset = sectors;
5517 fprintf(stderr, _("Warning: setting "
5518 "sector offset for DOS "
5527 write_table(); /* does not return */
5530 #ifdef CONFIG_FEATURE_SUN_LABEL
5532 sun_set_pcylcount();
5540 #endif /* ADVANCED mode */
5543 is_ide_cdrom_or_tape(const char *device) {
5546 struct stat statbuf;
5549 /* No device was given explicitly, and we are trying some
5550 likely things. But opening /dev/hdc may produce errors like
5551 "hdc: tray open or drive not ready"
5552 if it happens to be a CD-ROM drive. It even happens that
5553 the process hangs on the attempt to read a music CD.
5554 So try to be careful. This only works since 2.1.73. */
5556 if (strncmp("/dev/hd", device, 7))
5559 snprintf(buf, sizeof(buf), "/proc/ide/%s/media", device+5);
5560 procf = fopen(buf, "r");
5561 if (procf != NULL && fgets(buf, sizeof(buf), procf))
5562 is_ide = (!strncmp(buf, "cdrom", 5) ||
5563 !strncmp(buf, "tape", 4));
5565 /* Now when this proc file does not exist, skip the
5566 device when it is read-only. */
5567 if (stat(device, &statbuf) == 0)
5568 is_ide = ((statbuf.st_mode & 0222) == 0);
5576 try(const char *device, int user_specified) {
5579 disk_device = device;
5580 if (setjmp(listingbuf))
5582 if (!user_specified)
5583 if (is_ide_cdrom_or_tape(device))
5585 if ((fd = open(disk_device, type_open)) >= 0) {
5586 gb = get_boot(try_only);
5587 if (gb > 0) { /* I/O error */
5589 } else if (gb < 0) { /* no DOS signature */
5590 list_disk_geometry();
5593 #ifdef CONFIG_FEATURE_OSF_LABEL
5594 if (btrydev(device) < 0)
5597 _("Disk %s doesn't contain a valid "
5598 "partition table\n"), device);
5603 if (!sun_label && partitions > 4)
5604 delete_partition(ext_index);
5607 /* Ignore other errors, since we try IDE
5608 and SCSI hard disks which may not be
5609 installed on the system. */
5610 if (errno == EACCES) {
5611 fprintf(stderr, _("Cannot open %s\n"), device);
5617 /* for fdisk -l: try all things in /proc/partitions
5618 that look like a partition name (do not end in a digit) */
5622 char line[100], ptname[100], devname[120], *s;
5625 procpt = wfopen(PROC_PARTITIONS, "r");
5627 while (fgets(line, sizeof(line), procpt)) {
5628 if (sscanf (line, " %d %d %d %[^\n ]",
5629 &ma, &mi, &sz, ptname) != 4)
5631 for (s = ptname; *s; s++);
5634 snprintf(devname, sizeof(devname), "/dev/%s", ptname);
5641 unknown_command(int c) {
5642 printf(_("%c: unknown command\n"), c);
5645 int fdisk_main(int argc, char **argv) {
5647 int optl = 0, opts = 0;
5652 * fdisk -l [-b sectorsize] [-u] device ...
5653 * fdisk -s [partition] ...
5654 * fdisk [-b sectorsize] [-u] device
5656 * Options -C, -H, -S set the geometry.
5659 while ((c = getopt(argc, argv, "b:C:H:lsS:uvV")) != -1) {
5662 /* Ugly: this sector size is really per device,
5663 so cannot be combined with multiple disks,
5664 and te same goes for the C/H/S options.
5666 sector_size = atoi(optarg);
5667 if (sector_size != 512 && sector_size != 1024 &&
5668 sector_size != 2048)
5671 user_set_sector_size = 1;
5674 user_cylinders = atoi(optarg);
5677 user_heads = atoi(optarg);
5678 if (user_heads <= 0 || user_heads >= 256)
5682 user_sectors = atoi(optarg);
5683 if (user_sectors <= 0 || user_sectors >= 64)
5693 display_in_cyl_units = 0;
5697 printf("fdisk v" UTIL_LINUX_VERSION "\n");
5705 printf(_("This kernel finds the sector size itself - "
5706 "-b option ignored\n"));
5708 if (user_set_sector_size && argc-optind != 1)
5709 printf(_("Warning: the -b (set sector size) option should"
5710 " be used with one specified device\n"));
5715 type_open = O_RDONLY;
5716 if (argc > optind) {
5719 /* avoid gcc warning:
5720 variable `k' might be clobbered by `longjmp' */
5724 for (k=optind; k<argc; k++)
5727 /* we no longer have default device names */
5728 /* but, we can use /proc/partitions instead */
5738 type_open = O_RDONLY;
5740 opts = argc - optind;
5744 for (j = optind; j < argc; j++) {
5745 disk_device = argv[j];
5746 if ((fd = open(disk_device, type_open)) < 0)
5747 fdisk_fatal(unable_to_open);
5748 if (ioctl(fd, BLKGETSIZE, &size))
5749 fdisk_fatal(ioctl_error);
5752 printf("%ld\n", size/2);
5754 printf("%s: %ld\n", argv[j], size/2);
5759 if (argc-optind == 1)
5760 disk_device = argv[optind];
5766 #ifdef CONFIG_FEATURE_OSF_LABEL
5768 /* OSF label, and no DOS label */
5769 printf(_("Detected an OSF/1 disklabel on %s, entering "
5770 "disklabel mode.\n"),
5774 /* If we return we may want to make an empty DOS label? */
5780 c = tolower(read_char(_("Command (m for help): ")));
5784 toggle_active(get_partition(1, partitions));
5785 #ifdef CONFIG_FEATURE_SUN_LABEL
5787 toggle_sunflags(get_partition(1, partitions),
5790 #ifdef CONFIG_FEATURE_SGI_LABEL
5792 sgi_set_bootpartition(
5793 get_partition(1, partitions));
5799 #ifdef CONFIG_FEATURE_SGI_LABEL
5801 printf(_("\nThe current boot file is: %s\n"),
5802 sgi_get_bootfile());
5803 if (read_chars(_("Please enter the name of the "
5804 "new boot file: ")) == '\n')
5805 printf(_("Boot file unchanged\n"));
5807 sgi_set_bootfile(line_ptr);
5810 #ifdef CONFIG_FEATURE_OSF_LABEL
5816 toggle_dos_compatibility_flag();
5817 #ifdef CONFIG_FEATURE_SUN_LABEL
5819 toggle_sunflags(get_partition(1, partitions),
5822 #ifdef CONFIG_FEATURE_SGI_LABEL
5824 sgi_set_swappartition(
5825 get_partition(1, partitions));
5831 j = get_existing_partition(1, partitions);
5833 delete_partition(j);
5836 #ifdef CONFIG_FEATURE_SGI_LABEL
5843 list_types(get_sys_types());
5862 #ifdef CONFIG_FEATURE_SUN_LABEL
5876 write_table(); /* does not return */
5878 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
5880 #ifdef CONFIG_FEATURE_SGI_LABEL
5883 _("\n\tSorry, no experts menu for SGI "
5884 "partition tables available.\n\n"));