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.11z"
24 #define PROC_PARTITIONS "/proc/partitions"
26 #include <sys/types.h>
27 #include <sys/stat.h> /* stat */
36 #include <assert.h> /* assert */
40 #define u_char unsigned char
41 #include <scsi/scsi.h> /* SCSI_IOCTL_GET_IDLUN */
44 #include <sys/ioctl.h>
45 #include <sys/param.h>
47 #include <stdint.h> /* for uint32_t, uint16_t, uint8_t, int16_t, etc */
49 /* Copied from linux/major.h */
50 #define FLOPPY_MAJOR 2
52 #include <sys/utsname.h>
56 #define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r))
62 #define BLKRRPART _IO(0x12,95) /* re-read partition table */
63 #define BLKGETSIZE _IO(0x12,96) /* return device size */
64 #define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */
65 #define BLKSSZGET _IO(0x12,104) /* get block device sector size */
72 #define DEFAULT_SECTOR_SIZE 512
73 #define MAX_SECTOR_SIZE 2048
74 #define SECTOR_SIZE 512 /* still used in BSD code */
75 #define MAXIMUM_PARTS 60
77 #define ACTIVE_FLAG 0x80
80 #define WIN98_EXTENDED 0x0f
81 #define LINUX_PARTITION 0x81
82 #define LINUX_SWAP 0x82
83 #define LINUX_NATIVE 0x83
84 #define LINUX_EXTENDED 0x85
85 #define LINUX_LVM 0x8e
86 #define LINUX_RAID 0xfd
91 #define IS_EXTENDED(i) \
92 ((i) == EXTENDED || (i) == WIN98_EXTENDED || (i) == LINUX_EXTENDED)
94 #define SIZE(a) (sizeof(a)/sizeof((a)[0]))
96 #define cround(n) (display_in_cyl_units ? ((n)/units_per_sector)+1 : (n))
97 #define scround(x) (((x)+units_per_sector-1)/units_per_sector)
99 #if defined(__GNUC__) || defined(HAS_LONG_LONG)
100 typedef long long ext2_loff_t;
102 typedef long ext2_loff_t;
105 /* including <linux/hdreg.h> also fails */
108 unsigned char sectors;
109 unsigned short cylinders;
113 #define HDIO_GETGEO 0x0301 /* get device geometry */
117 const unsigned char *name;
122 * Raw disk label. For DOS-type partition tables the MBR,
123 * with descriptions of the primary partitions.
125 static char MBRbuffer[MAX_SECTOR_SIZE];
127 #ifdef CONFIG_FEATURE_SUN_LABEL
128 static int sun_label; /* looking at sun disklabel */
132 #ifdef CONFIG_FEATURE_SGI_LABEL
133 static int sgi_label; /* looking at sgi disklabel */
137 #ifdef CONFIG_FEATURE_AIX_LABEL
138 static int aix_label; /* looking at aix disklabel */
142 #ifdef CONFIG_FEATURE_OSF_LABEL
143 static int osf_label; /* looking at OSF/1 disklabel */
144 static int possibly_osf_label;
149 #define dos_label (!sun_label && !sgi_label && !aix_label && !osf_label)
151 static uint heads, sectors, cylinders;
152 static void update_units(void);
156 * return partition name - uses static storage unless buf is supplied
159 partname(const char *dev, int pno, int lth) {
160 static char buffer[80];
167 bufsiz = sizeof(buffer);
172 if (isdigit(dev[w-1]))
175 /* devfs kludge - note: fdisk partition names are not supposed
176 to equal kernel names, so there is no reason to do this */
177 if (strcmp (dev + w - 4, "disc") == 0) {
185 snprintf(bufp, bufsiz, "%*.*s%s%-2u",
186 lth-wp-2, w, dev, p, pno);
188 snprintf(bufp, bufsiz, "%.*s%s%-2u", w, dev, p, pno);
194 unsigned char boot_ind; /* 0x80 - active */
195 unsigned char head; /* starting head */
196 unsigned char sector; /* starting sector */
197 unsigned char cyl; /* starting cylinder */
198 unsigned char sys_ind; /* What partition type */
199 unsigned char end_head; /* end head */
200 unsigned char end_sector; /* end sector */
201 unsigned char end_cyl; /* end cylinder */
202 unsigned char start4[4]; /* starting sector counting from 0 */
203 unsigned char size4[4]; /* nr of sectors in partition */
207 ioctl_error, unable_to_open, unable_to_read, unable_to_seek,
211 enum action {fdisk, require, try_only, create_empty_dos, create_empty_sun};
213 static const char *disk_device;
214 static int fd; /* the disk */
215 static int partitions = 4; /* maximum partition + 1 */
216 static uint display_in_cyl_units = 1;
217 static uint units_per_sector = 1;
218 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
219 static char *line_ptr;
220 static void change_units(void);
221 static void reread_partition_table(int leave);
222 static void delete_partition(int i);
223 static int get_partition(int warn, int max);
224 static void list_types(const struct systypes *sys);
225 static uint read_int(uint low, uint dflt, uint high, uint base, char *mesg);
227 static const char *partition_type(unsigned char type);
228 static void fdisk_fatal(enum failure why) __attribute__ ((noreturn));
229 static void get_geometry(void);
230 static int get_boot(enum action what);
235 #define hex_val(c) ({ \
237 isdigit(_c) ? _c - '0' : \
238 tolower(_c) + 10 - 'a'; \
242 #define LINE_LENGTH 800
243 #define pt_offset(b, n) ((struct partition *)((b) + 0x1be + \
244 (n) * sizeof(struct partition)))
245 #define sector(s) ((s) & 0x3f)
246 #define cylinder(s, c) ((c) | (((s) & 0xc0) << 2))
248 #define hsc2sector(h,s,c) (sector(s) - 1 + sectors * \
249 ((h) + heads * cylinder(s,c)))
250 #define set_hsc(h,s,c,sector) { \
251 s = sector % sectors + 1; \
253 h = sector % heads; \
256 s |= (sector >> 2) & 0xc0; \
260 static unsigned int get_start_sect(const struct partition *p);
261 static unsigned int get_nr_sects(const struct partition *p);
264 * per partition table entry data
266 * The four primary partitions have the same sectorbuffer (MBRbuffer)
267 * and have NULL ext_pointer.
268 * Each logical partition table entry has two pointers, one for the
269 * partition and one link to the next one.
272 struct partition *part_table; /* points into sectorbuffer */
273 struct partition *ext_pointer; /* points into sectorbuffer */
274 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
275 char changed; /* boolean */
277 uint offset; /* disk sector number */
278 char *sectorbuffer; /* disk sector contents */
279 } ptes[MAXIMUM_PARTS];
282 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
284 set_all_unchanged(void) {
287 for (i = 0; i < MAXIMUM_PARTS; i++)
295 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
297 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_OSF_LABEL)
298 static struct partition *
299 get_part_table(int i) {
300 return ptes[i].part_table;
305 str_units(int n) { /* n==1: use singular */
307 return display_in_cyl_units ? _("cylinder") : _("sector");
309 return display_in_cyl_units ? _("cylinders") : _("sectors");
313 valid_part_table_flag(const unsigned char *b) {
314 return (b[510] == 0x55 && b[511] == 0xaa);
317 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
318 static char line_buffer[LINE_LENGTH];
320 /* read line; return 0 or first char */
324 static int got_eof = 0;
326 fflush (stdout); /* requested by niles@scyld.com */
327 line_ptr = line_buffer;
328 if (!fgets(line_buffer, LINE_LENGTH, stdin)) {
330 got_eof++; /* user typed ^D ? */
332 fprintf(stderr, _("\ngot EOF thrice - exiting..\n"));
337 while (*line_ptr && !isgraph(*line_ptr))
343 read_char(const char *mesg)
347 } while (!read_line());
352 read_chars(const char *mesg)
363 read_hex(const struct systypes *sys)
369 read_char(_("Hex code (type L to list codes): "));
370 if (*line_ptr == 'l' || *line_ptr == 'L')
372 else if (isxdigit (*line_ptr))
376 hex = hex << 4 | hex_val(*line_ptr++);
377 while (isxdigit(*line_ptr));
382 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
384 #ifdef CONFIG_FEATURE_AIX_LABEL
386 * Copyright (C) Andreas Neuper, Sep 1998.
387 * This file may be redistributed under
388 * the terms of the GNU Public License.
392 unsigned int magic; /* expect AIX_LABEL_MAGIC */
393 unsigned int fillbytes1[124];
394 unsigned int physical_volume_id;
395 unsigned int fillbytes2[124];
398 #define AIX_LABEL_MAGIC 0xc9c2d4c1
399 #define AIX_LABEL_MAGIC_SWAPPED 0xc1d4c2c9
400 #define AIX_INFO_MAGIC 0x00072959
401 #define AIX_INFO_MAGIC_SWAPPED 0x59290700
403 #define aixlabel ((aix_partition *)MBRbuffer)
408 Sat Mar 20 09:51:38 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
412 static int aix_other_endian;
413 static short aix_volumes=1;
416 * only dealing with free blocks here
422 _("\n\tThere is a valid AIX label on this disk.\n"
423 "\tUnfortunately Linux cannot handle these\n"
424 "\tdisks at the moment. Nevertheless some\n"
426 "\t1. fdisk will destroy its contents on write.\n"
427 "\t2. Be sure that this disk is NOT a still vital\n"
428 "\t part of a volume group. (Otherwise you may\n"
429 "\t erase the other disks as well, if unmirrored.)\n"
430 "\t3. Before deleting this physical volume be sure\n"
431 "\t to remove the disk logically from your AIX\n"
432 "\t machine. (Otherwise you become an AIXpert).")
442 memset( MBRbuffer, 0, sizeof(MBRbuffer) ); /* avoid fdisk cores */
447 check_aix_label( void )
449 if (aixlabel->magic != AIX_LABEL_MAGIC &&
450 aixlabel->magic != AIX_LABEL_MAGIC_SWAPPED) {
452 aix_other_endian = 0;
455 aix_other_endian = (aixlabel->magic == AIX_LABEL_MAGIC_SWAPPED);
461 aix_nolabel(); /* %% */
462 aix_label = 1; /* %% */
465 #endif /* AIX_LABEL */
467 #ifdef CONFIG_FEATURE_OSF_LABEL
469 * Copyright (c) 1987, 1988 Regents of the University of California.
470 * All rights reserved.
472 * Redistribution and use in source and binary forms, with or without
473 * modification, are permitted provided that the following conditions
475 * 1. Redistributions of source code must retain the above copyright
476 * notice, this list of conditions and the following disclaimer.
477 * 2. Redistributions in binary form must reproduce the above copyright
478 * notice, this list of conditions and the following disclaimer in the
479 * documentation and/or other materials provided with the distribution.
480 * 3. All advertising materials mentioning features or use of this software
481 * must display the following acknowledgement:
482 * This product includes software developed by the University of
483 * California, Berkeley and its contributors.
484 * 4. Neither the name of the University nor the names of its contributors
485 * may be used to endorse or promote products derived from this software
486 * without specific prior written permission.
488 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
489 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
490 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
491 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
492 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
493 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
494 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
495 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
496 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
497 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
502 #ifndef BSD_DISKMAGIC
503 #define BSD_DISKMAGIC ((uint32_t) 0x82564557)
506 #ifndef BSD_MAXPARTITIONS
507 #define BSD_MAXPARTITIONS 16
510 #define BSD_LINUX_BOOTDIR "/usr/ucb/mdec"
512 #if defined (i386) || defined (__sparc__) || defined (__arm__) || defined (__mips__) || defined (__s390__) || defined (__sh__) || defined(__x86_64__)
513 #define BSD_LABELSECTOR 1
514 #define BSD_LABELOFFSET 0
515 #elif defined (__alpha__) || defined (__powerpc__) || defined (__ia64__) || defined (__hppa__)
516 #define BSD_LABELSECTOR 0
517 #define BSD_LABELOFFSET 64
519 #error unknown architecture
522 #define BSD_BBSIZE 8192 /* size of boot area, with label */
523 #define BSD_SBSIZE 8192 /* max size of fs superblock */
525 struct xbsd_disklabel {
526 uint32_t d_magic; /* the magic number */
527 int16_t d_type; /* drive type */
528 int16_t d_subtype; /* controller/d_type specific */
529 char d_typename[16]; /* type name, e.g. "eagle" */
530 char d_packname[16]; /* pack identifier */
532 uint32_t d_secsize; /* # of bytes per sector */
533 uint32_t d_nsectors; /* # of data sectors per track */
534 uint32_t d_ntracks; /* # of tracks per cylinder */
535 uint32_t d_ncylinders; /* # of data cylinders per unit */
536 uint32_t d_secpercyl; /* # of data sectors per cylinder */
537 uint32_t d_secperunit; /* # of data sectors per unit */
539 * Spares (bad sector replacements) below
540 * are not counted in d_nsectors or d_secpercyl.
541 * Spare sectors are assumed to be physical sectors
542 * which occupy space at the end of each track and/or cylinder.
544 uint16_t d_sparespertrack; /* # of spare sectors per track */
545 uint16_t d_sparespercyl; /* # of spare sectors per cylinder */
547 * Alternate cylinders include maintenance, replacement,
548 * configuration description areas, etc.
550 uint32_t d_acylinders; /* # of alt. cylinders per unit */
552 /* hardware characteristics: */
554 * d_interleave, d_trackskew and d_cylskew describe perturbations
555 * in the media format used to compensate for a slow controller.
556 * Interleave is physical sector interleave, set up by the formatter
557 * or controller when formatting. When interleaving is in use,
558 * logically adjacent sectors are not physically contiguous,
559 * but instead are separated by some number of sectors.
560 * It is specified as the ratio of physical sectors traversed
561 * per logical sector. Thus an interleave of 1:1 implies contiguous
562 * layout, while 2:1 implies that logical sector 0 is separated
563 * by one sector from logical sector 1.
564 * d_trackskew is the offset of sector 0 on track N
565 * relative to sector 0 on track N-1 on the same cylinder.
566 * Finally, d_cylskew is the offset of sector 0 on cylinder N
567 * relative to sector 0 on cylinder N-1.
569 uint16_t d_rpm; /* rotational speed */
570 uint16_t d_interleave; /* hardware sector interleave */
571 uint16_t d_trackskew; /* sector 0 skew, per track */
572 uint16_t d_cylskew; /* sector 0 skew, per cylinder */
573 uint32_t d_headswitch; /* head switch time, usec */
574 uint32_t d_trkseek; /* track-to-track seek, usec */
575 uint32_t d_flags; /* generic flags */
577 uint32_t d_drivedata[NDDATA]; /* drive-type specific information */
579 uint32_t d_spare[NSPARE]; /* reserved for future use */
580 uint32_t d_magic2; /* the magic number (again) */
581 uint16_t d_checksum; /* xor of data incl. partitions */
582 /* filesystem and partition information: */
583 uint16_t d_npartitions; /* number of partitions in following */
584 uint32_t d_bbsize; /* size of boot area at sn0, bytes */
585 uint32_t d_sbsize; /* max size of fs superblock, bytes */
586 struct xbsd_partition { /* the partition table */
587 uint32_t p_size; /* number of sectors in partition */
588 uint32_t p_offset; /* starting sector */
589 uint32_t p_fsize; /* filesystem basic fragment size */
590 uint8_t p_fstype; /* filesystem type, see below */
591 uint8_t p_frag; /* filesystem fragments per block */
592 uint16_t p_cpg; /* filesystem cylinders per group */
593 } d_partitions[BSD_MAXPARTITIONS]; /* actually may be more */
597 #define BSD_DTYPE_SMD 1 /* SMD, XSMD; VAX hp/up */
598 #define BSD_DTYPE_MSCP 2 /* MSCP */
599 #define BSD_DTYPE_DEC 3 /* other DEC (rk, rl) */
600 #define BSD_DTYPE_SCSI 4 /* SCSI */
601 #define BSD_DTYPE_ESDI 5 /* ESDI interface */
602 #define BSD_DTYPE_ST506 6 /* ST506 etc. */
603 #define BSD_DTYPE_HPIB 7 /* CS/80 on HP-IB */
604 #define BSD_DTYPE_HPFL 8 /* HP Fiber-link */
605 #define BSD_DTYPE_FLOPPY 10 /* floppy */
607 /* d_subtype values: */
608 #define BSD_DSTYPE_INDOSPART 0x8 /* is inside dos partition */
609 #define BSD_DSTYPE_DOSPART(s) ((s) & 3) /* dos partition number */
610 #define BSD_DSTYPE_GEOMETRY 0x10 /* drive params in label */
613 static const char * const xbsd_dktypenames[] = {
627 #define BSD_DKMAXTYPES (sizeof(xbsd_dktypenames) / sizeof(xbsd_dktypenames[0]) - 1)
631 * Filesystem type and version.
632 * Used to interpret other filesystem-specific
633 * per-partition information.
635 #define BSD_FS_UNUSED 0 /* unused */
636 #define BSD_FS_SWAP 1 /* swap */
637 #define BSD_FS_V6 2 /* Sixth Edition */
638 #define BSD_FS_V7 3 /* Seventh Edition */
639 #define BSD_FS_SYSV 4 /* System V */
640 #define BSD_FS_V71K 5 /* V7 with 1K blocks (4.1, 2.9) */
641 #define BSD_FS_V8 6 /* Eighth Edition, 4K blocks */
642 #define BSD_FS_BSDFFS 7 /* 4.2BSD fast file system */
643 #define BSD_FS_BSDLFS 9 /* 4.4BSD log-structured file system */
644 #define BSD_FS_OTHER 10 /* in use, but unknown/unsupported */
645 #define BSD_FS_HPFS 11 /* OS/2 high-performance file system */
646 #define BSD_FS_ISO9660 12 /* ISO-9660 filesystem (cdrom) */
647 #define BSD_FS_ISOFS BSD_FS_ISO9660
648 #define BSD_FS_BOOT 13 /* partition contains bootstrap */
649 #define BSD_FS_ADOS 14 /* AmigaDOS fast file system */
650 #define BSD_FS_HFS 15 /* Macintosh HFS */
651 #define BSD_FS_ADVFS 16 /* Digital Unix AdvFS */
653 /* this is annoying, but it's also the way it is :-( */
655 #define BSD_FS_EXT2 8 /* ext2 file system */
657 #define BSD_FS_MSDOS 8 /* MS-DOS file system */
661 static const struct systypes xbsd_fstypes[] = {
662 /* BSD_FS_UNUSED */ {"\x00" "unused"},
663 /* BSD_FS_SWAP */ {"\x01" "swap"},
664 /* BSD_FS_V6 */ {"\x02" "Version 6"},
665 /* BSD_FS_V7 */ {"\x03" "Version 7"},
666 /* BSD_FS_SYSV */ {"\x04" "System V"},
667 /* BSD_FS_V71K */ {"\x05" "4.1BSD"},
668 /* BSD_FS_V8 */ {"\x06" "Eighth Edition"},
669 /* BSD_FS_BSDFFS */ {"\x07" "4.2BSD"},
671 /* BSD_FS_EXT2 */ {"\x08" "ext2"},
673 /* BSD_FS_MSDOS */ {"\x08" "MS-DOS"},
675 /* BSD_FS_BSDLFS */ {"\x09" "4.4LFS"},
676 /* BSD_FS_OTHER */ {"\x0a" "unknown"},
677 /* BSD_FS_HPFS */ {"\x0b" "HPFS"},
678 /* BSD_FS_ISO9660 */ {"\x0c" "ISO-9660"},
679 /* BSD_FS_BOOT */ {"\x0d" "boot"},
680 /* BSD_FS_ADOS */ {"\x0e" "ADOS"},
681 /* BSD_FS_HFS */ {"\x0f" "HFS"},
682 /* BSD_FS_ADVFS */ {"\x10" "AdvFS"},
685 #define BSD_FSMAXTYPES (SIZE(xbsd_fstypes)-1)
690 * flags shared by various drives:
692 #define BSD_D_REMOVABLE 0x01 /* removable media */
693 #define BSD_D_ECC 0x02 /* supports ECC */
694 #define BSD_D_BADSECT 0x04 /* supports bad sector forw. */
695 #define BSD_D_RAMDISK 0x08 /* disk emulator */
696 #define BSD_D_CHAIN 0x10 /* can do back-back transfers */
697 #define BSD_D_DOSPART 0x20 /* within MSDOS partition */
699 #endif /* OSF_LABEL */
702 * Copyright (C) Andreas Neuper, Sep 1998.
703 * This file may be modified and redistributed under
704 * the terms of the GNU Public License.
707 struct device_parameter { /* 48 bytes */
711 unsigned char sparecyl;
712 unsigned short pcylcount;
713 unsigned short head_vol0;
714 unsigned short ntrks; /* tracks in cyl 0 or vol 0 */
715 unsigned char cmd_tag_queue_depth;
716 unsigned char unused0;
717 unsigned short unused1;
718 unsigned short nsect; /* sectors/tracks in cyl 0 or vol 0 */
719 unsigned short bytes;
720 unsigned short ilfact;
721 unsigned int flags; /* controller flags */
722 unsigned int datarate;
723 unsigned int retries_on_error;
724 unsigned int ms_per_word;
725 unsigned short xylogics_gap1;
726 unsigned short xylogics_syncdelay;
727 unsigned short xylogics_readdelay;
728 unsigned short xylogics_gap2;
729 unsigned short xylogics_readgate;
730 unsigned short xylogics_writecont;
733 #define SGI_VOLHDR 0x00
734 /* 1 and 2 were used for drive types no longer supported by SGI */
735 #define SGI_SWAP 0x03
736 /* 4 and 5 were for filesystem types SGI haven't ever supported on MIPS CPUs */
737 #define SGI_VOLUME 0x06
739 #define SGI_LVOL 0x08
740 #define SGI_RLVOL 0x09
742 #define SGI_XFSLOG 0x0b
745 #define ENTIRE_DISK SGI_VOLUME
749 #define SECTOR_SLIP 0x01
750 #define SECTOR_FWD 0x02
751 #define TRACK_FWD 0x04
752 #define TRACK_MULTIVOL 0x08
753 #define IGNORE_ERRORS 0x10
755 #define ENABLE_CMDTAGQ 0x40
758 unsigned int magic; /* expect SGI_LABEL_MAGIC */
759 unsigned short boot_part; /* active boot partition */
760 unsigned short swap_part; /* active swap partition */
761 unsigned char boot_file[16]; /* name of the bootfile */
762 struct device_parameter devparam; /* 1 * 48 bytes */
763 struct volume_directory { /* 15 * 16 bytes */
764 unsigned char vol_file_name[8]; /* a character array */
765 unsigned int vol_file_start; /* number of logical block */
766 unsigned int vol_file_size; /* number of bytes */
768 struct sgi_partition { /* 16 * 12 bytes */
769 unsigned int num_sectors; /* number of blocks */
770 unsigned int start_sector; /* must be cylinder aligned */
774 unsigned int fillbytes;
778 unsigned int magic; /* looks like a magic number */
787 unsigned char scsi_string[50];
788 unsigned char serial[137];
789 unsigned short check1816;
790 unsigned char installer[225];
793 #define SGI_LABEL_MAGIC 0x0be5a941
794 #define SGI_LABEL_MAGIC_SWAPPED 0x41a9e50b
795 #define SGI_INFO_MAGIC 0x00072959
796 #define SGI_INFO_MAGIC_SWAPPED 0x59290700
797 #define SGI_SSWAP16(x) (sgi_other_endian ? __swap16(x) \
799 #define SGI_SSWAP32(x) (sgi_other_endian ? __swap32(x) \
802 #define sgilabel ((sgi_partition *)MBRbuffer)
803 #define sgiparam (sgilabel->devparam)
806 unsigned char info[128]; /* Informative text string */
807 unsigned char spare0[14];
809 unsigned char spare1;
811 unsigned char spare2;
814 unsigned char spare1[246]; /* Boot information etc. */
815 unsigned short rspeed; /* Disk rotational speed */
816 unsigned short pcylcount; /* Physical cylinder count */
817 unsigned short sparecyl; /* extra sects per cylinder */
818 unsigned char spare2[4]; /* More magic... */
819 unsigned short ilfact; /* Interleave factor */
820 unsigned short ncyl; /* Data cylinder count */
821 unsigned short nacyl; /* Alt. cylinder count */
822 unsigned short ntrks; /* Tracks per cylinder */
823 unsigned short nsect; /* Sectors per track */
824 unsigned char spare3[4]; /* Even more magic... */
825 struct sun_partition {
826 uint32_t start_cylinder;
827 uint32_t num_sectors;
829 unsigned short magic; /* Magic number */
830 unsigned short csum; /* Label xor'd checksum */
833 #define SUN_LABEL_MAGIC 0xDABE
834 #define SUN_LABEL_MAGIC_SWAPPED 0xBEDA
835 #define sunlabel ((sun_partition *)MBRbuffer)
836 #define SUN_SSWAP16(x) (sun_other_endian ? __swap16(x) \
838 #define SUN_SSWAP32(x) (sun_other_endian ? __swap32(x) \
841 #ifdef CONFIG_FEATURE_OSF_LABEL
844 19990319 - Arnaldo Carvalho de Melo <acme@conectiva.com.br> - i18n/nls
846 20000101 - David Huggins-Daines <dhuggins@linuxcare.com> - Better
847 support for OSF/1 disklabels on Alpha.
848 Also fixed unaligned accesses in alpha_bootblock_checksum()
851 #define FREEBSD_PARTITION 0xa5
852 #define NETBSD_PARTITION 0xa9
854 static void xbsd_delete_part (void);
855 static void xbsd_new_part (void);
856 static void xbsd_write_disklabel (void);
857 static int xbsd_create_disklabel (void);
858 static void xbsd_edit_disklabel (void);
859 static void xbsd_write_bootstrap (void);
860 static void xbsd_change_fstype (void);
861 static int xbsd_get_part_index (int max);
862 static int xbsd_check_new_partition (int *i);
863 static void xbsd_list_types (void);
864 static u_short xbsd_dkcksum (struct xbsd_disklabel *lp);
865 static int xbsd_initlabel (struct partition *p, struct xbsd_disklabel *d,
867 static int xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d);
868 static int xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d);
870 #if defined (__alpha__)
871 static void alpha_bootblock_checksum (char *boot);
874 #if !defined (__alpha__)
875 static int xbsd_translate_fstype (int linux_type);
876 static void xbsd_link_part (void);
877 static struct partition *xbsd_part;
878 static int xbsd_part_index;
881 #if defined (__alpha__)
882 /* We access this through a u_int64_t * when checksumming */
883 static char disklabelbuffer[BSD_BBSIZE] __attribute__((aligned(8)));
885 static char disklabelbuffer[BSD_BBSIZE];
888 static struct xbsd_disklabel xbsd_dlabel;
890 #define bsd_cround(n) \
891 (display_in_cyl_units ? ((n)/xbsd_dlabel.d_secpercyl) + 1 : (n))
894 * Test whether the whole disk has BSD disk label magic.
896 * Note: often reformatting with DOS-type label leaves the BSD magic,
897 * so this does not mean that there is a BSD disk label.
900 check_osf_label(void) {
901 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
906 static void xbsd_print_disklabel(int);
909 btrydev (const char * dev) {
910 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
912 printf(_("\nBSD label for device: %s\n"), dev);
913 xbsd_print_disklabel (0);
919 puts (_("Command action"));
920 puts (_("\td\tdelete a BSD partition"));
921 puts (_("\te\tedit drive data"));
922 puts (_("\ti\tinstall bootstrap"));
923 puts (_("\tl\tlist known filesystem types"));
924 puts (_("\tm\tprint this menu"));
925 puts (_("\tn\tadd a new BSD partition"));
926 puts (_("\tp\tprint BSD partition table"));
927 puts (_("\tq\tquit without saving changes"));
928 puts (_("\tr\treturn to main menu"));
929 puts (_("\ts\tshow complete disklabel"));
930 puts (_("\tt\tchange a partition's filesystem id"));
931 puts (_("\tu\tchange units (cylinders/sectors)"));
932 puts (_("\tw\twrite disklabel to disk"));
933 #if !defined (__alpha__)
934 puts (_("\tx\tlink BSD partition to non-BSD partition"));
938 #if !defined (__alpha__)
945 is_bsd_partition_type(int type) {
946 return (type == FREEBSD_PARTITION ||
947 type == hidden(FREEBSD_PARTITION) ||
948 type == NETBSD_PARTITION ||
949 type == hidden(NETBSD_PARTITION));
955 #if !defined (__alpha__)
959 for (t=0; t<4; t++) {
960 p = get_part_table(t);
961 if (p && is_bsd_partition_type(p->sys_ind)) {
964 ss = get_start_sect(xbsd_part);
966 fprintf (stderr, _("Partition %s has invalid starting sector 0.\n"),
967 partname(disk_device, t+1, 0));
970 printf (_("Reading disklabel of %s at sector %d.\n"),
971 partname(disk_device, t+1, 0), ss + BSD_LABELSECTOR);
972 if (xbsd_readlabel (xbsd_part, &xbsd_dlabel) == 0)
973 if (xbsd_create_disklabel () == 0)
980 printf (_("There is no *BSD partition on %s.\n"), disk_device);
984 #elif defined (__alpha__)
986 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
987 if (xbsd_create_disklabel () == 0)
988 exit ( EXIT_SUCCESS );
994 switch (tolower (read_char (_("BSD disklabel command (m for help): ")))) {
999 xbsd_edit_disklabel ();
1002 xbsd_write_bootstrap ();
1011 xbsd_print_disklabel (0);
1015 exit ( EXIT_SUCCESS );
1019 xbsd_print_disklabel (1);
1022 xbsd_change_fstype ();
1028 xbsd_write_disklabel ();
1030 #if !defined (__alpha__)
1043 xbsd_delete_part (void)
1047 i = xbsd_get_part_index (xbsd_dlabel.d_npartitions);
1048 xbsd_dlabel.d_partitions[i].p_size = 0;
1049 xbsd_dlabel.d_partitions[i].p_offset = 0;
1050 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
1051 if (xbsd_dlabel.d_npartitions == i + 1)
1052 while (xbsd_dlabel.d_partitions[xbsd_dlabel.d_npartitions-1].p_size == 0)
1053 xbsd_dlabel.d_npartitions--;
1057 xbsd_new_part (void)
1063 if (!xbsd_check_new_partition (&i))
1066 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
1067 begin = get_start_sect(xbsd_part);
1068 end = begin + get_nr_sects(xbsd_part) - 1;
1071 end = xbsd_dlabel.d_secperunit - 1;
1074 snprintf (mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
1075 begin = read_int (bsd_cround (begin), bsd_cround (begin), bsd_cround (end),
1078 if (display_in_cyl_units)
1079 begin = (begin - 1) * xbsd_dlabel.d_secpercyl;
1081 snprintf (mesg, sizeof(mesg), _("Last %s or +size or +sizeM or +sizeK"),
1082 str_units(SINGULAR));
1083 end = read_int (bsd_cround (begin), bsd_cround (end), bsd_cround (end),
1084 bsd_cround (begin), mesg);
1086 if (display_in_cyl_units)
1087 end = end * xbsd_dlabel.d_secpercyl - 1;
1089 xbsd_dlabel.d_partitions[i].p_size = end - begin + 1;
1090 xbsd_dlabel.d_partitions[i].p_offset = begin;
1091 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
1095 xbsd_print_disklabel (int show_all) {
1096 struct xbsd_disklabel *lp = &xbsd_dlabel;
1097 struct xbsd_partition *pp;
1101 #if defined (__alpha__)
1102 printf("# %s:\n", disk_device);
1104 printf("# %s:\n", partname(disk_device, xbsd_part_index+1, 0));
1106 if ((unsigned) lp->d_type < BSD_DKMAXTYPES)
1107 printf(_("type: %s\n"), xbsd_dktypenames[lp->d_type]);
1109 printf(_("type: %d\n"), lp->d_type);
1110 printf(_("disk: %.*s\n"), (int) sizeof(lp->d_typename), lp->d_typename);
1111 printf(_("label: %.*s\n"), (int) sizeof(lp->d_packname), lp->d_packname);
1112 printf(_("flags:"));
1113 if (lp->d_flags & BSD_D_REMOVABLE)
1114 printf(_(" removable"));
1115 if (lp->d_flags & BSD_D_ECC)
1117 if (lp->d_flags & BSD_D_BADSECT)
1118 printf(_(" badsect"));
1120 /* On various machines the fields of *lp are short/int/long */
1121 /* In order to avoid problems, we cast them all to long. */
1122 printf(_("bytes/sector: %ld\n"), (long) lp->d_secsize);
1123 printf(_("sectors/track: %ld\n"), (long) lp->d_nsectors);
1124 printf(_("tracks/cylinder: %ld\n"), (long) lp->d_ntracks);
1125 printf(_("sectors/cylinder: %ld\n"), (long) lp->d_secpercyl);
1126 printf(_("cylinders: %ld\n"), (long) lp->d_ncylinders);
1127 printf(_("rpm: %d\n"), lp->d_rpm);
1128 printf(_("interleave: %d\n"), lp->d_interleave);
1129 printf(_("trackskew: %d\n"), lp->d_trackskew);
1130 printf(_("cylinderskew: %d\n"), lp->d_cylskew);
1131 printf(_("headswitch: %ld\t\t# milliseconds\n"),
1132 (long) lp->d_headswitch);
1133 printf(_("track-to-track seek: %ld\t# milliseconds\n"),
1134 (long) lp->d_trkseek);
1135 printf(_("drivedata: "));
1136 for (i = NDDATA - 1; i >= 0; i--)
1137 if (lp->d_drivedata[i])
1141 for (j = 0; j <= i; j++)
1142 printf("%ld ", (long) lp->d_drivedata[j]);
1144 printf(_("\n%d partitions:\n"), lp->d_npartitions);
1145 printf(_("# start end size fstype [fsize bsize cpg]\n"));
1146 pp = lp->d_partitions;
1147 for (i = 0; i < lp->d_npartitions; i++, pp++) {
1149 if (display_in_cyl_units && lp->d_secpercyl) {
1150 printf(" %c: %8ld%c %8ld%c %8ld%c ",
1152 (long) pp->p_offset / lp->d_secpercyl + 1,
1153 (pp->p_offset % lp->d_secpercyl) ? '*' : ' ',
1154 (long) (pp->p_offset + pp->p_size + lp->d_secpercyl - 1)
1156 ((pp->p_offset + pp->p_size) % lp->d_secpercyl) ? '*' : ' ',
1157 (long) pp->p_size / lp->d_secpercyl,
1158 (pp->p_size % lp->d_secpercyl) ? '*' : ' ');
1160 printf(" %c: %8ld %8ld %8ld ",
1162 (long) pp->p_offset,
1163 (long) pp->p_offset + pp->p_size - 1,
1166 if ((unsigned) pp->p_fstype < BSD_FSMAXTYPES)
1167 printf("%8.8s", xbsd_fstypes[pp->p_fstype].name);
1169 printf("%8x", pp->p_fstype);
1170 switch (pp->p_fstype) {
1172 printf(" %5ld %5ld %5.5s ",
1173 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, "");
1177 printf(" %5ld %5ld %5d ",
1178 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag,
1183 printf("%22.22s", "");
1192 xbsd_write_disklabel (void) {
1193 #if defined (__alpha__)
1194 printf (_("Writing disklabel to %s.\n"), disk_device);
1195 xbsd_writelabel (NULL, &xbsd_dlabel);
1197 printf (_("Writing disklabel to %s.\n"),
1198 partname(disk_device, xbsd_part_index+1, 0));
1199 xbsd_writelabel (xbsd_part, &xbsd_dlabel);
1201 reread_partition_table(0); /* no exit yet */
1205 xbsd_create_disklabel (void) {
1208 #if defined (__alpha__)
1209 fprintf (stderr, _("%s contains no disklabel.\n"), disk_device);
1211 fprintf (stderr, _("%s contains no disklabel.\n"),
1212 partname(disk_device, xbsd_part_index+1, 0));
1216 c = read_char (_("Do you want to create a disklabel? (y/n) "));
1217 if (c == 'y' || c == 'Y') {
1218 if (xbsd_initlabel (
1219 #if defined (__alpha__) || defined (__powerpc__) || defined (__hppa__)
1220 NULL, &xbsd_dlabel, 0
1222 xbsd_part, &xbsd_dlabel, xbsd_part_index
1225 xbsd_print_disklabel (1);
1229 } else if (c == 'n')
1235 edit_int (int def, char *mesg)
1238 fputs (mesg, stdout);
1239 printf (" (%d): ", def);
1243 while (!isdigit (*line_ptr));
1244 return atoi (line_ptr);
1248 xbsd_edit_disklabel (void)
1250 struct xbsd_disklabel *d;
1254 #if defined (__alpha__) || defined (__ia64__)
1255 d -> d_secsize = (u_long) edit_int ((u_long) d -> d_secsize ,_("bytes/sector"));
1256 d -> d_nsectors = (u_long) edit_int ((u_long) d -> d_nsectors ,_("sectors/track"));
1257 d -> d_ntracks = (u_long) edit_int ((u_long) d -> d_ntracks ,_("tracks/cylinder"));
1258 d -> d_ncylinders = (u_long) edit_int ((u_long) d -> d_ncylinders ,_("cylinders"));
1261 /* d -> d_secpercyl can be != d -> d_nsectors * d -> d_ntracks */
1264 d -> d_secpercyl = (u_long) edit_int ((u_long) d -> d_nsectors * d -> d_ntracks,
1265 _("sectors/cylinder"));
1266 if (d -> d_secpercyl <= d -> d_nsectors * d -> d_ntracks)
1269 printf (_("Must be <= sectors/track * tracks/cylinder (default).\n"));
1271 d -> d_rpm = (u_short) edit_int ((u_short) d -> d_rpm ,_("rpm"));
1272 d -> d_interleave = (u_short) edit_int ((u_short) d -> d_interleave,_("interleave"));
1273 d -> d_trackskew = (u_short) edit_int ((u_short) d -> d_trackskew ,_("trackskew"));
1274 d -> d_cylskew = (u_short) edit_int ((u_short) d -> d_cylskew ,_("cylinderskew"));
1275 d -> d_headswitch = (u_long) edit_int ((u_long) d -> d_headswitch ,_("headswitch"));
1276 d -> d_trkseek = (u_long) edit_int ((u_long) d -> d_trkseek ,_("track-to-track seek"));
1278 d -> d_secperunit = d -> d_secpercyl * d -> d_ncylinders;
1282 xbsd_get_bootstrap (char *path, void *ptr, int size)
1286 if ((fdb = open (path, O_RDONLY)) < 0)
1291 if (read (fdb, ptr, size) < 0)
1297 printf (" ... %s\n", path);
1305 printf (_("\nSyncing disks.\n"));
1311 xbsd_write_bootstrap (void)
1313 char *bootdir = BSD_LINUX_BOOTDIR;
1314 char path[MAXPATHLEN];
1316 struct xbsd_disklabel dl;
1320 if (xbsd_dlabel.d_type == BSD_DTYPE_SCSI)
1325 printf (_("Bootstrap: %sboot -> boot%s (%s): "),
1326 dkbasename, dkbasename, dkbasename);
1328 line_ptr[strlen (line_ptr)-1] = '\0';
1329 dkbasename = line_ptr;
1331 snprintf (path, sizeof(path), "%s/%sboot", bootdir, dkbasename);
1332 if (!xbsd_get_bootstrap (path, disklabelbuffer, (int) xbsd_dlabel.d_secsize))
1335 /* We need a backup of the disklabel (xbsd_dlabel might have changed). */
1336 d = &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE];
1337 bcopy (d, &dl, sizeof (struct xbsd_disklabel));
1339 /* The disklabel will be overwritten by 0's from bootxx anyway */
1340 bzero (d, sizeof (struct xbsd_disklabel));
1342 snprintf (path, sizeof(path), "%s/boot%s", bootdir, dkbasename);
1343 if (!xbsd_get_bootstrap (path, &disklabelbuffer[xbsd_dlabel.d_secsize],
1344 (int) xbsd_dlabel.d_bbsize - xbsd_dlabel.d_secsize))
1347 e = d + sizeof (struct xbsd_disklabel);
1348 for (p=d; p < e; p++)
1350 fprintf (stderr, _("Bootstrap overlaps with disk label!\n"));
1351 exit ( EXIT_FAILURE );
1354 bcopy (&dl, d, sizeof (struct xbsd_disklabel));
1356 #if defined (__powerpc__) || defined (__hppa__)
1358 #elif defined (__alpha__)
1360 alpha_bootblock_checksum (disklabelbuffer);
1362 sector = get_start_sect(xbsd_part);
1365 if (lseek (fd, (ext2_loff_t) sector * SECTOR_SIZE, SEEK_SET) == -1)
1366 fdisk_fatal (unable_to_seek);
1367 if (BSD_BBSIZE != write (fd, disklabelbuffer, BSD_BBSIZE))
1368 fdisk_fatal (unable_to_write);
1370 #if defined (__alpha__)
1371 printf (_("Bootstrap installed on %s.\n"), disk_device);
1373 printf (_("Bootstrap installed on %s.\n"),
1374 partname (disk_device, xbsd_part_index+1, 0));
1381 xbsd_change_fstype (void)
1385 i = xbsd_get_part_index (xbsd_dlabel.d_npartitions);
1386 xbsd_dlabel.d_partitions[i].p_fstype = read_hex (xbsd_fstypes);
1390 xbsd_get_part_index (int max)
1395 snprintf (prompt, sizeof(prompt), _("Partition (a-%c): "), 'a' + max - 1);
1397 l = tolower (read_char (prompt));
1398 while (l < 'a' || l > 'a' + max - 1);
1403 xbsd_check_new_partition (int *i) {
1405 /* room for more? various BSD flavours have different maxima */
1406 if (xbsd_dlabel.d_npartitions == BSD_MAXPARTITIONS) {
1409 for (t = 0; t < BSD_MAXPARTITIONS; t++)
1410 if (xbsd_dlabel.d_partitions[t].p_size == 0)
1413 if (t == BSD_MAXPARTITIONS) {
1414 fprintf (stderr, _("The maximum number of partitions "
1415 "has been created\n"));
1420 *i = xbsd_get_part_index (BSD_MAXPARTITIONS);
1422 if (*i >= xbsd_dlabel.d_npartitions)
1423 xbsd_dlabel.d_npartitions = (*i) + 1;
1425 if (xbsd_dlabel.d_partitions[*i].p_size != 0) {
1426 fprintf (stderr, _("This partition already exists.\n"));
1434 xbsd_list_types (void) {
1435 list_types (xbsd_fstypes);
1439 xbsd_dkcksum (struct xbsd_disklabel *lp) {
1440 u_short *start, *end;
1443 start = (u_short *) lp;
1444 end = (u_short *) &lp->d_partitions[lp->d_npartitions];
1451 xbsd_initlabel (struct partition *p, struct xbsd_disklabel *d, int pindex) {
1452 struct xbsd_partition *pp;
1455 bzero (d, sizeof (struct xbsd_disklabel));
1457 d -> d_magic = BSD_DISKMAGIC;
1459 if (strncmp (disk_device, "/dev/sd", 7) == 0)
1460 d -> d_type = BSD_DTYPE_SCSI;
1462 d -> d_type = BSD_DTYPE_ST506;
1464 #if 0 /* not used (at least not written to disk) by NetBSD/i386 1.0 */
1465 d -> d_subtype = BSD_DSTYPE_INDOSPART & pindex;
1468 #if !defined (__alpha__)
1469 d -> d_flags = BSD_D_DOSPART;
1473 d -> d_secsize = SECTOR_SIZE; /* bytes/sector */
1474 d -> d_nsectors = sectors; /* sectors/track */
1475 d -> d_ntracks = heads; /* tracks/cylinder (heads) */
1476 d -> d_ncylinders = cylinders;
1477 d -> d_secpercyl = sectors * heads;/* sectors/cylinder */
1478 if (d -> d_secpercyl == 0)
1479 d -> d_secpercyl = 1; /* avoid segfaults */
1480 d -> d_secperunit = d -> d_secpercyl * d -> d_ncylinders;
1483 d -> d_interleave = 1;
1484 d -> d_trackskew = 0;
1486 d -> d_headswitch = 0;
1489 d -> d_magic2 = BSD_DISKMAGIC;
1490 d -> d_bbsize = BSD_BBSIZE;
1491 d -> d_sbsize = BSD_SBSIZE;
1493 #if !defined (__alpha__)
1494 d -> d_npartitions = 4;
1495 pp = &d -> d_partitions[2]; /* Partition C should be
1496 the NetBSD partition */
1497 pp -> p_offset = get_start_sect(p);
1498 pp -> p_size = get_nr_sects(p);
1499 pp -> p_fstype = BSD_FS_UNUSED;
1500 pp = &d -> d_partitions[3]; /* Partition D should be
1503 pp -> p_size = d -> d_secperunit;
1504 pp -> p_fstype = BSD_FS_UNUSED;
1505 #elif defined (__alpha__)
1506 d -> d_npartitions = 3;
1507 pp = &d -> d_partitions[2]; /* Partition C should be
1510 pp -> p_size = d -> d_secperunit;
1511 pp -> p_fstype = BSD_FS_UNUSED;
1518 * Read a xbsd_disklabel from sector 0 or from the starting sector of p.
1519 * If it has the right magic, return 1.
1522 xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d)
1526 /* p is used only to get the starting sector */
1527 #if !defined (__alpha__)
1528 sector = (p ? get_start_sect(p) : 0);
1529 #elif defined (__alpha__)
1533 if (lseek (fd, (ext2_loff_t) sector * SECTOR_SIZE, SEEK_SET) == -1)
1534 fdisk_fatal (unable_to_seek);
1535 if (BSD_BBSIZE != read (fd, disklabelbuffer, BSD_BBSIZE))
1536 fdisk_fatal (unable_to_read);
1538 bcopy (&disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
1539 d, sizeof (struct xbsd_disklabel));
1541 if (d -> d_magic != BSD_DISKMAGIC || d -> d_magic2 != BSD_DISKMAGIC)
1544 for (t = d -> d_npartitions; t < BSD_MAXPARTITIONS; t++) {
1545 d -> d_partitions[t].p_size = 0;
1546 d -> d_partitions[t].p_offset = 0;
1547 d -> d_partitions[t].p_fstype = BSD_FS_UNUSED;
1550 if (d -> d_npartitions > BSD_MAXPARTITIONS)
1551 fprintf (stderr, _("Warning: too many partitions "
1552 "(%d, maximum is %d).\n"),
1553 d -> d_npartitions, BSD_MAXPARTITIONS);
1558 xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d)
1562 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
1563 sector = get_start_sect(p) + BSD_LABELSECTOR;
1565 sector = BSD_LABELSECTOR;
1568 d -> d_checksum = 0;
1569 d -> d_checksum = xbsd_dkcksum (d);
1571 /* This is necessary if we want to write the bootstrap later,
1572 otherwise we'd write the old disklabel with the bootstrap.
1574 bcopy (d, &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
1575 sizeof (struct xbsd_disklabel));
1577 #if defined (__alpha__) && BSD_LABELSECTOR == 0
1578 alpha_bootblock_checksum (disklabelbuffer);
1579 if (lseek (fd, (ext2_loff_t) 0, SEEK_SET) == -1)
1580 fdisk_fatal (unable_to_seek);
1581 if (BSD_BBSIZE != write (fd, disklabelbuffer, BSD_BBSIZE))
1582 fdisk_fatal (unable_to_write);
1584 if (lseek (fd, (ext2_loff_t) sector * SECTOR_SIZE + BSD_LABELOFFSET,
1586 fdisk_fatal (unable_to_seek);
1587 if (sizeof (struct xbsd_disklabel) != write (fd, d, sizeof (struct xbsd_disklabel)))
1588 fdisk_fatal (unable_to_write);
1597 #if !defined (__alpha__)
1599 xbsd_translate_fstype (int linux_type)
1603 case 0x01: /* DOS 12-bit FAT */
1604 case 0x04: /* DOS 16-bit <32M */
1605 case 0x06: /* DOS 16-bit >=32M */
1606 case 0xe1: /* DOS access */
1607 case 0xe3: /* DOS R/O */
1608 case 0xf2: /* DOS secondary */
1609 return BSD_FS_MSDOS;
1610 case 0x07: /* OS/2 HPFS */
1613 return BSD_FS_OTHER;
1618 xbsd_link_part (void)
1621 struct partition *p;
1623 k = get_partition (1, partitions);
1625 if (!xbsd_check_new_partition (&i))
1628 p = get_part_table(k);
1630 xbsd_dlabel.d_partitions[i].p_size = get_nr_sects(p);
1631 xbsd_dlabel.d_partitions[i].p_offset = get_start_sect(p);
1632 xbsd_dlabel.d_partitions[i].p_fstype = xbsd_translate_fstype(p->sys_ind);
1636 #if defined (__alpha__)
1638 #if !defined(__GLIBC__)
1639 typedef unsigned long long u_int64_t;
1643 alpha_bootblock_checksum (char *boot)
1648 dp = (u_int64_t *)boot;
1650 for (i = 0; i < 63; i++)
1654 #endif /* __alpha__ */
1656 #endif /* OSF_LABEL */
1658 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
1659 static inline unsigned short
1660 __swap16(unsigned short x) {
1661 return (((uint16_t)(x) & 0xFF) << 8) | (((uint16_t)(x) & 0xFF00) >> 8);
1664 static inline uint32_t
1665 __swap32(uint32_t x) {
1666 return (((uint32_t)(x) & 0xFF) << 24) | (((uint32_t)(x) & 0xFF00) << 8) | (((uint32_t)(x) & 0xFF0000) >> 8) | (((uint32_t)(x) & 0xFF000000) >> 24);
1670 #ifdef CONFIG_FEATURE_SGI_LABEL
1675 * Copyright (C) Andreas Neuper, Sep 1998.
1676 * This file may be modified and redistributed under
1677 * the terms of the GNU Public License.
1679 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
1680 * Internationalization
1684 static int sgi_other_endian;
1686 static short sgi_volumes=1;
1689 * only dealing with free blocks here
1692 typedef struct { int first; int last; } freeblocks;
1693 static freeblocks freelist[17]; /* 16 partitions can produce 17 vacant slots */
1696 setfreelist( int i, int f, int l ) {
1697 freelist[i].first = f;
1698 freelist[i].last = l;
1702 add2freelist( int f, int l ) {
1704 for( ; i<17 ; i++ ) {
1705 if(freelist[i].last==0) break;
1707 setfreelist( i, f, l );
1711 clearfreelist(void) {
1713 for( ; i<17 ; i++ ) {
1714 setfreelist( i, 0, 0 );
1719 isinfreelist( int b ) {
1721 for( ; i<17 ; i++ ) {
1722 if (freelist[i].first <= b && freelist[i].last >= b) {
1723 return freelist[i].last;
1728 /* return last vacant block of this stride (never 0). */
1729 /* the '>=' is not quite correct, but simplifies the code */
1731 * end of free blocks section
1734 static const struct systypes sgi_sys_types[] = {
1735 /* SGI_VOLHDR */ {"\x00" "SGI volhdr" },
1736 /* 0x01 */ {"\x01" "SGI trkrepl" },
1737 /* 0x02 */ {"\x02" "SGI secrepl" },
1738 /* SGI_SWAP */ {"\x03" "SGI raw" },
1739 /* 0x04 */ {"\x04" "SGI bsd" },
1740 /* 0x05 */ {"\x05" "SGI sysv" },
1741 /* ENTIRE_DISK */ {"\x06" "SGI volume" },
1742 /* SGI_EFS */ {"\x07" "SGI efs" },
1743 /* 0x08 */ {"\x08" "SGI lvol" },
1744 /* 0x09 */ {"\x09" "SGI rlvol" },
1745 /* SGI_XFS */ {"\x0a" "SGI xfs" },
1746 /* SGI_XFSLOG */ {"\x0b" "SGI xfslog" },
1747 /* SGI_XLV */ {"\x0c" "SGI xlv" },
1748 /* SGI_XVM */ {"\x0d" "SGI xvm" },
1749 /* LINUX_SWAP */ {"\x82" "Linux swap" },
1750 /* LINUX_NATIVE */ {"\x83" "Linux native" },
1751 /* LINUX_LVM */ {"\x8d" "Linux LVM" },
1752 /* LINUX_RAID */ {"\xfd" "Linux RAID" },
1758 sgi_get_nsect(void) {
1759 return SGI_SSWAP16(sgilabel->devparam.nsect);
1763 sgi_get_ntrks(void) {
1764 return SGI_SSWAP16(sgilabel->devparam.ntrks);
1768 sgi_get_pcylcount(void) {
1769 return SGI_SSWAP16(sgilabel->devparam.pcylcount);
1774 sgilabel->magic = 0;
1780 two_s_complement_32bit_sum(unsigned int* base, int size /* in bytes */ ) {
1784 size = size / sizeof( unsigned int );
1785 for( i=0; i<size; i++ )
1786 sum = sum - SGI_SSWAP32(base[i]);
1791 check_sgi_label(void) {
1792 if (sizeof(sgilabel) > 512) {
1794 _("According to MIPS Computer Systems, Inc the "
1795 "Label must not contain more than 512 bytes\n"));
1799 if (sgilabel->magic != SGI_LABEL_MAGIC &&
1800 sgilabel->magic != SGI_LABEL_MAGIC_SWAPPED) {
1802 sgi_other_endian = 0;
1806 sgi_other_endian = (sgilabel->magic == SGI_LABEL_MAGIC_SWAPPED);
1808 * test for correct checksum
1810 if( two_s_complement_32bit_sum( (unsigned int*)sgilabel,
1811 sizeof(*sgilabel) ) )
1813 fprintf( stderr, _("Detected sgi disklabel with wrong checksum.\n"));
1816 heads = sgi_get_ntrks();
1817 cylinders = sgi_get_pcylcount();
1818 sectors = sgi_get_nsect();
1828 sgi_get_start_sector( int i ) {
1829 return SGI_SSWAP32(sgilabel->partitions[i].start_sector);
1833 sgi_get_num_sectors( int i ) {
1834 return SGI_SSWAP32(sgilabel->partitions[i].num_sectors);
1838 sgi_get_sysid( int i )
1840 return SGI_SSWAP32(sgilabel->partitions[i].id);
1844 sgi_get_bootpartition(void)
1846 return SGI_SSWAP16(sgilabel->boot_part);
1850 sgi_get_swappartition(void)
1852 return SGI_SSWAP16(sgilabel->swap_part);
1856 sgi_list_table( int xtra ) {
1858 int kpi = 0; /* kernel partition ID */
1860 w = strlen( disk_device );
1863 printf(_("\nDisk %s (SGI disk label): %d heads, %d sectors\n"
1864 "%d cylinders, %d physical cylinders\n"
1865 "%d extra sects/cyl, interleave %d:1\n"
1867 "Units = %s of %d * 512 bytes\n\n"),
1868 disk_device, heads, sectors, cylinders,
1869 SGI_SSWAP16(sgiparam.pcylcount),
1870 SGI_SSWAP16(sgiparam.sparecyl),
1871 SGI_SSWAP16(sgiparam.ilfact),
1873 str_units(PLURAL), units_per_sector);
1875 printf( _("\nDisk %s (SGI disk label): "
1876 "%d heads, %d sectors, %d cylinders\n"
1877 "Units = %s of %d * 512 bytes\n\n"),
1878 disk_device, heads, sectors, cylinders,
1879 str_units(PLURAL), units_per_sector );
1881 printf(_("----- partitions -----\n"
1882 "Pt# %*s Info Start End Sectors Id System\n"),
1883 w + 1, _("Device"));
1884 for (i = 0 ; i < partitions; i++) {
1885 if( sgi_get_num_sectors(i) || debug ) {
1886 uint32_t start = sgi_get_start_sector(i);
1887 uint32_t len = sgi_get_num_sectors(i);
1888 kpi++; /* only count nonempty partitions */
1890 "%2d: %s %4s %9ld %9ld %9ld %2x %s\n",
1891 /* fdisk part number */ i+1,
1892 /* device */ partname(disk_device, kpi, w+2),
1893 /* flags */ (sgi_get_swappartition() == i) ? "swap" :
1894 /* flags */ (sgi_get_bootpartition() == i) ? "boot" : " ",
1895 /* start */ (long) scround(start),
1896 /* end */ (long) scround(start+len)-1,
1897 /* no odd flag on end */ (long) len,
1898 /* type id */ sgi_get_sysid(i),
1899 /* type name */ partition_type(sgi_get_sysid(i)));
1902 printf(_("----- Bootinfo -----\nBootfile: %s\n"
1903 "----- Directory Entries -----\n"),
1904 sgilabel->boot_file );
1905 for (i = 0 ; i < sgi_volumes; i++)
1907 if (sgilabel->directory[i].vol_file_size)
1909 uint32_t start = SGI_SSWAP32(sgilabel->directory[i].vol_file_start);
1910 uint32_t len = SGI_SSWAP32(sgilabel->directory[i].vol_file_size);
1911 char*name = sgilabel->directory[i].vol_file_name;
1912 printf(_("%2d: %-10s sector%5u size%8u\n"),
1913 i, name, (unsigned int) start, (unsigned int) len);
1919 sgi_set_bootpartition( int i )
1921 sgilabel->boot_part = SGI_SSWAP16(((short)i));
1925 sgi_get_lastblock(void) {
1926 return heads * sectors * cylinders;
1930 sgi_set_swappartition( int i ) {
1931 sgilabel->swap_part = SGI_SSWAP16(((short)i));
1935 sgi_check_bootfile( const char* aFile ) {
1936 if( strlen( aFile ) < 3 ) /* "/a\n" is minimum */
1938 printf( _("\nInvalid Bootfile!\n"
1939 "\tThe bootfile must be an absolute non-zero pathname,\n"
1940 "\te.g. \"/unix\" or \"/unix.save\".\n") );
1943 if( strlen( aFile ) > 16 )
1945 printf( _("\n\tName of Bootfile too long: 16 bytes maximum.\n") );
1948 if( aFile[0] != '/' )
1950 printf( _("\n\tBootfile must have a fully qualified pathname.\n") );
1953 if( strncmp( aFile, sgilabel->boot_file, 16 ) )
1955 printf( _("\n\tBe aware, that the bootfile is not checked for existence.\n\t"
1956 "SGI's default is \"/unix\" and for backup \"/unix.save\".\n") );
1957 /* filename is correct and did change */
1960 return 0; /* filename did not change */
1964 sgi_get_bootfile(void) {
1965 return sgilabel->boot_file;
1969 sgi_set_bootfile( const char* aFile )
1972 if( sgi_check_bootfile( aFile ) )
1976 if( (aFile[i] != '\n') /* in principle caught again by next line */
1977 && (strlen( aFile ) > i ) )
1978 sgilabel->boot_file[i] = aFile[i];
1980 sgilabel->boot_file[i] = 0;
1983 printf( _("\n\tBootfile is changed to \"%s\".\n"), sgilabel->boot_file );
1988 create_sgiinfo(void)
1990 /* I keep SGI's habit to write the sgilabel to the second block */
1991 sgilabel->directory[0].vol_file_start = SGI_SSWAP32( 2 );
1992 sgilabel->directory[0].vol_file_size = SGI_SSWAP32( sizeof( sgiinfo ) );
1993 strncpy( sgilabel->directory[0].vol_file_name, "sgilabel", 8 );
1996 static sgiinfo * fill_sgiinfo(void);
1999 sgi_write_table(void)
2002 sgilabel->csum = SGI_SSWAP32( two_s_complement_32bit_sum(
2003 (unsigned int*)sgilabel,
2004 sizeof(*sgilabel) ) );
2005 assert( two_s_complement_32bit_sum(
2006 (unsigned int*)sgilabel, sizeof(*sgilabel) ) == 0 );
2007 if( lseek(fd, 0, SEEK_SET) < 0 )
2008 fdisk_fatal(unable_to_seek);
2009 if( write(fd, sgilabel, SECTOR_SIZE) != SECTOR_SIZE )
2010 fdisk_fatal(unable_to_write);
2011 if( ! strncmp( sgilabel->directory[0].vol_file_name, "sgilabel",8 ) )
2014 * keep this habbit of first writing the "sgilabel".
2015 * I never tested whether it works without (AN 981002).
2017 sgiinfo*info = fill_sgiinfo(); /* fills the block appropriately */
2018 int infostartblock = SGI_SSWAP32( sgilabel->directory[0].vol_file_start );
2019 if( lseek(fd, (ext2_loff_t)infostartblock*
2020 SECTOR_SIZE, SEEK_SET) < 0 )
2021 fdisk_fatal(unable_to_seek);
2022 if( write(fd, info, SECTOR_SIZE) != SECTOR_SIZE )
2023 fdisk_fatal(unable_to_write);
2029 compare_start( int *x, int *y ) {
2031 * sort according to start sectors
2032 * and prefers largest partition:
2033 * entry zero is entire disk entry
2037 int a = sgi_get_start_sector(i);
2038 int b = sgi_get_start_sector(j);
2039 int c = sgi_get_num_sectors(i);
2040 int d = sgi_get_num_sectors(j);
2050 verify_sgi( int verbose )
2052 int Index[16]; /* list of valid partitions */
2053 int sortcount = 0; /* number of used partitions, i.e. non-zero lengths */
2054 int entire = 0, i = 0; /* local counters */
2056 int gap = 0; /* count unused blocks */
2057 int lastblock = sgi_get_lastblock();
2061 for( i=0; i<16; i++ )
2063 if( sgi_get_num_sectors(i)!=0 )
2065 Index[sortcount++]=i;
2066 if( sgi_get_sysid(i) == ENTIRE_DISK )
2071 printf(_("More than one entire disk entry present.\n"));
2076 if( sortcount == 0 )
2079 printf(_("No partitions defined\n"));
2082 qsort( Index, sortcount, sizeof(Index[0]), (void*)compare_start );
2083 if( sgi_get_sysid( Index[0] ) == ENTIRE_DISK )
2085 if( ( Index[0] != 10 ) && verbose )
2086 printf( _("IRIX likes when Partition 11 covers the entire disk.\n") );
2087 if( ( sgi_get_start_sector( Index[0] ) != 0 ) && verbose )
2088 printf( _("The entire disk partition should start at block 0,\nnot "
2089 "at diskblock %d.\n"), sgi_get_start_sector(Index[0] ) );
2090 if(debug) /* I do not understand how some disks fulfil it */
2091 if( ( sgi_get_num_sectors( Index[0] ) != lastblock ) && verbose )
2092 printf( _("The entire disk partition is only %d diskblock large,\n"
2093 "but the disk is %d diskblocks long.\n"),
2094 sgi_get_num_sectors( Index[0] ), lastblock );
2095 lastblock = sgi_get_num_sectors( Index[0] );
2099 printf( _("One Partition (#11) should cover the entire disk.\n") );
2101 printf( "sysid=%d\tpartition=%d\n",
2102 sgi_get_sysid( Index[0] ), Index[0]+1 );
2104 for( i=1, start=0; i<sortcount; i++ )
2106 int cylsize = sgi_get_nsect() * sgi_get_ntrks();
2107 if( (sgi_get_start_sector( Index[i] ) % cylsize) != 0 )
2109 if(debug) /* I do not understand how some disks fulfil it */
2111 printf( _("Partition %d does not start on cylinder boundary.\n"),
2114 if( sgi_get_num_sectors( Index[i] ) % cylsize != 0 )
2116 if(debug) /* I do not understand how some disks fulfil it */
2118 printf( _("Partition %d does not end on cylinder boundary.\n"),
2121 /* We cannot handle several "entire disk" entries. */
2122 if( sgi_get_sysid( Index[i] ) == ENTIRE_DISK ) continue;
2123 if( start > sgi_get_start_sector( Index[i] ) )
2126 printf( _("The Partition %d and %d overlap by %d sectors.\n"),
2127 Index[i-1]+1, Index[i]+1,
2128 start - sgi_get_start_sector( Index[i] ) );
2129 if( gap > 0 ) gap = -gap;
2130 if( gap == 0 ) gap = -1;
2132 if( start < sgi_get_start_sector( Index[i] ) )
2135 printf( _("Unused gap of %8d sectors - sectors %8d-%d\n"),
2136 sgi_get_start_sector( Index[i] ) - start,
2137 start, sgi_get_start_sector( Index[i] )-1 );
2138 gap += sgi_get_start_sector( Index[i] ) - start;
2139 add2freelist( start, sgi_get_start_sector( Index[i] ) );
2141 start = sgi_get_start_sector( Index[i] )
2142 + sgi_get_num_sectors( Index[i] );
2146 printf( "%2d:%12d\t%12d\t%12d\n", Index[i],
2147 sgi_get_start_sector(Index[i]),
2148 sgi_get_num_sectors(Index[i]),
2149 sgi_get_sysid(Index[i]) );
2152 if( ( start < lastblock ) )
2155 printf( _("Unused gap of %8d sectors - sectors %8d-%d\n"),
2156 lastblock - start, start, lastblock-1 );
2157 gap += lastblock - start;
2158 add2freelist( start, lastblock );
2161 * Done with arithmetics
2162 * Go for details now
2166 if( !sgi_get_num_sectors( sgi_get_bootpartition() ) )
2168 printf( _("\nThe boot partition does not exist.\n") );
2170 if( !sgi_get_num_sectors( sgi_get_swappartition() ) )
2172 printf( _("\nThe swap partition does not exist.\n") );
2174 if( ( sgi_get_sysid( sgi_get_swappartition() ) != SGI_SWAP )
2175 && ( sgi_get_sysid( sgi_get_swappartition() ) != LINUX_SWAP ) )
2177 printf( _("\nThe swap partition has no swap type.\n") );
2179 if( sgi_check_bootfile( "/unix" ) )
2181 printf( _("\tYou have chosen an unusual boot file name.\n") );
2190 * returned value is:
2191 * = 0 : disk is properly filled to the rim
2192 * < 0 : there is an overlap
2193 * > 0 : there is still some vacant space
2195 return verify_sgi(0);
2199 sgi_change_sysid( int i, int sys )
2201 if( sgi_get_num_sectors(i) == 0 ) /* caught already before, ... */
2203 printf(_("Sorry You may change the Tag of non-empty partitions.\n"));
2206 if( ((sys != ENTIRE_DISK ) && (sys != SGI_VOLHDR))
2207 && (sgi_get_start_sector(i)<1) )
2210 _("It is highly recommended that the partition at offset 0\n"
2211 "is of type \"SGI volhdr\", the IRIX system will rely on it to\n"
2212 "retrieve from its directory standalone tools like sash and fx.\n"
2213 "Only the \"SGI volume\" entire disk section may violate this.\n"
2214 "Type YES if you are sure about tagging this partition differently.\n"));
2215 if (strcmp (line_ptr, _("YES\n")))
2218 sgilabel->partitions[i].id = SGI_SSWAP32(sys);
2221 /* returns partition index of first entry marked as entire disk */
2225 for( i=0; i<16; i++ )
2226 if( sgi_get_sysid(i) == SGI_VOLUME )
2232 sgi_set_partition( int i, uint start, uint length, int sys ) {
2233 sgilabel->partitions[i].id =
2235 sgilabel->partitions[i].num_sectors =
2236 SGI_SSWAP32( length );
2237 sgilabel->partitions[i].start_sector =
2238 SGI_SSWAP32( start );
2240 if( sgi_gaps() < 0 ) /* rebuild freelist */
2241 printf(_("Do You know, You got a partition overlap on the disk?\n"));
2245 sgi_set_entire(void) {
2247 for( n=10; n<partitions; n++ ) {
2248 if(!sgi_get_num_sectors( n ) ) {
2249 sgi_set_partition( n, 0, sgi_get_lastblock(), SGI_VOLUME );
2256 sgi_set_volhdr(void)
2259 for( n=8; n<partitions; n++ )
2261 if(!sgi_get_num_sectors( n ) )
2264 * 5 cylinders is an arbitrary value I like
2265 * IRIX 5.3 stored files in the volume header
2266 * (like sash, symmon, fx, ide) with ca. 3200
2269 if( heads * sectors * 5 < sgi_get_lastblock() )
2270 sgi_set_partition( n, 0, heads * sectors * 5, SGI_VOLHDR );
2277 sgi_delete_partition( int i )
2279 sgi_set_partition( i, 0, 0, 0 );
2283 sgi_add_partition( int n, int sys )
2286 int first=0, last=0;
2290 } else if ( n == 8 ) {
2293 if( sgi_get_num_sectors(n) )
2295 printf(_("Partition %d is already defined. Delete "
2296 "it before re-adding it.\n"), n + 1);
2299 if( (sgi_entire() == -1)
2300 && (sys != SGI_VOLUME) )
2302 printf(_("Attempting to generate entire disk entry automatically.\n"));
2306 if( (sgi_gaps() == 0)
2307 && (sys != SGI_VOLUME) )
2309 printf(_("The entire disk is already covered with partitions.\n"));
2312 if( sgi_gaps() < 0 )
2314 printf(_("You got a partition overlap on the disk. Fix it first!\n"));
2317 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
2319 if(sys == SGI_VOLUME) {
2320 last = sgi_get_lastblock();
2321 first = read_int(0, 0, last-1, 0, mesg);
2323 printf(_("It is highly recommended that eleventh partition\n"
2324 "covers the entire disk and is of type `SGI volume'\n"));
2327 first = freelist[0].first;
2328 last = freelist[0].last;
2329 first = read_int(scround(first), scround(first), scround(last)-1,
2332 if (display_in_cyl_units)
2333 first *= units_per_sector;
2335 first = first; /* align to cylinder if you know how ... */
2337 last = isinfreelist(first);
2339 printf(_("You will get a partition overlap on the disk. "
2340 "Fix it first!\n"));
2344 snprintf(mesg, sizeof(mesg), _(" Last %s"), str_units(SINGULAR));
2345 last = read_int(scround(first), scround(last)-1, scround(last)-1,
2346 scround(first), mesg)+1;
2347 if (display_in_cyl_units)
2348 last *= units_per_sector;
2350 last = last; /* align to cylinder if You know how ... */
2351 if( (sys == SGI_VOLUME) && ( first != 0 || last != sgi_get_lastblock() ) )
2352 printf(_("It is highly recommended that eleventh partition\n"
2353 "covers the entire disk and is of type `SGI volume'\n"));
2354 sgi_set_partition( n, first, last-first, sys );
2358 create_sgilabel(void)
2360 struct hd_geometry geometry;
2363 int sysid; } old[4];
2366 _("Building a new SGI disklabel. Changes will remain in memory only,\n"
2367 "until you decide to write them. After that, of course, the previous\n"
2368 "content will be unrecoverably lost.\n\n"));
2370 sgi_other_endian = (BYTE_ORDER == LITTLE_ENDIAN);
2373 if (!ioctl(fd, HDIO_REQ, &geometry))
2375 if (!ioctl(fd, HDIO_GETGEO, &geometry))
2378 heads = geometry.heads;
2379 sectors = geometry.sectors;
2380 cylinders = geometry.cylinders;
2382 for (i = 0; i < 4; i++)
2385 if( valid_part_table_flag(MBRbuffer) )
2387 if( get_part_table(i)->sys_ind )
2389 old[i].sysid = get_part_table(i)->sys_ind;
2390 old[i].start = get_start_sect( get_part_table(i) );
2391 old[i].nsect = get_nr_sects( get_part_table(i) );
2392 printf( _("Trying to keep parameters of partition %d.\n"), i );
2394 printf( _("ID=%02x\tSTART=%d\tLENGTH=%d\n"),
2395 old[i].sysid, old[i].start, old[i].nsect );
2399 memset(MBRbuffer, 0, sizeof(MBRbuffer));
2400 sgilabel->magic = SGI_SSWAP32(SGI_LABEL_MAGIC);
2401 sgilabel->boot_part = SGI_SSWAP16(0);
2402 sgilabel->swap_part = SGI_SSWAP16(1);
2404 /* sizeof(sgilabel->boot_file) = 16 > 6 */
2405 memset(sgilabel->boot_file, 0, 16);
2406 strcpy(sgilabel->boot_file, "/unix");
2408 sgilabel->devparam.skew = (0);
2409 sgilabel->devparam.gap1 = (0);
2410 sgilabel->devparam.gap2 = (0);
2411 sgilabel->devparam.sparecyl = (0);
2412 sgilabel->devparam.pcylcount = SGI_SSWAP16(geometry.cylinders);
2413 sgilabel->devparam.head_vol0 = SGI_SSWAP16(0);
2414 sgilabel->devparam.ntrks = SGI_SSWAP16(geometry.heads);
2415 /* tracks/cylinder (heads) */
2416 sgilabel->devparam.cmd_tag_queue_depth = (0);
2417 sgilabel->devparam.unused0 = (0);
2418 sgilabel->devparam.unused1 = SGI_SSWAP16(0);
2419 sgilabel->devparam.nsect = SGI_SSWAP16(geometry.sectors);
2421 sgilabel->devparam.bytes = SGI_SSWAP16(512);
2422 sgilabel->devparam.ilfact = SGI_SSWAP16(1);
2423 sgilabel->devparam.flags = SGI_SSWAP32(TRACK_FWD|
2424 IGNORE_ERRORS|RESEEK);
2425 sgilabel->devparam.datarate = SGI_SSWAP32(0);
2426 sgilabel->devparam.retries_on_error = SGI_SSWAP32(1);
2427 sgilabel->devparam.ms_per_word = SGI_SSWAP32(0);
2428 sgilabel->devparam.xylogics_gap1 = SGI_SSWAP16(0);
2429 sgilabel->devparam.xylogics_syncdelay = SGI_SSWAP16(0);
2430 sgilabel->devparam.xylogics_readdelay = SGI_SSWAP16(0);
2431 sgilabel->devparam.xylogics_gap2 = SGI_SSWAP16(0);
2432 sgilabel->devparam.xylogics_readgate = SGI_SSWAP16(0);
2433 sgilabel->devparam.xylogics_writecont = SGI_SSWAP16(0);
2434 memset( &(sgilabel->directory), 0, sizeof(struct volume_directory)*15 );
2435 memset( &(sgilabel->partitions), 0, sizeof(struct sgi_partition)*16 );
2441 for (i = 0; i < 4; i++)
2445 sgi_set_partition( i, old[i].start, old[i].nsect, old[i].sysid );
2453 /* do nothing in the beginning */
2456 /* _____________________________________________________________
2462 sgiinfo*info=calloc( 1, sizeof(sgiinfo) );
2463 info->magic=SGI_SSWAP32(SGI_INFO_MAGIC);
2464 info->b1=SGI_SSWAP32(-1);
2465 info->b2=SGI_SSWAP16(-1);
2466 info->b3=SGI_SSWAP16(1);
2467 /* You may want to replace this string !!!!!!! */
2468 strcpy( info->scsi_string, "IBM OEM 0662S12 3 30" );
2469 strcpy( info->serial, "0000" );
2470 info->check1816 = SGI_SSWAP16(18*256 +16 );
2471 strcpy( info->installer, "Sfx version 5.3, Oct 18, 1994" );
2474 #endif /* SGI_LABEL */
2477 #ifdef CONFIG_FEATURE_SUN_LABEL
2481 * I think this is mostly, or entirely, due to
2482 * Jakub Jelinek (jj@sunsite.mff.cuni.cz), July 1996
2484 * Merged with fdisk for other architectures, aeb, June 1998.
2486 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
2487 * Internationalization
2491 static int sun_other_endian;
2492 static int scsi_disk;
2496 #define IDE0_MAJOR 3
2499 #define IDE1_MAJOR 22
2501 static void guess_device_type(void) {
2502 struct stat bootstat;
2504 if (fstat (fd, &bootstat) < 0) {
2507 } else if (S_ISBLK(bootstat.st_mode)
2508 && ((bootstat.st_rdev >> 8) == IDE0_MAJOR ||
2509 (bootstat.st_rdev >> 8) == IDE1_MAJOR)) {
2512 } else if (S_ISBLK(bootstat.st_mode)
2513 && (bootstat.st_rdev >> 8) == FLOPPY_MAJOR) {
2522 static const struct systypes sun_sys_types[] = {
2523 /* 0 */ {"\x00" "Empty" },
2524 /* 1 */ {"\x01" "Boot" },
2525 /* 2 */ {"\x02" "SunOS root" },
2526 /* SUNOS_SWAP */ {"\x03" "SunOS swap" },
2527 /* 4 */ {"\x04" "SunOS usr" },
2528 /* WHOLE_DISK */ {"\x05" "Whole disk" },
2529 /* 6 */ {"\x06" "SunOS stand" },
2530 /* 7 */ {"\x07" "SunOS var" },
2531 /* 8 */ {"\x08" "SunOS home" },
2532 /* LINUX_SWAP */ {"\x82" "Linux swap" },
2533 /* LINUX_NATIVE */ {"\x83" "Linux native" },
2534 /* 0x8e */ {"\x8e" "Linux LVM" },
2535 /* New (2.2.x) raid partition with autodetect using persistent superblock */
2536 /* 0xfd */ {"\xfd" "Linux raid autodetect" },
2542 set_sun_partition(int i, uint start, uint stop, int sysid) {
2543 sunlabel->infos[i].id = sysid;
2544 sunlabel->partitions[i].start_cylinder =
2545 SUN_SSWAP32(start / (heads * sectors));
2546 sunlabel->partitions[i].num_sectors =
2547 SUN_SSWAP32(stop - start);
2554 sunlabel->magic = 0;
2559 check_sun_label(void) {
2560 unsigned short *ush;
2563 if (sunlabel->magic != SUN_LABEL_MAGIC &&
2564 sunlabel->magic != SUN_LABEL_MAGIC_SWAPPED) {
2566 sun_other_endian = 0;
2569 sun_other_endian = (sunlabel->magic == SUN_LABEL_MAGIC_SWAPPED);
2570 ush = ((unsigned short *) (sunlabel + 1)) - 1;
2571 for (csum = 0; ush >= (unsigned short *)sunlabel;) csum ^= *ush--;
2573 fprintf(stderr,_("Detected sun disklabel with wrong checksum.\n"
2574 "Probably you'll have to set all the values,\n"
2575 "e.g. heads, sectors, cylinders and partitions\n"
2576 "or force a fresh label (s command in main menu)\n"));
2578 heads = SUN_SSWAP16(sunlabel->ntrks);
2579 cylinders = SUN_SSWAP16(sunlabel->ncyl);
2580 sectors = SUN_SSWAP16(sunlabel->nsect);
2588 static const struct sun_predefined_drives {
2591 unsigned short sparecyl;
2592 unsigned short ncyl;
2593 unsigned short nacyl;
2594 unsigned short pcylcount;
2595 unsigned short ntrks;
2596 unsigned short nsect;
2597 unsigned short rspeed;
2599 {"Quantum","ProDrive 80S",1,832,2,834,6,34,3662},
2600 {"Quantum","ProDrive 105S",1,974,2,1019,6,35,3662},
2601 {"CDC","Wren IV 94171-344",3,1545,2,1549,9,46,3600},
2602 {"IBM","DPES-31080",0,4901,2,4903,4,108,5400},
2603 {"IBM","DORS-32160",0,1015,2,1017,67,62,5400},
2604 {"IBM","DNES-318350",0,11199,2,11474,10,320,7200},
2605 {"SEAGATE","ST34371",0,3880,2,3882,16,135,7228},
2606 {"","SUN0104",1,974,2,1019,6,35,3662},
2607 {"","SUN0207",4,1254,2,1272,9,36,3600},
2608 {"","SUN0327",3,1545,2,1549,9,46,3600},
2609 {"","SUN0340",0,1538,2,1544,6,72,4200},
2610 {"","SUN0424",2,1151,2,2500,9,80,4400},
2611 {"","SUN0535",0,1866,2,2500,7,80,5400},
2612 {"","SUN0669",5,1614,2,1632,15,54,3600},
2613 {"","SUN1.0G",5,1703,2,1931,15,80,3597},
2614 {"","SUN1.05",0,2036,2,2038,14,72,5400},
2615 {"","SUN1.3G",6,1965,2,3500,17,80,5400},
2616 {"","SUN2.1G",0,2733,2,3500,19,80,5400},
2617 {"IOMEGA","Jaz",0,1019,2,1021,64,32,5394},
2620 static const struct sun_predefined_drives *
2621 sun_autoconfigure_scsi(void) {
2622 const struct sun_predefined_drives *p = NULL;
2624 #ifdef SCSI_IOCTL_GET_IDLUN
2634 if (!ioctl(fd, SCSI_IOCTL_GET_IDLUN, &id)) {
2636 "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n",
2638 ((id[0]>>24)&0xff)-/*PROC_SCSI_SCSI+PROC_SCSI_FILE*/33,
2640 /* This is very wrong (works only if you have one HBA),
2641 but I haven't found a way how to get hostno
2642 from the current kernel */
2648 pfd = fopen("/proc/scsi/scsi","r");
2650 while (fgets(buffer2,2048,pfd)) {
2651 if (!strcmp(buffer, buffer2)) {
2652 if (fgets(buffer2,2048,pfd)) {
2653 q = strstr(buffer2,"Vendor: ");
2658 *q++ = 0; /* truncate vendor name */
2659 q = strstr(q,"Model: ");
2664 q = strstr(q," Rev: ");
2667 for (i = 0; i < SIZE(sun_drives); i++) {
2668 if (*sun_drives[i].vendor && strcasecmp(sun_drives[i].vendor, vendor))
2670 if (!strstr(model, sun_drives[i].model))
2672 printf(_("Autoconfigure found a %s%s%s\n"),sun_drives[i].vendor,(*sun_drives[i].vendor) ? " " : "",sun_drives[i].model);
2690 static void create_sunlabel(void)
2692 struct hd_geometry geometry;
2696 const struct sun_predefined_drives *p = NULL;
2699 _("Building a new sun disklabel. Changes will remain in memory only,\n"
2700 "until you decide to write them. After that, of course, the previous\n"
2701 "content won't be recoverable.\n\n"));
2702 #if BYTE_ORDER == LITTLE_ENDIAN
2703 sun_other_endian = 1;
2705 sun_other_endian = 0;
2707 memset(MBRbuffer, 0, sizeof(MBRbuffer));
2708 sunlabel->magic = SUN_SSWAP16(SUN_LABEL_MAGIC);
2710 puts(_("Drive type\n"
2711 " ? auto configure\n"
2712 " 0 custom (with hardware detected defaults)"));
2713 for (i = 0; i < SIZE(sun_drives); i++) {
2714 printf(" %c %s%s%s\n",
2715 i + 'a', sun_drives[i].vendor,
2716 (*sun_drives[i].vendor) ? " " : "",
2717 sun_drives[i].model);
2720 c = read_char(_("Select type (? for auto, 0 for custom): "));
2721 if (c >= 'a' && c < 'a' + SIZE(sun_drives)) {
2722 p = sun_drives + c - 'a';
2724 } else if (c >= 'A' && c < 'A' + SIZE(sun_drives)) {
2725 p = sun_drives + c - 'A';
2727 } else if (c == '0') {
2729 } else if (c == '?' && scsi_disk) {
2730 p = sun_autoconfigure_scsi();
2732 printf(_("Autoconfigure failed.\n"));
2740 if (!ioctl(fd, HDIO_REQ, &geometry)) {
2742 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
2744 heads = geometry.heads;
2745 sectors = geometry.sectors;
2746 cylinders = geometry.cylinders;
2753 sunlabel->nacyl = 0;
2754 sunlabel->pcylcount = SUN_SSWAP16(cylinders);
2755 sunlabel->rspeed = SUN_SSWAP16(300);
2756 sunlabel->ilfact = SUN_SSWAP16(1);
2757 sunlabel->sparecyl = 0;
2759 heads = read_int(1,heads,1024,0,_("Heads"));
2760 sectors = read_int(1,sectors,1024,0,_("Sectors/track"));
2762 cylinders = read_int(1,cylinders-2,65535,0,_("Cylinders"));
2764 cylinders = read_int(1,0,65535,0,_("Cylinders"));
2766 SUN_SSWAP16(read_int(0,2,65535,0,
2767 _("Alternate cylinders")));
2768 sunlabel->pcylcount =
2769 SUN_SSWAP16(read_int(0,cylinders+SUN_SSWAP16(sunlabel->nacyl),
2770 65535,0,_("Physical cylinders")));
2772 SUN_SSWAP16(read_int(1,5400,100000,0,
2773 _("Rotation speed (rpm)")));
2775 SUN_SSWAP16(read_int(1,1,32,0,_("Interleave factor")));
2776 sunlabel->sparecyl =
2777 SUN_SSWAP16(read_int(0,0,sectors,0,
2778 _("Extra sectors per cylinder")));
2781 sunlabel->sparecyl = SUN_SSWAP16(p->sparecyl);
2782 sunlabel->ncyl = SUN_SSWAP16(p->ncyl);
2783 sunlabel->nacyl = SUN_SSWAP16(p->nacyl);
2784 sunlabel->pcylcount = SUN_SSWAP16(p->pcylcount);
2785 sunlabel->ntrks = SUN_SSWAP16(p->ntrks);
2786 sunlabel->nsect = SUN_SSWAP16(p->nsect);
2787 sunlabel->rspeed = SUN_SSWAP16(p->rspeed);
2788 sunlabel->ilfact = SUN_SSWAP16(1);
2789 cylinders = p->ncyl;
2792 puts(_("You may change all the disk params from the x menu"));
2795 snprintf(sunlabel->info, sizeof(sunlabel->info),
2796 "%s%s%s cyl %d alt %d hd %d sec %d",
2797 p ? p->vendor : "", (p && *p->vendor) ? " " : "",
2799 : (floppy ? _("3,5\" floppy") : _("Linux custom")),
2800 cylinders, SUN_SSWAP16(sunlabel->nacyl), heads, sectors);
2802 sunlabel->ntrks = SUN_SSWAP16(heads);
2803 sunlabel->nsect = SUN_SSWAP16(sectors);
2804 sunlabel->ncyl = SUN_SSWAP16(cylinders);
2806 set_sun_partition(0, 0, cylinders * heads * sectors, LINUX_NATIVE);
2808 if (cylinders * heads * sectors >= 150 * 2048) {
2809 ndiv = cylinders - (50 * 2048 / (heads * sectors)); /* 50M swap */
2811 ndiv = cylinders * 2 / 3;
2812 set_sun_partition(0, 0, ndiv * heads * sectors, LINUX_NATIVE);
2813 set_sun_partition(1, ndiv * heads * sectors, cylinders * heads * sectors, LINUX_SWAP);
2814 sunlabel->infos[1].flags |= 0x01; /* Not mountable */
2816 set_sun_partition(2, 0, cylinders * heads * sectors, WHOLE_DISK);
2818 unsigned short *ush = (unsigned short *)sunlabel;
2819 unsigned short csum = 0;
2820 while(ush < (unsigned short *)(&sunlabel->csum))
2822 sunlabel->csum = csum;
2825 set_all_unchanged();
2827 get_boot(create_empty_sun);
2831 toggle_sunflags(int i, unsigned char mask) {
2832 if (sunlabel->infos[i].flags & mask)
2833 sunlabel->infos[i].flags &= ~mask;
2834 else sunlabel->infos[i].flags |= mask;
2839 fetch_sun(uint *starts, uint *lens, uint *start, uint *stop) {
2840 int i, continuous = 1;
2841 *start = 0; *stop = cylinders * heads * sectors;
2842 for (i = 0; i < partitions; i++) {
2843 if (sunlabel->partitions[i].num_sectors
2844 && sunlabel->infos[i].id
2845 && sunlabel->infos[i].id != WHOLE_DISK) {
2846 starts[i] = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
2847 lens[i] = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
2849 if (starts[i] == *start)
2851 else if (starts[i] + lens[i] >= *stop)
2855 /* There will be probably more gaps
2856 than one, so lets check afterwards */
2865 static uint *verify_sun_starts;
2868 verify_sun_cmp(int *a, int *b) {
2869 if (*a == -1) return 1;
2870 if (*b == -1) return -1;
2871 if (verify_sun_starts[*a] > verify_sun_starts[*b]) return 1;
2877 uint starts[8], lens[8], start, stop;
2878 int i,j,k,starto,endo;
2881 verify_sun_starts = starts;
2882 fetch_sun(starts,lens,&start,&stop);
2883 for (k = 0; k < 7; k++) {
2884 for (i = 0; i < 8; i++) {
2885 if (k && (lens[i] % (heads * sectors))) {
2886 printf(_("Partition %d doesn't end on cylinder boundary\n"), i+1);
2889 for (j = 0; j < i; j++)
2891 if (starts[j] == starts[i]+lens[i]) {
2892 starts[j] = starts[i]; lens[j] += lens[i];
2894 } else if (starts[i] == starts[j]+lens[j]){
2898 if (starts[i] < starts[j]+lens[j] &&
2899 starts[j] < starts[i]+lens[i]) {
2901 if (starts[j] > starto)
2903 endo = starts[i]+lens[i];
2904 if (starts[j]+lens[j] < endo)
2905 endo = starts[j]+lens[j];
2906 printf(_("Partition %d overlaps with others in "
2907 "sectors %d-%d\n"), i+1, starto, endo);
2914 for (i = 0; i < 8; i++) {
2920 qsort(array,SIZE(array),sizeof(array[0]),
2921 (int (*)(const void *,const void *)) verify_sun_cmp);
2922 if (array[0] == -1) {
2923 printf(_("No partitions defined\n"));
2926 stop = cylinders * heads * sectors;
2927 if (starts[array[0]])
2928 printf(_("Unused gap - sectors 0-%d\n"),starts[array[0]]);
2929 for (i = 0; i < 7 && array[i+1] != -1; i++) {
2930 printf(_("Unused gap - sectors %d-%d\n"),starts[array[i]]+lens[array[i]],starts[array[i+1]]);
2932 start = starts[array[i]]+lens[array[i]];
2934 printf(_("Unused gap - sectors %d-%d\n"),start,stop);
2938 add_sun_partition(int n, int sys) {
2939 uint start, stop, stop2;
2940 uint starts[8], lens[8];
2946 if (sunlabel->partitions[n].num_sectors && sunlabel->infos[n].id) {
2947 printf(_("Partition %d is already defined. Delete "
2948 "it before re-adding it.\n"), n + 1);
2952 fetch_sun(starts,lens,&start,&stop);
2953 if (stop <= start) {
2957 printf(_("Other partitions already cover the whole disk.\nDelete "
2958 "some/shrink them before retry.\n"));
2962 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
2965 first = read_int(0, 0, 0, 0, mesg);
2967 first = read_int(scround(start), scround(stop)+1,
2968 scround(stop), 0, mesg);
2969 if (display_in_cyl_units)
2970 first *= units_per_sector;
2972 /* Starting sector has to be properly aligned */
2973 first = (first + heads * sectors - 1) / (heads * sectors);
2974 if (n == 2 && first != 0)
2976 It is highly recommended that the third partition covers the whole disk\n\
2977 and is of type `Whole disk'\n");
2978 /* ewt asks to add: "don't start a partition at cyl 0"
2979 However, edmundo@rano.demon.co.uk writes:
2980 "In addition to having a Sun partition table, to be able to
2981 boot from the disc, the first partition, /dev/sdX1, must
2982 start at cylinder 0. This means that /dev/sdX1 contains
2983 the partition table and the boot block, as these are the
2984 first two sectors of the disc. Therefore you must be
2985 careful what you use /dev/sdX1 for. In particular, you must
2986 not use a partition starting at cylinder 0 for Linux swap,
2987 as that would overwrite the partition table and the boot
2988 block. You may, however, use such a partition for a UFS
2989 or EXT2 file system, as these file systems leave the first
2990 1024 bytes undisturbed. */
2991 /* On the other hand, one should not use partitions
2992 starting at block 0 in an md, or the label will
2994 for (i = 0; i < partitions; i++)
2995 if (lens[i] && starts[i] <= first
2996 && starts[i] + lens[i] > first)
2998 if (i < partitions && !whole_disk) {
2999 if (n == 2 && !first) {
3003 printf(_("Sector %d is already allocated\n"), first);
3007 stop = cylinders * heads * sectors;
3009 for (i = 0; i < partitions; i++) {
3010 if (starts[i] > first && starts[i] < stop)
3013 snprintf(mesg, sizeof(mesg),
3014 _("Last %s or +size or +sizeM or +sizeK"),
3015 str_units(SINGULAR));
3017 last = read_int(scround(stop2), scround(stop2), scround(stop2),
3019 else if (n == 2 && !first)
3020 last = read_int(scround(first), scround(stop2), scround(stop2),
3021 scround(first), mesg);
3023 last = read_int(scround(first), scround(stop), scround(stop),
3024 scround(first), mesg);
3025 if (display_in_cyl_units)
3026 last *= units_per_sector;
3027 if (n == 2 && !first) {
3028 if (last >= stop2) {
3031 } else if (last > stop) {
3033 _("You haven't covered the whole disk with the 3rd partition, but your value\n"
3034 "%d %s covers some other partition. Your entry has been changed\n"
3036 scround(last), str_units(SINGULAR),
3037 scround(stop), str_units(SINGULAR));
3040 } else if (!whole_disk && last > stop)
3043 if (whole_disk) sys = WHOLE_DISK;
3044 set_sun_partition(n, first, last, sys);
3048 sun_delete_partition(int i) {
3049 if (i == 2 && sunlabel->infos[i].id == WHOLE_DISK &&
3050 !sunlabel->partitions[i].start_cylinder &&
3051 SUN_SSWAP32(sunlabel->partitions[i].num_sectors)
3052 == heads * sectors * cylinders)
3053 printf(_("If you want to maintain SunOS/Solaris compatibility, "
3054 "consider leaving this\n"
3055 "partition as Whole disk (5), starting at 0, with %u "
3057 (uint) SUN_SSWAP32(sunlabel->partitions[i].num_sectors));
3058 sunlabel->infos[i].id = 0;
3059 sunlabel->partitions[i].num_sectors = 0;
3063 sun_change_sysid(int i, int sys) {
3064 if (sys == LINUX_SWAP && !sunlabel->partitions[i].start_cylinder) {
3066 _("It is highly recommended that the partition at offset 0\n"
3067 "is UFS, EXT2FS filesystem or SunOS swap. Putting Linux swap\n"
3068 "there may destroy your partition table and bootblock.\n"
3069 "Type YES if you're very sure you would like that partition\n"
3070 "tagged with 82 (Linux swap): "));
3071 if (strcmp (line_ptr, _("YES\n")))
3077 /* swaps are not mountable by default */
3078 sunlabel->infos[i].flags |= 0x01;
3081 /* assume other types are mountable;
3082 user can change it anyway */
3083 sunlabel->infos[i].flags &= ~0x01;
3086 sunlabel->infos[i].id = sys;
3090 sun_list_table(int xtra) {
3093 w = strlen(disk_device);
3096 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d rpm\n"
3097 "%d cylinders, %d alternate cylinders, %d physical cylinders\n"
3098 "%d extra sects/cyl, interleave %d:1\n"
3100 "Units = %s of %d * 512 bytes\n\n"),
3101 disk_device, heads, sectors, SUN_SSWAP16(sunlabel->rspeed),
3102 cylinders, SUN_SSWAP16(sunlabel->nacyl),
3103 SUN_SSWAP16(sunlabel->pcylcount),
3104 SUN_SSWAP16(sunlabel->sparecyl),
3105 SUN_SSWAP16(sunlabel->ilfact),
3107 str_units(PLURAL), units_per_sector);
3110 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d cylinders\n"
3111 "Units = %s of %d * 512 bytes\n\n"),
3112 disk_device, heads, sectors, cylinders,
3113 str_units(PLURAL), units_per_sector);
3115 printf(_("%*s Flag Start End Blocks Id System\n"),
3116 w + 1, _("Device"));
3117 for (i = 0 ; i < partitions; i++) {
3118 if (sunlabel->partitions[i].num_sectors) {
3119 uint32_t start = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
3120 uint32_t len = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
3122 "%s %c%c %9ld %9ld %9ld%c %2x %s\n",
3123 /* device */ partname(disk_device, i+1, w),
3124 /* flags */ (sunlabel->infos[i].flags & 0x01) ? 'u' : ' ',
3125 (sunlabel->infos[i].flags & 0x10) ? 'r' : ' ',
3126 /* start */ (long) scround(start),
3127 /* end */ (long) scround(start+len),
3128 /* odd flag on end */ (long) len / 2, len & 1 ? '+' : ' ',
3129 /* type id */ sunlabel->infos[i].id,
3130 /* type name */ partition_type(sunlabel->infos[i].id));
3136 sun_set_alt_cyl(void) {
3138 SUN_SSWAP16(read_int(0,SUN_SSWAP16(sunlabel->nacyl), 65535, 0,
3139 _("Number of alternate cylinders")));
3143 sun_set_ncyl(int cyl) {
3144 sunlabel->ncyl = SUN_SSWAP16(cyl);
3148 sun_set_xcyl(void) {
3149 sunlabel->sparecyl =
3150 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->sparecyl), sectors, 0,
3151 _("Extra sectors per cylinder")));
3155 sun_set_ilfact(void) {
3157 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->ilfact), 32, 0,
3158 _("Interleave factor")));
3162 sun_set_rspeed(void) {
3164 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->rspeed), 100000, 0,
3165 _("Rotation speed (rpm)")));
3169 sun_set_pcylcount(void) {
3170 sunlabel->pcylcount =
3171 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->pcylcount), 65535, 0,
3172 _("Number of physical cylinders")));
3176 sun_write_table(void) {
3177 unsigned short *ush = (unsigned short *)sunlabel;
3178 unsigned short csum = 0;
3180 while(ush < (unsigned short *)(&sunlabel->csum))
3182 sunlabel->csum = csum;
3183 if (lseek(fd, 0, SEEK_SET) < 0)
3184 fdisk_fatal(unable_to_seek);
3185 if (write(fd, sunlabel, SECTOR_SIZE) != SECTOR_SIZE)
3186 fdisk_fatal(unable_to_write);
3188 #endif /* SUN_LABEL */
3190 /* DOS partition types */
3192 static const struct systypes i386_sys_types[] = {
3195 {"\x04" "FAT16 <32M"},
3196 {"\x05" "Extended"}, /* DOS 3.3+ extended partition */
3197 {"\x06" "FAT16"}, /* DOS 16-bit >=32M */
3198 {"\x07" "HPFS/NTFS"}, /* OS/2 IFS, eg, HPFS or NTFS or QNX */
3199 {"\x0a" "OS/2 Boot Manager"},/* OS/2 Boot Manager */
3200 {"\x0b" "Win95 FAT32"},
3201 {"\x0c" "Win95 FAT32 (LBA)"},/* LBA really is `Extended Int 13h' */
3202 {"\x0e" "Win95 FAT16 (LBA)"},
3203 {"\x0f" "Win95 Ext'd (LBA)"},
3204 {"\x11" "Hidden FAT12"},
3205 {"\x12" "Compaq diagnostics"},
3206 {"\x14" "Hidden FAT16 <32M"},
3207 {"\x16" "Hidden FAT16"},
3208 {"\x17" "Hidden HPFS/NTFS"},
3209 {"\x1b" "Hidden Win95 FAT32"},
3210 {"\x1c" "Hidden Win95 FAT32 (LBA)"},
3211 {"\x1e" "Hidden Win95 FAT16 (LBA)"},
3212 {"\x3c" "PartitionMagic recovery"},
3213 {"\x41" "PPC PReP Boot"},
3215 {"\x63" "GNU HURD or SysV"}, /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */
3216 {"\x80" "Old Minix"}, /* Minix 1.4a and earlier */
3217 {"\x81" "Minix / old Linux"},/* Minix 1.4b and later */
3218 {"\x82" "Linux swap"}, /* also Solaris */
3220 {"\x84" "OS/2 hidden C: drive"},
3221 {"\x85" "Linux extended"},
3222 {"\x86" "NTFS volume set"},
3223 {"\x87" "NTFS volume set"},
3224 {"\x8e" "Linux LVM"},
3225 {"\x9f" "BSD/OS"}, /* BSDI */
3226 {"\xa0" "IBM Thinkpad hibernation"},
3227 {"\xa5" "FreeBSD"}, /* various BSD flavours */
3229 {"\xa8" "Darwin UFS"},
3231 {"\xab" "Darwin boot"},
3233 {"\xb8" "BSDI swap"},
3234 {"\xbe" "Solaris boot"},
3236 {"\xee" "EFI GPT"}, /* Intel EFI GUID Partition Table */
3237 {"\xef" "EFI (FAT-12/16/32)"},/* Intel EFI System Partition */
3238 {"\xf0" "Linux/PA-RISC boot"},/* Linux/PA-RISC boot loader */
3239 {"\xf2" "DOS secondary"}, /* DOS 3.3+ secondary */
3240 {"\xfd" "Linux raid autodetect"},/* New (2.2.x) raid partition with
3241 autodetect using persistent
3243 #ifdef CONFIG_WEIRD_PARTITION_TYPES
3244 {"\x02" "XENIX root"},
3245 {"\x03" "XENIX usr"},
3246 {"\x08" "AIX"}, /* AIX boot (AIX -- PS/2 port) or SplitDrive */
3247 {"\x09" "AIX bootable"}, /* AIX data or Coherent */
3249 {"\x18" "AST SmartSleep"},
3252 {"\x40" "Venix 80286"},
3254 {"\x4e" "QNX4.x 2nd part"},
3255 {"\x4f" "QNX4.x 3rd part"},
3256 {"\x50" "OnTrack DM"},
3257 {"\x51" "OnTrack DM6 Aux1"}, /* (or Novell) */
3258 {"\x52" "CP/M"}, /* CP/M or Microport SysV/AT */
3259 {"\x53" "OnTrack DM6 Aux3"},
3260 {"\x54" "OnTrackDM6"},
3261 {"\x55" "EZ-Drive"},
3262 {"\x56" "Golden Bow"},
3263 {"\x5c" "Priam Edisk"},
3264 {"\x61" "SpeedStor"},
3265 {"\x64" "Novell Netware 286"},
3266 {"\x65" "Novell Netware 386"},
3267 {"\x70" "DiskSecure Multi-Boot"},
3270 {"\x94" "Amoeba BBT"}, /* (bad block table) */
3271 {"\xa7" "NeXTSTEP"},
3272 {"\xbb" "Boot Wizard hidden"},
3273 {"\xc1" "DRDOS/sec (FAT-12)"},
3274 {"\xc4" "DRDOS/sec (FAT-16 < 32M)"},
3275 {"\xc6" "DRDOS/sec (FAT-16)"},
3277 {"\xda" "Non-FS data"},
3278 {"\xdb" "CP/M / CTOS / ..."},/* CP/M or Concurrent CP/M or
3279 Concurrent DOS or CTOS */
3280 {"\xde" "Dell Utility"}, /* Dell PowerEdge Server utilities */
3281 {"\xdf" "BootIt"}, /* BootIt EMBRM */
3282 {"\xe1" "DOS access"}, /* DOS access or SpeedStor 12-bit FAT
3283 extended partition */
3284 {"\xe3" "DOS R/O"}, /* DOS R/O or SpeedStor */
3285 {"\xe4" "SpeedStor"}, /* SpeedStor 16-bit FAT extended
3286 partition < 1024 cyl. */
3287 {"\xf1" "SpeedStor"},
3288 {"\xf4" "SpeedStor"}, /* SpeedStor large partition */
3289 {"\xfe" "LANstep"}, /* SpeedStor >1024 cyl. or LANstep */
3290 {"\xff" "BBT"}, /* Xenix Bad Block Table */
3297 /* A valid partition table sector ends in 0x55 0xaa */
3299 part_table_flag(const char *b) {
3300 return ((uint) b[510]) + (((uint) b[511]) << 8);
3304 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3306 write_part_table_flag(char *b) {
3311 /* start_sect and nr_sects are stored little endian on all machines */
3312 /* moreover, they are not aligned correctly */
3314 store4_little_endian(unsigned char *cp, unsigned int val) {
3315 cp[0] = (val & 0xff);
3316 cp[1] = ((val >> 8) & 0xff);
3317 cp[2] = ((val >> 16) & 0xff);
3318 cp[3] = ((val >> 24) & 0xff);
3320 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3323 read4_little_endian(const unsigned char *cp) {
3324 return (uint)(cp[0]) + ((uint)(cp[1]) << 8)
3325 + ((uint)(cp[2]) << 16) + ((uint)(cp[3]) << 24);
3328 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3330 set_start_sect(struct partition *p, unsigned int start_sect) {
3331 store4_little_endian(p->start4, start_sect);
3336 get_start_sect(const struct partition *p) {
3337 return read4_little_endian(p->start4);
3340 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3342 set_nr_sects(struct partition *p, unsigned int nr_sects) {
3343 store4_little_endian(p->size4, nr_sects);
3348 get_nr_sects(const struct partition *p) {
3349 return read4_little_endian(p->size4);
3352 /* normally O_RDWR, -l option gives O_RDONLY */
3353 static int type_open = O_RDWR;
3356 static int ext_index, /* the prime extended partition */
3357 listing, /* no aborts for fdisk -l */
3358 dos_compatible_flag = ~0;
3359 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3360 static int dos_changed;
3361 static int nowarn; /* no warnings for fdisk -l/-s */
3366 static uint user_cylinders, user_heads, user_sectors;
3367 static uint pt_heads, pt_sectors;
3368 static uint kern_heads, kern_sectors;
3370 static uint extended_offset; /* offset of link pointers */
3371 static uint sector_size = DEFAULT_SECTOR_SIZE,
3372 user_set_sector_size,
3375 static unsigned long total_number_of_sectors;
3378 static jmp_buf listingbuf;
3380 static void fdisk_fatal(enum failure why) {
3381 const char *message;
3385 longjmp(listingbuf, 1);
3389 case unable_to_open:
3390 message = "Unable to open %s\n";
3392 case unable_to_read:
3393 message = "Unable to read %s\n";
3395 case unable_to_seek:
3396 message = "Unable to seek on %s\n";
3398 case unable_to_write:
3399 message = "Unable to write %s\n";
3402 message = "BLKGETSIZE ioctl failed on %s\n";
3405 message = "Fatal error\n";
3408 fputc('\n', stderr);
3409 fprintf(stderr, message, disk_device);
3414 seek_sector(uint secno) {
3415 ext2_loff_t offset = (ext2_loff_t) secno * sector_size;
3416 if (lseek(fd, offset, SEEK_SET) == (ext2_loff_t) -1)
3417 fdisk_fatal(unable_to_seek);
3420 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3422 write_sector(uint secno, char *buf) {
3424 if (write(fd, buf, sector_size) != sector_size)
3425 fdisk_fatal(unable_to_write);
3429 /* Allocate a buffer and read a partition table sector */
3431 read_pte(struct pte *pe, uint offset) {
3433 pe->offset = offset;
3434 pe->sectorbuffer = (char *) xmalloc(sector_size);
3435 seek_sector(offset);
3436 if (read(fd, pe->sectorbuffer, sector_size) != sector_size)
3437 fdisk_fatal(unable_to_read);
3438 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3441 pe->part_table = pe->ext_pointer = NULL;
3445 get_partition_start(const struct pte *pe) {
3446 return pe->offset + get_start_sect(pe->part_table);
3449 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3451 * Avoid warning about DOS partitions when no DOS partition was changed.
3452 * Here a heuristic "is probably dos partition".
3453 * We might also do the opposite and warn in all cases except
3454 * for "is probably nondos partition".
3457 is_dos_partition(int t) {
3458 return (t == 1 || t == 4 || t == 6 ||
3459 t == 0x0b || t == 0x0c || t == 0x0e ||
3460 t == 0x11 || t == 0x12 || t == 0x14 || t == 0x16 ||
3461 t == 0x1b || t == 0x1c || t == 0x1e || t == 0x24 ||
3462 t == 0xc1 || t == 0xc4 || t == 0xc6);
3467 #ifdef CONFIG_FEATURE_SUN_LABEL
3469 puts(_("Command action"));
3470 puts(_("\ta\ttoggle a read only flag")); /* sun */
3471 puts(_("\tb\tedit bsd disklabel"));
3472 puts(_("\tc\ttoggle the mountable flag")); /* sun */
3473 puts(_("\td\tdelete a partition"));
3474 puts(_("\tl\tlist known partition types"));
3475 puts(_("\tm\tprint this menu"));
3476 puts(_("\tn\tadd a new partition"));
3477 puts(_("\to\tcreate a new empty DOS partition table"));
3478 puts(_("\tp\tprint the partition table"));
3479 puts(_("\tq\tquit without saving changes"));
3480 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3481 puts(_("\tt\tchange a partition's system id"));
3482 puts(_("\tu\tchange display/entry units"));
3483 puts(_("\tv\tverify the partition table"));
3484 puts(_("\tw\twrite table to disk and exit"));
3485 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3486 puts(_("\tx\textra functionality (experts only)"));
3490 #ifdef CONFIG_FEATURE_SGI_LABEL
3492 puts(_("Command action"));
3493 puts(_("\ta\tselect bootable partition")); /* sgi flavour */
3494 puts(_("\tb\tedit bootfile entry")); /* sgi */
3495 puts(_("\tc\tselect sgi swap partition")); /* sgi flavour */
3496 puts(_("\td\tdelete a partition"));
3497 puts(_("\tl\tlist known partition types"));
3498 puts(_("\tm\tprint this menu"));
3499 puts(_("\tn\tadd a new partition"));
3500 puts(_("\to\tcreate a new empty DOS partition table"));
3501 puts(_("\tp\tprint the partition table"));
3502 puts(_("\tq\tquit without saving changes"));
3503 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3504 puts(_("\tt\tchange a partition's system id"));
3505 puts(_("\tu\tchange display/entry units"));
3506 puts(_("\tv\tverify the partition table"));
3507 puts(_("\tw\twrite table to disk and exit"));
3510 #ifdef CONFIG_FEATURE_AIX_LABEL
3512 puts(_("Command action"));
3513 puts(_("\tm\tprint this menu"));
3514 puts(_("\to\tcreate a new empty DOS partition table"));
3515 puts(_("\tq\tquit without saving changes"));
3516 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3520 puts(_("Command action"));
3521 puts(_("\ta\ttoggle a bootable flag"));
3522 puts(_("\tb\tedit bsd disklabel"));
3523 puts(_("\tc\ttoggle the dos compatibility flag"));
3524 puts(_("\td\tdelete a partition"));
3525 puts(_("\tl\tlist known partition types"));
3526 puts(_("\tm\tprint this menu"));
3527 puts(_("\tn\tadd a new partition"));
3528 puts(_("\to\tcreate a new empty DOS partition table"));
3529 puts(_("\tp\tprint the partition table"));
3530 puts(_("\tq\tquit without saving changes"));
3531 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3532 puts(_("\tt\tchange a partition's system id"));
3533 puts(_("\tu\tchange display/entry units"));
3534 puts(_("\tv\tverify the partition table"));
3535 puts(_("\tw\twrite table to disk and exit"));
3536 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3537 puts(_("\tx\textra functionality (experts only)"));
3541 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3544 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3547 #ifdef CONFIG_FEATURE_SUN_LABEL
3549 puts(_("Command action"));
3550 puts(_("\ta\tchange number of alternate cylinders")); /*sun*/
3551 puts(_("\tc\tchange number of cylinders"));
3552 puts(_("\td\tprint the raw data in the partition table"));
3553 puts(_("\te\tchange number of extra sectors per cylinder"));/*sun*/
3554 puts(_("\th\tchange number of heads"));
3555 puts(_("\ti\tchange interleave factor")); /*sun*/
3556 puts(_("\to\tchange rotation speed (rpm)")); /*sun*/
3557 puts(_("\tm\tprint this menu"));
3558 puts(_("\tp\tprint the partition table"));
3559 puts(_("\tq\tquit without saving changes"));
3560 puts(_("\tr\treturn to main menu"));
3561 puts(_("\ts\tchange number of sectors/track"));
3562 puts(_("\tv\tverify the partition table"));
3563 puts(_("\tw\twrite table to disk and exit"));
3564 puts(_("\ty\tchange number of physical cylinders")); /*sun*/
3567 #ifdef CONFIG_FEATURE_SGI_LABEL
3569 puts(_("Command action"));
3570 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3571 puts(_("\tc\tchange number of cylinders"));
3572 puts(_("\td\tprint the raw data in the partition table"));
3573 puts(_("\te\tlist extended partitions")); /* !sun */
3574 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3575 puts(_("\th\tchange number of heads"));
3576 puts(_("\tm\tprint this menu"));
3577 puts(_("\tp\tprint the partition table"));
3578 puts(_("\tq\tquit without saving changes"));
3579 puts(_("\tr\treturn to main menu"));
3580 puts(_("\ts\tchange number of sectors/track"));
3581 puts(_("\tv\tverify the partition table"));
3582 puts(_("\tw\twrite table to disk and exit"));
3585 #ifdef CONFIG_FEATURE_AIX_LABEL
3587 puts(_("Command action"));
3588 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3589 puts(_("\tc\tchange number of cylinders"));
3590 puts(_("\td\tprint the raw data in the partition table"));
3591 puts(_("\te\tlist extended partitions")); /* !sun */
3592 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3593 puts(_("\th\tchange number of heads"));
3594 puts(_("\tm\tprint this menu"));
3595 puts(_("\tp\tprint the partition table"));
3596 puts(_("\tq\tquit without saving changes"));
3597 puts(_("\tr\treturn to main menu"));
3598 puts(_("\ts\tchange number of sectors/track"));
3599 puts(_("\tv\tverify the partition table"));
3600 puts(_("\tw\twrite table to disk and exit"));
3604 puts(_("Command action"));
3605 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3606 puts(_("\tc\tchange number of cylinders"));
3607 puts(_("\td\tprint the raw data in the partition table"));
3608 puts(_("\te\tlist extended partitions")); /* !sun */
3609 puts(_("\tf\tfix partition order")); /* !sun, !aix, !sgi */
3610 #ifdef CONFIG_FEATURE_SGI_LABEL
3611 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3613 puts(_("\th\tchange number of heads"));
3614 puts(_("\tm\tprint this menu"));
3615 puts(_("\tp\tprint the partition table"));
3616 puts(_("\tq\tquit without saving changes"));
3617 puts(_("\tr\treturn to main menu"));
3618 puts(_("\ts\tchange number of sectors/track"));
3619 puts(_("\tv\tverify the partition table"));
3620 puts(_("\tw\twrite table to disk and exit"));
3623 #endif /* ADVANCED mode */
3625 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3626 static const struct systypes *
3627 get_sys_types(void) {
3629 #ifdef CONFIG_FEATURE_SUN_LABEL
3630 sun_label ? sun_sys_types :
3632 #ifdef CONFIG_FEATURE_SGI_LABEL
3633 sgi_label ? sgi_sys_types :
3638 #define get_sys_types() i386_sys_types
3639 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3641 static const char *partition_type(unsigned char type)
3644 const struct systypes *types = get_sys_types();
3646 for (i=0; types[i].name; i++)
3647 if (types[i].name[0] == type)
3648 return types[i].name + 1;
3650 return _("Unknown");
3654 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3658 #ifdef CONFIG_FEATURE_SUN_LABEL
3659 sun_label ? sunlabel->infos[i].id :
3661 #ifdef CONFIG_FEATURE_SGI_LABEL
3662 sgi_label ? sgi_get_sysid(i) :
3664 ptes[i].part_table->sys_ind);
3667 void list_types(const struct systypes *sys)
3669 uint last[4], done = 0, next = 0, size;
3672 for (i = 0; sys[i].name; i++);
3675 for (i = 3; i >= 0; i--)
3676 last[3 - i] = done += (size + i - done) / (i + 1);
3680 printf("%c%2x %-15.15s", i ? ' ' : '\n',
3681 sys[next].name[0], partition_type(sys[next].name[0]));
3682 next = last[i++] + done;
3683 if (i > 3 || next >= last[i]) {
3687 } while (done < last[0]);
3690 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3693 is_cleared_partition(const struct partition *p) {
3694 return !(!p || p->boot_ind || p->head || p->sector || p->cyl ||
3695 p->sys_ind || p->end_head || p->end_sector || p->end_cyl ||
3696 get_start_sect(p) || get_nr_sects(p));
3700 clear_partition(struct partition *p) {
3703 memset(p, 0, sizeof(struct partition));
3706 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3708 set_partition(int i, int doext, uint start, uint stop, int sysid) {
3709 struct partition *p;
3713 p = ptes[i].ext_pointer;
3714 offset = extended_offset;
3716 p = ptes[i].part_table;
3717 offset = ptes[i].offset;
3721 set_start_sect(p, start - offset);
3722 set_nr_sects(p, stop - start + 1);
3723 if (dos_compatible_flag && (start/(sectors*heads) > 1023))
3724 start = heads*sectors*1024 - 1;
3725 set_hsc(p->head, p->sector, p->cyl, start);
3726 if (dos_compatible_flag && (stop/(sectors*heads) > 1023))
3727 stop = heads*sectors*1024 - 1;
3728 set_hsc(p->end_head, p->end_sector, p->end_cyl, stop);
3729 ptes[i].changed = 1;
3734 test_c(const char **m, const char *mesg) {
3737 fprintf(stderr, _("You must set"));
3739 fprintf(stderr, " %s", *m);
3747 warn_geometry(void) {
3748 const char *m = NULL;
3752 prev = test_c(&m, _("heads"));
3754 prev = test_c(&m, _("sectors"));
3756 prev = test_c(&m, _("cylinders"));
3760 fprintf(stderr, "%s%s.\n"
3761 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3762 "You can do this from the extra functions menu.\n"
3764 , prev ? _(" and ") : " ", m);
3769 static void update_units(void)
3771 int cyl_units = heads * sectors;
3773 if (display_in_cyl_units && cyl_units)
3774 units_per_sector = cyl_units;
3776 units_per_sector = 1; /* in sectors */
3779 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3781 warn_cylinders(void) {
3782 if (dos_label && cylinders > 1024 && !nowarn)
3783 fprintf(stderr, _("\n"
3784 "The number of cylinders for this disk is set to %d.\n"
3785 "There is nothing wrong with that, but this is larger than 1024,\n"
3786 "and could in certain setups cause problems with:\n"
3787 "1) software that runs at boot time (e.g., old versions of LILO)\n"
3788 "2) booting and partitioning software from other OSs\n"
3789 " (e.g., DOS FDISK, OS/2 FDISK)\n"),
3795 read_extended(int ext) {
3798 struct partition *p, *q;
3802 pex->ext_pointer = pex->part_table;
3804 p = pex->part_table;
3805 if (!get_start_sect(p)) {
3807 _("Bad offset in primary extended partition\n"));
3811 while (IS_EXTENDED (p->sys_ind)) {
3812 struct pte *pe = &ptes[partitions];
3814 if (partitions >= MAXIMUM_PARTS) {
3815 /* This is not a Linux restriction, but
3816 this program uses arrays of size MAXIMUM_PARTS.
3817 Do not try to `improve' this test. */
3818 struct pte *pre = &ptes[partitions-1];
3819 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3821 _("Warning: deleting partitions after %d\n"),
3825 clear_partition(pre->ext_pointer);
3829 read_pte(pe, extended_offset + get_start_sect(p));
3831 if (!extended_offset)
3832 extended_offset = get_start_sect(p);
3834 q = p = pt_offset(pe->sectorbuffer, 0);
3835 for (i = 0; i < 4; i++, p++) if (get_nr_sects(p)) {
3836 if (IS_EXTENDED (p->sys_ind)) {
3837 if (pe->ext_pointer)
3839 _("Warning: extra link "
3840 "pointer in partition table"
3841 " %d\n"), partitions + 1);
3843 pe->ext_pointer = p;
3844 } else if (p->sys_ind) {
3847 _("Warning: ignoring extra "
3848 "data in partition table"
3849 " %d\n"), partitions + 1);
3855 /* very strange code here... */
3856 if (!pe->part_table) {
3857 if (q != pe->ext_pointer)
3860 pe->part_table = q + 1;
3862 if (!pe->ext_pointer) {
3863 if (q != pe->part_table)
3864 pe->ext_pointer = q;
3866 pe->ext_pointer = q + 1;
3869 p = pe->ext_pointer;
3873 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3874 /* remove empty links */
3876 for (i = 4; i < partitions; i++) {
3877 struct pte *pe = &ptes[i];
3879 if (!get_nr_sects(pe->part_table) &&
3880 (partitions > 5 || ptes[4].part_table->sys_ind)) {
3881 printf("omitting empty partition (%d)\n", i+1);
3882 delete_partition(i);
3883 goto remove; /* numbering changed */
3889 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3891 create_doslabel(void) {
3895 _("Building a new DOS disklabel. Changes will remain in memory only,\n"
3896 "until you decide to write them. After that, of course, the previous\n"
3897 "content won't be recoverable.\n\n"));
3898 #ifdef CONFIG_FEATURE_SUN_LABEL
3899 sun_nolabel(); /* otherwise always recognised as sun */
3901 #ifdef CONFIG_FEATURE_SGI_LABEL
3902 sgi_nolabel(); /* otherwise always recognised as sgi */
3904 #ifdef CONFIG_FEATURE_AIX_LABEL
3907 #ifdef CONFIG_FEATURE_OSF_LABEL
3909 possibly_osf_label = 0;
3913 for (i = 510-64; i < 510; i++)
3915 write_part_table_flag(MBRbuffer);
3916 extended_offset = 0;
3917 set_all_unchanged();
3919 get_boot(create_empty_dos);
3921 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3924 get_sectorsize(void) {
3925 if (!user_set_sector_size &&
3926 get_kernel_revision() >= MAKE_VERSION(2,3,3)) {
3928 if (ioctl(fd, BLKSSZGET, &arg) == 0)
3930 if (sector_size != DEFAULT_SECTOR_SIZE)
3931 printf(_("Note: sector size is %d (not %d)\n"),
3932 sector_size, DEFAULT_SECTOR_SIZE);
3937 get_kernel_geometry(void) {
3938 struct hd_geometry geometry;
3940 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
3941 kern_heads = geometry.heads;
3942 kern_sectors = geometry.sectors;
3943 /* never use geometry.cylinders - it is truncated */
3948 get_partition_table_geometry(void) {
3949 const unsigned char *bufp = MBRbuffer;
3950 struct partition *p;
3951 int i, h, s, hh, ss;
3955 if (!(valid_part_table_flag(bufp)))
3959 for (i=0; i<4; i++) {
3960 p = pt_offset(bufp, i);
3961 if (p->sys_ind != 0) {
3962 h = p->end_head + 1;
3963 s = (p->end_sector & 077);
3968 } else if (hh != h || ss != s)
3973 if (!first && !bad) {
3980 get_geometry(void) {
3982 unsigned long longsectors;
3985 sec_fac = sector_size / 512;
3986 #ifdef CONFIG_FEATURE_SUN_LABEL
3987 guess_device_type();
3989 heads = cylinders = sectors = 0;
3990 kern_heads = kern_sectors = 0;
3991 pt_heads = pt_sectors = 0;
3993 get_kernel_geometry();
3994 get_partition_table_geometry();
3996 heads = user_heads ? user_heads :
3997 pt_heads ? pt_heads :
3998 kern_heads ? kern_heads : 255;
3999 sectors = user_sectors ? user_sectors :
4000 pt_sectors ? pt_sectors :
4001 kern_sectors ? kern_sectors : 63;
4003 if (ioctl(fd, BLKGETSIZE, &longsectors))
4007 if (dos_compatible_flag)
4008 sector_offset = sectors;
4010 cylinders = longsectors / (heads * sectors);
4011 cylinders /= sec_fac;
4013 cylinders = user_cylinders;
4015 total_number_of_sectors = longsectors;
4019 * Read MBR. Returns:
4020 * -1: no 0xaa55 flag present (possibly entire disk BSD)
4021 * 0: found or created label
4025 get_boot(enum action what) {
4030 for (i = 0; i < 4; i++) {
4031 struct pte *pe = &ptes[i];
4033 pe->part_table = pt_offset(MBRbuffer, i);
4034 pe->ext_pointer = NULL;
4036 pe->sectorbuffer = MBRbuffer;
4037 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4038 pe->changed = (what == create_empty_dos);
4042 #ifdef CONFIG_FEATURE_SUN_LABEL
4043 if (what == create_empty_sun && check_sun_label())
4047 memset(MBRbuffer, 0, 512);
4049 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4050 if (what == create_empty_dos)
4051 goto got_dos_table; /* skip reading disk */
4053 if ((fd = open(disk_device, type_open)) < 0) {
4054 if ((fd = open(disk_device, O_RDONLY)) < 0) {
4055 if (what == try_only)
4057 fdisk_fatal(unable_to_open);
4059 printf(_("You will not be able to write "
4060 "the partition table.\n"));
4063 if (512 != read(fd, MBRbuffer, 512)) {
4064 if (what == try_only)
4066 fdisk_fatal(unable_to_read);
4069 if ((fd = open(disk_device, O_RDONLY)) < 0)
4071 if (512 != read(fd, MBRbuffer, 512))
4079 #ifdef CONFIG_FEATURE_SUN_LABEL
4080 if (check_sun_label())
4084 #ifdef CONFIG_FEATURE_SGI_LABEL
4085 if (check_sgi_label())
4089 #ifdef CONFIG_FEATURE_AIX_LABEL
4090 if (check_aix_label())
4094 #ifdef CONFIG_FEATURE_OSF_LABEL
4095 if (check_osf_label()) {
4096 possibly_osf_label = 1;
4097 if (!valid_part_table_flag(MBRbuffer)) {
4101 printf(_("This disk has both DOS and BSD magic.\n"
4102 "Give the 'b' command to go to BSD mode.\n"));
4106 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4110 if (!valid_part_table_flag(MBRbuffer)) {
4111 #ifndef CONFIG_FEATURE_FDISK_WRITABLE
4117 _("Device contains neither a valid DOS "
4118 "partition table, nor Sun, SGI or OSF "
4121 #ifdef CONFIG_FEATURE_SUN_LABEL
4130 case create_empty_dos:
4131 #ifdef CONFIG_FEATURE_SUN_LABEL
4132 case create_empty_sun:
4136 fprintf(stderr, _("Internal error\n"));
4139 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
4142 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4147 for (i = 0; i < 4; i++) {
4148 struct pte *pe = &ptes[i];
4150 if (IS_EXTENDED (pe->part_table->sys_ind)) {
4151 if (partitions != 4)
4152 fprintf(stderr, _("Ignoring extra extended "
4153 "partition %d\n"), i + 1);
4159 for (i = 3; i < partitions; i++) {
4160 struct pte *pe = &ptes[i];
4162 if (!valid_part_table_flag(pe->sectorbuffer)) {
4164 _("Warning: invalid flag 0x%04x of partition "
4165 "table %d will be corrected by w(rite)\n"),
4166 part_table_flag(pe->sectorbuffer), i + 1);
4167 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4176 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4178 * Print the message MESG, then read an integer between LOW and HIGH (inclusive).
4179 * If the user hits Enter, DFLT is returned.
4180 * Answers like +10 are interpreted as offsets from BASE.
4182 * There is no default if DFLT is not between LOW and HIGH.
4185 read_int(uint low, uint dflt, uint high, uint base, char *mesg)
4189 static char *ms = NULL;
4190 static int mslen = 0;
4192 if (!ms || strlen(mesg)+100 > mslen) {
4193 mslen = strlen(mesg)+200;
4194 ms = xrealloc(ms,mslen);
4197 if (dflt < low || dflt > high)
4201 snprintf(ms, mslen, _("%s (%d-%d, default %d): "),
4202 mesg, low, high, dflt);
4204 snprintf(ms, mslen, "%s (%d-%d): ",
4208 int use_default = default_ok;
4210 /* ask question and read answer */
4211 while (read_chars(ms) != '\n' && !isdigit(*line_ptr)
4212 && *line_ptr != '-' && *line_ptr != '+')
4215 if (*line_ptr == '+' || *line_ptr == '-') {
4216 int minus = (*line_ptr == '-');
4219 i = atoi(line_ptr+1);
4221 while (isdigit(*++line_ptr))
4224 switch (*line_ptr) {
4227 if (!display_in_cyl_units)
4228 i *= heads * sectors;
4240 absolute = 1000000000;
4246 unsigned long long bytes;
4249 bytes = (unsigned long long) i * absolute;
4250 unit = sector_size * units_per_sector;
4251 bytes += unit/2; /* round */
4260 while (isdigit(*line_ptr)) {
4266 printf(_("Using default value %d\n"), i = dflt);
4267 if (i >= low && i <= high)
4270 printf(_("Value out of range.\n"));
4276 get_partition(int warn, int max) {
4280 i = read_int(1, 0, max, 0, _("Partition number")) - 1;
4284 if ((!sun_label && !sgi_label && !pe->part_table->sys_ind)
4285 #ifdef CONFIG_FEATURE_SUN_LABEL
4287 (!sunlabel->partitions[i].num_sectors ||
4288 !sunlabel->infos[i].id))
4290 #ifdef CONFIG_FEATURE_SGI_LABEL
4291 || (sgi_label && (!sgi_get_num_sectors(i)))
4295 _("Warning: partition %d has empty type\n"),
4302 get_existing_partition(int warn, int max) {
4306 for (i = 0; i < max; i++) {
4307 struct pte *pe = &ptes[i];
4308 struct partition *p = pe->part_table;
4310 if (p && !is_cleared_partition(p)) {
4317 printf(_("Selected partition %d\n"), pno+1);
4320 printf(_("No partition is defined yet!\n"));
4324 return get_partition(warn, max);
4328 get_nonexisting_partition(int warn, int max) {
4332 for (i = 0; i < max; i++) {
4333 struct pte *pe = &ptes[i];
4334 struct partition *p = pe->part_table;
4336 if (p && is_cleared_partition(p)) {
4343 printf(_("Selected partition %d\n"), pno+1);
4346 printf(_("All primary partitions have been defined already!\n"));
4350 return get_partition(warn, max);
4354 void change_units(void)
4356 display_in_cyl_units = !display_in_cyl_units;
4358 printf(_("Changing display/entry units to %s\n"),
4363 toggle_active(int i) {
4364 struct pte *pe = &ptes[i];
4365 struct partition *p = pe->part_table;
4367 if (IS_EXTENDED (p->sys_ind) && !p->boot_ind)
4369 _("WARNING: Partition %d is an extended partition\n"),
4371 p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG);
4376 toggle_dos_compatibility_flag(void) {
4377 dos_compatible_flag = ~dos_compatible_flag;
4378 if (dos_compatible_flag) {
4379 sector_offset = sectors;
4380 printf(_("DOS Compatibility flag is set\n"));
4384 printf(_("DOS Compatibility flag is not set\n"));
4389 delete_partition(int i) {
4390 struct pte *pe = &ptes[i];
4391 struct partition *p = pe->part_table;
4392 struct partition *q = pe->ext_pointer;
4394 /* Note that for the fifth partition (i == 4) we don't actually
4395 * decrement partitions.
4398 if (warn_geometry())
4399 return; /* C/H/S not set */
4402 #ifdef CONFIG_FEATURE_SUN_LABEL
4404 sun_delete_partition(i);
4408 #ifdef CONFIG_FEATURE_SGI_LABEL
4410 sgi_delete_partition(i);
4416 if (IS_EXTENDED (p->sys_ind) && i == ext_index) {
4418 ptes[ext_index].ext_pointer = NULL;
4419 extended_offset = 0;
4425 if (!q->sys_ind && i > 4) {
4426 /* the last one in the chain - just delete */
4429 clear_partition(ptes[i].ext_pointer);
4430 ptes[i].changed = 1;
4432 /* not the last one - further ones will be moved down */
4434 /* delete this link in the chain */
4435 p = ptes[i-1].ext_pointer;
4437 set_start_sect(p, get_start_sect(q));
4438 set_nr_sects(p, get_nr_sects(q));
4439 ptes[i-1].changed = 1;
4440 } else if (partitions > 5) { /* 5 will be moved to 4 */
4441 /* the first logical in a longer chain */
4444 if (pe->part_table) /* prevent SEGFAULT */
4445 set_start_sect(pe->part_table,
4446 get_partition_start(pe) -
4448 pe->offset = extended_offset;
4452 if (partitions > 5) {
4454 while (i < partitions) {
4455 ptes[i] = ptes[i+1];
4459 /* the only logical: clear only */
4460 clear_partition(ptes[i].part_table);
4465 change_sysid(void) {
4466 int i, sys, origsys;
4467 struct partition *p;
4469 i = get_existing_partition(0, partitions);
4472 p = ptes[i].part_table;
4473 origsys = sys = get_sysid(i);
4475 /* if changing types T to 0 is allowed, then
4476 the reverse change must be allowed, too */
4477 if (!sys && !sgi_label && !sun_label && !get_nr_sects(p))
4478 printf(_("Partition %d does not exist yet!\n"), i + 1);
4480 sys = read_hex (get_sys_types());
4482 if (!sys && !sgi_label && !sun_label) {
4483 printf(_("Type 0 means free space to many systems\n"
4484 "(but not to Linux). Having partitions of\n"
4485 "type 0 is probably unwise. You can delete\n"
4486 "a partition using the `d' command.\n"));
4490 if (!sun_label && !sgi_label) {
4491 if (IS_EXTENDED (sys) != IS_EXTENDED (p->sys_ind)) {
4492 printf(_("You cannot change a partition into"
4493 " an extended one or vice versa\n"
4494 "Delete it first.\n"));
4500 #ifdef CONFIG_FEATURE_SUN_LABEL
4501 if (sun_label && i == 2 && sys != WHOLE_DISK)
4502 printf(_("Consider leaving partition 3 "
4503 "as Whole disk (5),\n"
4504 "as SunOS/Solaris expects it and "
4505 "even Linux likes it.\n\n"));
4507 #ifdef CONFIG_FEATURE_SGI_LABEL
4508 if (sgi_label && ((i == 10 && sys != ENTIRE_DISK)
4509 || (i == 8 && sys != 0)))
4510 printf(_("Consider leaving partition 9 "
4511 "as volume header (0),\nand "
4512 "partition 11 as entire volume (6)"
4513 "as IRIX expects it.\n\n"));
4517 #ifdef CONFIG_FEATURE_SUN_LABEL
4519 sun_change_sysid(i, sys);
4522 #ifdef CONFIG_FEATURE_SGI_LABEL
4524 sgi_change_sysid(i, sys);
4528 printf (_("Changed system type of partition %d "
4529 "to %x (%s)\n"), i + 1, sys,
4530 partition_type(sys));
4531 ptes[i].changed = 1;
4532 if (is_dos_partition(origsys) ||
4533 is_dos_partition(sys))
4539 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
4542 /* check_consistency() and long2chs() added Sat Mar 6 12:28:16 1993,
4543 * faith@cs.unc.edu, based on code fragments from pfdisk by Gordon W. Ross,
4544 * Jan. 1990 (version 1.2.1 by Gordon W. Ross Aug. 1990; Modified by S.
4545 * Lubkin Oct. 1991). */
4547 static void long2chs(ulong ls, uint *c, uint *h, uint *s) {
4548 int spc = heads * sectors;
4553 *s = ls % sectors + 1; /* sectors count from 1 */
4556 static void check_consistency(const struct partition *p, int partition) {
4557 uint pbc, pbh, pbs; /* physical beginning c, h, s */
4558 uint pec, peh, pes; /* physical ending c, h, s */
4559 uint lbc, lbh, lbs; /* logical beginning c, h, s */
4560 uint lec, leh, les; /* logical ending c, h, s */
4562 if (!heads || !sectors || (partition >= 4))
4563 return; /* do not check extended partitions */
4565 /* physical beginning c, h, s */
4566 pbc = (p->cyl & 0xff) | ((p->sector << 2) & 0x300);
4568 pbs = p->sector & 0x3f;
4570 /* physical ending c, h, s */
4571 pec = (p->end_cyl & 0xff) | ((p->end_sector << 2) & 0x300);
4573 pes = p->end_sector & 0x3f;
4575 /* compute logical beginning (c, h, s) */
4576 long2chs(get_start_sect(p), &lbc, &lbh, &lbs);
4578 /* compute logical ending (c, h, s) */
4579 long2chs(get_start_sect(p) + get_nr_sects(p) - 1, &lec, &leh, &les);
4581 /* Same physical / logical beginning? */
4582 if (cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) {
4583 printf(_("Partition %d has different physical/logical "
4584 "beginnings (non-Linux?):\n"), partition + 1);
4585 printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs);
4586 printf(_("logical=(%d, %d, %d)\n"),lbc, lbh, lbs);
4589 /* Same physical / logical ending? */
4590 if (cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) {
4591 printf(_("Partition %d has different physical/logical "
4592 "endings:\n"), partition + 1);
4593 printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
4594 printf(_("logical=(%d, %d, %d)\n"),lec, leh, les);
4598 /* Beginning on cylinder boundary? */
4599 if (pbh != !pbc || pbs != 1) {
4600 printf(_("Partition %i does not start on cylinder "
4601 "boundary:\n"), partition + 1);
4602 printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs);
4603 printf(_("should be (%d, %d, 1)\n"), pbc, !pbc);
4607 /* Ending on cylinder boundary? */
4608 if (peh != (heads - 1) || pes != sectors) {
4609 printf(_("Partition %i does not end on cylinder boundary.\n"),
4612 printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
4613 printf(_("should be (%d, %d, %d)\n"),
4614 pec, heads - 1, sectors);
4620 list_disk_geometry(void) {
4621 long long bytes = (long long) total_number_of_sectors * 512;
4622 long megabytes = bytes/1000000;
4624 if (megabytes < 10000)
4625 printf(_("\nDisk %s: %ld MB, %lld bytes\n"),
4626 disk_device, megabytes, bytes);
4628 printf(_("\nDisk %s: %ld.%ld GB, %lld bytes\n"),
4629 disk_device, megabytes/1000, (megabytes/100)%10, bytes);
4630 printf(_("%d heads, %d sectors/track, %d cylinders"),
4631 heads, sectors, cylinders);
4632 if (units_per_sector == 1)
4633 printf(_(", total %lu sectors"),
4634 total_number_of_sectors / (sector_size/512));
4635 printf(_("\nUnits = %s of %d * %d = %d bytes\n\n"),
4637 units_per_sector, sector_size, units_per_sector * sector_size);
4641 * Check whether partition entries are ordered by their starting positions.
4642 * Return 0 if OK. Return i if partition i should have been earlier.
4643 * Two separate checks: primary and logical partitions.
4646 wrong_p_order(int *prev) {
4647 const struct pte *pe;
4648 const struct partition *p;
4649 uint last_p_start_pos = 0, p_start_pos;
4652 for (i = 0 ; i < partitions; i++) {
4655 last_p_start_pos = 0;
4658 if ((p = pe->part_table)->sys_ind) {
4659 p_start_pos = get_partition_start(pe);
4661 if (last_p_start_pos > p_start_pos) {
4667 last_p_start_pos = p_start_pos;
4674 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
4676 * Fix the chain of logicals.
4677 * extended_offset is unchanged, the set of sectors used is unchanged
4678 * The chain is sorted so that sectors increase, and so that
4679 * starting sectors increase.
4681 * After this it may still be that cfdisk doesnt like the table.
4682 * (This is because cfdisk considers expanded parts, from link to
4683 * end of partition, and these may still overlap.)
4685 * sfdisk /dev/hda > ohda; sfdisk /dev/hda < ohda
4689 fix_chain_of_logicals(void) {
4690 int j, oj, ojj, sj, sjj;
4691 struct partition *pj,*pjj,tmp;
4693 /* Stage 1: sort sectors but leave sector of part 4 */
4694 /* (Its sector is the global extended_offset.) */
4696 for (j = 5; j < partitions-1; j++) {
4697 oj = ptes[j].offset;
4698 ojj = ptes[j+1].offset;
4700 ptes[j].offset = ojj;
4701 ptes[j+1].offset = oj;
4702 pj = ptes[j].part_table;
4703 set_start_sect(pj, get_start_sect(pj)+oj-ojj);
4704 pjj = ptes[j+1].part_table;
4705 set_start_sect(pjj, get_start_sect(pjj)+ojj-oj);
4706 set_start_sect(ptes[j-1].ext_pointer,
4707 ojj-extended_offset);
4708 set_start_sect(ptes[j].ext_pointer,
4709 oj-extended_offset);
4714 /* Stage 2: sort starting sectors */
4716 for (j = 4; j < partitions-1; j++) {
4717 pj = ptes[j].part_table;
4718 pjj = ptes[j+1].part_table;
4719 sj = get_start_sect(pj);
4720 sjj = get_start_sect(pjj);
4721 oj = ptes[j].offset;
4722 ojj = ptes[j+1].offset;
4723 if (oj+sj > ojj+sjj) {
4727 set_start_sect(pj, ojj+sjj-oj);
4728 set_start_sect(pjj, oj+sj-ojj);
4733 /* Probably something was changed */
4734 for (j = 4; j < partitions; j++)
4735 ptes[j].changed = 1;
4740 fix_partition_table_order(void) {
4741 struct pte *pei, *pek;
4744 if (!wrong_p_order(NULL)) {
4745 printf(_("Nothing to do. Ordering is correct already.\n\n"));
4749 while ((i = wrong_p_order(&k)) != 0 && i < 4) {
4750 /* partition i should have come earlier, move it */
4751 /* We have to move data in the MBR */
4752 struct partition *pi, *pk, *pe, pbuf;
4756 pe = pei->ext_pointer;
4757 pei->ext_pointer = pek->ext_pointer;
4758 pek->ext_pointer = pe;
4760 pi = pei->part_table;
4761 pk = pek->part_table;
4763 memmove(&pbuf, pi, sizeof(struct partition));
4764 memmove(pi, pk, sizeof(struct partition));
4765 memmove(pk, &pbuf, sizeof(struct partition));
4767 pei->changed = pek->changed = 1;
4771 fix_chain_of_logicals();
4779 list_table(int xtra) {
4780 const struct partition *p;
4783 #ifdef CONFIG_FEATURE_SUN_LABEL
4785 sun_list_table(xtra);
4790 #ifdef CONFIG_FEATURE_SGI_LABEL
4792 sgi_list_table(xtra);
4797 list_disk_geometry();
4799 #ifdef CONFIG_FEATURE_OSF_LABEL
4801 xbsd_print_disklabel(xtra);
4806 /* Heuristic: we list partition 3 of /dev/foo as /dev/foo3,
4807 but if the device name ends in a digit, say /dev/foo1,
4808 then the partition is called /dev/foo1p3. */
4809 w = strlen(disk_device);
4810 if (w && isdigit(disk_device[w-1]))
4815 printf(_("%*s Boot Start End Blocks Id System\n"),
4818 for (i = 0; i < partitions; i++) {
4819 const struct pte *pe = &ptes[i];
4822 if (p && !is_cleared_partition(p)) {
4823 unsigned int psects = get_nr_sects(p);
4824 unsigned int pblocks = psects;
4825 unsigned int podd = 0;
4827 if (sector_size < 1024) {
4828 pblocks /= (1024 / sector_size);
4829 podd = psects % (1024 / sector_size);
4831 if (sector_size > 1024)
4832 pblocks *= (sector_size / 1024);
4834 "%s %c %9ld %9ld %9ld%c %2x %s\n",
4835 partname(disk_device, i+1, w+2),
4836 /* boot flag */ !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG
4838 /* start */ (long) cround(get_partition_start(pe)),
4839 /* end */ (long) cround(get_partition_start(pe) + psects
4840 - (psects ? 1 : 0)),
4841 /* odd flag on end */ (long) pblocks, podd ? '+' : ' ',
4842 /* type id */ p->sys_ind,
4843 /* type name */ partition_type(p->sys_ind));
4844 check_consistency(p, i);
4848 /* Is partition table in disk order? It need not be, but... */
4849 /* partition table entries are not checked for correct order if this
4850 is a sgi, sun or aix labeled disk... */
4851 if (dos_label && wrong_p_order(NULL)) {
4852 printf(_("\nPartition table entries are not in disk order\n"));
4856 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
4858 x_list_table(int extend) {
4859 const struct pte *pe;
4860 const struct partition *p;
4863 printf(_("\nDisk %s: %d heads, %d sectors, %d cylinders\n\n"),
4864 disk_device, heads, sectors, cylinders);
4865 printf(_("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n"));
4866 for (i = 0 ; i < partitions; i++) {
4868 p = (extend ? pe->ext_pointer : pe->part_table);
4870 printf("%2d %02x%4d%4d%5d%4d%4d%5d%9d%9d %02x\n",
4871 i + 1, p->boot_ind, p->head,
4873 cylinder(p->sector, p->cyl), p->end_head,
4874 sector(p->end_sector),
4875 cylinder(p->end_sector, p->end_cyl),
4876 get_start_sect(p), get_nr_sects(p), p->sys_ind);
4878 check_consistency(p, i);
4884 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4886 fill_bounds(uint *first, uint *last) {
4888 const struct pte *pe = &ptes[0];
4889 const struct partition *p;
4891 for (i = 0; i < partitions; pe++,i++) {
4893 if (!p->sys_ind || IS_EXTENDED (p->sys_ind)) {
4894 first[i] = 0xffffffff;
4897 first[i] = get_partition_start(pe);
4898 last[i] = first[i] + get_nr_sects(p) - 1;
4904 check(int n, uint h, uint s, uint c, uint start) {
4905 uint total, real_s, real_c;
4907 real_s = sector(s) - 1;
4908 real_c = cylinder(s, c);
4909 total = (real_c * sectors + real_s) * heads + h;
4911 fprintf(stderr, _("Warning: partition %d contains sector 0\n"), n);
4914 _("Partition %d: head %d greater than maximum %d\n"),
4916 if (real_s >= sectors)
4917 fprintf(stderr, _("Partition %d: sector %d greater than "
4918 "maximum %d\n"), n, s, sectors);
4919 if (real_c >= cylinders)
4920 fprintf(stderr, _("Partitions %d: cylinder %d greater than "
4921 "maximum %d\n"), n, real_c + 1, cylinders);
4922 if (cylinders <= 1024 && start != total)
4924 _("Partition %d: previous sectors %d disagrees with "
4925 "total %d\n"), n, start, total);
4932 uint first[partitions], last[partitions];
4933 struct partition *p;
4935 if (warn_geometry())
4938 #ifdef CONFIG_FEATURE_SUN_LABEL
4944 #ifdef CONFIG_FEATURE_SGI_LABEL
4951 fill_bounds(first, last);
4952 for (i = 0; i < partitions; i++) {
4953 struct pte *pe = &ptes[i];
4956 if (p->sys_ind && !IS_EXTENDED (p->sys_ind)) {
4957 check_consistency(p, i);
4958 if (get_partition_start(pe) < first[i])
4959 printf(_("Warning: bad start-of-data in "
4960 "partition %d\n"), i + 1);
4961 check(i + 1, p->end_head, p->end_sector, p->end_cyl,
4963 total += last[i] + 1 - first[i];
4964 for (j = 0; j < i; j++)
4965 if ((first[i] >= first[j] && first[i] <= last[j])
4966 || ((last[i] <= last[j] && last[i] >= first[j]))) {
4967 printf(_("Warning: partition %d overlaps "
4968 "partition %d.\n"), j + 1, i + 1);
4969 total += first[i] >= first[j] ?
4970 first[i] : first[j];
4971 total -= last[i] <= last[j] ?
4977 if (extended_offset) {
4978 struct pte *pex = &ptes[ext_index];
4979 uint e_last = get_start_sect(pex->part_table) +
4980 get_nr_sects(pex->part_table) - 1;
4982 for (i = 4; i < partitions; i++) {
4984 p = ptes[i].part_table;
4986 if (i != 4 || i + 1 < partitions)
4987 printf(_("Warning: partition %d "
4988 "is empty\n"), i + 1);
4990 else if (first[i] < extended_offset ||
4992 printf(_("Logical partition %d not entirely in "
4993 "partition %d\n"), i + 1, ext_index + 1);
4997 if (total > heads * sectors * cylinders)
4998 printf(_("Total allocated sectors %d greater than the maximum "
4999 "%d\n"), total, heads * sectors * cylinders);
5000 else if ((total = heads * sectors * cylinders - total) != 0)
5001 printf(_("%d unallocated sectors\n"), total);
5005 add_partition(int n, int sys) {
5006 char mesg[256]; /* 48 does not suffice in Japanese */
5008 struct partition *p = ptes[n].part_table;
5009 struct partition *q = ptes[ext_index].part_table;
5010 uint start, stop = 0, limit, temp,
5011 first[partitions], last[partitions];
5013 if (p && p->sys_ind) {
5014 printf(_("Partition %d is already defined. Delete "
5015 "it before re-adding it.\n"), n + 1);
5018 fill_bounds(first, last);
5020 start = sector_offset;
5021 if (display_in_cyl_units)
5022 limit = heads * sectors * cylinders - 1;
5024 limit = total_number_of_sectors - 1;
5025 if (extended_offset) {
5026 first[ext_index] = extended_offset;
5027 last[ext_index] = get_start_sect(q) +
5028 get_nr_sects(q) - 1;
5031 start = extended_offset + sector_offset;
5032 limit = get_start_sect(q) + get_nr_sects(q) - 1;
5034 if (display_in_cyl_units)
5035 for (i = 0; i < partitions; i++)
5036 first[i] = (cround(first[i]) - 1) * units_per_sector;
5038 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
5041 for (i = 0; i < partitions; i++) {
5044 if (start == ptes[i].offset)
5045 start += sector_offset;
5046 lastplusoff = last[i] + ((n<4) ? 0 : sector_offset);
5047 if (start >= first[i] && start <= lastplusoff)
5048 start = lastplusoff + 1;
5052 if (start >= temp+units_per_sector && readed) {
5053 printf(_("Sector %d is already allocated\n"), temp);
5057 if (!readed && start == temp) {
5060 saved_start = start;
5061 start = read_int(cround(saved_start), cround(saved_start), cround(limit),
5063 if (display_in_cyl_units) {
5064 start = (start - 1) * units_per_sector;
5065 if (start < saved_start) start = saved_start;
5069 } while (start != temp || !readed);
5070 if (n > 4) { /* NOT for fifth partition */
5071 struct pte *pe = &ptes[n];
5073 pe->offset = start - sector_offset;
5074 if (pe->offset == extended_offset) { /* must be corrected */
5076 if (sector_offset == 1)
5081 for (i = 0; i < partitions; i++) {
5082 struct pte *pe = &ptes[i];
5084 if (start < pe->offset && limit >= pe->offset)
5085 limit = pe->offset - 1;
5086 if (start < first[i] && limit >= first[i])
5087 limit = first[i] - 1;
5089 if (start > limit) {
5090 printf(_("No free sectors available\n"));
5095 if (cround(start) == cround(limit)) {
5098 snprintf(mesg, sizeof(mesg),
5099 _("Last %s or +size or +sizeM or +sizeK"),
5100 str_units(SINGULAR));
5101 stop = read_int(cround(start), cround(limit), cround(limit),
5102 cround(start), mesg);
5103 if (display_in_cyl_units) {
5104 stop = stop * units_per_sector - 1;
5110 set_partition(n, 0, start, stop, sys);
5112 set_partition(n - 1, 1, ptes[n].offset, stop, EXTENDED);
5114 if (IS_EXTENDED (sys)) {
5115 struct pte *pe4 = &ptes[4];
5116 struct pte *pen = &ptes[n];
5119 pen->ext_pointer = p;
5120 pe4->offset = extended_offset = start;
5121 pe4->sectorbuffer = xcalloc(1, sector_size);
5122 pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
5123 pe4->ext_pointer = pe4->part_table + 1;
5131 if (partitions > 5 || ptes[4].part_table->sys_ind) {
5132 struct pte *pe = &ptes[partitions];
5134 pe->sectorbuffer = xcalloc(1, sector_size);
5135 pe->part_table = pt_offset(pe->sectorbuffer, 0);
5136 pe->ext_pointer = pe->part_table + 1;
5141 add_partition(partitions - 1, LINUX_NATIVE);
5145 new_partition(void) {
5146 int i, free_primary = 0;
5148 if (warn_geometry())
5151 #ifdef CONFIG_FEATURE_SUN_LABEL
5153 add_sun_partition(get_partition(0, partitions), LINUX_NATIVE);
5157 #ifdef CONFIG_FEATURE_SGI_LABEL
5159 sgi_add_partition(get_partition(0, partitions), LINUX_NATIVE);
5163 #ifdef CONFIG_FEATURE_AIX_LABEL
5165 printf(_("\tSorry - this fdisk cannot handle AIX disk labels."
5166 "\n\tIf you want to add DOS-type partitions, create"
5167 "\n\ta new empty DOS partition table first. (Use o.)"
5169 "This will destroy the present disk contents.\n"));
5174 for (i = 0; i < 4; i++)
5175 free_primary += !ptes[i].part_table->sys_ind;
5177 if (!free_primary && partitions >= MAXIMUM_PARTS) {
5178 printf(_("The maximum number of partitions has been created\n"));
5182 if (!free_primary) {
5183 if (extended_offset)
5186 printf(_("You must delete some partition and add "
5187 "an extended partition first\n"));
5189 char c, line[LINE_LENGTH];
5190 snprintf(line, sizeof(line), "%s\n %s\n p primary "
5191 "partition (1-4)\n",
5192 "Command action", (extended_offset ?
5193 "l logical (5 or over)" : "e extended"));
5195 if ((c = read_char(line)) == 'p' || c == 'P') {
5196 i = get_nonexisting_partition(0, 4);
5198 add_partition(i, LINUX_NATIVE);
5201 else if (c == 'l' && extended_offset) {
5205 else if (c == 'e' && !extended_offset) {
5206 i = get_nonexisting_partition(0, 4);
5208 add_partition(i, EXTENDED);
5212 printf(_("Invalid partition number "
5213 "for type `%c'\n"), c);
5224 if (ptes[i].changed)
5225 ptes[3].changed = 1;
5226 for (i = 3; i < partitions; i++) {
5227 struct pte *pe = &ptes[i];
5230 write_part_table_flag(pe->sectorbuffer);
5231 write_sector(pe->offset, pe->sectorbuffer);
5235 #ifdef CONFIG_FEATURE_SGI_LABEL
5236 else if (sgi_label) {
5237 /* no test on change? the printf below might be mistaken */
5241 #ifdef CONFIG_FEATURE_SUN_LABEL
5242 else if (sun_label) {
5246 if (ptes[i].changed)
5253 printf(_("The partition table has been altered!\n\n"));
5254 reread_partition_table(1);
5258 reread_partition_table(int leave) {
5262 printf(_("Calling ioctl() to re-read partition table.\n"));
5265 if ((i = ioctl(fd, BLKRRPART)) != 0) {
5268 /* some kernel versions (1.2.x) seem to have trouble
5269 rereading the partition table, but if asked to do it
5270 twice, the second time works. - biro@yggdrasil.com */
5273 if ((i = ioctl(fd, BLKRRPART)) != 0)
5278 printf(_("\nWARNING: Re-reading the partition table "
5279 "failed with error %d: %s.\n"
5280 "The kernel still uses the old table.\n"
5281 "The new table will be used "
5282 "at the next reboot.\n"),
5283 error, strerror(error));
5288 _("\nWARNING: If you have created or modified any DOS 6.x\n"
5289 "partitions, please see the fdisk manual page for additional\n"
5295 printf(_("Syncing disks.\n"));
5297 sleep(4); /* for sync() */
5301 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
5303 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
5304 #define MAX_PER_LINE 16
5306 print_buffer(char pbuffer[]) {
5310 for (i = 0, l = 0; i < sector_size; i++, l++) {
5312 printf("0x%03X:", i);
5313 printf(" %02X", (unsigned char) pbuffer[i]);
5314 if (l == MAX_PER_LINE - 1) {
5329 printf(_("Device: %s\n"), disk_device);
5330 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
5331 if (sun_label || sgi_label)
5332 print_buffer(MBRbuffer);
5335 for (i = 3; i < partitions; i++)
5336 print_buffer(ptes[i].sectorbuffer);
5341 struct pte *pe = &ptes[i];
5342 struct partition *p = pe->part_table;
5345 if (warn_geometry())
5347 if (!p->sys_ind || !get_nr_sects(p) || IS_EXTENDED (p->sys_ind)) {
5348 printf(_("Partition %d has no data area\n"), i + 1);
5351 first = get_partition_start(pe);
5352 new = read_int(first, first, first + get_nr_sects(p) - 1, first,
5353 _("New beginning of data")) - pe->offset;
5355 if (new != get_nr_sects(p)) {
5356 first = get_nr_sects(p) + get_start_sect(p) - new;
5357 set_nr_sects(p, first);
5358 set_start_sect(p, new);
5369 c = tolower(read_char(_("Expert command (m for help): ")));
5372 #ifdef CONFIG_FEATURE_SUN_LABEL
5379 move_begin(get_partition(0, partitions));
5382 user_cylinders = cylinders =
5383 read_int(1, cylinders, 1048576, 0,
5384 _("Number of cylinders"));
5385 #ifdef CONFIG_FEATURE_SUN_LABEL
5387 sun_set_ncyl(cylinders);
5396 #ifdef CONFIG_FEATURE_SGI_LABEL
5401 #ifdef CONFIG_FEATURE_SUN_LABEL
5411 fix_partition_table_order();
5414 #ifdef CONFIG_FEATURE_SGI_LABEL
5419 user_heads = heads = read_int(1, heads, 256, 0,
5420 _("Number of heads"));
5424 #ifdef CONFIG_FEATURE_SUN_LABEL
5430 #ifdef CONFIG_FEATURE_SUN_LABEL
5436 #ifdef CONFIG_FEATURE_SUN_LABEL
5450 user_sectors = sectors = read_int(1, sectors, 63, 0,
5451 _("Number of sectors"));
5452 if (dos_compatible_flag) {
5453 sector_offset = sectors;
5454 fprintf(stderr, _("Warning: setting "
5455 "sector offset for DOS "
5464 write_table(); /* does not return */
5467 #ifdef CONFIG_FEATURE_SUN_LABEL
5469 sun_set_pcylcount();
5477 #endif /* ADVANCED mode */
5480 is_ide_cdrom_or_tape(const char *device) {
5483 struct stat statbuf;
5486 /* No device was given explicitly, and we are trying some
5487 likely things. But opening /dev/hdc may produce errors like
5488 "hdc: tray open or drive not ready"
5489 if it happens to be a CD-ROM drive. It even happens that
5490 the process hangs on the attempt to read a music CD.
5491 So try to be careful. This only works since 2.1.73. */
5493 if (strncmp("/dev/hd", device, 7))
5496 snprintf(buf, sizeof(buf), "/proc/ide/%s/media", device+5);
5497 procf = fopen(buf, "r");
5498 if (procf != NULL && fgets(buf, sizeof(buf), procf))
5499 is_ide = (!strncmp(buf, "cdrom", 5) ||
5500 !strncmp(buf, "tape", 4));
5502 /* Now when this proc file does not exist, skip the
5503 device when it is read-only. */
5504 if (stat(device, &statbuf) == 0)
5505 is_ide = ((statbuf.st_mode & 0222) == 0);
5513 try(const char *device, int user_specified) {
5516 disk_device = device;
5517 if (setjmp(listingbuf))
5519 if (!user_specified)
5520 if (is_ide_cdrom_or_tape(device))
5522 if ((fd = open(disk_device, type_open)) >= 0) {
5523 gb = get_boot(try_only);
5524 if (gb > 0) { /* I/O error */
5526 } else if (gb < 0) { /* no DOS signature */
5527 list_disk_geometry();
5530 #ifdef CONFIG_FEATURE_OSF_LABEL
5531 if (btrydev(device) < 0)
5534 _("Disk %s doesn't contain a valid "
5535 "partition table\n"), device);
5540 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5541 if (!sun_label && partitions > 4)
5542 delete_partition(ext_index);
5546 /* Ignore other errors, since we try IDE
5547 and SCSI hard disks which may not be
5548 installed on the system. */
5549 if (errno == EACCES) {
5550 fprintf(stderr, _("Cannot open %s\n"), device);
5556 /* for fdisk -l: try all things in /proc/partitions
5557 that look like a partition name (do not end in a digit) */
5561 char line[100], ptname[100], devname[120], *s;
5564 procpt = bb_wfopen(PROC_PARTITIONS, "r");
5566 while (fgets(line, sizeof(line), procpt)) {
5567 if (sscanf (line, " %d %d %d %[^\n ]",
5568 &ma, &mi, &sz, ptname) != 4)
5570 for (s = ptname; *s; s++);
5573 sprintf(devname, "/dev/%s", ptname);
5576 #ifdef CONFIG_FEATURE_CLEAN_UP
5581 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5583 unknown_command(int c) {
5584 printf(_("%c: unknown command\n"), c);
5588 int fdisk_main(int argc, char **argv) {
5590 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5593 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5599 * fdisk -l [-b sectorsize] [-u] device ...
5600 * fdisk -s [partition] ...
5601 * fdisk [-b sectorsize] [-u] device
5603 * Options -C, -H, -S set the geometry.
5606 while ((c = getopt(argc, argv, "b:C:H:lS:uvV"
5607 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5613 /* Ugly: this sector size is really per device,
5614 so cannot be combined with multiple disks,
5615 and te same goes for the C/H/S options.
5617 sector_size = atoi(optarg);
5618 if (sector_size != 512 && sector_size != 1024 &&
5619 sector_size != 2048)
5622 user_set_sector_size = 1;
5625 user_cylinders = atoi(optarg);
5628 user_heads = atoi(optarg);
5629 if (user_heads <= 0 || user_heads >= 256)
5633 user_sectors = atoi(optarg);
5634 if (user_sectors <= 0 || user_sectors >= 64)
5638 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5642 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5648 display_in_cyl_units = 0;
5652 printf("fdisk v" UTIL_LINUX_VERSION "\n");
5660 printf(_("This kernel finds the sector size itself - "
5661 "-b option ignored\n"));
5663 if (user_set_sector_size && argc-optind != 1)
5664 printf(_("Warning: the -b (set sector size) option should"
5665 " be used with one specified device\n"));
5668 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5672 type_open = O_RDONLY;
5673 if (argc > optind) {
5676 /* avoid gcc warning:
5677 variable `k' might be clobbered by `longjmp' */
5681 for (k=optind; k<argc; k++)
5684 /* we no longer have default device names */
5685 /* but, we can use /proc/partitions instead */
5689 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5693 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5699 type_open = O_RDONLY;
5701 opts = argc - optind;
5705 for (j = optind; j < argc; j++) {
5706 disk_device = argv[j];
5707 if ((fd = open(disk_device, type_open)) < 0)
5708 fdisk_fatal(unable_to_open);
5709 if (ioctl(fd, BLKGETSIZE, &size))
5710 fdisk_fatal(ioctl_error);
5713 printf("%ld\n", size/2);
5715 printf("%s: %ld\n", argv[j], size/2);
5721 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5722 if (argc-optind == 1)
5723 disk_device = argv[optind];
5729 #ifdef CONFIG_FEATURE_OSF_LABEL
5731 /* OSF label, and no DOS label */
5732 printf(_("Detected an OSF/1 disklabel on %s, entering "
5733 "disklabel mode.\n"),
5737 /* If we return we may want to make an empty DOS label? */
5743 c = tolower(read_char(_("Command (m for help): ")));
5747 toggle_active(get_partition(1, partitions));
5748 #ifdef CONFIG_FEATURE_SUN_LABEL
5750 toggle_sunflags(get_partition(1, partitions),
5753 #ifdef CONFIG_FEATURE_SGI_LABEL
5755 sgi_set_bootpartition(
5756 get_partition(1, partitions));
5762 #ifdef CONFIG_FEATURE_SGI_LABEL
5764 printf(_("\nThe current boot file is: %s\n"),
5765 sgi_get_bootfile());
5766 if (read_chars(_("Please enter the name of the "
5767 "new boot file: ")) == '\n')
5768 printf(_("Boot file unchanged\n"));
5770 sgi_set_bootfile(line_ptr);
5773 #ifdef CONFIG_FEATURE_OSF_LABEL
5779 toggle_dos_compatibility_flag();
5780 #ifdef CONFIG_FEATURE_SUN_LABEL
5782 toggle_sunflags(get_partition(1, partitions),
5785 #ifdef CONFIG_FEATURE_SGI_LABEL
5787 sgi_set_swappartition(
5788 get_partition(1, partitions));
5795 int j = get_existing_partition(1, partitions);
5797 delete_partition(j);
5801 #ifdef CONFIG_FEATURE_SGI_LABEL
5808 list_types(get_sys_types());
5827 #ifdef CONFIG_FEATURE_SUN_LABEL
5841 write_table(); /* does not return */
5843 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
5845 #ifdef CONFIG_FEATURE_SGI_LABEL
5848 _("\n\tSorry, no experts menu for SGI "
5849 "partition tables available.\n\n"));
5862 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */