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 */
45 #include <linux/blkpg.h>
48 #include <sys/ioctl.h>
49 #include <sys/param.h>
51 #include <linux/types.h> /* for __u32, __u16, __u8, __s16 */
52 #include <linux/major.h> /* FLOPPY_MAJOR */
54 #include <sys/utsname.h>
58 #define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r))
64 #define BLKRRPART _IO(0x12,95) /* re-read partition table */
65 #define BLKGETSIZE _IO(0x12,96) /* return device size */
66 #define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */
67 #define BLKSSZGET _IO(0x12,104) /* get block device sector size */
74 #define DEFAULT_SECTOR_SIZE 512
75 #define MAX_SECTOR_SIZE 2048
76 #define SECTOR_SIZE 512 /* still used in BSD code */
77 #define MAXIMUM_PARTS 60
79 #define ACTIVE_FLAG 0x80
82 #define WIN98_EXTENDED 0x0f
83 #define LINUX_PARTITION 0x81
84 #define LINUX_SWAP 0x82
85 #define LINUX_NATIVE 0x83
86 #define LINUX_EXTENDED 0x85
87 #define LINUX_LVM 0x8e
88 #define LINUX_RAID 0xfd
93 #define IS_EXTENDED(i) \
94 ((i) == EXTENDED || (i) == WIN98_EXTENDED || (i) == LINUX_EXTENDED)
96 #define SIZE(a) (sizeof(a)/sizeof((a)[0]))
98 #define cround(n) (display_in_cyl_units ? ((n)/units_per_sector)+1 : (n))
99 #define scround(x) (((x)+units_per_sector-1)/units_per_sector)
101 #if defined(__GNUC__) || defined(HAS_LONG_LONG)
102 typedef long long ext2_loff_t;
104 typedef long ext2_loff_t;
107 /* including <linux/hdreg.h> also fails */
110 unsigned char sectors;
111 unsigned short cylinders;
115 #define HDIO_GETGEO 0x0301 /* get device geometry */
119 const unsigned char *name;
124 * Raw disk label. For DOS-type partition tables the MBR,
125 * with descriptions of the primary partitions.
127 static char MBRbuffer[MAX_SECTOR_SIZE];
129 #ifdef CONFIG_FEATURE_SUN_LABEL
130 static int sun_label; /* looking at sun disklabel */
133 #define check_sun_label() 0
135 #ifdef CONFIG_FEATURE_SGI_LABEL
136 static int sgi_label; /* looking at sgi disklabel */
140 #ifdef CONFIG_FEATURE_AIX_LABEL
141 static int aix_label; /* looking at aix disklabel */
145 #ifdef CONFIG_FEATURE_OSF_LABEL
146 static int osf_label; /* looking at OSF/1 disklabel */
147 static int possibly_osf_label;
152 #define dos_label (!sun_label && !sgi_label && !aix_label && !osf_label)
154 static uint heads, sectors, cylinders;
155 static void update_units(void);
157 static const char *partition_type(unsigned char type);
160 * return partition name - uses static storage unless buf is supplied
163 partname(const char *dev, int pno, int lth) {
164 static char buffer[80];
171 bufsiz = sizeof(buffer);
176 if (isdigit(dev[w-1]))
179 /* devfs kludge - note: fdisk partition names are not supposed
180 to equal kernel names, so there is no reason to do this */
181 if (strcmp (dev + w - 4, "disc") == 0) {
189 snprintf(bufp, bufsiz, "%*.*s%s%-2u",
190 lth-wp-2, w, dev, p, pno);
192 snprintf(bufp, bufsiz, "%.*s%s%-2u", w, dev, p, pno);
198 unsigned char boot_ind; /* 0x80 - active */
199 unsigned char head; /* starting head */
200 unsigned char sector; /* starting sector */
201 unsigned char cyl; /* starting cylinder */
202 unsigned char sys_ind; /* What partition type */
203 unsigned char end_head; /* end head */
204 unsigned char end_sector; /* end sector */
205 unsigned char end_cyl; /* end cylinder */
206 unsigned char start4[4]; /* starting sector counting from 0 */
207 unsigned char size4[4]; /* nr of sectors in partition */
211 ioctl_error, unable_to_open, unable_to_read, unable_to_seek,
215 enum action {fdisk, require, try_only, create_empty_dos, create_empty_sun};
219 unsigned int sectors;
220 unsigned int cylinders;
223 static const char *disk_device;
224 static char *line_ptr;
225 static int fd; /* the disk */
226 static int partitions = 4; /* maximum partition + 1 */
227 static uint display_in_cyl_units = 1;
228 static uint units_per_sector = 1;
229 static void change_units(void);
230 static void fdisk_fatal(enum failure why) __attribute__ ((noreturn));
231 static void get_geometry(struct geom *);
232 static int get_boot(enum action what);
233 static int get_partition(int warn, int max);
234 static void list_types(const struct systypes *sys);
235 static void reread_partition_table(int leave);
236 static int valid_part_table_flag(const unsigned char *b);
237 static uint read_int(uint low, uint dflt, uint high, uint base, char *mesg);
242 #define hex_val(c) ({ \
244 isdigit(_c) ? _c - '0' : \
245 tolower(_c) + 10 - 'a'; \
249 #define LINE_LENGTH 800
250 #define pt_offset(b, n) ((struct partition *)((b) + 0x1be + \
251 (n) * sizeof(struct partition)))
252 #define sector(s) ((s) & 0x3f)
253 #define cylinder(s, c) ((c) | (((s) & 0xc0) << 2))
255 #define hsc2sector(h,s,c) (sector(s) - 1 + sectors * \
256 ((h) + heads * cylinder(s,c)))
257 #define set_hsc(h,s,c,sector) { \
258 s = sector % sectors + 1; \
260 h = sector % heads; \
263 s |= (sector >> 2) & 0xc0; \
267 static unsigned int get_start_sect(const struct partition *p);
268 static unsigned int get_nr_sects(const struct partition *p);
271 * per partition table entry data
273 * The four primary partitions have the same sectorbuffer (MBRbuffer)
274 * and have NULL ext_pointer.
275 * Each logical partition table entry has two pointers, one for the
276 * partition and one link to the next one.
279 struct partition *part_table; /* points into sectorbuffer */
280 struct partition *ext_pointer; /* points into sectorbuffer */
281 char changed; /* boolean */
282 uint offset; /* disk sector number */
283 char *sectorbuffer; /* disk sector contents */
284 } ptes[MAXIMUM_PARTS];
286 static char line_buffer[LINE_LENGTH];
289 set_all_unchanged(void) {
292 for (i = 0; i < MAXIMUM_PARTS; i++)
302 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_OSF_LABEL)
303 static struct partition *
304 get_part_table(int i) {
305 return ptes[i].part_table;
310 str_units(int n) { /* n==1: use singular */
312 return display_in_cyl_units ? _("cylinder") : _("sector");
314 return display_in_cyl_units ? _("cylinders") : _("sectors");
317 /* read line; return 0 or first char */
321 static int got_eof = 0;
323 fflush (stdout); /* requested by niles@scyld.com */
324 line_ptr = line_buffer;
325 if (!fgets(line_buffer, LINE_LENGTH, stdin)) {
327 got_eof++; /* user typed ^D ? */
330 fprintf(stderr, _("\ngot EOF thrice - exiting..\n"));
335 while (*line_ptr && !isgraph(*line_ptr))
341 read_char(const char *mesg)
345 } while (!read_line());
350 read_chars(const char *mesg)
361 read_hex(const struct systypes *sys)
367 read_char(_("Hex code (type L to list codes): "));
368 if (*line_ptr == 'l' || *line_ptr == 'L')
370 else if (isxdigit (*line_ptr))
374 hex = hex << 4 | hex_val(*line_ptr++);
375 while (isxdigit(*line_ptr));
381 #ifdef CONFIG_FEATURE_AIX_LABEL
383 * Copyright (C) Andreas Neuper, Sep 1998.
384 * This file may be redistributed under
385 * the terms of the GNU Public License.
389 unsigned int magic; /* expect AIX_LABEL_MAGIC */
390 unsigned int fillbytes1[124];
391 unsigned int physical_volume_id;
392 unsigned int fillbytes2[124];
395 #define AIX_LABEL_MAGIC 0xc9c2d4c1
396 #define AIX_LABEL_MAGIC_SWAPPED 0xc1d4c2c9
397 #define AIX_INFO_MAGIC 0x00072959
398 #define AIX_INFO_MAGIC_SWAPPED 0x59290700
400 #define aixlabel ((aix_partition *)MBRbuffer)
405 Sat Mar 20 09:51:38 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
409 static int aix_other_endian;
410 static short aix_volumes=1;
413 * only dealing with free blocks here
419 _("\n\tThere is a valid AIX label on this disk.\n"
420 "\tUnfortunately Linux cannot handle these\n"
421 "\tdisks at the moment. Nevertheless some\n"
423 "\t1. fdisk will destroy its contents on write.\n"
424 "\t2. Be sure that this disk is NOT a still vital\n"
425 "\t part of a volume group. (Otherwise you may\n"
426 "\t erase the other disks as well, if unmirrored.)\n"
427 "\t3. Before deleting this physical volume be sure\n"
428 "\t to remove the disk logically from your AIX\n"
429 "\t machine. (Otherwise you become an AIXpert).")
439 memset( MBRbuffer, 0, sizeof(MBRbuffer) ); /* avoid fdisk cores */
444 check_aix_label( void )
446 if (aixlabel->magic != AIX_LABEL_MAGIC &&
447 aixlabel->magic != AIX_LABEL_MAGIC_SWAPPED) {
449 aix_other_endian = 0;
452 aix_other_endian = (aixlabel->magic == AIX_LABEL_MAGIC_SWAPPED);
458 aix_nolabel(); /* %% */
459 aix_label = 1; /* %% */
462 #endif /* AIX_LABEL */
464 #ifdef CONFIG_FEATURE_OSF_LABEL
466 * Copyright (c) 1987, 1988 Regents of the University of California.
467 * All rights reserved.
469 * Redistribution and use in source and binary forms, with or without
470 * modification, are permitted provided that the following conditions
472 * 1. Redistributions of source code must retain the above copyright
473 * notice, this list of conditions and the following disclaimer.
474 * 2. Redistributions in binary form must reproduce the above copyright
475 * notice, this list of conditions and the following disclaimer in the
476 * documentation and/or other materials provided with the distribution.
477 * 3. All advertising materials mentioning features or use of this software
478 * must display the following acknowledgement:
479 * This product includes software developed by the University of
480 * California, Berkeley and its contributors.
481 * 4. Neither the name of the University nor the names of its contributors
482 * may be used to endorse or promote products derived from this software
483 * without specific prior written permission.
485 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
486 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
487 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
488 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
489 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
490 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
491 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
492 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
493 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
494 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
499 #ifndef BSD_DISKMAGIC
500 #define BSD_DISKMAGIC ((__u32) 0x82564557)
503 #ifndef BSD_MAXPARTITIONS
504 #define BSD_MAXPARTITIONS 16
507 #define BSD_LINUX_BOOTDIR "/usr/ucb/mdec"
509 #if defined (i386) || defined (__sparc__) || defined (__arm__) || defined (__mips__) || defined (__s390__) || defined (__sh__) || defined(__x86_64__)
510 #define BSD_LABELSECTOR 1
511 #define BSD_LABELOFFSET 0
512 #elif defined (__alpha__) || defined (__powerpc__) || defined (__ia64__) || defined (__hppa__)
513 #define BSD_LABELSECTOR 0
514 #define BSD_LABELOFFSET 64
516 #error unknown architecture
519 #define BSD_BBSIZE 8192 /* size of boot area, with label */
520 #define BSD_SBSIZE 8192 /* max size of fs superblock */
522 struct xbsd_disklabel {
523 __u32 d_magic; /* the magic number */
524 __s16 d_type; /* drive type */
525 __s16 d_subtype; /* controller/d_type specific */
526 char d_typename[16]; /* type name, e.g. "eagle" */
527 char d_packname[16]; /* pack identifier */
529 __u32 d_secsize; /* # of bytes per sector */
530 __u32 d_nsectors; /* # of data sectors per track */
531 __u32 d_ntracks; /* # of tracks per cylinder */
532 __u32 d_ncylinders; /* # of data cylinders per unit */
533 __u32 d_secpercyl; /* # of data sectors per cylinder */
534 __u32 d_secperunit; /* # of data sectors per unit */
536 * Spares (bad sector replacements) below
537 * are not counted in d_nsectors or d_secpercyl.
538 * Spare sectors are assumed to be physical sectors
539 * which occupy space at the end of each track and/or cylinder.
541 __u16 d_sparespertrack; /* # of spare sectors per track */
542 __u16 d_sparespercyl; /* # of spare sectors per cylinder */
544 * Alternate cylinders include maintenance, replacement,
545 * configuration description areas, etc.
547 __u32 d_acylinders; /* # of alt. cylinders per unit */
549 /* hardware characteristics: */
551 * d_interleave, d_trackskew and d_cylskew describe perturbations
552 * in the media format used to compensate for a slow controller.
553 * Interleave is physical sector interleave, set up by the formatter
554 * or controller when formatting. When interleaving is in use,
555 * logically adjacent sectors are not physically contiguous,
556 * but instead are separated by some number of sectors.
557 * It is specified as the ratio of physical sectors traversed
558 * per logical sector. Thus an interleave of 1:1 implies contiguous
559 * layout, while 2:1 implies that logical sector 0 is separated
560 * by one sector from logical sector 1.
561 * d_trackskew is the offset of sector 0 on track N
562 * relative to sector 0 on track N-1 on the same cylinder.
563 * Finally, d_cylskew is the offset of sector 0 on cylinder N
564 * relative to sector 0 on cylinder N-1.
566 __u16 d_rpm; /* rotational speed */
567 __u16 d_interleave; /* hardware sector interleave */
568 __u16 d_trackskew; /* sector 0 skew, per track */
569 __u16 d_cylskew; /* sector 0 skew, per cylinder */
570 __u32 d_headswitch; /* head switch time, usec */
571 __u32 d_trkseek; /* track-to-track seek, usec */
572 __u32 d_flags; /* generic flags */
574 __u32 d_drivedata[NDDATA]; /* drive-type specific information */
576 __u32 d_spare[NSPARE]; /* reserved for future use */
577 __u32 d_magic2; /* the magic number (again) */
578 __u16 d_checksum; /* xor of data incl. partitions */
579 /* filesystem and partition information: */
580 __u16 d_npartitions; /* number of partitions in following */
581 __u32 d_bbsize; /* size of boot area at sn0, bytes */
582 __u32 d_sbsize; /* max size of fs superblock, bytes */
583 struct xbsd_partition { /* the partition table */
584 __u32 p_size; /* number of sectors in partition */
585 __u32 p_offset; /* starting sector */
586 __u32 p_fsize; /* filesystem basic fragment size */
587 __u8 p_fstype; /* filesystem type, see below */
588 __u8 p_frag; /* filesystem fragments per block */
589 __u16 p_cpg; /* filesystem cylinders per group */
590 } d_partitions[BSD_MAXPARTITIONS]; /* actually may be more */
594 #define BSD_DTYPE_SMD 1 /* SMD, XSMD; VAX hp/up */
595 #define BSD_DTYPE_MSCP 2 /* MSCP */
596 #define BSD_DTYPE_DEC 3 /* other DEC (rk, rl) */
597 #define BSD_DTYPE_SCSI 4 /* SCSI */
598 #define BSD_DTYPE_ESDI 5 /* ESDI interface */
599 #define BSD_DTYPE_ST506 6 /* ST506 etc. */
600 #define BSD_DTYPE_HPIB 7 /* CS/80 on HP-IB */
601 #define BSD_DTYPE_HPFL 8 /* HP Fiber-link */
602 #define BSD_DTYPE_FLOPPY 10 /* floppy */
604 /* d_subtype values: */
605 #define BSD_DSTYPE_INDOSPART 0x8 /* is inside dos partition */
606 #define BSD_DSTYPE_DOSPART(s) ((s) & 3) /* dos partition number */
607 #define BSD_DSTYPE_GEOMETRY 0x10 /* drive params in label */
610 static const char * const xbsd_dktypenames[] = {
624 #define BSD_DKMAXTYPES (sizeof(xbsd_dktypenames) / sizeof(xbsd_dktypenames[0]) - 1)
628 * Filesystem type and version.
629 * Used to interpret other filesystem-specific
630 * per-partition information.
632 #define BSD_FS_UNUSED 0 /* unused */
633 #define BSD_FS_SWAP 1 /* swap */
634 #define BSD_FS_V6 2 /* Sixth Edition */
635 #define BSD_FS_V7 3 /* Seventh Edition */
636 #define BSD_FS_SYSV 4 /* System V */
637 #define BSD_FS_V71K 5 /* V7 with 1K blocks (4.1, 2.9) */
638 #define BSD_FS_V8 6 /* Eighth Edition, 4K blocks */
639 #define BSD_FS_BSDFFS 7 /* 4.2BSD fast file system */
640 #define BSD_FS_BSDLFS 9 /* 4.4BSD log-structured file system */
641 #define BSD_FS_OTHER 10 /* in use, but unknown/unsupported */
642 #define BSD_FS_HPFS 11 /* OS/2 high-performance file system */
643 #define BSD_FS_ISO9660 12 /* ISO-9660 filesystem (cdrom) */
644 #define BSD_FS_ISOFS BSD_FS_ISO9660
645 #define BSD_FS_BOOT 13 /* partition contains bootstrap */
646 #define BSD_FS_ADOS 14 /* AmigaDOS fast file system */
647 #define BSD_FS_HFS 15 /* Macintosh HFS */
648 #define BSD_FS_ADVFS 16 /* Digital Unix AdvFS */
650 /* this is annoying, but it's also the way it is :-( */
652 #define BSD_FS_EXT2 8 /* ext2 file system */
654 #define BSD_FS_MSDOS 8 /* MS-DOS file system */
658 static const struct systypes xbsd_fstypes[] = {
659 /* BSD_FS_UNUSED */ {"\x00" "unused"},
660 /* BSD_FS_SWAP */ {"\x01" "swap"},
661 /* BSD_FS_V6 */ {"\x02" "Version 6"},
662 /* BSD_FS_V7 */ {"\x03" "Version 7"},
663 /* BSD_FS_SYSV */ {"\x04" "System V"},
664 /* BSD_FS_V71K */ {"\x05" "4.1BSD"},
665 /* BSD_FS_V8 */ {"\x06" "Eighth Edition"},
666 /* BSD_FS_BSDFFS */ {"\x07" "4.2BSD"},
668 /* BSD_FS_EXT2 */ {"\x08" "ext2"},
670 /* BSD_FS_MSDOS */ {"\x08" "MS-DOS"},
672 /* BSD_FS_BSDLFS */ {"\x09" "4.4LFS"},
673 /* BSD_FS_OTHER */ {"\x0a" "unknown"},
674 /* BSD_FS_HPFS */ {"\x0b" "HPFS"},
675 /* BSD_FS_ISO9660 */ {"\x0c" "ISO-9660"},
676 /* BSD_FS_BOOT */ {"\x0d" "boot"},
677 /* BSD_FS_ADOS */ {"\x0e" "ADOS"},
678 /* BSD_FS_HFS */ {"\x0f" "HFS"},
679 /* BSD_FS_ADVFS */ {"\x10" "AdvFS"},
682 #define BSD_FSMAXTYPES (SIZE(xbsd_fstypes)-1)
687 * flags shared by various drives:
689 #define BSD_D_REMOVABLE 0x01 /* removable media */
690 #define BSD_D_ECC 0x02 /* supports ECC */
691 #define BSD_D_BADSECT 0x04 /* supports bad sector forw. */
692 #define BSD_D_RAMDISK 0x08 /* disk emulator */
693 #define BSD_D_CHAIN 0x10 /* can do back-back transfers */
694 #define BSD_D_DOSPART 0x20 /* within MSDOS partition */
696 #endif /* OSF_LABEL */
699 * Copyright (C) Andreas Neuper, Sep 1998.
700 * This file may be modified and redistributed under
701 * the terms of the GNU Public License.
704 struct device_parameter { /* 48 bytes */
708 unsigned char sparecyl;
709 unsigned short pcylcount;
710 unsigned short head_vol0;
711 unsigned short ntrks; /* tracks in cyl 0 or vol 0 */
712 unsigned char cmd_tag_queue_depth;
713 unsigned char unused0;
714 unsigned short unused1;
715 unsigned short nsect; /* sectors/tracks in cyl 0 or vol 0 */
716 unsigned short bytes;
717 unsigned short ilfact;
718 unsigned int flags; /* controller flags */
719 unsigned int datarate;
720 unsigned int retries_on_error;
721 unsigned int ms_per_word;
722 unsigned short xylogics_gap1;
723 unsigned short xylogics_syncdelay;
724 unsigned short xylogics_readdelay;
725 unsigned short xylogics_gap2;
726 unsigned short xylogics_readgate;
727 unsigned short xylogics_writecont;
730 #define SGI_VOLHDR 0x00
731 /* 1 and 2 were used for drive types no longer supported by SGI */
732 #define SGI_SWAP 0x03
733 /* 4 and 5 were for filesystem types SGI haven't ever supported on MIPS CPUs */
734 #define SGI_VOLUME 0x06
736 #define SGI_LVOL 0x08
737 #define SGI_RLVOL 0x09
739 #define SGI_XFSLOG 0x0b
742 #define ENTIRE_DISK SGI_VOLUME
746 #define SECTOR_SLIP 0x01
747 #define SECTOR_FWD 0x02
748 #define TRACK_FWD 0x04
749 #define TRACK_MULTIVOL 0x08
750 #define IGNORE_ERRORS 0x10
752 #define ENABLE_CMDTAGQ 0x40
755 unsigned int magic; /* expect SGI_LABEL_MAGIC */
756 unsigned short boot_part; /* active boot partition */
757 unsigned short swap_part; /* active swap partition */
758 unsigned char boot_file[16]; /* name of the bootfile */
759 struct device_parameter devparam; /* 1 * 48 bytes */
760 struct volume_directory { /* 15 * 16 bytes */
761 unsigned char vol_file_name[8]; /* a character array */
762 unsigned int vol_file_start; /* number of logical block */
763 unsigned int vol_file_size; /* number of bytes */
765 struct sgi_partition { /* 16 * 12 bytes */
766 unsigned int num_sectors; /* number of blocks */
767 unsigned int start_sector; /* must be cylinder aligned */
771 unsigned int fillbytes;
775 unsigned int magic; /* looks like a magic number */
784 unsigned char scsi_string[50];
785 unsigned char serial[137];
786 unsigned short check1816;
787 unsigned char installer[225];
790 #define SGI_LABEL_MAGIC 0x0be5a941
791 #define SGI_LABEL_MAGIC_SWAPPED 0x41a9e50b
792 #define SGI_INFO_MAGIC 0x00072959
793 #define SGI_INFO_MAGIC_SWAPPED 0x59290700
794 #define SGI_SSWAP16(x) (sgi_other_endian ? __swap16(x) \
796 #define SGI_SSWAP32(x) (sgi_other_endian ? __swap32(x) \
799 #define sgilabel ((sgi_partition *)MBRbuffer)
800 #define sgiparam (sgilabel->devparam)
803 unsigned char info[128]; /* Informative text string */
804 unsigned char spare0[14];
806 unsigned char spare1;
808 unsigned char spare2;
811 unsigned char spare1[246]; /* Boot information etc. */
812 unsigned short rspeed; /* Disk rotational speed */
813 unsigned short pcylcount; /* Physical cylinder count */
814 unsigned short sparecyl; /* extra sects per cylinder */
815 unsigned char spare2[4]; /* More magic... */
816 unsigned short ilfact; /* Interleave factor */
817 unsigned short ncyl; /* Data cylinder count */
818 unsigned short nacyl; /* Alt. cylinder count */
819 unsigned short ntrks; /* Tracks per cylinder */
820 unsigned short nsect; /* Sectors per track */
821 unsigned char spare3[4]; /* Even more magic... */
822 struct sun_partition {
823 __u32 start_cylinder;
826 unsigned short magic; /* Magic number */
827 unsigned short csum; /* Label xor'd checksum */
830 #define SUN_LABEL_MAGIC 0xDABE
831 #define SUN_LABEL_MAGIC_SWAPPED 0xBEDA
832 #define sunlabel ((sun_partition *)MBRbuffer)
833 #define SUN_SSWAP16(x) (sun_other_endian ? __swap16(x) \
835 #define SUN_SSWAP32(x) (sun_other_endian ? __swap32(x) \
839 * llseek.c -- stub calling the llseek system call
841 * Copyright (C) 1994 Remy Card. This file may be redistributed
842 * under the terms of the GNU Public License.
851 #else /* HAVE_LLSEEK */
853 #if defined(__alpha__) || defined(__ia64__)
855 #define my_llseek lseek
858 #include <linux/unistd.h> /* for __NR__llseek */
860 static int _llseek (unsigned int, unsigned long,
861 unsigned long, ext2_loff_t *, unsigned int);
865 static _syscall5(int,_llseek,unsigned int,f_d,unsigned long,offset_high,
866 unsigned long, offset_low,ext2_loff_t *,result,
867 unsigned int, origin)
871 /* no __NR__llseek on compilation machine - might give it explicitly */
872 static int _llseek (unsigned int f_d, unsigned long oh,
873 unsigned long ol, ext2_loff_t *result,
874 unsigned int origin) {
881 static ext2_loff_t my_llseek (unsigned int f_d, ext2_loff_t offset,
887 retval = _llseek (f_d, ((unsigned long long) offset) >> 32,
888 ((unsigned long long) offset) & 0xffffffff,
890 return (retval == -1 ? (ext2_loff_t) retval : result);
893 #endif /* __alpha__ */
895 #endif /* HAVE_LLSEEK */
897 static ext2_loff_t ext2_llseek (unsigned int f_d, ext2_loff_t offset,
901 static int do_compat = 0;
904 result = my_llseek (f_d, offset, origin);
905 if (!(result == -1 && errno == ENOSYS))
909 * Just in case this code runs on top of an old kernel
910 * which does not support the llseek system call
914 * Now try ordinary lseek.
918 if ((sizeof(off_t) >= sizeof(ext2_loff_t)) ||
919 (offset < ((ext2_loff_t) 1 << ((sizeof(off_t)*8) -1))))
920 return lseek(f_d, (off_t) offset, origin);
928 static ext2_loff_t ext2_llseek (unsigned int f_d, ext2_loff_t offset,
931 if ((sizeof(off_t) < sizeof(ext2_loff_t)) &&
932 (offset >= ((ext2_loff_t) 1 << ((sizeof(off_t)*8) -1)))) {
936 return lseek (f_d, (off_t) offset, origin);
942 #ifdef CONFIG_FEATURE_OSF_LABEL
945 19990319 - Arnaldo Carvalho de Melo <acme@conectiva.com.br> - i18n/nls
947 20000101 - David Huggins-Daines <dhuggins@linuxcare.com> - Better
948 support for OSF/1 disklabels on Alpha.
949 Also fixed unaligned accesses in alpha_bootblock_checksum()
952 #define FREEBSD_PARTITION 0xa5
953 #define NETBSD_PARTITION 0xa9
955 static void xbsd_delete_part (void);
956 static void xbsd_new_part (void);
957 static void xbsd_write_disklabel (void);
958 static int xbsd_create_disklabel (void);
959 static void xbsd_edit_disklabel (void);
960 static void xbsd_write_bootstrap (void);
961 static void xbsd_change_fstype (void);
962 static int xbsd_get_part_index (int max);
963 static int xbsd_check_new_partition (int *i);
964 static void xbsd_list_types (void);
965 static u_short xbsd_dkcksum (struct xbsd_disklabel *lp);
966 static int xbsd_initlabel (struct partition *p, struct xbsd_disklabel *d,
968 static int xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d);
969 static int xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d);
971 #if defined (__alpha__)
972 static void alpha_bootblock_checksum (char *boot);
975 #if !defined (__alpha__)
976 static int xbsd_translate_fstype (int linux_type);
977 static void xbsd_link_part (void);
978 static struct partition *xbsd_part;
979 static int xbsd_part_index;
982 #if defined (__alpha__)
983 /* We access this through a u_int64_t * when checksumming */
984 static char disklabelbuffer[BSD_BBSIZE] __attribute__((aligned(8)));
986 static char disklabelbuffer[BSD_BBSIZE];
989 static struct xbsd_disklabel xbsd_dlabel;
991 #define bsd_cround(n) \
992 (display_in_cyl_units ? ((n)/xbsd_dlabel.d_secpercyl) + 1 : (n))
995 * Test whether the whole disk has BSD disk label magic.
997 * Note: often reformatting with DOS-type label leaves the BSD magic,
998 * so this does not mean that there is a BSD disk label.
1001 check_osf_label(void) {
1002 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
1007 static void xbsd_print_disklabel(int);
1010 btrydev (char * dev) {
1011 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
1013 printf(_("\nBSD label for device: %s\n"), dev);
1014 xbsd_print_disklabel (0);
1020 puts (_("Command action"));
1021 puts (_("\td\tdelete a BSD partition"));
1022 puts (_("\te\tedit drive data"));
1023 puts (_("\ti\tinstall bootstrap"));
1024 puts (_("\tl\tlist known filesystem types"));
1025 puts (_("\tm\tprint this menu"));
1026 puts (_("\tn\tadd a new BSD partition"));
1027 puts (_("\tp\tprint BSD partition table"));
1028 puts (_("\tq\tquit without saving changes"));
1029 puts (_("\tr\treturn to main menu"));
1030 puts (_("\ts\tshow complete disklabel"));
1031 puts (_("\tt\tchange a partition's filesystem id"));
1032 puts (_("\tu\tchange units (cylinders/sectors)"));
1033 puts (_("\tw\twrite disklabel to disk"));
1034 #if !defined (__alpha__)
1035 puts (_("\tx\tlink BSD partition to non-BSD partition"));
1039 #if !defined (__alpha__)
1046 is_bsd_partition_type(int type) {
1047 return (type == FREEBSD_PARTITION ||
1048 type == hidden(FREEBSD_PARTITION) ||
1049 type == NETBSD_PARTITION ||
1050 type == hidden(NETBSD_PARTITION));
1056 #if !defined (__alpha__)
1058 struct partition *p;
1060 for (t=0; t<4; t++) {
1061 p = get_part_table(t);
1062 if (p && is_bsd_partition_type(p->sys_ind)) {
1064 xbsd_part_index = t;
1065 ss = get_start_sect(xbsd_part);
1067 fprintf (stderr, _("Partition %s has invalid starting sector 0.\n"),
1068 partname(disk_device, t+1, 0));
1071 printf (_("Reading disklabel of %s at sector %d.\n"),
1072 partname(disk_device, t+1, 0), ss + BSD_LABELSECTOR);
1073 if (xbsd_readlabel (xbsd_part, &xbsd_dlabel) == 0)
1074 if (xbsd_create_disklabel () == 0)
1081 printf (_("There is no *BSD partition on %s.\n"), disk_device);
1085 #elif defined (__alpha__)
1087 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
1088 if (xbsd_create_disklabel () == 0)
1089 exit ( EXIT_SUCCESS );
1095 switch (tolower (read_char (_("BSD disklabel command (m for help): ")))) {
1097 xbsd_delete_part ();
1100 xbsd_edit_disklabel ();
1103 xbsd_write_bootstrap ();
1112 xbsd_print_disklabel (0);
1116 exit ( EXIT_SUCCESS );
1120 xbsd_print_disklabel (1);
1123 xbsd_change_fstype ();
1129 xbsd_write_disklabel ();
1131 #if !defined (__alpha__)
1144 xbsd_delete_part (void)
1148 i = xbsd_get_part_index (xbsd_dlabel.d_npartitions);
1149 xbsd_dlabel.d_partitions[i].p_size = 0;
1150 xbsd_dlabel.d_partitions[i].p_offset = 0;
1151 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
1152 if (xbsd_dlabel.d_npartitions == i + 1)
1153 while (xbsd_dlabel.d_partitions[xbsd_dlabel.d_npartitions-1].p_size == 0)
1154 xbsd_dlabel.d_npartitions--;
1158 xbsd_new_part (void)
1164 if (!xbsd_check_new_partition (&i))
1167 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
1168 begin = get_start_sect(xbsd_part);
1169 end = begin + get_nr_sects(xbsd_part) - 1;
1172 end = xbsd_dlabel.d_secperunit - 1;
1175 snprintf (mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
1176 begin = read_int (bsd_cround (begin), bsd_cround (begin), bsd_cround (end),
1179 if (display_in_cyl_units)
1180 begin = (begin - 1) * xbsd_dlabel.d_secpercyl;
1182 snprintf (mesg, sizeof(mesg), _("Last %s or +size or +sizeM or +sizeK"),
1183 str_units(SINGULAR));
1184 end = read_int (bsd_cround (begin), bsd_cround (end), bsd_cround (end),
1185 bsd_cround (begin), mesg);
1187 if (display_in_cyl_units)
1188 end = end * xbsd_dlabel.d_secpercyl - 1;
1190 xbsd_dlabel.d_partitions[i].p_size = end - begin + 1;
1191 xbsd_dlabel.d_partitions[i].p_offset = begin;
1192 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
1196 xbsd_print_disklabel (int show_all) {
1197 struct xbsd_disklabel *lp = &xbsd_dlabel;
1198 struct xbsd_partition *pp;
1203 #if defined (__alpha__)
1204 fprintf(f, "# %s:\n", disk_device);
1206 fprintf(f, "# %s:\n", partname(disk_device, xbsd_part_index+1, 0));
1208 if ((unsigned) lp->d_type < BSD_DKMAXTYPES)
1209 fprintf(f, _("type: %s\n"), xbsd_dktypenames[lp->d_type]);
1211 fprintf(f, _("type: %d\n"), lp->d_type);
1212 fprintf(f, _("disk: %.*s\n"), (int) sizeof(lp->d_typename), lp->d_typename);
1213 fprintf(f, _("label: %.*s\n"), (int) sizeof(lp->d_packname), lp->d_packname);
1214 fprintf(f, _("flags:"));
1215 if (lp->d_flags & BSD_D_REMOVABLE)
1216 fprintf(f, _(" removable"));
1217 if (lp->d_flags & BSD_D_ECC)
1218 fprintf(f, _(" ecc"));
1219 if (lp->d_flags & BSD_D_BADSECT)
1220 fprintf(f, _(" badsect"));
1222 /* On various machines the fields of *lp are short/int/long */
1223 /* In order to avoid problems, we cast them all to long. */
1224 fprintf(f, _("bytes/sector: %ld\n"), (long) lp->d_secsize);
1225 fprintf(f, _("sectors/track: %ld\n"), (long) lp->d_nsectors);
1226 fprintf(f, _("tracks/cylinder: %ld\n"), (long) lp->d_ntracks);
1227 fprintf(f, _("sectors/cylinder: %ld\n"), (long) lp->d_secpercyl);
1228 fprintf(f, _("cylinders: %ld\n"), (long) lp->d_ncylinders);
1229 fprintf(f, _("rpm: %d\n"), lp->d_rpm);
1230 fprintf(f, _("interleave: %d\n"), lp->d_interleave);
1231 fprintf(f, _("trackskew: %d\n"), lp->d_trackskew);
1232 fprintf(f, _("cylinderskew: %d\n"), lp->d_cylskew);
1233 fprintf(f, _("headswitch: %ld\t\t# milliseconds\n"),
1234 (long) lp->d_headswitch);
1235 fprintf(f, _("track-to-track seek: %ld\t# milliseconds\n"),
1236 (long) lp->d_trkseek);
1237 fprintf(f, _("drivedata: "));
1238 for (i = NDDATA - 1; i >= 0; i--)
1239 if (lp->d_drivedata[i])
1243 for (j = 0; j <= i; j++)
1244 fprintf(f, "%ld ", (long) lp->d_drivedata[j]);
1246 fprintf (f, _("\n%d partitions:\n"), lp->d_npartitions);
1247 fprintf (f, _("# start end size fstype [fsize bsize cpg]\n"));
1248 pp = lp->d_partitions;
1249 for (i = 0; i < lp->d_npartitions; i++, pp++) {
1251 if (display_in_cyl_units && lp->d_secpercyl) {
1252 fprintf(f, " %c: %8ld%c %8ld%c %8ld%c ",
1254 (long) pp->p_offset / lp->d_secpercyl + 1,
1255 (pp->p_offset % lp->d_secpercyl) ? '*' : ' ',
1256 (long) (pp->p_offset + pp->p_size + lp->d_secpercyl - 1)
1258 ((pp->p_offset + pp->p_size) % lp->d_secpercyl) ? '*' : ' ',
1259 (long) pp->p_size / lp->d_secpercyl,
1260 (pp->p_size % lp->d_secpercyl) ? '*' : ' ');
1262 fprintf(f, " %c: %8ld %8ld %8ld ",
1264 (long) pp->p_offset,
1265 (long) pp->p_offset + pp->p_size - 1,
1268 if ((unsigned) pp->p_fstype < BSD_FSMAXTYPES)
1269 fprintf(f, "%8.8s", xbsd_fstypes[pp->p_fstype].name);
1271 fprintf(f, "%8x", pp->p_fstype);
1272 switch (pp->p_fstype) {
1274 fprintf(f, " %5ld %5ld %5.5s ",
1275 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, "");
1279 fprintf(f, " %5ld %5ld %5d ",
1280 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag,
1285 fprintf(f, "%22.22s", "");
1294 xbsd_write_disklabel (void) {
1295 #if defined (__alpha__)
1296 printf (_("Writing disklabel to %s.\n"), disk_device);
1297 xbsd_writelabel (NULL, &xbsd_dlabel);
1299 printf (_("Writing disklabel to %s.\n"),
1300 partname(disk_device, xbsd_part_index+1, 0));
1301 xbsd_writelabel (xbsd_part, &xbsd_dlabel);
1303 reread_partition_table(0); /* no exit yet */
1307 xbsd_create_disklabel (void) {
1310 #if defined (__alpha__)
1311 fprintf (stderr, _("%s contains no disklabel.\n"), disk_device);
1313 fprintf (stderr, _("%s contains no disklabel.\n"),
1314 partname(disk_device, xbsd_part_index+1, 0));
1318 c = read_char (_("Do you want to create a disklabel? (y/n) "));
1319 if (c == 'y' || c == 'Y') {
1320 if (xbsd_initlabel (
1321 #if defined (__alpha__) || defined (__powerpc__) || defined (__hppa__)
1322 NULL, &xbsd_dlabel, 0
1324 xbsd_part, &xbsd_dlabel, xbsd_part_index
1327 xbsd_print_disklabel (1);
1331 } else if (c == 'n')
1337 edit_int (int def, char *mesg)
1340 fputs (mesg, stdout);
1341 printf (" (%d): ", def);
1345 while (!isdigit (*line_ptr));
1346 return atoi (line_ptr);
1350 xbsd_edit_disklabel (void)
1352 struct xbsd_disklabel *d;
1356 #if defined (__alpha__) || defined (__ia64__)
1357 d -> d_secsize = (u_long) edit_int ((u_long) d -> d_secsize ,_("bytes/sector"));
1358 d -> d_nsectors = (u_long) edit_int ((u_long) d -> d_nsectors ,_("sectors/track"));
1359 d -> d_ntracks = (u_long) edit_int ((u_long) d -> d_ntracks ,_("tracks/cylinder"));
1360 d -> d_ncylinders = (u_long) edit_int ((u_long) d -> d_ncylinders ,_("cylinders"));
1363 /* d -> d_secpercyl can be != d -> d_nsectors * d -> d_ntracks */
1366 d -> d_secpercyl = (u_long) edit_int ((u_long) d -> d_nsectors * d -> d_ntracks,
1367 _("sectors/cylinder"));
1368 if (d -> d_secpercyl <= d -> d_nsectors * d -> d_ntracks)
1371 printf (_("Must be <= sectors/track * tracks/cylinder (default).\n"));
1373 d -> d_rpm = (u_short) edit_int ((u_short) d -> d_rpm ,_("rpm"));
1374 d -> d_interleave = (u_short) edit_int ((u_short) d -> d_interleave,_("interleave"));
1375 d -> d_trackskew = (u_short) edit_int ((u_short) d -> d_trackskew ,_("trackskew"));
1376 d -> d_cylskew = (u_short) edit_int ((u_short) d -> d_cylskew ,_("cylinderskew"));
1377 d -> d_headswitch = (u_long) edit_int ((u_long) d -> d_headswitch ,_("headswitch"));
1378 d -> d_trkseek = (u_long) edit_int ((u_long) d -> d_trkseek ,_("track-to-track seek"));
1380 d -> d_secperunit = d -> d_secpercyl * d -> d_ncylinders;
1384 xbsd_get_bootstrap (char *path, void *ptr, int size)
1388 if ((fdb = open (path, O_RDONLY)) < 0)
1393 if (read (fdb, ptr, size) < 0)
1399 printf (" ... %s\n", path);
1407 printf (_("\nSyncing disks.\n"));
1413 xbsd_write_bootstrap (void)
1415 char *bootdir = BSD_LINUX_BOOTDIR;
1416 char path[MAXPATHLEN];
1418 struct xbsd_disklabel dl;
1422 if (xbsd_dlabel.d_type == BSD_DTYPE_SCSI)
1427 printf (_("Bootstrap: %sboot -> boot%s (%s): "),
1428 dkbasename, dkbasename, dkbasename);
1430 line_ptr[strlen (line_ptr)-1] = '\0';
1431 dkbasename = line_ptr;
1433 snprintf (path, sizeof(path), "%s/%sboot", bootdir, dkbasename);
1434 if (!xbsd_get_bootstrap (path, disklabelbuffer, (int) xbsd_dlabel.d_secsize))
1437 /* We need a backup of the disklabel (xbsd_dlabel might have changed). */
1438 d = &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE];
1439 bcopy (d, &dl, sizeof (struct xbsd_disklabel));
1441 /* The disklabel will be overwritten by 0's from bootxx anyway */
1442 bzero (d, sizeof (struct xbsd_disklabel));
1444 snprintf (path, sizeof(path), "%s/boot%s", bootdir, dkbasename);
1445 if (!xbsd_get_bootstrap (path, &disklabelbuffer[xbsd_dlabel.d_secsize],
1446 (int) xbsd_dlabel.d_bbsize - xbsd_dlabel.d_secsize))
1449 e = d + sizeof (struct xbsd_disklabel);
1450 for (p=d; p < e; p++)
1452 fprintf (stderr, _("Bootstrap overlaps with disk label!\n"));
1453 exit ( EXIT_FAILURE );
1456 bcopy (&dl, d, sizeof (struct xbsd_disklabel));
1458 #if defined (__powerpc__) || defined (__hppa__)
1460 #elif defined (__alpha__)
1462 alpha_bootblock_checksum (disklabelbuffer);
1464 sector = get_start_sect(xbsd_part);
1467 if (ext2_llseek (fd, (ext2_loff_t) sector * SECTOR_SIZE, SEEK_SET) == -1)
1468 fdisk_fatal (unable_to_seek);
1469 if (BSD_BBSIZE != write (fd, disklabelbuffer, BSD_BBSIZE))
1470 fdisk_fatal (unable_to_write);
1472 #if defined (__alpha__)
1473 printf (_("Bootstrap installed on %s.\n"), disk_device);
1475 printf (_("Bootstrap installed on %s.\n"),
1476 partname (disk_device, xbsd_part_index+1, 0));
1483 xbsd_change_fstype (void)
1487 i = xbsd_get_part_index (xbsd_dlabel.d_npartitions);
1488 xbsd_dlabel.d_partitions[i].p_fstype = read_hex (xbsd_fstypes);
1492 xbsd_get_part_index (int max)
1497 snprintf (prompt, sizeof(prompt), _("Partition (a-%c): "), 'a' + max - 1);
1499 l = tolower (read_char (prompt));
1500 while (l < 'a' || l > 'a' + max - 1);
1505 xbsd_check_new_partition (int *i) {
1507 /* room for more? various BSD flavours have different maxima */
1508 if (xbsd_dlabel.d_npartitions == BSD_MAXPARTITIONS) {
1511 for (t = 0; t < BSD_MAXPARTITIONS; t++)
1512 if (xbsd_dlabel.d_partitions[t].p_size == 0)
1515 if (t == BSD_MAXPARTITIONS) {
1516 fprintf (stderr, _("The maximum number of partitions "
1517 "has been created\n"));
1522 *i = xbsd_get_part_index (BSD_MAXPARTITIONS);
1524 if (*i >= xbsd_dlabel.d_npartitions)
1525 xbsd_dlabel.d_npartitions = (*i) + 1;
1527 if (xbsd_dlabel.d_partitions[*i].p_size != 0) {
1528 fprintf (stderr, _("This partition already exists.\n"));
1536 xbsd_list_types (void) {
1537 list_types (xbsd_fstypes);
1541 xbsd_dkcksum (struct xbsd_disklabel *lp) {
1542 u_short *start, *end;
1545 start = (u_short *) lp;
1546 end = (u_short *) &lp->d_partitions[lp->d_npartitions];
1553 xbsd_initlabel (struct partition *p, struct xbsd_disklabel *d, int pindex) {
1554 struct xbsd_partition *pp;
1558 bzero (d, sizeof (struct xbsd_disklabel));
1560 d -> d_magic = BSD_DISKMAGIC;
1562 if (strncmp (disk_device, "/dev/sd", 7) == 0)
1563 d -> d_type = BSD_DTYPE_SCSI;
1565 d -> d_type = BSD_DTYPE_ST506;
1567 #if 0 /* not used (at least not written to disk) by NetBSD/i386 1.0 */
1568 d -> d_subtype = BSD_DSTYPE_INDOSPART & pindex;
1571 #if !defined (__alpha__)
1572 d -> d_flags = BSD_D_DOSPART;
1576 d -> d_secsize = SECTOR_SIZE; /* bytes/sector */
1577 d -> d_nsectors = g.sectors; /* sectors/track */
1578 d -> d_ntracks = g.heads; /* tracks/cylinder (heads) */
1579 d -> d_ncylinders = g.cylinders;
1580 d -> d_secpercyl = g.sectors * g.heads;/* sectors/cylinder */
1581 if (d -> d_secpercyl == 0)
1582 d -> d_secpercyl = 1; /* avoid segfaults */
1583 d -> d_secperunit = d -> d_secpercyl * d -> d_ncylinders;
1586 d -> d_interleave = 1;
1587 d -> d_trackskew = 0;
1589 d -> d_headswitch = 0;
1592 d -> d_magic2 = BSD_DISKMAGIC;
1593 d -> d_bbsize = BSD_BBSIZE;
1594 d -> d_sbsize = BSD_SBSIZE;
1596 #if !defined (__alpha__)
1597 d -> d_npartitions = 4;
1598 pp = &d -> d_partitions[2]; /* Partition C should be
1599 the NetBSD partition */
1600 pp -> p_offset = get_start_sect(p);
1601 pp -> p_size = get_nr_sects(p);
1602 pp -> p_fstype = BSD_FS_UNUSED;
1603 pp = &d -> d_partitions[3]; /* Partition D should be
1606 pp -> p_size = d -> d_secperunit;
1607 pp -> p_fstype = BSD_FS_UNUSED;
1608 #elif defined (__alpha__)
1609 d -> d_npartitions = 3;
1610 pp = &d -> d_partitions[2]; /* Partition C should be
1613 pp -> p_size = d -> d_secperunit;
1614 pp -> p_fstype = BSD_FS_UNUSED;
1621 * Read a xbsd_disklabel from sector 0 or from the starting sector of p.
1622 * If it has the right magic, return 1.
1625 xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d)
1629 /* p is used only to get the starting sector */
1630 #if !defined (__alpha__)
1631 sector = (p ? get_start_sect(p) : 0);
1632 #elif defined (__alpha__)
1636 if (ext2_llseek (fd, (ext2_loff_t) sector * SECTOR_SIZE, SEEK_SET) == -1)
1637 fdisk_fatal (unable_to_seek);
1638 if (BSD_BBSIZE != read (fd, disklabelbuffer, BSD_BBSIZE))
1639 fdisk_fatal (unable_to_read);
1641 bcopy (&disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
1642 d, sizeof (struct xbsd_disklabel));
1644 if (d -> d_magic != BSD_DISKMAGIC || d -> d_magic2 != BSD_DISKMAGIC)
1647 for (t = d -> d_npartitions; t < BSD_MAXPARTITIONS; t++) {
1648 d -> d_partitions[t].p_size = 0;
1649 d -> d_partitions[t].p_offset = 0;
1650 d -> d_partitions[t].p_fstype = BSD_FS_UNUSED;
1653 if (d -> d_npartitions > BSD_MAXPARTITIONS)
1654 fprintf (stderr, _("Warning: too many partitions "
1655 "(%d, maximum is %d).\n"),
1656 d -> d_npartitions, BSD_MAXPARTITIONS);
1661 xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d)
1665 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
1666 sector = get_start_sect(p) + BSD_LABELSECTOR;
1668 sector = BSD_LABELSECTOR;
1671 d -> d_checksum = 0;
1672 d -> d_checksum = xbsd_dkcksum (d);
1674 /* This is necessary if we want to write the bootstrap later,
1675 otherwise we'd write the old disklabel with the bootstrap.
1677 bcopy (d, &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
1678 sizeof (struct xbsd_disklabel));
1680 #if defined (__alpha__) && BSD_LABELSECTOR == 0
1681 alpha_bootblock_checksum (disklabelbuffer);
1682 if (ext2_llseek (fd, (ext2_loff_t) 0, SEEK_SET) == -1)
1683 fdisk_fatal (unable_to_seek);
1684 if (BSD_BBSIZE != write (fd, disklabelbuffer, BSD_BBSIZE))
1685 fdisk_fatal (unable_to_write);
1687 if (ext2_llseek (fd, (ext2_loff_t) sector * SECTOR_SIZE + BSD_LABELOFFSET,
1689 fdisk_fatal (unable_to_seek);
1690 if (sizeof (struct xbsd_disklabel) != write (fd, d, sizeof (struct xbsd_disklabel)))
1691 fdisk_fatal (unable_to_write);
1700 #if !defined (__alpha__)
1702 xbsd_translate_fstype (int linux_type)
1706 case 0x01: /* DOS 12-bit FAT */
1707 case 0x04: /* DOS 16-bit <32M */
1708 case 0x06: /* DOS 16-bit >=32M */
1709 case 0xe1: /* DOS access */
1710 case 0xe3: /* DOS R/O */
1711 case 0xf2: /* DOS secondary */
1712 return BSD_FS_MSDOS;
1713 case 0x07: /* OS/2 HPFS */
1716 return BSD_FS_OTHER;
1721 xbsd_link_part (void)
1724 struct partition *p;
1726 k = get_partition (1, partitions);
1728 if (!xbsd_check_new_partition (&i))
1731 p = get_part_table(k);
1733 xbsd_dlabel.d_partitions[i].p_size = get_nr_sects(p);
1734 xbsd_dlabel.d_partitions[i].p_offset = get_start_sect(p);
1735 xbsd_dlabel.d_partitions[i].p_fstype = xbsd_translate_fstype(p->sys_ind);
1739 #if defined (__alpha__)
1741 #if !defined(__GLIBC__)
1742 typedef unsigned long long u_int64_t;
1746 alpha_bootblock_checksum (char *boot)
1751 dp = (u_int64_t *)boot;
1753 for (i = 0; i < 63; i++)
1757 #endif /* __alpha__ */
1759 #endif /* OSF_LABEL */
1761 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
1762 static inline unsigned short
1763 __swap16(unsigned short x) {
1764 return (((__u16)(x) & 0xFF) << 8) | (((__u16)(x) & 0xFF00) >> 8);
1769 return (((__u32)(x) & 0xFF) << 24) | (((__u32)(x) & 0xFF00) << 8) | (((__u32)(x) & 0xFF0000) >> 8) | (((__u32)(x) & 0xFF000000) >> 24);
1773 #ifdef CONFIG_FEATURE_SGI_LABEL
1778 * Copyright (C) Andreas Neuper, Sep 1998.
1779 * This file may be modified and redistributed under
1780 * the terms of the GNU Public License.
1782 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
1783 * Internationalization
1787 static int sgi_other_endian;
1789 static short sgi_volumes=1;
1792 * only dealing with free blocks here
1795 typedef struct { int first; int last; } freeblocks;
1796 static freeblocks freelist[17]; /* 16 partitions can produce 17 vacant slots */
1799 setfreelist( int i, int f, int l ) {
1800 freelist[i].first = f;
1801 freelist[i].last = l;
1805 add2freelist( int f, int l ) {
1807 for( ; i<17 ; i++ ) {
1808 if(freelist[i].last==0) break;
1810 setfreelist( i, f, l );
1814 clearfreelist(void) {
1816 for( ; i<17 ; i++ ) {
1817 setfreelist( i, 0, 0 );
1822 isinfreelist( int b ) {
1824 for( ; i<17 ; i++ ) {
1825 if (freelist[i].first <= b && freelist[i].last >= b) {
1826 return freelist[i].last;
1831 /* return last vacant block of this stride (never 0). */
1832 /* the '>=' is not quite correct, but simplifies the code */
1834 * end of free blocks section
1837 static const struct systypes sgi_sys_types[] = {
1838 /* SGI_VOLHDR */ {"\x00" "SGI volhdr" },
1839 /* 0x01 */ {"\x01" "SGI trkrepl" },
1840 /* 0x02 */ {"\x02" "SGI secrepl" },
1841 /* SGI_SWAP */ {"\x03" "SGI raw" },
1842 /* 0x04 */ {"\x04" "SGI bsd" },
1843 /* 0x05 */ {"\x05" "SGI sysv" },
1844 /* ENTIRE_DISK */ {"\x06" "SGI volume" },
1845 /* SGI_EFS */ {"\x07" "SGI efs" },
1846 /* 0x08 */ {"\x08" "SGI lvol" },
1847 /* 0x09 */ {"\x09" "SGI rlvol" },
1848 /* SGI_XFS */ {"\x0a" "SGI xfs" },
1849 /* SGI_XFSLOG */ {"\x0b" "SGI xfslog" },
1850 /* SGI_XLV */ {"\x0c" "SGI xlv" },
1851 /* SGI_XVM */ {"\x0d" "SGI xvm" },
1852 /* LINUX_SWAP */ {"\x82" "Linux swap" },
1853 /* LINUX_NATIVE */ {"\x83" "Linux native" },
1854 /* LINUX_LVM */ {"\x8d" "Linux LVM" },
1855 /* LINUX_RAID */ {"\xfd" "Linux RAID" },
1861 sgi_get_nsect(void) {
1862 return SGI_SSWAP16(sgilabel->devparam.nsect);
1866 sgi_get_ntrks(void) {
1867 return SGI_SSWAP16(sgilabel->devparam.ntrks);
1871 sgi_get_pcylcount(void) {
1872 return SGI_SSWAP16(sgilabel->devparam.pcylcount);
1877 sgilabel->magic = 0;
1883 two_s_complement_32bit_sum(unsigned int* base, int size /* in bytes */ ) {
1887 size = size / sizeof( unsigned int );
1888 for( i=0; i<size; i++ )
1889 sum = sum - SGI_SSWAP32(base[i]);
1894 check_sgi_label(void) {
1895 if (sizeof(sgilabel) > 512) {
1897 _("According to MIPS Computer Systems, Inc the "
1898 "Label must not contain more than 512 bytes\n"));
1902 if (sgilabel->magic != SGI_LABEL_MAGIC &&
1903 sgilabel->magic != SGI_LABEL_MAGIC_SWAPPED) {
1905 sgi_other_endian = 0;
1909 sgi_other_endian = (sgilabel->magic == SGI_LABEL_MAGIC_SWAPPED);
1911 * test for correct checksum
1913 if( two_s_complement_32bit_sum( (unsigned int*)sgilabel,
1914 sizeof(*sgilabel) ) )
1916 fprintf( stderr, _("Detected sgi disklabel with wrong checksum.\n"));
1919 heads = sgi_get_ntrks();
1920 cylinders = sgi_get_pcylcount();
1921 sectors = sgi_get_nsect();
1931 sgi_get_start_sector( int i ) {
1932 return SGI_SSWAP32(sgilabel->partitions[i].start_sector);
1936 sgi_get_num_sectors( int i ) {
1937 return SGI_SSWAP32(sgilabel->partitions[i].num_sectors);
1941 sgi_get_sysid( int i )
1943 return SGI_SSWAP32(sgilabel->partitions[i].id);
1947 sgi_get_bootpartition(void)
1949 return SGI_SSWAP16(sgilabel->boot_part);
1953 sgi_get_swappartition(void)
1955 return SGI_SSWAP16(sgilabel->swap_part);
1959 sgi_list_table( int xtra ) {
1961 int kpi = 0; /* kernel partition ID */
1964 w = strlen( disk_device );
1967 printf(_("\nDisk %s (SGI disk label): %d heads, %d sectors\n"
1968 "%d cylinders, %d physical cylinders\n"
1969 "%d extra sects/cyl, interleave %d:1\n"
1971 "Units = %s of %d * 512 bytes\n\n"),
1972 disk_device, heads, sectors, cylinders,
1973 SGI_SSWAP16(sgiparam.pcylcount),
1974 SGI_SSWAP16(sgiparam.sparecyl),
1975 SGI_SSWAP16(sgiparam.ilfact),
1977 str_units(PLURAL), units_per_sector);
1979 printf( _("\nDisk %s (SGI disk label): "
1980 "%d heads, %d sectors, %d cylinders\n"
1981 "Units = %s of %d * 512 bytes\n\n"),
1982 disk_device, heads, sectors, cylinders,
1983 str_units(PLURAL), units_per_sector );
1985 printf(_("----- partitions -----\n"
1986 "Pt# %*s Info Start End Sectors Id System\n"),
1987 w + 1, _("Device"));
1988 for (i = 0 ; i < partitions; i++) {
1989 if( sgi_get_num_sectors(i) || debug ) {
1990 __u32 start = sgi_get_start_sector(i);
1991 __u32 len = sgi_get_num_sectors(i);
1992 kpi++; /* only count nonempty partitions */
1994 "%2d: %s %4s %9ld %9ld %9ld %2x %s\n",
1995 /* fdisk part number */ i+1,
1996 /* device */ partname(disk_device, kpi, w+2),
1997 /* flags */ (sgi_get_swappartition() == i) ? "swap" :
1998 /* flags */ (sgi_get_bootpartition() == i) ? "boot" : " ",
1999 /* start */ (long) scround(start),
2000 /* end */ (long) scround(start+len)-1,
2001 /* no odd flag on end */ (long) len,
2002 /* type id */ sgi_get_sysid(i),
2003 /* type name */ (type = partition_type(sgi_get_sysid(i)))
2004 ? type : _("Unknown"));
2007 printf(_("----- Bootinfo -----\nBootfile: %s\n"
2008 "----- Directory Entries -----\n"),
2009 sgilabel->boot_file );
2010 for (i = 0 ; i < sgi_volumes; i++)
2012 if (sgilabel->directory[i].vol_file_size)
2014 __u32 start = SGI_SSWAP32(sgilabel->directory[i].vol_file_start);
2015 __u32 len = SGI_SSWAP32(sgilabel->directory[i].vol_file_size);
2016 char*name = sgilabel->directory[i].vol_file_name;
2017 printf(_("%2d: %-10s sector%5u size%8u\n"),
2018 i, name, (unsigned int) start, (unsigned int) len);
2024 sgi_set_bootpartition( int i )
2026 sgilabel->boot_part = SGI_SSWAP16(((short)i));
2030 sgi_get_lastblock(void) {
2031 return heads * sectors * cylinders;
2035 sgi_set_swappartition( int i ) {
2036 sgilabel->swap_part = SGI_SSWAP16(((short)i));
2040 sgi_check_bootfile( const char* aFile ) {
2041 if( strlen( aFile ) < 3 ) /* "/a\n" is minimum */
2043 printf( _("\nInvalid Bootfile!\n"
2044 "\tThe bootfile must be an absolute non-zero pathname,\n"
2045 "\te.g. \"/unix\" or \"/unix.save\".\n") );
2048 if( strlen( aFile ) > 16 )
2050 printf( _("\n\tName of Bootfile too long: 16 bytes maximum.\n") );
2053 if( aFile[0] != '/' )
2055 printf( _("\n\tBootfile must have a fully qualified pathname.\n") );
2058 if( strncmp( aFile, sgilabel->boot_file, 16 ) )
2060 printf( _("\n\tBe aware, that the bootfile is not checked for existence.\n\t"
2061 "SGI's default is \"/unix\" and for backup \"/unix.save\".\n") );
2062 /* filename is correct and did change */
2065 return 0; /* filename did not change */
2069 sgi_get_bootfile(void) {
2070 return sgilabel->boot_file;
2074 sgi_set_bootfile( const char* aFile )
2077 if( sgi_check_bootfile( aFile ) )
2081 if( (aFile[i] != '\n') /* in principle caught again by next line */
2082 && (strlen( aFile ) > i ) )
2083 sgilabel->boot_file[i] = aFile[i];
2085 sgilabel->boot_file[i] = 0;
2088 printf( _("\n\tBootfile is changed to \"%s\".\n"), sgilabel->boot_file );
2093 create_sgiinfo(void)
2095 /* I keep SGI's habit to write the sgilabel to the second block */
2096 sgilabel->directory[0].vol_file_start = SGI_SSWAP32( 2 );
2097 sgilabel->directory[0].vol_file_size = SGI_SSWAP32( sizeof( sgiinfo ) );
2098 strncpy( sgilabel->directory[0].vol_file_name, "sgilabel", 8 );
2101 static sgiinfo * fill_sgiinfo(void);
2104 sgi_write_table(void)
2107 sgilabel->csum = SGI_SSWAP32( two_s_complement_32bit_sum(
2108 (unsigned int*)sgilabel,
2109 sizeof(*sgilabel) ) );
2110 assert( two_s_complement_32bit_sum(
2111 (unsigned int*)sgilabel, sizeof(*sgilabel) ) == 0 );
2112 if( lseek(fd, 0, SEEK_SET) < 0 )
2113 fdisk_fatal(unable_to_seek);
2114 if( write(fd, sgilabel, SECTOR_SIZE) != SECTOR_SIZE )
2115 fdisk_fatal(unable_to_write);
2116 if( ! strncmp( sgilabel->directory[0].vol_file_name, "sgilabel",8 ) )
2119 * keep this habbit of first writing the "sgilabel".
2120 * I never tested whether it works without (AN 981002).
2122 sgiinfo*info = fill_sgiinfo(); /* fills the block appropriately */
2123 int infostartblock = SGI_SSWAP32( sgilabel->directory[0].vol_file_start );
2124 if( ext2_llseek(fd, (ext2_loff_t)infostartblock*
2125 SECTOR_SIZE, SEEK_SET) < 0 )
2126 fdisk_fatal(unable_to_seek);
2127 if( write(fd, info, SECTOR_SIZE) != SECTOR_SIZE )
2128 fdisk_fatal(unable_to_write);
2134 compare_start( int *x, int *y ) {
2136 * sort according to start sectors
2137 * and prefers largest partition:
2138 * entry zero is entire disk entry
2142 int a = sgi_get_start_sector(i);
2143 int b = sgi_get_start_sector(j);
2144 int c = sgi_get_num_sectors(i);
2145 int d = sgi_get_num_sectors(j);
2155 verify_sgi( int verbose )
2157 int Index[16]; /* list of valid partitions */
2158 int sortcount = 0; /* number of used partitions, i.e. non-zero lengths */
2159 int entire = 0, i = 0; /* local counters */
2161 int gap = 0; /* count unused blocks */
2162 int lastblock = sgi_get_lastblock();
2166 for( i=0; i<16; i++ )
2168 if( sgi_get_num_sectors(i)!=0 )
2170 Index[sortcount++]=i;
2171 if( sgi_get_sysid(i) == ENTIRE_DISK )
2176 printf(_("More than one entire disk entry present.\n"));
2181 if( sortcount == 0 )
2184 printf(_("No partitions defined\n"));
2187 qsort( Index, sortcount, sizeof(Index[0]), (void*)compare_start );
2188 if( sgi_get_sysid( Index[0] ) == ENTIRE_DISK )
2190 if( ( Index[0] != 10 ) && verbose )
2191 printf( _("IRIX likes when Partition 11 covers the entire disk.\n") );
2192 if( ( sgi_get_start_sector( Index[0] ) != 0 ) && verbose )
2193 printf( _("The entire disk partition should start at block 0,\nnot "
2194 "at diskblock %d.\n"), sgi_get_start_sector(Index[0] ) );
2195 if(debug) /* I do not understand how some disks fulfil it */
2196 if( ( sgi_get_num_sectors( Index[0] ) != lastblock ) && verbose )
2197 printf( _("The entire disk partition is only %d diskblock large,\n"
2198 "but the disk is %d diskblocks long.\n"),
2199 sgi_get_num_sectors( Index[0] ), lastblock );
2200 lastblock = sgi_get_num_sectors( Index[0] );
2204 printf( _("One Partition (#11) should cover the entire disk.\n") );
2206 printf( "sysid=%d\tpartition=%d\n",
2207 sgi_get_sysid( Index[0] ), Index[0]+1 );
2209 for( i=1, start=0; i<sortcount; i++ )
2211 int cylsize = sgi_get_nsect() * sgi_get_ntrks();
2212 if( (sgi_get_start_sector( Index[i] ) % cylsize) != 0 )
2214 if(debug) /* I do not understand how some disks fulfil it */
2216 printf( _("Partition %d does not start on cylinder boundary.\n"),
2219 if( sgi_get_num_sectors( Index[i] ) % cylsize != 0 )
2221 if(debug) /* I do not understand how some disks fulfil it */
2223 printf( _("Partition %d does not end on cylinder boundary.\n"),
2226 /* We cannot handle several "entire disk" entries. */
2227 if( sgi_get_sysid( Index[i] ) == ENTIRE_DISK ) continue;
2228 if( start > sgi_get_start_sector( Index[i] ) )
2231 printf( _("The Partition %d and %d overlap by %d sectors.\n"),
2232 Index[i-1]+1, Index[i]+1,
2233 start - sgi_get_start_sector( Index[i] ) );
2234 if( gap > 0 ) gap = -gap;
2235 if( gap == 0 ) gap = -1;
2237 if( start < sgi_get_start_sector( Index[i] ) )
2240 printf( _("Unused gap of %8d sectors - sectors %8d-%d\n"),
2241 sgi_get_start_sector( Index[i] ) - start,
2242 start, sgi_get_start_sector( Index[i] )-1 );
2243 gap += sgi_get_start_sector( Index[i] ) - start;
2244 add2freelist( start, sgi_get_start_sector( Index[i] ) );
2246 start = sgi_get_start_sector( Index[i] )
2247 + sgi_get_num_sectors( Index[i] );
2251 printf( "%2d:%12d\t%12d\t%12d\n", Index[i],
2252 sgi_get_start_sector(Index[i]),
2253 sgi_get_num_sectors(Index[i]),
2254 sgi_get_sysid(Index[i]) );
2257 if( ( start < lastblock ) )
2260 printf( _("Unused gap of %8d sectors - sectors %8d-%d\n"),
2261 lastblock - start, start, lastblock-1 );
2262 gap += lastblock - start;
2263 add2freelist( start, lastblock );
2266 * Done with arithmetics
2267 * Go for details now
2271 if( !sgi_get_num_sectors( sgi_get_bootpartition() ) )
2273 printf( _("\nThe boot partition does not exist.\n") );
2275 if( !sgi_get_num_sectors( sgi_get_swappartition() ) )
2277 printf( _("\nThe swap partition does not exist.\n") );
2279 if( ( sgi_get_sysid( sgi_get_swappartition() ) != SGI_SWAP )
2280 && ( sgi_get_sysid( sgi_get_swappartition() ) != LINUX_SWAP ) )
2282 printf( _("\nThe swap partition has no swap type.\n") );
2284 if( sgi_check_bootfile( "/unix" ) )
2286 printf( _("\tYou have chosen an unusual boot file name.\n") );
2295 * returned value is:
2296 * = 0 : disk is properly filled to the rim
2297 * < 0 : there is an overlap
2298 * > 0 : there is still some vacant space
2300 return verify_sgi(0);
2304 sgi_change_sysid( int i, int sys )
2306 if( sgi_get_num_sectors(i) == 0 ) /* caught already before, ... */
2308 printf(_("Sorry You may change the Tag of non-empty partitions.\n"));
2311 if( ((sys != ENTIRE_DISK ) && (sys != SGI_VOLHDR))
2312 && (sgi_get_start_sector(i)<1) )
2315 _("It is highly recommended that the partition at offset 0\n"
2316 "is of type \"SGI volhdr\", the IRIX system will rely on it to\n"
2317 "retrieve from its directory standalone tools like sash and fx.\n"
2318 "Only the \"SGI volume\" entire disk section may violate this.\n"
2319 "Type YES if you are sure about tagging this partition differently.\n"));
2320 if (strcmp (line_ptr, _("YES\n")))
2323 sgilabel->partitions[i].id = SGI_SSWAP32(sys);
2326 /* returns partition index of first entry marked as entire disk */
2330 for( i=0; i<16; i++ )
2331 if( sgi_get_sysid(i) == SGI_VOLUME )
2337 sgi_set_partition( int i, uint start, uint length, int sys ) {
2338 sgilabel->partitions[i].id =
2340 sgilabel->partitions[i].num_sectors =
2341 SGI_SSWAP32( length );
2342 sgilabel->partitions[i].start_sector =
2343 SGI_SSWAP32( start );
2345 if( sgi_gaps() < 0 ) /* rebuild freelist */
2346 printf(_("Do You know, You got a partition overlap on the disk?\n"));
2350 sgi_set_entire(void) {
2352 for( n=10; n<partitions; n++ ) {
2353 if(!sgi_get_num_sectors( n ) ) {
2354 sgi_set_partition( n, 0, sgi_get_lastblock(), SGI_VOLUME );
2361 sgi_set_volhdr(void)
2364 for( n=8; n<partitions; n++ )
2366 if(!sgi_get_num_sectors( n ) )
2369 * 5 cylinders is an arbitrary value I like
2370 * IRIX 5.3 stored files in the volume header
2371 * (like sash, symmon, fx, ide) with ca. 3200
2374 if( heads * sectors * 5 < sgi_get_lastblock() )
2375 sgi_set_partition( n, 0, heads * sectors * 5, SGI_VOLHDR );
2382 sgi_delete_partition( int i )
2384 sgi_set_partition( i, 0, 0, 0 );
2388 sgi_add_partition( int n, int sys )
2391 int first=0, last=0;
2395 } else if ( n == 8 ) {
2398 if( sgi_get_num_sectors(n) )
2400 printf(_("Partition %d is already defined. Delete "
2401 "it before re-adding it.\n"), n + 1);
2404 if( (sgi_entire() == -1)
2405 && (sys != SGI_VOLUME) )
2407 printf(_("Attempting to generate entire disk entry automatically.\n"));
2411 if( (sgi_gaps() == 0)
2412 && (sys != SGI_VOLUME) )
2414 printf(_("The entire disk is already covered with partitions.\n"));
2417 if( sgi_gaps() < 0 )
2419 printf(_("You got a partition overlap on the disk. Fix it first!\n"));
2422 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
2424 if(sys == SGI_VOLUME) {
2425 last = sgi_get_lastblock();
2426 first = read_int(0, 0, last-1, 0, mesg);
2428 printf(_("It is highly recommended that eleventh partition\n"
2429 "covers the entire disk and is of type `SGI volume'\n"));
2432 first = freelist[0].first;
2433 last = freelist[0].last;
2434 first = read_int(scround(first), scround(first), scround(last)-1,
2437 if (display_in_cyl_units)
2438 first *= units_per_sector;
2440 first = first; /* align to cylinder if you know how ... */
2442 last = isinfreelist(first);
2444 printf(_("You will get a partition overlap on the disk. "
2445 "Fix it first!\n"));
2449 snprintf(mesg, sizeof(mesg), _(" Last %s"), str_units(SINGULAR));
2450 last = read_int(scround(first), scround(last)-1, scround(last)-1,
2451 scround(first), mesg)+1;
2452 if (display_in_cyl_units)
2453 last *= units_per_sector;
2455 last = last; /* align to cylinder if You know how ... */
2456 if( (sys == SGI_VOLUME) && ( first != 0 || last != sgi_get_lastblock() ) )
2457 printf(_("It is highly recommended that eleventh partition\n"
2458 "covers the entire disk and is of type `SGI volume'\n"));
2459 sgi_set_partition( n, first, last-first, sys );
2463 create_sgilabel(void)
2465 struct hd_geometry geometry;
2468 int sysid; } old[4];
2471 _("Building a new SGI disklabel. Changes will remain in memory only,\n"
2472 "until you decide to write them. After that, of course, the previous\n"
2473 "content will be unrecoverably lost.\n\n"));
2475 sgi_other_endian = (BYTE_ORDER == LITTLE_ENDIAN);
2478 if (!ioctl(fd, HDIO_REQ, &geometry))
2480 if (!ioctl(fd, HDIO_GETGEO, &geometry))
2483 heads = geometry.heads;
2484 sectors = geometry.sectors;
2485 cylinders = geometry.cylinders;
2487 for (i = 0; i < 4; i++)
2490 if( valid_part_table_flag(MBRbuffer) )
2492 if( get_part_table(i)->sys_ind )
2494 old[i].sysid = get_part_table(i)->sys_ind;
2495 old[i].start = get_start_sect( get_part_table(i) );
2496 old[i].nsect = get_nr_sects( get_part_table(i) );
2497 printf( _("Trying to keep parameters of partition %d.\n"), i );
2499 printf( _("ID=%02x\tSTART=%d\tLENGTH=%d\n"),
2500 old[i].sysid, old[i].start, old[i].nsect );
2504 memset(MBRbuffer, 0, sizeof(MBRbuffer));
2505 sgilabel->magic = SGI_SSWAP32(SGI_LABEL_MAGIC);
2506 sgilabel->boot_part = SGI_SSWAP16(0);
2507 sgilabel->swap_part = SGI_SSWAP16(1);
2509 /* sizeof(sgilabel->boot_file) = 16 > 6 */
2510 memset(sgilabel->boot_file, 0, 16);
2511 strcpy(sgilabel->boot_file, "/unix");
2513 sgilabel->devparam.skew = (0);
2514 sgilabel->devparam.gap1 = (0);
2515 sgilabel->devparam.gap2 = (0);
2516 sgilabel->devparam.sparecyl = (0);
2517 sgilabel->devparam.pcylcount = SGI_SSWAP16(geometry.cylinders);
2518 sgilabel->devparam.head_vol0 = SGI_SSWAP16(0);
2519 sgilabel->devparam.ntrks = SGI_SSWAP16(geometry.heads);
2520 /* tracks/cylinder (heads) */
2521 sgilabel->devparam.cmd_tag_queue_depth = (0);
2522 sgilabel->devparam.unused0 = (0);
2523 sgilabel->devparam.unused1 = SGI_SSWAP16(0);
2524 sgilabel->devparam.nsect = SGI_SSWAP16(geometry.sectors);
2526 sgilabel->devparam.bytes = SGI_SSWAP16(512);
2527 sgilabel->devparam.ilfact = SGI_SSWAP16(1);
2528 sgilabel->devparam.flags = SGI_SSWAP32(TRACK_FWD|
2529 IGNORE_ERRORS|RESEEK);
2530 sgilabel->devparam.datarate = SGI_SSWAP32(0);
2531 sgilabel->devparam.retries_on_error = SGI_SSWAP32(1);
2532 sgilabel->devparam.ms_per_word = SGI_SSWAP32(0);
2533 sgilabel->devparam.xylogics_gap1 = SGI_SSWAP16(0);
2534 sgilabel->devparam.xylogics_syncdelay = SGI_SSWAP16(0);
2535 sgilabel->devparam.xylogics_readdelay = SGI_SSWAP16(0);
2536 sgilabel->devparam.xylogics_gap2 = SGI_SSWAP16(0);
2537 sgilabel->devparam.xylogics_readgate = SGI_SSWAP16(0);
2538 sgilabel->devparam.xylogics_writecont = SGI_SSWAP16(0);
2539 memset( &(sgilabel->directory), 0, sizeof(struct volume_directory)*15 );
2540 memset( &(sgilabel->partitions), 0, sizeof(struct sgi_partition)*16 );
2546 for (i = 0; i < 4; i++)
2550 sgi_set_partition( i, old[i].start, old[i].nsect, old[i].sysid );
2558 /* do nothing in the beginning */
2561 /* _____________________________________________________________
2567 sgiinfo*info=calloc( 1, sizeof(sgiinfo) );
2568 info->magic=SGI_SSWAP32(SGI_INFO_MAGIC);
2569 info->b1=SGI_SSWAP32(-1);
2570 info->b2=SGI_SSWAP16(-1);
2571 info->b3=SGI_SSWAP16(1);
2572 /* You may want to replace this string !!!!!!! */
2573 strcpy( info->scsi_string, "IBM OEM 0662S12 3 30" );
2574 strcpy( info->serial, "0000" );
2575 info->check1816 = SGI_SSWAP16(18*256 +16 );
2576 strcpy( info->installer, "Sfx version 5.3, Oct 18, 1994" );
2579 #endif /* SGI_LABEL */
2582 #ifdef CONFIG_FEATURE_SUN_LABEL
2586 * I think this is mostly, or entirely, due to
2587 * Jakub Jelinek (jj@sunsite.mff.cuni.cz), July 1996
2589 * Merged with fdisk for other architectures, aeb, June 1998.
2591 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
2592 * Internationalization
2596 static int sun_other_endian;
2597 static int scsi_disk;
2601 #define IDE0_MAJOR 3
2604 #define IDE1_MAJOR 22
2606 static void guess_device_type(void) {
2607 struct stat bootstat;
2609 if (fstat (fd, &bootstat) < 0) {
2612 } else if (S_ISBLK(bootstat.st_mode)
2613 && ((bootstat.st_rdev >> 8) == IDE0_MAJOR ||
2614 (bootstat.st_rdev >> 8) == IDE1_MAJOR)) {
2617 } else if (S_ISBLK(bootstat.st_mode)
2618 && (bootstat.st_rdev >> 8) == FLOPPY_MAJOR) {
2627 static const struct systypes sun_sys_types[] = {
2628 /* 0 */ {"\x00" "Empty" },
2629 /* 1 */ {"\x01" "Boot" },
2630 /* 2 */ {"\x02" "SunOS root" },
2631 /* SUNOS_SWAP */ {"\x03" "SunOS swap" },
2632 /* 4 */ {"\x04" "SunOS usr" },
2633 /* WHOLE_DISK */ {"\x05" "Whole disk" },
2634 /* 6 */ {"\x06" "SunOS stand" },
2635 /* 7 */ {"\x07" "SunOS var" },
2636 /* 8 */ {"\x08" "SunOS home" },
2637 /* LINUX_SWAP */ {"\x82" "Linux swap" },
2638 /* LINUX_NATIVE */ {"\x83" "Linux native" },
2639 /* 0x8e */ {"\x8e" "Linux LVM" },
2640 /* New (2.2.x) raid partition with autodetect using persistent superblock */
2641 /* 0xfd */ {"\xfd" "Linux raid autodetect" },
2647 set_sun_partition(int i, uint start, uint stop, int sysid) {
2648 sunlabel->infos[i].id = sysid;
2649 sunlabel->partitions[i].start_cylinder =
2650 SUN_SSWAP32(start / (heads * sectors));
2651 sunlabel->partitions[i].num_sectors =
2652 SUN_SSWAP32(stop - start);
2659 sunlabel->magic = 0;
2664 check_sun_label(void) {
2665 unsigned short *ush;
2668 if (sunlabel->magic != SUN_LABEL_MAGIC &&
2669 sunlabel->magic != SUN_LABEL_MAGIC_SWAPPED) {
2671 sun_other_endian = 0;
2674 sun_other_endian = (sunlabel->magic == SUN_LABEL_MAGIC_SWAPPED);
2675 ush = ((unsigned short *) (sunlabel + 1)) - 1;
2676 for (csum = 0; ush >= (unsigned short *)sunlabel;) csum ^= *ush--;
2678 fprintf(stderr,_("Detected sun disklabel with wrong checksum.\n"
2679 "Probably you'll have to set all the values,\n"
2680 "e.g. heads, sectors, cylinders and partitions\n"
2681 "or force a fresh label (s command in main menu)\n"));
2683 heads = SUN_SSWAP16(sunlabel->ntrks);
2684 cylinders = SUN_SSWAP16(sunlabel->ncyl);
2685 sectors = SUN_SSWAP16(sunlabel->nsect);
2693 static const struct sun_predefined_drives {
2696 unsigned short sparecyl;
2697 unsigned short ncyl;
2698 unsigned short nacyl;
2699 unsigned short pcylcount;
2700 unsigned short ntrks;
2701 unsigned short nsect;
2702 unsigned short rspeed;
2704 {"Quantum","ProDrive 80S",1,832,2,834,6,34,3662},
2705 {"Quantum","ProDrive 105S",1,974,2,1019,6,35,3662},
2706 {"CDC","Wren IV 94171-344",3,1545,2,1549,9,46,3600},
2707 {"IBM","DPES-31080",0,4901,2,4903,4,108,5400},
2708 {"IBM","DORS-32160",0,1015,2,1017,67,62,5400},
2709 {"IBM","DNES-318350",0,11199,2,11474,10,320,7200},
2710 {"SEAGATE","ST34371",0,3880,2,3882,16,135,7228},
2711 {"","SUN0104",1,974,2,1019,6,35,3662},
2712 {"","SUN0207",4,1254,2,1272,9,36,3600},
2713 {"","SUN0327",3,1545,2,1549,9,46,3600},
2714 {"","SUN0340",0,1538,2,1544,6,72,4200},
2715 {"","SUN0424",2,1151,2,2500,9,80,4400},
2716 {"","SUN0535",0,1866,2,2500,7,80,5400},
2717 {"","SUN0669",5,1614,2,1632,15,54,3600},
2718 {"","SUN1.0G",5,1703,2,1931,15,80,3597},
2719 {"","SUN1.05",0,2036,2,2038,14,72,5400},
2720 {"","SUN1.3G",6,1965,2,3500,17,80,5400},
2721 {"","SUN2.1G",0,2733,2,3500,19,80,5400},
2722 {"IOMEGA","Jaz",0,1019,2,1021,64,32,5394},
2725 static const struct sun_predefined_drives *
2726 sun_autoconfigure_scsi(void) {
2727 const struct sun_predefined_drives *p = NULL;
2729 #ifdef SCSI_IOCTL_GET_IDLUN
2739 if (!ioctl(fd, SCSI_IOCTL_GET_IDLUN, &id)) {
2741 "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n",
2743 ((id[0]>>24)&0xff)-/*PROC_SCSI_SCSI+PROC_SCSI_FILE*/33,
2745 /* This is very wrong (works only if you have one HBA),
2746 but I haven't found a way how to get hostno
2747 from the current kernel */
2753 pfd = fopen("/proc/scsi/scsi","r");
2755 while (fgets(buffer2,2048,pfd)) {
2756 if (!strcmp(buffer, buffer2)) {
2757 if (fgets(buffer2,2048,pfd)) {
2758 q = strstr(buffer2,"Vendor: ");
2763 *q++ = 0; /* truncate vendor name */
2764 q = strstr(q,"Model: ");
2769 q = strstr(q," Rev: ");
2772 for (i = 0; i < SIZE(sun_drives); i++) {
2773 if (*sun_drives[i].vendor && strcasecmp(sun_drives[i].vendor, vendor))
2775 if (!strstr(model, sun_drives[i].model))
2777 printf(_("Autoconfigure found a %s%s%s\n"),sun_drives[i].vendor,(*sun_drives[i].vendor) ? " " : "",sun_drives[i].model);
2795 static void create_sunlabel(void)
2797 struct hd_geometry geometry;
2801 const struct sun_predefined_drives *p = NULL;
2804 _("Building a new sun disklabel. Changes will remain in memory only,\n"
2805 "until you decide to write them. After that, of course, the previous\n"
2806 "content won't be recoverable.\n\n"));
2807 #if BYTE_ORDER == LITTLE_ENDIAN
2808 sun_other_endian = 1;
2810 sun_other_endian = 0;
2812 memset(MBRbuffer, 0, sizeof(MBRbuffer));
2813 sunlabel->magic = SUN_SSWAP16(SUN_LABEL_MAGIC);
2815 puts(_("Drive type\n"
2816 " ? auto configure\n"
2817 " 0 custom (with hardware detected defaults)"));
2818 for (i = 0; i < SIZE(sun_drives); i++) {
2819 printf(" %c %s%s%s\n",
2820 i + 'a', sun_drives[i].vendor,
2821 (*sun_drives[i].vendor) ? " " : "",
2822 sun_drives[i].model);
2825 c = read_char(_("Select type (? for auto, 0 for custom): "));
2826 if (c >= 'a' && c < 'a' + SIZE(sun_drives)) {
2827 p = sun_drives + c - 'a';
2829 } else if (c >= 'A' && c < 'A' + SIZE(sun_drives)) {
2830 p = sun_drives + c - 'A';
2832 } else if (c == '0') {
2834 } else if (c == '?' && scsi_disk) {
2835 p = sun_autoconfigure_scsi();
2837 printf(_("Autoconfigure failed.\n"));
2845 if (!ioctl(fd, HDIO_REQ, &geometry)) {
2847 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
2849 heads = geometry.heads;
2850 sectors = geometry.sectors;
2851 cylinders = geometry.cylinders;
2858 sunlabel->nacyl = 0;
2859 sunlabel->pcylcount = SUN_SSWAP16(cylinders);
2860 sunlabel->rspeed = SUN_SSWAP16(300);
2861 sunlabel->ilfact = SUN_SSWAP16(1);
2862 sunlabel->sparecyl = 0;
2864 heads = read_int(1,heads,1024,0,_("Heads"));
2865 sectors = read_int(1,sectors,1024,0,_("Sectors/track"));
2867 cylinders = read_int(1,cylinders-2,65535,0,_("Cylinders"));
2869 cylinders = read_int(1,0,65535,0,_("Cylinders"));
2871 SUN_SSWAP16(read_int(0,2,65535,0,
2872 _("Alternate cylinders")));
2873 sunlabel->pcylcount =
2874 SUN_SSWAP16(read_int(0,cylinders+SUN_SSWAP16(sunlabel->nacyl),
2875 65535,0,_("Physical cylinders")));
2877 SUN_SSWAP16(read_int(1,5400,100000,0,
2878 _("Rotation speed (rpm)")));
2880 SUN_SSWAP16(read_int(1,1,32,0,_("Interleave factor")));
2881 sunlabel->sparecyl =
2882 SUN_SSWAP16(read_int(0,0,sectors,0,
2883 _("Extra sectors per cylinder")));
2886 sunlabel->sparecyl = SUN_SSWAP16(p->sparecyl);
2887 sunlabel->ncyl = SUN_SSWAP16(p->ncyl);
2888 sunlabel->nacyl = SUN_SSWAP16(p->nacyl);
2889 sunlabel->pcylcount = SUN_SSWAP16(p->pcylcount);
2890 sunlabel->ntrks = SUN_SSWAP16(p->ntrks);
2891 sunlabel->nsect = SUN_SSWAP16(p->nsect);
2892 sunlabel->rspeed = SUN_SSWAP16(p->rspeed);
2893 sunlabel->ilfact = SUN_SSWAP16(1);
2894 cylinders = p->ncyl;
2897 puts(_("You may change all the disk params from the x menu"));
2900 snprintf(sunlabel->info, sizeof(sunlabel->info),
2901 "%s%s%s cyl %d alt %d hd %d sec %d",
2902 p ? p->vendor : "", (p && *p->vendor) ? " " : "",
2904 : (floppy ? _("3,5\" floppy") : _("Linux custom")),
2905 cylinders, SUN_SSWAP16(sunlabel->nacyl), heads, sectors);
2907 sunlabel->ntrks = SUN_SSWAP16(heads);
2908 sunlabel->nsect = SUN_SSWAP16(sectors);
2909 sunlabel->ncyl = SUN_SSWAP16(cylinders);
2911 set_sun_partition(0, 0, cylinders * heads * sectors, LINUX_NATIVE);
2913 if (cylinders * heads * sectors >= 150 * 2048) {
2914 ndiv = cylinders - (50 * 2048 / (heads * sectors)); /* 50M swap */
2916 ndiv = cylinders * 2 / 3;
2917 set_sun_partition(0, 0, ndiv * heads * sectors, LINUX_NATIVE);
2918 set_sun_partition(1, ndiv * heads * sectors, cylinders * heads * sectors, LINUX_SWAP);
2919 sunlabel->infos[1].flags |= 0x01; /* Not mountable */
2921 set_sun_partition(2, 0, cylinders * heads * sectors, WHOLE_DISK);
2923 unsigned short *ush = (unsigned short *)sunlabel;
2924 unsigned short csum = 0;
2925 while(ush < (unsigned short *)(&sunlabel->csum))
2927 sunlabel->csum = csum;
2930 set_all_unchanged();
2932 get_boot(create_empty_sun);
2936 toggle_sunflags(int i, unsigned char mask) {
2937 if (sunlabel->infos[i].flags & mask)
2938 sunlabel->infos[i].flags &= ~mask;
2939 else sunlabel->infos[i].flags |= mask;
2944 fetch_sun(uint *starts, uint *lens, uint *start, uint *stop) {
2945 int i, continuous = 1;
2946 *start = 0; *stop = cylinders * heads * sectors;
2947 for (i = 0; i < partitions; i++) {
2948 if (sunlabel->partitions[i].num_sectors
2949 && sunlabel->infos[i].id
2950 && sunlabel->infos[i].id != WHOLE_DISK) {
2951 starts[i] = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
2952 lens[i] = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
2954 if (starts[i] == *start)
2956 else if (starts[i] + lens[i] >= *stop)
2960 /* There will be probably more gaps
2961 than one, so lets check afterwards */
2970 static uint *verify_sun_starts;
2973 verify_sun_cmp(int *a, int *b) {
2974 if (*a == -1) return 1;
2975 if (*b == -1) return -1;
2976 if (verify_sun_starts[*a] > verify_sun_starts[*b]) return 1;
2982 uint starts[8], lens[8], start, stop;
2983 int i,j,k,starto,endo;
2986 verify_sun_starts = starts;
2987 fetch_sun(starts,lens,&start,&stop);
2988 for (k = 0; k < 7; k++) {
2989 for (i = 0; i < 8; i++) {
2990 if (k && (lens[i] % (heads * sectors))) {
2991 printf(_("Partition %d doesn't end on cylinder boundary\n"), i+1);
2994 for (j = 0; j < i; j++)
2996 if (starts[j] == starts[i]+lens[i]) {
2997 starts[j] = starts[i]; lens[j] += lens[i];
2999 } else if (starts[i] == starts[j]+lens[j]){
3003 if (starts[i] < starts[j]+lens[j] &&
3004 starts[j] < starts[i]+lens[i]) {
3006 if (starts[j] > starto)
3008 endo = starts[i]+lens[i];
3009 if (starts[j]+lens[j] < endo)
3010 endo = starts[j]+lens[j];
3011 printf(_("Partition %d overlaps with others in "
3012 "sectors %d-%d\n"), i+1, starto, endo);
3019 for (i = 0; i < 8; i++) {
3025 qsort(array,SIZE(array),sizeof(array[0]),
3026 (int (*)(const void *,const void *)) verify_sun_cmp);
3027 if (array[0] == -1) {
3028 printf(_("No partitions defined\n"));
3031 stop = cylinders * heads * sectors;
3032 if (starts[array[0]])
3033 printf(_("Unused gap - sectors 0-%d\n"),starts[array[0]]);
3034 for (i = 0; i < 7 && array[i+1] != -1; i++) {
3035 printf(_("Unused gap - sectors %d-%d\n"),starts[array[i]]+lens[array[i]],starts[array[i+1]]);
3037 start = starts[array[i]]+lens[array[i]];
3039 printf(_("Unused gap - sectors %d-%d\n"),start,stop);
3043 add_sun_partition(int n, int sys) {
3044 uint start, stop, stop2;
3045 uint starts[8], lens[8];
3051 if (sunlabel->partitions[n].num_sectors && sunlabel->infos[n].id) {
3052 printf(_("Partition %d is already defined. Delete "
3053 "it before re-adding it.\n"), n + 1);
3057 fetch_sun(starts,lens,&start,&stop);
3058 if (stop <= start) {
3062 printf(_("Other partitions already cover the whole disk.\nDelete "
3063 "some/shrink them before retry.\n"));
3067 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
3070 first = read_int(0, 0, 0, 0, mesg);
3072 first = read_int(scround(start), scround(stop)+1,
3073 scround(stop), 0, mesg);
3074 if (display_in_cyl_units)
3075 first *= units_per_sector;
3077 /* Starting sector has to be properly aligned */
3078 first = (first + heads * sectors - 1) / (heads * sectors);
3079 if (n == 2 && first != 0)
3081 It is highly recommended that the third partition covers the whole disk\n\
3082 and is of type `Whole disk'\n");
3083 /* ewt asks to add: "don't start a partition at cyl 0"
3084 However, edmundo@rano.demon.co.uk writes:
3085 "In addition to having a Sun partition table, to be able to
3086 boot from the disc, the first partition, /dev/sdX1, must
3087 start at cylinder 0. This means that /dev/sdX1 contains
3088 the partition table and the boot block, as these are the
3089 first two sectors of the disc. Therefore you must be
3090 careful what you use /dev/sdX1 for. In particular, you must
3091 not use a partition starting at cylinder 0 for Linux swap,
3092 as that would overwrite the partition table and the boot
3093 block. You may, however, use such a partition for a UFS
3094 or EXT2 file system, as these file systems leave the first
3095 1024 bytes undisturbed. */
3096 /* On the other hand, one should not use partitions
3097 starting at block 0 in an md, or the label will
3099 for (i = 0; i < partitions; i++)
3100 if (lens[i] && starts[i] <= first
3101 && starts[i] + lens[i] > first)
3103 if (i < partitions && !whole_disk) {
3104 if (n == 2 && !first) {
3108 printf(_("Sector %d is already allocated\n"), first);
3112 stop = cylinders * heads * sectors;
3114 for (i = 0; i < partitions; i++) {
3115 if (starts[i] > first && starts[i] < stop)
3118 snprintf(mesg, sizeof(mesg),
3119 _("Last %s or +size or +sizeM or +sizeK"),
3120 str_units(SINGULAR));
3122 last = read_int(scround(stop2), scround(stop2), scround(stop2),
3124 else if (n == 2 && !first)
3125 last = read_int(scround(first), scround(stop2), scround(stop2),
3126 scround(first), mesg);
3128 last = read_int(scround(first), scround(stop), scround(stop),
3129 scround(first), mesg);
3130 if (display_in_cyl_units)
3131 last *= units_per_sector;
3132 if (n == 2 && !first) {
3133 if (last >= stop2) {
3136 } else if (last > stop) {
3138 _("You haven't covered the whole disk with the 3rd partition, but your value\n"
3139 "%d %s covers some other partition. Your entry has been changed\n"
3141 scround(last), str_units(SINGULAR),
3142 scround(stop), str_units(SINGULAR));
3145 } else if (!whole_disk && last > stop)
3148 if (whole_disk) sys = WHOLE_DISK;
3149 set_sun_partition(n, first, last, sys);
3153 sun_delete_partition(int i) {
3154 if (i == 2 && sunlabel->infos[i].id == WHOLE_DISK &&
3155 !sunlabel->partitions[i].start_cylinder &&
3156 SUN_SSWAP32(sunlabel->partitions[i].num_sectors)
3157 == heads * sectors * cylinders)
3158 printf(_("If you want to maintain SunOS/Solaris compatibility, "
3159 "consider leaving this\n"
3160 "partition as Whole disk (5), starting at 0, with %u "
3162 (uint) SUN_SSWAP32(sunlabel->partitions[i].num_sectors));
3163 sunlabel->infos[i].id = 0;
3164 sunlabel->partitions[i].num_sectors = 0;
3168 sun_change_sysid(int i, int sys) {
3169 if (sys == LINUX_SWAP && !sunlabel->partitions[i].start_cylinder) {
3171 _("It is highly recommended that the partition at offset 0\n"
3172 "is UFS, EXT2FS filesystem or SunOS swap. Putting Linux swap\n"
3173 "there may destroy your partition table and bootblock.\n"
3174 "Type YES if you're very sure you would like that partition\n"
3175 "tagged with 82 (Linux swap): "));
3176 if (strcmp (line_ptr, _("YES\n")))
3182 /* swaps are not mountable by default */
3183 sunlabel->infos[i].flags |= 0x01;
3186 /* assume other types are mountable;
3187 user can change it anyway */
3188 sunlabel->infos[i].flags &= ~0x01;
3191 sunlabel->infos[i].id = sys;
3195 sun_list_table(int xtra) {
3199 w = strlen(disk_device);
3202 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d rpm\n"
3203 "%d cylinders, %d alternate cylinders, %d physical cylinders\n"
3204 "%d extra sects/cyl, interleave %d:1\n"
3206 "Units = %s of %d * 512 bytes\n\n"),
3207 disk_device, heads, sectors, SUN_SSWAP16(sunlabel->rspeed),
3208 cylinders, SUN_SSWAP16(sunlabel->nacyl),
3209 SUN_SSWAP16(sunlabel->pcylcount),
3210 SUN_SSWAP16(sunlabel->sparecyl),
3211 SUN_SSWAP16(sunlabel->ilfact),
3213 str_units(PLURAL), units_per_sector);
3216 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d cylinders\n"
3217 "Units = %s of %d * 512 bytes\n\n"),
3218 disk_device, heads, sectors, cylinders,
3219 str_units(PLURAL), units_per_sector);
3221 printf(_("%*s Flag Start End Blocks Id System\n"),
3222 w + 1, _("Device"));
3223 for (i = 0 ; i < partitions; i++) {
3224 if (sunlabel->partitions[i].num_sectors) {
3225 __u32 start = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
3226 __u32 len = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
3228 "%s %c%c %9ld %9ld %9ld%c %2x %s\n",
3229 /* device */ partname(disk_device, i+1, w),
3230 /* flags */ (sunlabel->infos[i].flags & 0x01) ? 'u' : ' ',
3231 (sunlabel->infos[i].flags & 0x10) ? 'r' : ' ',
3232 /* start */ (long) scround(start),
3233 /* end */ (long) scround(start+len),
3234 /* odd flag on end */ (long) len / 2, len & 1 ? '+' : ' ',
3235 /* type id */ sunlabel->infos[i].id,
3236 /* type name */ (type = partition_type(sunlabel->infos[i].id))
3237 ? type : _("Unknown"));
3243 sun_set_alt_cyl(void) {
3245 SUN_SSWAP16(read_int(0,SUN_SSWAP16(sunlabel->nacyl), 65535, 0,
3246 _("Number of alternate cylinders")));
3250 sun_set_ncyl(int cyl) {
3251 sunlabel->ncyl = SUN_SSWAP16(cyl);
3255 sun_set_xcyl(void) {
3256 sunlabel->sparecyl =
3257 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->sparecyl), sectors, 0,
3258 _("Extra sectors per cylinder")));
3262 sun_set_ilfact(void) {
3264 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->ilfact), 32, 0,
3265 _("Interleave factor")));
3269 sun_set_rspeed(void) {
3271 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->rspeed), 100000, 0,
3272 _("Rotation speed (rpm)")));
3276 sun_set_pcylcount(void) {
3277 sunlabel->pcylcount =
3278 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->pcylcount), 65535, 0,
3279 _("Number of physical cylinders")));
3283 sun_write_table(void) {
3284 unsigned short *ush = (unsigned short *)sunlabel;
3285 unsigned short csum = 0;
3287 while(ush < (unsigned short *)(&sunlabel->csum))
3289 sunlabel->csum = csum;
3290 if (lseek(fd, 0, SEEK_SET) < 0)
3291 fdisk_fatal(unable_to_seek);
3292 if (write(fd, sunlabel, SECTOR_SIZE) != SECTOR_SIZE)
3293 fdisk_fatal(unable_to_write);
3295 #endif /* SUN_LABEL */
3297 /* DOS partition types */
3299 static const struct systypes i386_sys_types[] = {
3302 {"\x02" "XENIX root"},
3303 {"\x03" "XENIX usr"},
3304 {"\x04" "FAT16 <32M"},
3305 {"\x05" "Extended"}, /* DOS 3.3+ extended partition */
3306 {"\x06" "FAT16"}, /* DOS 16-bit >=32M */
3307 {"\x07" "HPFS/NTFS"}, /* OS/2 IFS, eg, HPFS or NTFS or QNX */
3308 {"\x08" "AIX"}, /* AIX boot (AIX -- PS/2 port) or SplitDrive */
3309 {"\x09" "AIX bootable"}, /* AIX data or Coherent */
3310 {"\x0a" "OS/2 Boot Manager"},/* OS/2 Boot Manager */
3311 {"\x0b" "Win95 FAT32"},
3312 {"\x0c" "Win95 FAT32 (LBA)"},/* LBA really is `Extended Int 13h' */
3313 {"\x0e" "Win95 FAT16 (LBA)"},
3314 {"\x0f" "Win95 Ext'd (LBA)"},
3316 {"\x11" "Hidden FAT12"},
3317 {"\x12" "Compaq diagnostics"},
3318 {"\x14" "Hidden FAT16 <32M"},
3319 {"\x16" "Hidden FAT16"},
3320 {"\x17" "Hidden HPFS/NTFS"},
3321 {"\x18" "AST SmartSleep"},
3322 {"\x1b" "Hidden Win95 FAT32"},
3323 {"\x1c" "Hidden Win95 FAT32 (LBA)"},
3324 {"\x1e" "Hidden Win95 FAT16 (LBA)"},
3327 {"\x3c" "PartitionMagic recovery"},
3328 {"\x40" "Venix 80286"},
3329 {"\x41" "PPC PReP Boot"},
3332 {"\x4e" "QNX4.x 2nd part"},
3333 {"\x4f" "QNX4.x 3rd part"},
3334 {"\x50" "OnTrack DM"},
3335 {"\x51" "OnTrack DM6 Aux1"}, /* (or Novell) */
3336 {"\x52" "CP/M"}, /* CP/M or Microport SysV/AT */
3337 {"\x53" "OnTrack DM6 Aux3"},
3338 {"\x54" "OnTrackDM6"},
3339 {"\x55" "EZ-Drive"},
3340 {"\x56" "Golden Bow"},
3341 {"\x5c" "Priam Edisk"},
3342 {"\x61" "SpeedStor"},
3343 {"\x63" "GNU HURD or SysV"}, /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */
3344 {"\x64" "Novell Netware 286"},
3345 {"\x65" "Novell Netware 386"},
3346 {"\x70" "DiskSecure Multi-Boot"},
3348 {"\x80" "Old Minix"}, /* Minix 1.4a and earlier */
3349 {"\x81" "Minix / old Linux"},/* Minix 1.4b and later */
3350 {"\x82" "Linux swap"}, /* also Solaris */
3352 {"\x84" "OS/2 hidden C: drive"},
3353 {"\x85" "Linux extended"},
3354 {"\x86" "NTFS volume set"},
3355 {"\x87" "NTFS volume set"},
3356 {"\x8e" "Linux LVM"},
3358 {"\x94" "Amoeba BBT"}, /* (bad block table) */
3359 {"\x9f" "BSD/OS"}, /* BSDI */
3360 {"\xa0" "IBM Thinkpad hibernation"},
3361 {"\xa5" "FreeBSD"}, /* various BSD flavours */
3363 {"\xa7" "NeXTSTEP"},
3364 {"\xa8" "Darwin UFS"},
3366 {"\xab" "Darwin boot"},
3368 {"\xb8" "BSDI swap"},
3369 {"\xbb" "Boot Wizard hidden"},
3370 {"\xbe" "Solaris boot"},
3371 {"\xc1" "DRDOS/sec (FAT-12)"},
3372 {"\xc4" "DRDOS/sec (FAT-16 < 32M)"},
3373 {"\xc6" "DRDOS/sec (FAT-16)"},
3375 {"\xda" "Non-FS data"},
3376 {"\xdb" "CP/M / CTOS / ..."},/* CP/M or Concurrent CP/M or
3377 Concurrent DOS or CTOS */
3378 {"\xde" "Dell Utility"}, /* Dell PowerEdge Server utilities */
3379 {"\xdf" "BootIt"}, /* BootIt EMBRM */
3380 {"\xe1" "DOS access"}, /* DOS access or SpeedStor 12-bit FAT
3381 extended partition */
3382 {"\xe3" "DOS R/O"}, /* DOS R/O or SpeedStor */
3383 {"\xe4" "SpeedStor"}, /* SpeedStor 16-bit FAT extended
3384 partition < 1024 cyl. */
3386 {"\xee" "EFI GPT"}, /* Intel EFI GUID Partition Table */
3387 {"\xef" "EFI (FAT-12/16/32)"},/* Intel EFI System Partition */
3388 {"\xf0" "Linux/PA-RISC boot"},/* Linux/PA-RISC boot loader */
3389 {"\xf1" "SpeedStor"},
3390 {"\xf4" "SpeedStor"}, /* SpeedStor large partition */
3391 {"\xf2" "DOS secondary"}, /* DOS 3.3+ secondary */
3392 {"\xfd" "Linux raid autodetect"},/* New (2.2.x) raid partition with
3393 autodetect using persistent
3395 {"\xfe" "LANstep"}, /* SpeedStor >1024 cyl. or LANstep */
3396 {"\xff" "BBT"}, /* Xenix Bad Block Table */
3401 static void delete_partition(int i);
3403 /* A valid partition table sector ends in 0x55 0xaa */
3405 part_table_flag(const char *b) {
3406 return ((uint) b[510]) + (((uint) b[511]) << 8);
3410 valid_part_table_flag(const unsigned char *b) {
3411 return (b[510] == 0x55 && b[511] == 0xaa);
3415 write_part_table_flag(char *b) {
3420 /* start_sect and nr_sects are stored little endian on all machines */
3421 /* moreover, they are not aligned correctly */
3423 store4_little_endian(unsigned char *cp, unsigned int val) {
3424 cp[0] = (val & 0xff);
3425 cp[1] = ((val >> 8) & 0xff);
3426 cp[2] = ((val >> 16) & 0xff);
3427 cp[3] = ((val >> 24) & 0xff);
3431 read4_little_endian(const unsigned char *cp) {
3432 return (uint)(cp[0]) + ((uint)(cp[1]) << 8)
3433 + ((uint)(cp[2]) << 16) + ((uint)(cp[3]) << 24);
3437 set_start_sect(struct partition *p, unsigned int start_sect) {
3438 store4_little_endian(p->start4, start_sect);
3442 get_start_sect(const struct partition *p) {
3443 return read4_little_endian(p->start4);
3447 set_nr_sects(struct partition *p, unsigned int nr_sects) {
3448 store4_little_endian(p->size4, nr_sects);
3452 get_nr_sects(const struct partition *p) {
3453 return read4_little_endian(p->size4);
3456 /* normally O_RDWR, -l option gives O_RDONLY */
3457 static int type_open = O_RDWR;
3460 static int ext_index, /* the prime extended partition */
3461 listing, /* no aborts for fdisk -l */
3462 nowarn, /* no warnings for fdisk -l/-s */
3463 dos_compatible_flag = ~0,
3467 static uint user_cylinders, user_heads, user_sectors;
3468 static uint pt_heads, pt_sectors;
3469 static uint kern_heads, kern_sectors;
3471 static uint extended_offset; /* offset of link pointers */
3472 static uint sector_size = DEFAULT_SECTOR_SIZE,
3473 user_set_sector_size,
3476 static unsigned long total_number_of_sectors;
3479 static jmp_buf listingbuf;
3481 static void fdisk_fatal(enum failure why) {
3482 const char *message;
3486 longjmp(listingbuf, 1);
3490 case unable_to_open:
3491 message = "Unable to open %s\n";
3493 case unable_to_read:
3494 message = "Unable to read %s\n";
3496 case unable_to_seek:
3497 message = "Unable to seek on %s\n";
3499 case unable_to_write:
3500 message = "Unable to write %s\n";
3503 message = "BLKGETSIZE ioctl failed on %s\n";
3506 message = "Fatal error\n";
3509 fputc('\n', stderr);
3510 fprintf(stderr, message, disk_device);
3515 seek_sector(uint secno) {
3516 ext2_loff_t offset = (ext2_loff_t) secno * sector_size;
3517 if (ext2_llseek(fd, offset, SEEK_SET) == (ext2_loff_t) -1)
3518 fdisk_fatal(unable_to_seek);
3522 read_sector(uint secno, char *buf) {
3524 if (read(fd, buf, sector_size) != sector_size)
3525 fdisk_fatal(unable_to_read);
3529 write_sector(uint secno, char *buf) {
3531 if (write(fd, buf, sector_size) != sector_size)
3532 fdisk_fatal(unable_to_write);
3535 /* Allocate a buffer and read a partition table sector */
3537 read_pte(int pno, uint offset) {
3538 struct pte *pe = &ptes[pno];
3540 pe->offset = offset;
3541 pe->sectorbuffer = (char *) xmalloc(sector_size);
3542 read_sector(offset, pe->sectorbuffer);
3544 pe->part_table = pe->ext_pointer = NULL;
3548 get_partition_start(const struct pte *pe) {
3549 return pe->offset + get_start_sect(pe->part_table);
3553 * Avoid warning about DOS partitions when no DOS partition was changed.
3554 * Here a heuristic "is probably dos partition".
3555 * We might also do the opposite and warn in all cases except
3556 * for "is probably nondos partition".
3559 is_dos_partition(int t) {
3560 return (t == 1 || t == 4 || t == 6 ||
3561 t == 0x0b || t == 0x0c || t == 0x0e ||
3562 t == 0x11 || t == 0x12 || t == 0x14 || t == 0x16 ||
3563 t == 0x1b || t == 0x1c || t == 0x1e || t == 0x24 ||
3564 t == 0xc1 || t == 0xc4 || t == 0xc6);
3569 #ifdef CONFIG_FEATURE_SUN_LABEL
3571 puts(_("Command action"));
3572 puts(_("\ta\ttoggle a read only flag")); /* sun */
3573 puts(_("\tb\tedit bsd disklabel"));
3574 puts(_("\tc\ttoggle the mountable flag")); /* sun */
3575 puts(_("\td\tdelete a partition"));
3576 puts(_("\tl\tlist known partition types"));
3577 puts(_("\tm\tprint this menu"));
3578 puts(_("\tn\tadd a new partition"));
3579 puts(_("\to\tcreate a new empty DOS partition table"));
3580 puts(_("\tp\tprint the partition table"));
3581 puts(_("\tq\tquit without saving changes"));
3582 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3583 puts(_("\tt\tchange a partition's system id"));
3584 puts(_("\tu\tchange display/entry units"));
3585 puts(_("\tv\tverify the partition table"));
3586 puts(_("\tw\twrite table to disk and exit"));
3587 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3588 puts(_("\tx\textra functionality (experts only)"));
3592 #ifdef CONFIG_FEATURE_SGI_LABEL
3594 puts(_("Command action"));
3595 puts(_("\ta\tselect bootable partition")); /* sgi flavour */
3596 puts(_("\tb\tedit bootfile entry")); /* sgi */
3597 puts(_("\tc\tselect sgi swap partition")); /* sgi flavour */
3598 puts(_("\td\tdelete a partition"));
3599 puts(_("\tl\tlist known partition types"));
3600 puts(_("\tm\tprint this menu"));
3601 puts(_("\tn\tadd a new partition"));
3602 puts(_("\to\tcreate a new empty DOS partition table"));
3603 puts(_("\tp\tprint the partition table"));
3604 puts(_("\tq\tquit without saving changes"));
3605 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3606 puts(_("\tt\tchange a partition's system id"));
3607 puts(_("\tu\tchange display/entry units"));
3608 puts(_("\tv\tverify the partition table"));
3609 puts(_("\tw\twrite table to disk and exit"));
3612 #ifdef CONFIG_FEATURE_AIX_LABEL
3614 puts(_("Command action"));
3615 puts(_("\tm\tprint this menu"));
3616 puts(_("\to\tcreate a new empty DOS partition table"));
3617 puts(_("\tq\tquit without saving changes"));
3618 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3622 puts(_("Command action"));
3623 puts(_("\ta\ttoggle a bootable flag"));
3624 puts(_("\tb\tedit bsd disklabel"));
3625 puts(_("\tc\ttoggle the dos compatibility flag"));
3626 puts(_("\td\tdelete a partition"));
3627 puts(_("\tl\tlist known partition types"));
3628 puts(_("\tm\tprint this menu"));
3629 puts(_("\tn\tadd a new partition"));
3630 puts(_("\to\tcreate a new empty DOS partition table"));
3631 puts(_("\tp\tprint the partition table"));
3632 puts(_("\tq\tquit without saving changes"));
3633 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3634 puts(_("\tt\tchange a partition's system id"));
3635 puts(_("\tu\tchange display/entry units"));
3636 puts(_("\tv\tverify the partition table"));
3637 puts(_("\tw\twrite table to disk and exit"));
3638 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3639 puts(_("\tx\textra functionality (experts only)"));
3644 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3647 #ifdef CONFIG_FEATURE_SUN_LABEL
3649 puts(_("Command action"));
3650 puts(_("\ta\tchange number of alternate cylinders")); /*sun*/
3651 puts(_("\tc\tchange number of cylinders"));
3652 puts(_("\td\tprint the raw data in the partition table"));
3653 puts(_("\te\tchange number of extra sectors per cylinder"));/*sun*/
3654 puts(_("\th\tchange number of heads"));
3655 puts(_("\ti\tchange interleave factor")); /*sun*/
3656 puts(_("\to\tchange rotation speed (rpm)")); /*sun*/
3657 puts(_("\tm\tprint this menu"));
3658 puts(_("\tp\tprint the partition table"));
3659 puts(_("\tq\tquit without saving changes"));
3660 puts(_("\tr\treturn to main menu"));
3661 puts(_("\ts\tchange number of sectors/track"));
3662 puts(_("\tv\tverify the partition table"));
3663 puts(_("\tw\twrite table to disk and exit"));
3664 puts(_("\ty\tchange number of physical cylinders")); /*sun*/
3667 #ifdef CONFIG_FEATURE_SGI_LABEL
3669 puts(_("Command action"));
3670 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3671 puts(_("\tc\tchange number of cylinders"));
3672 puts(_("\td\tprint the raw data in the partition table"));
3673 puts(_("\te\tlist extended partitions")); /* !sun */
3674 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3675 puts(_("\th\tchange number of heads"));
3676 puts(_("\tm\tprint this menu"));
3677 puts(_("\tp\tprint the partition table"));
3678 puts(_("\tq\tquit without saving changes"));
3679 puts(_("\tr\treturn to main menu"));
3680 puts(_("\ts\tchange number of sectors/track"));
3681 puts(_("\tv\tverify the partition table"));
3682 puts(_("\tw\twrite table to disk and exit"));
3685 #ifdef CONFIG_FEATURE_AIX_LABEL
3687 puts(_("Command action"));
3688 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3689 puts(_("\tc\tchange number of cylinders"));
3690 puts(_("\td\tprint the raw data in the partition table"));
3691 puts(_("\te\tlist extended partitions")); /* !sun */
3692 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3693 puts(_("\th\tchange number of heads"));
3694 puts(_("\tm\tprint this menu"));
3695 puts(_("\tp\tprint the partition table"));
3696 puts(_("\tq\tquit without saving changes"));
3697 puts(_("\tr\treturn to main menu"));
3698 puts(_("\ts\tchange number of sectors/track"));
3699 puts(_("\tv\tverify the partition table"));
3700 puts(_("\tw\twrite table to disk and exit"));
3704 puts(_("Command action"));
3705 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3706 puts(_("\tc\tchange number of cylinders"));
3707 puts(_("\td\tprint the raw data in the partition table"));
3708 puts(_("\te\tlist extended partitions")); /* !sun */
3709 puts(_("\tf\tfix partition order")); /* !sun, !aix, !sgi */
3710 #ifdef CONFIG_FEATURE_SGI_LABEL
3711 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3713 puts(_("\th\tchange number of heads"));
3714 puts(_("\tm\tprint this menu"));
3715 puts(_("\tp\tprint the partition table"));
3716 puts(_("\tq\tquit without saving changes"));
3717 puts(_("\tr\treturn to main menu"));
3718 puts(_("\ts\tchange number of sectors/track"));
3719 puts(_("\tv\tverify the partition table"));
3720 puts(_("\tw\twrite table to disk and exit"));
3723 #endif /* ADVANCED mode */
3729 #ifdef CONFIG_FEATURE_SUN_LABEL
3730 sun_label ? sunlabel->infos[i].id :
3732 #ifdef CONFIG_FEATURE_SGI_LABEL
3733 sgi_label ? sgi_get_sysid(i) :
3735 ptes[i].part_table->sys_ind);
3738 static const struct systypes *
3739 get_sys_types(void) {
3741 #ifdef CONFIG_FEATURE_SUN_LABEL
3742 sun_label ? sun_sys_types :
3744 #ifdef CONFIG_FEATURE_SGI_LABEL
3745 sgi_label ? sgi_sys_types :
3750 static const char *partition_type(unsigned char type)
3753 const struct systypes *types = get_sys_types();
3755 for (i=0; types[i].name; i++)
3756 if (types[i].name[0] == type)
3757 return types[i].name + 1;
3762 void list_types(const struct systypes *sys)
3764 uint last[4], done = 0, next = 0, size;
3767 for (i = 0; sys[i].name; i++);
3770 for (i = 3; i >= 0; i--)
3771 last[3 - i] = done += (size + i - done) / (i + 1);
3775 printf("%c%2x %-15.15s", i ? ' ' : '\n',
3776 sys[next].name[0], sys[next].name + 1);
3777 next = last[i++] + done;
3778 if (i > 3 || next >= last[i]) {
3782 } while (done < last[0]);
3787 is_cleared_partition(const struct partition *p) {
3788 return !(!p || p->boot_ind || p->head || p->sector || p->cyl ||
3789 p->sys_ind || p->end_head || p->end_sector || p->end_cyl ||
3790 get_start_sect(p) || get_nr_sects(p));
3794 clear_partition(struct partition *p) {
3805 set_start_sect(p,0);
3810 set_partition(int i, int doext, uint start, uint stop, int sysid) {
3811 struct partition *p;
3815 p = ptes[i].ext_pointer;
3816 offset = extended_offset;
3818 p = ptes[i].part_table;
3819 offset = ptes[i].offset;
3823 set_start_sect(p, start - offset);
3824 set_nr_sects(p, stop - start + 1);
3825 if (dos_compatible_flag && (start/(sectors*heads) > 1023))
3826 start = heads*sectors*1024 - 1;
3827 set_hsc(p->head, p->sector, p->cyl, start);
3828 if (dos_compatible_flag && (stop/(sectors*heads) > 1023))
3829 stop = heads*sectors*1024 - 1;
3830 set_hsc(p->end_head, p->end_sector, p->end_cyl, stop);
3831 ptes[i].changed = 1;
3835 test_c(const char **m, const char *mesg) {
3838 fprintf(stderr, _("You must set"));
3840 fprintf(stderr, " %s", *m);
3848 warn_geometry(void) {
3849 const char *m = NULL;
3853 prev = test_c(&m, _("heads"));
3855 prev = test_c(&m, _("sectors"));
3857 prev = test_c(&m, _("cylinders"));
3861 _("%s%s.\nYou can do this from the extra functions menu.\n"),
3862 prev ? _(" and ") : " ", m);
3866 static void update_units(void)
3868 int cyl_units = heads * sectors;
3870 if (display_in_cyl_units && cyl_units)
3871 units_per_sector = cyl_units;
3873 units_per_sector = 1; /* in sectors */
3877 warn_cylinders(void) {
3878 if (dos_label && cylinders > 1024 && !nowarn)
3879 fprintf(stderr, _("\n"
3880 "The number of cylinders for this disk is set to %d.\n"
3881 "There is nothing wrong with that, but this is larger than 1024,\n"
3882 "and could in certain setups cause problems with:\n"
3883 "1) software that runs at boot time (e.g., old versions of LILO)\n"
3884 "2) booting and partitioning software from other OSs\n"
3885 " (e.g., DOS FDISK, OS/2 FDISK)\n"),
3890 read_extended(int ext) {
3893 struct partition *p, *q;
3897 pex->ext_pointer = pex->part_table;
3899 p = pex->part_table;
3900 if (!get_start_sect(p)) {
3902 _("Bad offset in primary extended partition\n"));
3906 while (IS_EXTENDED (p->sys_ind)) {
3907 struct pte *pe = &ptes[partitions];
3909 if (partitions >= MAXIMUM_PARTS) {
3910 /* This is not a Linux restriction, but
3911 this program uses arrays of size MAXIMUM_PARTS.
3912 Do not try to `improve' this test. */
3913 struct pte *pre = &ptes[partitions-1];
3916 _("Warning: deleting partitions after %d\n"),
3918 clear_partition(pre->ext_pointer);
3923 read_pte(partitions, extended_offset + get_start_sect(p));
3925 if (!extended_offset)
3926 extended_offset = get_start_sect(p);
3928 q = p = pt_offset(pe->sectorbuffer, 0);
3929 for (i = 0; i < 4; i++, p++) if (get_nr_sects(p)) {
3930 if (IS_EXTENDED (p->sys_ind)) {
3931 if (pe->ext_pointer)
3933 _("Warning: extra link "
3934 "pointer in partition table"
3935 " %d\n"), partitions + 1);
3937 pe->ext_pointer = p;
3938 } else if (p->sys_ind) {
3941 _("Warning: ignoring extra "
3942 "data in partition table"
3943 " %d\n"), partitions + 1);
3949 /* very strange code here... */
3950 if (!pe->part_table) {
3951 if (q != pe->ext_pointer)
3954 pe->part_table = q + 1;
3956 if (!pe->ext_pointer) {
3957 if (q != pe->part_table)
3958 pe->ext_pointer = q;
3960 pe->ext_pointer = q + 1;
3963 p = pe->ext_pointer;
3967 /* remove empty links */
3969 for (i = 4; i < partitions; i++) {
3970 struct pte *pe = &ptes[i];
3972 if (!get_nr_sects(pe->part_table) &&
3973 (partitions > 5 || ptes[4].part_table->sys_ind)) {
3974 printf("omitting empty partition (%d)\n", i+1);
3975 delete_partition(i);
3976 goto remove; /* numbering changed */
3982 create_doslabel(void) {
3986 _("Building a new DOS disklabel. Changes will remain in memory only,\n"
3987 "until you decide to write them. After that, of course, the previous\n"
3988 "content won't be recoverable.\n\n"));
3989 #ifdef CONFIG_FEATURE_SUN_LABEL
3990 sun_nolabel(); /* otherwise always recognised as sun */
3992 #ifdef CONFIG_FEATURE_SGI_LABEL
3993 sgi_nolabel(); /* otherwise always recognised as sgi */
3995 #ifdef CONFIG_FEATURE_AIX_LABEL
3998 #ifdef CONFIG_FEATURE_OSF_LABEL
4000 possibly_osf_label = 0;
4004 for (i = 510-64; i < 510; i++)
4006 write_part_table_flag(MBRbuffer);
4007 extended_offset = 0;
4008 set_all_unchanged();
4010 get_boot(create_empty_dos);
4015 get_sectorsize(void) {
4016 if (!user_set_sector_size &&
4017 get_kernel_revision() >= MAKE_VERSION(2,3,3)) {
4019 if (ioctl(fd, BLKSSZGET, &arg) == 0)
4021 if (sector_size != DEFAULT_SECTOR_SIZE)
4022 printf(_("Note: sector size is %d (not %d)\n"),
4023 sector_size, DEFAULT_SECTOR_SIZE);
4028 get_kernel_geometry(void) {
4029 struct hd_geometry geometry;
4031 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
4032 kern_heads = geometry.heads;
4033 kern_sectors = geometry.sectors;
4034 /* never use geometry.cylinders - it is truncated */
4039 get_partition_table_geometry(void) {
4040 unsigned char *bufp = MBRbuffer;
4041 struct partition *p;
4042 int i, h, s, hh, ss;
4046 if (!(valid_part_table_flag(bufp)))
4050 for (i=0; i<4; i++) {
4051 p = pt_offset(bufp, i);
4052 if (p->sys_ind != 0) {
4053 h = p->end_head + 1;
4054 s = (p->end_sector & 077);
4059 } else if (hh != h || ss != s)
4064 if (!first && !bad) {
4071 get_geometry(struct geom *g) {
4073 unsigned long longsectors;
4076 sec_fac = sector_size / 512;
4077 #ifdef CONFIG_FEATURE_SUN_LABEL
4078 guess_device_type();
4080 heads = cylinders = sectors = 0;
4081 kern_heads = kern_sectors = 0;
4082 pt_heads = pt_sectors = 0;
4084 get_kernel_geometry();
4085 get_partition_table_geometry();
4087 heads = user_heads ? user_heads :
4088 pt_heads ? pt_heads :
4089 kern_heads ? kern_heads : 255;
4090 sectors = user_sectors ? user_sectors :
4091 pt_sectors ? pt_sectors :
4092 kern_sectors ? kern_sectors : 63;
4094 if (ioctl(fd, BLKGETSIZE, &longsectors))
4098 if (dos_compatible_flag)
4099 sector_offset = sectors;
4101 cylinders = longsectors / (heads * sectors);
4102 cylinders /= sec_fac;
4104 cylinders = user_cylinders;
4108 g->sectors = sectors;
4109 g->cylinders = cylinders;
4112 total_number_of_sectors = longsectors;
4116 * Read MBR. Returns:
4117 * -1: no 0xaa55 flag present (possibly entire disk BSD)
4118 * 0: found or created label
4122 get_boot(enum action what) {
4127 for (i = 0; i < 4; i++) {
4128 struct pte *pe = &ptes[i];
4130 pe->part_table = pt_offset(MBRbuffer, i);
4131 pe->ext_pointer = NULL;
4133 pe->sectorbuffer = MBRbuffer;
4134 pe->changed = (what == create_empty_dos);
4137 if (what == create_empty_sun && check_sun_label())
4140 memset(MBRbuffer, 0, 512);
4142 if (what == create_empty_dos)
4143 goto got_dos_table; /* skip reading disk */
4145 if ((fd = open(disk_device, type_open)) < 0) {
4146 if ((fd = open(disk_device, O_RDONLY)) < 0) {
4147 if (what == try_only)
4149 fdisk_fatal(unable_to_open);
4151 printf(_("You will not be able to write "
4152 "the partition table.\n"));
4155 if (512 != read(fd, MBRbuffer, 512)) {
4156 if (what == try_only)
4158 fdisk_fatal(unable_to_read);
4165 if (check_sun_label())
4168 #ifdef CONFIG_FEATURE_SGI_LABEL
4169 if (check_sgi_label())
4173 #ifdef CONFIG_FEATURE_AIX_LABEL
4174 if (check_aix_label())
4178 #ifdef CONFIG_FEATURE_OSF_LABEL
4179 if (check_osf_label()) {
4180 possibly_osf_label = 1;
4181 if (!valid_part_table_flag(MBRbuffer)) {
4185 printf(_("This disk has both DOS and BSD magic.\n"
4186 "Give the 'b' command to go to BSD mode.\n"));
4192 if (!valid_part_table_flag(MBRbuffer)) {
4196 _("Device contains neither a valid DOS "
4197 "partition table, nor Sun, SGI or OSF "
4200 #ifdef CONFIG_FEATURE_SUN_LABEL
4211 case create_empty_dos:
4212 case create_empty_sun:
4215 fprintf(stderr, _("Internal error\n"));
4223 for (i = 0; i < 4; i++) {
4224 struct pte *pe = &ptes[i];
4226 if (IS_EXTENDED (pe->part_table->sys_ind)) {
4227 if (partitions != 4)
4228 fprintf(stderr, _("Ignoring extra extended "
4229 "partition %d\n"), i + 1);
4235 for (i = 3; i < partitions; i++) {
4236 struct pte *pe = &ptes[i];
4238 if (!valid_part_table_flag(pe->sectorbuffer)) {
4240 _("Warning: invalid flag 0x%04x of partition "
4241 "table %d will be corrected by w(rite)\n"),
4242 part_table_flag(pe->sectorbuffer), i + 1);
4251 * Print the message MESG, then read an integer between LOW and HIGH (inclusive).
4252 * If the user hits Enter, DFLT is returned.
4253 * Answers like +10 are interpreted as offsets from BASE.
4255 * There is no default if DFLT is not between LOW and HIGH.
4258 read_int(uint low, uint dflt, uint high, uint base, char *mesg)
4262 static char *ms = NULL;
4263 static int mslen = 0;
4265 if (!ms || strlen(mesg)+100 > mslen) {
4266 mslen = strlen(mesg)+200;
4267 ms = xrealloc(ms,mslen);
4270 if (dflt < low || dflt > high)
4274 snprintf(ms, mslen, _("%s (%d-%d, default %d): "),
4275 mesg, low, high, dflt);
4277 snprintf(ms, mslen, "%s (%d-%d): ",
4281 int use_default = default_ok;
4283 /* ask question and read answer */
4284 while (read_chars(ms) != '\n' && !isdigit(*line_ptr)
4285 && *line_ptr != '-' && *line_ptr != '+')
4288 if (*line_ptr == '+' || *line_ptr == '-') {
4289 i = atoi(line_ptr+1);
4290 if (*line_ptr == '-')
4292 while (isdigit(*++line_ptr))
4294 switch (*line_ptr) {
4297 if (!display_in_cyl_units)
4298 i *= heads * sectors;
4303 i /= (sector_size / 512);
4304 i /= units_per_sector;
4309 i /= (sector_size / 512);
4310 i /= units_per_sector;
4315 i /= (sector_size / 512);
4316 i /= units_per_sector;
4324 while (isdigit(*line_ptr)) {
4330 printf(_("Using default value %d\n"), i = dflt);
4331 if (i >= low && i <= high)
4334 printf(_("Value out of range.\n"));
4340 get_partition(int warn, int max) {
4344 i = read_int(1, 0, max, 0, _("Partition number")) - 1;
4348 if ((!sun_label && !sgi_label && !pe->part_table->sys_ind)
4349 #ifdef CONFIG_FEATURE_SUN_LABEL
4351 (!sunlabel->partitions[i].num_sectors ||
4352 !sunlabel->infos[i].id))
4354 #ifdef CONFIG_FEATURE_SGI_LABEL
4355 || (sgi_label && (!sgi_get_num_sectors(i)))
4359 _("Warning: partition %d has empty type\n"),
4366 get_existing_partition(int warn, int max) {
4370 for (i = 0; i < max; i++) {
4371 struct pte *pe = &ptes[i];
4372 struct partition *p = pe->part_table;
4374 if (p && !is_cleared_partition(p)) {
4381 printf(_("Selected partition %d\n"), pno+1);
4384 printf(_("No partition is defined yet!\n"));
4388 return get_partition(warn, max);
4392 get_nonexisting_partition(int warn, int max) {
4396 for (i = 0; i < max; i++) {
4397 struct pte *pe = &ptes[i];
4398 struct partition *p = pe->part_table;
4400 if (p && is_cleared_partition(p)) {
4407 printf(_("Selected partition %d\n"), pno+1);
4410 printf(_("All primary partitions have been defined already!\n"));
4414 return get_partition(warn, max);
4418 void change_units(void)
4420 display_in_cyl_units = !display_in_cyl_units;
4422 printf(_("Changing display/entry units to %s\n"),
4427 toggle_active(int i) {
4428 struct pte *pe = &ptes[i];
4429 struct partition *p = pe->part_table;
4431 if (IS_EXTENDED (p->sys_ind) && !p->boot_ind)
4433 _("WARNING: Partition %d is an extended partition\n"),
4435 p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG);
4440 toggle_dos_compatibility_flag(void) {
4441 dos_compatible_flag = ~dos_compatible_flag;
4442 if (dos_compatible_flag) {
4443 sector_offset = sectors;
4444 printf(_("DOS Compatibility flag is set\n"));
4448 printf(_("DOS Compatibility flag is not set\n"));
4453 delete_partition(int i) {
4454 struct pte *pe = &ptes[i];
4455 struct partition *p = pe->part_table;
4456 struct partition *q = pe->ext_pointer;
4458 /* Note that for the fifth partition (i == 4) we don't actually
4459 * decrement partitions.
4462 if (warn_geometry())
4463 return; /* C/H/S not set */
4466 #ifdef CONFIG_FEATURE_SUN_LABEL
4468 sun_delete_partition(i);
4472 #ifdef CONFIG_FEATURE_SGI_LABEL
4474 sgi_delete_partition(i);
4480 if (IS_EXTENDED (p->sys_ind) && i == ext_index) {
4482 ptes[ext_index].ext_pointer = NULL;
4483 extended_offset = 0;
4489 if (!q->sys_ind && i > 4) {
4490 /* the last one in the chain - just delete */
4493 clear_partition(ptes[i].ext_pointer);
4494 ptes[i].changed = 1;
4496 /* not the last one - further ones will be moved down */
4498 /* delete this link in the chain */
4499 p = ptes[i-1].ext_pointer;
4501 set_start_sect(p, get_start_sect(q));
4502 set_nr_sects(p, get_nr_sects(q));
4503 ptes[i-1].changed = 1;
4504 } else if (partitions > 5) { /* 5 will be moved to 4 */
4505 /* the first logical in a longer chain */
4508 if (pe->part_table) /* prevent SEGFAULT */
4509 set_start_sect(pe->part_table,
4510 get_partition_start(pe) -
4512 pe->offset = extended_offset;
4516 if (partitions > 5) {
4518 while (i < partitions) {
4519 ptes[i] = ptes[i+1];
4523 /* the only logical: clear only */
4524 clear_partition(ptes[i].part_table);
4529 change_sysid(void) {
4531 int i, sys, origsys;
4532 struct partition *p;
4534 i = get_existing_partition(0, partitions);
4537 p = ptes[i].part_table;
4538 origsys = sys = get_sysid(i);
4540 /* if changing types T to 0 is allowed, then
4541 the reverse change must be allowed, too */
4542 if (!sys && !sgi_label && !sun_label && !get_nr_sects(p))
4543 printf(_("Partition %d does not exist yet!\n"), i + 1);
4545 sys = read_hex (get_sys_types());
4547 if (!sys && !sgi_label && !sun_label) {
4548 printf(_("Type 0 means free space to many systems\n"
4549 "(but not to Linux). Having partitions of\n"
4550 "type 0 is probably unwise. You can delete\n"
4551 "a partition using the `d' command.\n"));
4555 if (!sun_label && !sgi_label) {
4556 if (IS_EXTENDED (sys) != IS_EXTENDED (p->sys_ind)) {
4557 printf(_("You cannot change a partition into"
4558 " an extended one or vice versa\n"
4559 "Delete it first.\n"));
4565 #ifdef CONFIG_FEATURE_SUN_LABEL
4566 if (sun_label && i == 2 && sys != WHOLE_DISK)
4567 printf(_("Consider leaving partition 3 "
4568 "as Whole disk (5),\n"
4569 "as SunOS/Solaris expects it and "
4570 "even Linux likes it.\n\n"));
4572 #ifdef CONFIG_FEATURE_SGI_LABEL
4573 if (sgi_label && ((i == 10 && sys != ENTIRE_DISK)
4574 || (i == 8 && sys != 0)))
4575 printf(_("Consider leaving partition 9 "
4576 "as volume header (0),\nand "
4577 "partition 11 as entire volume (6)"
4578 "as IRIX expects it.\n\n"));
4582 #ifdef CONFIG_FEATURE_SUN_LABEL
4584 sun_change_sysid(i, sys);
4587 #ifdef CONFIG_FEATURE_SGI_LABEL
4589 sgi_change_sysid(i, sys);
4593 printf (_("Changed system type of partition %d "
4594 "to %x (%s)\n"), i + 1, sys,
4595 (temp = partition_type(sys)) ? temp :
4597 ptes[i].changed = 1;
4598 if (is_dos_partition(origsys) ||
4599 is_dos_partition(sys))
4606 /* check_consistency() and long2chs() added Sat Mar 6 12:28:16 1993,
4607 * faith@cs.unc.edu, based on code fragments from pfdisk by Gordon W. Ross,
4608 * Jan. 1990 (version 1.2.1 by Gordon W. Ross Aug. 1990; Modified by S.
4609 * Lubkin Oct. 1991). */
4611 static void long2chs(ulong ls, uint *c, uint *h, uint *s) {
4612 int spc = heads * sectors;
4617 *s = ls % sectors + 1; /* sectors count from 1 */
4620 static void check_consistency(const struct partition *p, int partition) {
4621 uint pbc, pbh, pbs; /* physical beginning c, h, s */
4622 uint pec, peh, pes; /* physical ending c, h, s */
4623 uint lbc, lbh, lbs; /* logical beginning c, h, s */
4624 uint lec, leh, les; /* logical ending c, h, s */
4626 if (!heads || !sectors || (partition >= 4))
4627 return; /* do not check extended partitions */
4629 /* physical beginning c, h, s */
4630 pbc = (p->cyl & 0xff) | ((p->sector << 2) & 0x300);
4632 pbs = p->sector & 0x3f;
4634 /* physical ending c, h, s */
4635 pec = (p->end_cyl & 0xff) | ((p->end_sector << 2) & 0x300);
4637 pes = p->end_sector & 0x3f;
4639 /* compute logical beginning (c, h, s) */
4640 long2chs(get_start_sect(p), &lbc, &lbh, &lbs);
4642 /* compute logical ending (c, h, s) */
4643 long2chs(get_start_sect(p) + get_nr_sects(p) - 1, &lec, &leh, &les);
4645 /* Same physical / logical beginning? */
4646 if (cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) {
4647 printf(_("Partition %d has different physical/logical "
4648 "beginnings (non-Linux?):\n"), partition + 1);
4649 printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs);
4650 printf(_("logical=(%d, %d, %d)\n"),lbc, lbh, lbs);
4653 /* Same physical / logical ending? */
4654 if (cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) {
4655 printf(_("Partition %d has different physical/logical "
4656 "endings:\n"), partition + 1);
4657 printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
4658 printf(_("logical=(%d, %d, %d)\n"),lec, leh, les);
4662 /* Beginning on cylinder boundary? */
4663 if (pbh != !pbc || pbs != 1) {
4664 printf(_("Partition %i does not start on cylinder "
4665 "boundary:\n"), partition + 1);
4666 printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs);
4667 printf(_("should be (%d, %d, 1)\n"), pbc, !pbc);
4671 /* Ending on cylinder boundary? */
4672 if (peh != (heads - 1) || pes != sectors) {
4673 printf(_("Partition %i does not end on cylinder boundary:\n"),
4676 printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
4677 printf(_("should be (%d, %d, %d)\n"),
4678 pec, heads - 1, sectors);
4684 list_disk_geometry(void) {
4685 long long bytes = (long long) total_number_of_sectors * 512;
4686 long megabytes = bytes/1000000;
4688 if (megabytes < 10000)
4689 printf(_("\nDisk %s: %ld MB, %lld bytes\n"),
4690 disk_device, megabytes, bytes);
4692 printf(_("\nDisk %s: %ld.%ld GB, %lld bytes\n"),
4693 disk_device, megabytes/1000, (megabytes/100)%10, bytes);
4694 printf(_("%d heads, %d sectors/track, %d cylinders"),
4695 heads, sectors, cylinders);
4696 if (units_per_sector == 1)
4697 printf(_(", total %lu sectors"),
4698 total_number_of_sectors / (sector_size/512));
4700 printf(_("Units = %s of %d * %d = %d bytes\n\n"),
4702 units_per_sector, sector_size, units_per_sector * sector_size);
4706 * Check whether partition entries are ordered by their starting positions.
4707 * Return 0 if OK. Return i if partition i should have been earlier.
4708 * Two separate checks: primary and logical partitions.
4711 wrong_p_order(int *prev) {
4712 const struct pte *pe;
4713 const struct partition *p;
4714 uint last_p_start_pos = 0, p_start_pos;
4717 for (i = 0 ; i < partitions; i++) {
4720 last_p_start_pos = 0;
4723 if ((p = pe->part_table)->sys_ind) {
4724 p_start_pos = get_partition_start(pe);
4726 if (last_p_start_pos > p_start_pos) {
4732 last_p_start_pos = p_start_pos;
4739 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
4741 * Fix the chain of logicals.
4742 * extended_offset is unchanged, the set of sectors used is unchanged
4743 * The chain is sorted so that sectors increase, and so that
4744 * starting sectors increase.
4746 * After this it may still be that cfdisk doesnt like the table.
4747 * (This is because cfdisk considers expanded parts, from link to
4748 * end of partition, and these may still overlap.)
4750 * sfdisk /dev/hda > ohda; sfdisk /dev/hda < ohda
4754 fix_chain_of_logicals(void) {
4755 int j, oj, ojj, sj, sjj;
4756 struct partition *pj,*pjj,tmp;
4758 /* Stage 1: sort sectors but leave sector of part 4 */
4759 /* (Its sector is the global extended_offset.) */
4761 for (j = 5; j < partitions-1; j++) {
4762 oj = ptes[j].offset;
4763 ojj = ptes[j+1].offset;
4765 ptes[j].offset = ojj;
4766 ptes[j+1].offset = oj;
4767 pj = ptes[j].part_table;
4768 set_start_sect(pj, get_start_sect(pj)+oj-ojj);
4769 pjj = ptes[j+1].part_table;
4770 set_start_sect(pjj, get_start_sect(pjj)+ojj-oj);
4771 set_start_sect(ptes[j-1].ext_pointer,
4772 ojj-extended_offset);
4773 set_start_sect(ptes[j].ext_pointer,
4774 oj-extended_offset);
4779 /* Stage 2: sort starting sectors */
4781 for (j = 4; j < partitions-1; j++) {
4782 pj = ptes[j].part_table;
4783 pjj = ptes[j+1].part_table;
4784 sj = get_start_sect(pj);
4785 sjj = get_start_sect(pjj);
4786 oj = ptes[j].offset;
4787 ojj = ptes[j+1].offset;
4788 if (oj+sj > ojj+sjj) {
4792 set_start_sect(pj, ojj+sjj-oj);
4793 set_start_sect(pjj, oj+sj-ojj);
4798 /* Probably something was changed */
4799 for (j = 4; j < partitions; j++)
4800 ptes[j].changed = 1;
4806 fix_partition_table_order(void) {
4807 struct pte *pei, *pek;
4810 if (!wrong_p_order(NULL)) {
4811 printf(_("Nothing to do. Ordering is correct already.\n\n"));
4815 while ((i = wrong_p_order(&k)) != 0 && i < 4) {
4816 /* partition i should have come earlier, move it */
4817 /* We have to move data in the MBR */
4818 struct partition *pi, *pk, *pe, pbuf;
4822 pe = pei->ext_pointer;
4823 pei->ext_pointer = pek->ext_pointer;
4824 pek->ext_pointer = pe;
4826 pi = pei->part_table;
4827 pk = pek->part_table;
4829 memmove(&pbuf, pi, sizeof(struct partition));
4830 memmove(pi, pk, sizeof(struct partition));
4831 memmove(pk, &pbuf, sizeof(struct partition));
4833 pei->changed = pek->changed = 1;
4837 fix_chain_of_logicals();
4845 list_table(int xtra) {
4846 const struct partition *p;
4850 #ifdef CONFIG_FEATURE_SUN_LABEL
4852 sun_list_table(xtra);
4857 #ifdef CONFIG_FEATURE_SGI_LABEL
4859 sgi_list_table(xtra);
4864 list_disk_geometry();
4866 #ifdef CONFIG_FEATURE_OSF_LABEL
4868 xbsd_print_disklabel(xtra);
4873 /* Heuristic: we list partition 3 of /dev/foo as /dev/foo3,
4874 but if the device name ends in a digit, say /dev/foo1,
4875 then the partition is called /dev/foo1p3. */
4876 w = strlen(disk_device);
4877 if (w && isdigit(disk_device[w-1]))
4882 printf(_("%*s Boot Start End Blocks Id System\n"),
4885 for (i = 0; i < partitions; i++) {
4886 const struct pte *pe = &ptes[i];
4889 if (p && !is_cleared_partition(p)) {
4890 unsigned int psects = get_nr_sects(p);
4891 unsigned int pblocks = psects;
4892 unsigned int podd = 0;
4894 if (sector_size < 1024) {
4895 pblocks /= (1024 / sector_size);
4896 podd = psects % (1024 / sector_size);
4898 if (sector_size > 1024)
4899 pblocks *= (sector_size / 1024);
4901 "%s %c %9ld %9ld %9ld%c %2x %s\n",
4902 partname(disk_device, i+1, w+2),
4903 /* boot flag */ !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG
4905 /* start */ (long) cround(get_partition_start(pe)),
4906 /* end */ (long) cround(get_partition_start(pe) + psects
4907 - (psects ? 1 : 0)),
4908 /* odd flag on end */ (long) pblocks, podd ? '+' : ' ',
4909 /* type id */ p->sys_ind,
4910 /* type name */ (type = partition_type(p->sys_ind)) ?
4911 type : _("Unknown"));
4912 check_consistency(p, i);
4916 /* Is partition table in disk order? It need not be, but... */
4917 /* partition table entries are not checked for correct order if this
4918 is a sgi, sun or aix labeled disk... */
4919 if (dos_label && wrong_p_order(NULL)) {
4920 printf(_("\nPartition table entries are not in disk order\n"));
4924 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
4926 x_list_table(int extend) {
4927 const struct pte *pe;
4928 const struct partition *p;
4931 printf(_("\nDisk %s: %d heads, %d sectors, %d cylinders\n\n"),
4932 disk_device, heads, sectors, cylinders);
4933 printf(_("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n"));
4934 for (i = 0 ; i < partitions; i++) {
4936 p = (extend ? pe->ext_pointer : pe->part_table);
4938 printf("%2d %02x%4d%4d%5d%4d%4d%5d%9d%9d %02x\n",
4939 i + 1, p->boot_ind, p->head,
4941 cylinder(p->sector, p->cyl), p->end_head,
4942 sector(p->end_sector),
4943 cylinder(p->end_sector, p->end_cyl),
4944 get_start_sect(p), get_nr_sects(p), p->sys_ind);
4946 check_consistency(p, i);
4953 fill_bounds(uint *first, uint *last) {
4955 const struct pte *pe = &ptes[0];
4956 const struct partition *p;
4958 for (i = 0; i < partitions; pe++,i++) {
4960 if (!p->sys_ind || IS_EXTENDED (p->sys_ind)) {
4961 first[i] = 0xffffffff;
4964 first[i] = get_partition_start(pe);
4965 last[i] = first[i] + get_nr_sects(p) - 1;
4971 check(int n, uint h, uint s, uint c, uint start) {
4972 uint total, real_s, real_c;
4974 real_s = sector(s) - 1;
4975 real_c = cylinder(s, c);
4976 total = (real_c * sectors + real_s) * heads + h;
4978 fprintf(stderr, _("Warning: partition %d contains sector 0\n"), n);
4981 _("Partition %d: head %d greater than maximum %d\n"),
4983 if (real_s >= sectors)
4984 fprintf(stderr, _("Partition %d: sector %d greater than "
4985 "maximum %d\n"), n, s, sectors);
4986 if (real_c >= cylinders)
4987 fprintf(stderr, _("Partitions %d: cylinder %d greater than "
4988 "maximum %d\n"), n, real_c + 1, cylinders);
4989 if (cylinders <= 1024 && start != total)
4991 _("Partition %d: previous sectors %d disagrees with "
4992 "total %d\n"), n, start, total);
4999 uint first[partitions], last[partitions];
5000 struct partition *p;
5002 if (warn_geometry())
5005 #ifdef CONFIG_FEATURE_SUN_LABEL
5011 #ifdef CONFIG_FEATURE_SGI_LABEL
5018 fill_bounds(first, last);
5019 for (i = 0; i < partitions; i++) {
5020 struct pte *pe = &ptes[i];
5023 if (p->sys_ind && !IS_EXTENDED (p->sys_ind)) {
5024 check_consistency(p, i);
5025 if (get_partition_start(pe) < first[i])
5026 printf(_("Warning: bad start-of-data in "
5027 "partition %d\n"), i + 1);
5028 check(i + 1, p->end_head, p->end_sector, p->end_cyl,
5030 total += last[i] + 1 - first[i];
5031 for (j = 0; j < i; j++)
5032 if ((first[i] >= first[j] && first[i] <= last[j])
5033 || ((last[i] <= last[j] && last[i] >= first[j]))) {
5034 printf(_("Warning: partition %d overlaps "
5035 "partition %d.\n"), j + 1, i + 1);
5036 total += first[i] >= first[j] ?
5037 first[i] : first[j];
5038 total -= last[i] <= last[j] ?
5044 if (extended_offset) {
5045 struct pte *pex = &ptes[ext_index];
5046 uint e_last = get_start_sect(pex->part_table) +
5047 get_nr_sects(pex->part_table) - 1;
5049 for (i = 4; i < partitions; i++) {
5051 p = ptes[i].part_table;
5053 if (i != 4 || i + 1 < partitions)
5054 printf(_("Warning: partition %d "
5055 "is empty\n"), i + 1);
5057 else if (first[i] < extended_offset ||
5059 printf(_("Logical partition %d not entirely in "
5060 "partition %d\n"), i + 1, ext_index + 1);
5064 if (total > heads * sectors * cylinders)
5065 printf(_("Total allocated sectors %d greater than the maximum "
5066 "%d\n"), total, heads * sectors * cylinders);
5067 else if ((total = heads * sectors * cylinders - total) != 0)
5068 printf(_("%d unallocated sectors\n"), total);
5072 add_partition(int n, int sys) {
5073 char mesg[256]; /* 48 does not suffice in Japanese */
5075 struct partition *p = ptes[n].part_table;
5076 struct partition *q = ptes[ext_index].part_table;
5077 uint start, stop = 0, limit, temp,
5078 first[partitions], last[partitions];
5080 if (p && p->sys_ind) {
5081 printf(_("Partition %d is already defined. Delete "
5082 "it before re-adding it.\n"), n + 1);
5085 fill_bounds(first, last);
5087 start = sector_offset;
5088 if (display_in_cyl_units)
5089 limit = heads * sectors * cylinders - 1;
5091 limit = total_number_of_sectors - 1;
5092 if (extended_offset) {
5093 first[ext_index] = extended_offset;
5094 last[ext_index] = get_start_sect(q) +
5095 get_nr_sects(q) - 1;
5098 start = extended_offset + sector_offset;
5099 limit = get_start_sect(q) + get_nr_sects(q) - 1;
5101 if (display_in_cyl_units)
5102 for (i = 0; i < partitions; i++)
5103 first[i] = (cround(first[i]) - 1) * units_per_sector;
5105 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
5108 for (i = 0; i < partitions; i++) {
5111 if (start == ptes[i].offset)
5112 start += sector_offset;
5113 lastplusoff = last[i] + ((n<4) ? 0 : sector_offset);
5114 if (start >= first[i] && start <= lastplusoff)
5115 start = lastplusoff + 1;
5119 if (start >= temp+units_per_sector && readed) {
5120 printf(_("Sector %d is already allocated\n"), temp);
5124 if (!readed && start == temp) {
5127 saved_start = start;
5128 start = read_int(cround(saved_start), cround(saved_start), cround(limit),
5130 if (display_in_cyl_units) {
5131 start = (start - 1) * units_per_sector;
5132 if (start < saved_start) start = saved_start;
5136 } while (start != temp || !readed);
5137 if (n > 4) { /* NOT for fifth partition */
5138 struct pte *pe = &ptes[n];
5140 pe->offset = start - sector_offset;
5141 if (pe->offset == extended_offset) { /* must be corrected */
5143 if (sector_offset == 1)
5148 for (i = 0; i < partitions; i++) {
5149 struct pte *pe = &ptes[i];
5151 if (start < pe->offset && limit >= pe->offset)
5152 limit = pe->offset - 1;
5153 if (start < first[i] && limit >= first[i])
5154 limit = first[i] - 1;
5156 if (start > limit) {
5157 printf(_("No free sectors available\n"));
5162 if (cround(start) == cround(limit)) {
5165 snprintf(mesg, sizeof(mesg),
5166 _("Last %s or +size or +sizeM or +sizeK"),
5167 str_units(SINGULAR));
5168 stop = read_int(cround(start), cround(limit), cround(limit),
5169 cround(start), mesg);
5170 if (display_in_cyl_units) {
5171 stop = stop * units_per_sector - 1;
5177 set_partition(n, 0, start, stop, sys);
5179 set_partition(n - 1, 1, ptes[n].offset, stop, EXTENDED);
5181 if (IS_EXTENDED (sys)) {
5182 struct pte *pe4 = &ptes[4];
5183 struct pte *pen = &ptes[n];
5186 pen->ext_pointer = p;
5187 pe4->offset = extended_offset = start;
5188 pe4->sectorbuffer = xcalloc(1, sector_size);
5189 pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
5190 pe4->ext_pointer = pe4->part_table + 1;
5198 if (partitions > 5 || ptes[4].part_table->sys_ind) {
5199 struct pte *pe = &ptes[partitions];
5201 pe->sectorbuffer = xcalloc(1, sector_size);
5202 pe->part_table = pt_offset(pe->sectorbuffer, 0);
5203 pe->ext_pointer = pe->part_table + 1;
5208 add_partition(partitions - 1, LINUX_NATIVE);
5212 new_partition(void) {
5213 int i, free_primary = 0;
5215 if (warn_geometry())
5218 #ifdef CONFIG_FEATURE_SUN_LABEL
5220 add_sun_partition(get_partition(0, partitions), LINUX_NATIVE);
5224 #ifdef CONFIG_FEATURE_SGI_LABEL
5226 sgi_add_partition(get_partition(0, partitions), LINUX_NATIVE);
5230 #ifdef CONFIG_FEATURE_AIX_LABEL
5232 printf(_("\tSorry - this fdisk cannot handle AIX disk labels."
5233 "\n\tIf you want to add DOS-type partitions, create"
5234 "\n\ta new empty DOS partition table first. (Use o.)"
5236 "This will destroy the present disk contents.\n"));
5241 if (partitions >= MAXIMUM_PARTS) {
5242 printf(_("The maximum number of partitions has been created\n"));
5246 for (i = 0; i < 4; i++)
5247 free_primary += !ptes[i].part_table->sys_ind;
5248 if (!free_primary) {
5249 if (extended_offset)
5252 printf(_("You must delete some partition and add "
5253 "an extended partition first\n"));
5255 char c, line[LINE_LENGTH];
5256 snprintf(line, sizeof(line), "%s\n %s\n p primary "
5257 "partition (1-4)\n",
5258 "Command action", (extended_offset ?
5259 "l logical (5 or over)" : "e extended"));
5261 if ((c = read_char(line)) == 'p' || c == 'P') {
5262 i = get_nonexisting_partition(0, 4);
5264 add_partition(i, LINUX_NATIVE);
5267 else if (c == 'l' && extended_offset) {
5271 else if (c == 'e' && !extended_offset) {
5272 i = get_nonexisting_partition(0, 4);
5274 add_partition(i, EXTENDED);
5278 printf(_("Invalid partition number "
5279 "for type `%c'\n"), c);
5290 if (ptes[i].changed)
5291 ptes[3].changed = 1;
5292 for (i = 3; i < partitions; i++) {
5293 struct pte *pe = &ptes[i];
5296 write_part_table_flag(pe->sectorbuffer);
5297 write_sector(pe->offset, pe->sectorbuffer);
5301 #ifdef CONFIG_FEATURE_SGI_LABEL
5302 else if (sgi_label) {
5303 /* no test on change? the printf below might be mistaken */
5307 #ifdef CONFIG_FEATURE_SUN_LABEL
5308 else if (sun_label) {
5312 if (ptes[i].changed)
5319 printf(_("The partition table has been altered!\n\n"));
5320 reread_partition_table(1);
5324 reread_partition_table(int leave) {
5328 printf(_("Calling ioctl() to re-read partition table.\n"));
5331 if ((i = ioctl(fd, BLKRRPART)) != 0) {
5334 /* some kernel versions (1.2.x) seem to have trouble
5335 rereading the partition table, but if asked to do it
5336 twice, the second time works. - biro@yggdrasil.com */
5339 if ((i = ioctl(fd, BLKRRPART)) != 0)
5344 printf(_("\nWARNING: Re-reading the partition table "
5345 "failed with error %d: %s.\n"
5346 "The kernel still uses the old table.\n"
5347 "The new table will be used "
5348 "at the next reboot.\n"),
5349 error, strerror(error));
5354 _("\nWARNING: If you have created or modified any DOS 6.x\n"
5355 "partitions, please see the fdisk manual page for additional\n"
5361 printf(_("Syncing disks.\n"));
5363 sleep(4); /* for sync() */
5368 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
5369 #define MAX_PER_LINE 16
5371 print_buffer(char pbuffer[]) {
5375 for (i = 0, l = 0; i < sector_size; i++, l++) {
5377 printf("0x%03X:", i);
5378 printf(" %02X", (unsigned char) pbuffer[i]);
5379 if (l == MAX_PER_LINE - 1) {
5394 printf(_("Device: %s\n"), disk_device);
5395 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
5396 if (sun_label || sgi_label)
5397 print_buffer(MBRbuffer);
5400 for (i = 3; i < partitions; i++)
5401 print_buffer(ptes[i].sectorbuffer);
5406 struct pte *pe = &ptes[i];
5407 struct partition *p = pe->part_table;
5410 if (warn_geometry())
5412 if (!p->sys_ind || !get_nr_sects(p) || IS_EXTENDED (p->sys_ind)) {
5413 printf(_("Partition %d has no data area\n"), i + 1);
5416 first = get_partition_start(pe);
5417 new = read_int(first, first, first + get_nr_sects(p) - 1, first,
5418 _("New beginning of data")) - pe->offset;
5420 if (new != get_nr_sects(p)) {
5421 first = get_nr_sects(p) + get_start_sect(p) - new;
5422 set_nr_sects(p, first);
5423 set_start_sect(p, new);
5434 c = tolower(read_char(_("Expert command (m for help): ")));
5437 #ifdef CONFIG_FEATURE_SUN_LABEL
5444 move_begin(get_partition(0, partitions));
5447 user_cylinders = cylinders =
5448 read_int(1, cylinders, 1048576, 0,
5449 _("Number of cylinders"));
5450 #ifdef CONFIG_FEATURE_SUN_LABEL
5452 sun_set_ncyl(cylinders);
5461 #ifdef CONFIG_FEATURE_SGI_LABEL
5466 #ifdef CONFIG_FEATURE_SUN_LABEL
5476 fix_partition_table_order();
5479 #ifdef CONFIG_FEATURE_SGI_LABEL
5484 user_heads = heads = read_int(1, heads, 256, 0,
5485 _("Number of heads"));
5489 #ifdef CONFIG_FEATURE_SUN_LABEL
5495 #ifdef CONFIG_FEATURE_SUN_LABEL
5501 #ifdef CONFIG_FEATURE_SUN_LABEL
5515 user_sectors = sectors = read_int(1, sectors, 63, 0,
5516 _("Number of sectors"));
5517 if (dos_compatible_flag) {
5518 sector_offset = sectors;
5519 fprintf(stderr, _("Warning: setting "
5520 "sector offset for DOS "
5529 write_table(); /* does not return */
5532 #ifdef CONFIG_FEATURE_SUN_LABEL
5534 sun_set_pcylcount();
5542 #endif /* ADVANCED mode */
5545 is_ide_cdrom_or_tape(const char *device) {
5548 struct stat statbuf;
5551 /* No device was given explicitly, and we are trying some
5552 likely things. But opening /dev/hdc may produce errors like
5553 "hdc: tray open or drive not ready"
5554 if it happens to be a CD-ROM drive. It even happens that
5555 the process hangs on the attempt to read a music CD.
5556 So try to be careful. This only works since 2.1.73. */
5558 if (strncmp("/dev/hd", device, 7))
5561 snprintf(buf, sizeof(buf), "/proc/ide/%s/media", device+5);
5562 procf = fopen(buf, "r");
5563 if (procf != NULL && fgets(buf, sizeof(buf), procf))
5564 is_ide = (!strncmp(buf, "cdrom", 5) ||
5565 !strncmp(buf, "tape", 4));
5567 /* Now when this proc file does not exist, skip the
5568 device when it is read-only. */
5569 if (stat(device, &statbuf) == 0)
5570 is_ide = ((statbuf.st_mode & 0222) == 0);
5578 try(const char *device, int user_specified) {
5581 disk_device = device;
5582 if (setjmp(listingbuf))
5584 if (!user_specified)
5585 if (is_ide_cdrom_or_tape(device))
5587 if ((fd = open(disk_device, type_open)) >= 0) {
5588 gb = get_boot(try_only);
5589 if (gb > 0) { /* I/O error */
5591 } else if (gb < 0) { /* no DOS signature */
5592 list_disk_geometry();
5595 #ifdef CONFIG_FEATURE_OSF_LABEL
5596 if (btrydev(device) < 0)
5599 _("Disk %s doesn't contain a valid "
5600 "partition table\n"), device);
5605 if (!sun_label && partitions > 4)
5606 delete_partition(ext_index);
5609 /* Ignore other errors, since we try IDE
5610 and SCSI hard disks which may not be
5611 installed on the system. */
5612 if (errno == EACCES) {
5613 fprintf(stderr, _("Cannot open %s\n"), device);
5619 /* for fdisk -l: try all things in /proc/partitions
5620 that look like a partition name (do not end in a digit) */
5624 char line[100], ptname[100], devname[120], *s;
5627 procpt = wfopen(PROC_PARTITIONS, "r");
5629 while (fgets(line, sizeof(line), procpt)) {
5630 if (sscanf (line, " %d %d %d %[^\n ]",
5631 &ma, &mi, &sz, ptname) != 4)
5633 for (s = ptname; *s; s++);
5636 snprintf(devname, sizeof(devname), "/dev/%s", ptname);
5643 unknown_command(int c) {
5644 printf(_("%c: unknown command\n"), c);
5647 int fdisk_main(int argc, char **argv) {
5649 int optl = 0, opts = 0;
5654 * fdisk -l [-b sectorsize] [-u] device ...
5655 * fdisk -s [partition] ...
5656 * fdisk [-b sectorsize] [-u] device
5658 * Options -C, -H, -S set the geometry.
5661 while ((c = getopt(argc, argv, "b:C:H:lsS:uvV")) != -1) {
5664 /* Ugly: this sector size is really per device,
5665 so cannot be combined with multiple disks,
5666 and te same goes for the C/H/S options.
5668 sector_size = atoi(optarg);
5669 if (sector_size != 512 && sector_size != 1024 &&
5670 sector_size != 2048)
5673 user_set_sector_size = 1;
5676 user_cylinders = atoi(optarg);
5679 user_heads = atoi(optarg);
5680 if (user_heads <= 0 || user_heads >= 256)
5684 user_sectors = atoi(optarg);
5685 if (user_sectors <= 0 || user_sectors >= 64)
5695 display_in_cyl_units = 0;
5699 printf("fdisk v" UTIL_LINUX_VERSION "\n");
5707 printf(_("This kernel finds the sector size itself - "
5708 "-b option ignored\n"));
5710 if (user_set_sector_size && argc-optind != 1)
5711 printf(_("Warning: the -b (set sector size) option should"
5712 " be used with one specified device\n"));
5717 type_open = O_RDONLY;
5718 if (argc > optind) {
5721 /* avoid gcc warning:
5722 variable `k' might be clobbered by `longjmp' */
5726 for (k=optind; k<argc; k++)
5729 /* we no longer have default device names */
5730 /* but, we can use /proc/partitions instead */
5740 type_open = O_RDONLY;
5742 opts = argc - optind;
5746 for (j = optind; j < argc; j++) {
5747 disk_device = argv[j];
5748 if ((fd = open(disk_device, type_open)) < 0)
5749 fdisk_fatal(unable_to_open);
5750 if (ioctl(fd, BLKGETSIZE, &size))
5751 fdisk_fatal(ioctl_error);
5754 printf("%ld\n", size/2);
5756 printf("%s: %ld\n", argv[j], size/2);
5761 if (argc-optind == 1)
5762 disk_device = argv[optind];
5768 #ifdef CONFIG_FEATURE_OSF_LABEL
5770 /* OSF label, and no DOS label */
5771 printf(_("Detected an OSF/1 disklabel on %s, entering "
5772 "disklabel mode.\n"),
5776 /* If we return we may want to make an empty DOS label? */
5782 c = tolower(read_char(_("Command (m for help): ")));
5786 toggle_active(get_partition(1, partitions));
5787 #ifdef CONFIG_FEATURE_SUN_LABEL
5789 toggle_sunflags(get_partition(1, partitions),
5792 #ifdef CONFIG_FEATURE_SGI_LABEL
5794 sgi_set_bootpartition(
5795 get_partition(1, partitions));
5801 #ifdef CONFIG_FEATURE_SGI_LABEL
5803 printf(_("\nThe current boot file is: %s\n"),
5804 sgi_get_bootfile());
5805 if (read_chars(_("Please enter the name of the "
5806 "new boot file: ")) == '\n')
5807 printf(_("Boot file unchanged\n"));
5809 sgi_set_bootfile(line_ptr);
5812 #ifdef CONFIG_FEATURE_OSF_LABEL
5818 toggle_dos_compatibility_flag();
5819 #ifdef CONFIG_FEATURE_SUN_LABEL
5821 toggle_sunflags(get_partition(1, partitions),
5824 #ifdef CONFIG_FEATURE_SGI_LABEL
5826 sgi_set_swappartition(
5827 get_partition(1, partitions));
5833 j = get_existing_partition(1, partitions);
5835 delete_partition(j);
5838 #ifdef CONFIG_FEATURE_SGI_LABEL
5845 list_types(get_sys_types());
5864 #ifdef CONFIG_FEATURE_SUN_LABEL
5878 write_table(); /* does not return */
5880 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
5882 #ifdef CONFIG_FEATURE_SGI_LABEL
5885 _("\n\tSorry, no experts menu for SGI "
5886 "partition tables available.\n\n"));