1 /* fdisk.c -- Partition table manipulator for Linux.
3 * Copyright (C) 1992 A. V. Le Blanc (LeBlanc@mcc.ac.uk)
5 * This program is free software. You can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation: either version 1 or
8 * (at your option) any later version.
10 * Vladimir Oleynik <dzo@simtreas.ru> 2001,2002 Busybox port
13 #define UTIL_LINUX_VERSION "2.12"
15 #define PROC_PARTITIONS "/proc/partitions"
17 #include <sys/types.h>
18 #include <sys/stat.h> /* stat */
27 #include <assert.h> /* assert */
30 #include <sys/ioctl.h>
31 #include <sys/param.h>
32 #include <sys/sysmacros.h> /* major */
34 #include <stdint.h> /* for uint32_t, uint16_t, uint8_t, int16_t, etc */
36 /* Copied from linux/major.h */
37 #define FLOPPY_MAJOR 2
39 #include <sys/utsname.h>
43 #define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r))
49 #define BLKRRPART _IO(0x12,95) /* re-read partition table */
50 #define BLKGETSIZE _IO(0x12,96) /* return device size */
51 #define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */
52 #define BLKSSZGET _IO(0x12,104) /* get block device sector size */
54 /* Avoid conflicts with the 2.6 kernel headers, which define
55 * _IOR rather differently */
57 #define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size))
58 #define BLKGETSIZE64 _IOR(0x12,114,uint64_t)
64 #define DEFAULT_SECTOR_SIZE 512
65 #define MAX_SECTOR_SIZE 2048
66 #define SECTOR_SIZE 512 /* still used in BSD code */
67 #define MAXIMUM_PARTS 60
69 #define ACTIVE_FLAG 0x80
72 #define WIN98_EXTENDED 0x0f
73 #define LINUX_PARTITION 0x81
74 #define LINUX_SWAP 0x82
75 #define LINUX_NATIVE 0x83
76 #define LINUX_EXTENDED 0x85
77 #define LINUX_LVM 0x8e
78 #define LINUX_RAID 0xfd
83 #define IS_EXTENDED(i) \
84 ((i) == EXTENDED || (i) == WIN98_EXTENDED || (i) == LINUX_EXTENDED)
86 #define SIZE(a) (sizeof(a)/sizeof((a)[0]))
88 #define cround(n) (display_in_cyl_units ? ((n)/units_per_sector)+1 : (n))
89 #define scround(x) (((x)+units_per_sector-1)/units_per_sector)
91 #ifdef CONFIG_FEATURE_SUN_LABEL
92 #define SCSI_IOCTL_GET_IDLUN 0x5382
96 /* including <linux/hdreg.h> also fails */
99 unsigned char sectors;
100 unsigned short cylinders;
104 #define HDIO_GETGEO 0x0301 /* get device geometry */
108 const unsigned char *name;
111 static uint sector_size = DEFAULT_SECTOR_SIZE,
112 user_set_sector_size,
116 * Raw disk label. For DOS-type partition tables the MBR,
117 * with descriptions of the primary partitions.
119 static char MBRbuffer[MAX_SECTOR_SIZE];
121 #ifdef CONFIG_FEATURE_SUN_LABEL
122 static int sun_label; /* looking at sun disklabel */
126 #ifdef CONFIG_FEATURE_SGI_LABEL
127 static int sgi_label; /* looking at sgi disklabel */
131 #ifdef CONFIG_FEATURE_AIX_LABEL
132 static int aix_label; /* looking at aix disklabel */
136 #ifdef CONFIG_FEATURE_OSF_LABEL
137 static int osf_label; /* looking at OSF/1 disklabel */
138 static int possibly_osf_label;
143 #define dos_label (!sun_label && !sgi_label && !aix_label && !osf_label)
145 static uint heads, sectors, cylinders;
146 static void update_units(void);
150 * return partition name - uses static storage unless buf is supplied
153 partname(const char *dev, int pno, int lth) {
154 static char buffer[80];
161 bufsiz = sizeof(buffer);
166 if (isdigit(dev[w-1]))
169 /* devfs kludge - note: fdisk partition names are not supposed
170 to equal kernel names, so there is no reason to do this */
171 if (strcmp (dev + w - 4, "disc") == 0) {
179 snprintf(bufp, bufsiz, "%*.*s%s%-2u",
180 lth-wp-2, w, dev, p, pno);
182 snprintf(bufp, bufsiz, "%.*s%s%-2u", w, dev, p, pno);
188 unsigned char boot_ind; /* 0x80 - active */
189 unsigned char head; /* starting head */
190 unsigned char sector; /* starting sector */
191 unsigned char cyl; /* starting cylinder */
192 unsigned char sys_ind; /* What partition type */
193 unsigned char end_head; /* end head */
194 unsigned char end_sector; /* end sector */
195 unsigned char end_cyl; /* end cylinder */
196 unsigned char start4[4]; /* starting sector counting from 0 */
197 unsigned char size4[4]; /* nr of sectors in partition */
198 } __attribute__((__packed__));
201 ioctl_error, unable_to_open, unable_to_read, unable_to_seek,
205 enum action {fdisk, require, try_only, create_empty_dos, create_empty_sun};
207 static const char *disk_device;
208 static int fd; /* the disk */
209 static int partitions = 4; /* maximum partition + 1 */
210 static uint display_in_cyl_units = 1;
211 static uint units_per_sector = 1;
212 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
213 static char *line_ptr;
214 static void change_units(void);
215 static void reread_partition_table(int leave);
216 static void delete_partition(int i);
217 static int get_partition(int warn, int max);
218 static void list_types(const struct systypes *sys);
219 static uint read_int(uint low, uint dflt, uint high, uint base, char *mesg);
221 static const char *partition_type(unsigned char type);
222 static void fdisk_fatal(enum failure why) __attribute__ ((noreturn));
223 static void get_geometry(void);
224 static int get_boot(enum action what);
229 #define hex_val(c) ({ \
231 isdigit(_c) ? _c - '0' : \
232 tolower(_c) + 10 - 'a'; \
236 #define LINE_LENGTH 800
237 #define pt_offset(b, n) ((struct partition *)((b) + 0x1be + \
238 (n) * sizeof(struct partition)))
239 #define sector(s) ((s) & 0x3f)
240 #define cylinder(s, c) ((c) | (((s) & 0xc0) << 2))
242 #define hsc2sector(h,s,c) (sector(s) - 1 + sectors * \
243 ((h) + heads * cylinder(s,c)))
244 #define set_hsc(h,s,c,sector) { \
245 s = sector % sectors + 1; \
247 h = sector % heads; \
250 s |= (sector >> 2) & 0xc0; \
254 static unsigned int get_start_sect(const struct partition *p);
255 static unsigned int get_nr_sects(const struct partition *p);
258 * per partition table entry data
260 * The four primary partitions have the same sectorbuffer (MBRbuffer)
261 * and have NULL ext_pointer.
262 * Each logical partition table entry has two pointers, one for the
263 * partition and one link to the next one.
266 struct partition *part_table; /* points into sectorbuffer */
267 struct partition *ext_pointer; /* points into sectorbuffer */
268 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
269 char changed; /* boolean */
271 uint offset; /* disk sector number */
272 char *sectorbuffer; /* disk sector contents */
273 } ptes[MAXIMUM_PARTS];
276 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
278 set_all_unchanged(void) {
281 for (i = 0; i < MAXIMUM_PARTS; i++)
289 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
291 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_OSF_LABEL)
292 static struct partition *
293 get_part_table(int i) {
294 return ptes[i].part_table;
299 str_units(int n) { /* n==1: use singular */
301 return display_in_cyl_units ? _("cylinder") : _("sector");
303 return display_in_cyl_units ? _("cylinders") : _("sectors");
307 valid_part_table_flag(const unsigned char *b) {
308 return (b[510] == 0x55 && b[511] == 0xaa);
311 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
312 static char line_buffer[LINE_LENGTH];
314 /* read line; return 0 or first char */
318 static int got_eof = 0;
320 fflush (stdout); /* requested by niles@scyld.com */
321 line_ptr = line_buffer;
322 if (!fgets(line_buffer, LINE_LENGTH, stdin)) {
324 got_eof++; /* user typed ^D ? */
326 fprintf(stderr, _("\ngot EOF thrice - exiting..\n"));
331 while (*line_ptr && !isgraph(*line_ptr))
337 read_char(const char *mesg)
341 } while (!read_line());
346 read_chars(const char *mesg)
357 read_hex(const struct systypes *sys)
363 read_char(_("Hex code (type L to list codes): "));
364 if (*line_ptr == 'l' || *line_ptr == 'L')
366 else if (isxdigit (*line_ptr))
370 hex = hex << 4 | hex_val(*line_ptr++);
371 while (isxdigit(*line_ptr));
376 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
378 #ifdef CONFIG_FEATURE_AIX_LABEL
380 * Copyright (C) Andreas Neuper, Sep 1998.
381 * This file may be redistributed under
382 * the terms of the GNU Public License.
386 unsigned int magic; /* expect AIX_LABEL_MAGIC */
387 unsigned int fillbytes1[124];
388 unsigned int physical_volume_id;
389 unsigned int fillbytes2[124];
392 #define AIX_LABEL_MAGIC 0xc9c2d4c1
393 #define AIX_LABEL_MAGIC_SWAPPED 0xc1d4c2c9
394 #define AIX_INFO_MAGIC 0x00072959
395 #define AIX_INFO_MAGIC_SWAPPED 0x59290700
397 #define aixlabel ((aix_partition *)MBRbuffer)
402 * 1999-03-20 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
403 * Internationalization
405 * 2003-03-20 Phillip Kesling <pkesling@sgi.com>
409 static int aix_other_endian;
410 static short aix_volumes=1;
413 * only dealing with free blocks here
419 _("\n\tThere is a valid AIX label on this disk.\n"
420 "\tUnfortunately Linux cannot handle these\n"
421 "\tdisks at the moment. Nevertheless some\n"
423 "\t1. fdisk will destroy its contents on write.\n"
424 "\t2. Be sure that this disk is NOT a still vital\n"
425 "\t part of a volume group. (Otherwise you may\n"
426 "\t erase the other disks as well, if unmirrored.)\n"
427 "\t3. Before deleting this physical volume be sure\n"
428 "\t to remove the disk logically from your AIX\n"
429 "\t machine. (Otherwise you become an AIXpert).")
439 memset( MBRbuffer, 0, sizeof(MBRbuffer) ); /* avoid fdisk cores */
444 check_aix_label( void )
446 if (aixlabel->magic != AIX_LABEL_MAGIC &&
447 aixlabel->magic != AIX_LABEL_MAGIC_SWAPPED) {
449 aix_other_endian = 0;
452 aix_other_endian = (aixlabel->magic == AIX_LABEL_MAGIC_SWAPPED);
458 aix_nolabel(); /* %% */
459 aix_label = 1; /* %% */
462 #endif /* AIX_LABEL */
464 #ifdef CONFIG_FEATURE_OSF_LABEL
466 * Copyright (c) 1987, 1988 Regents of the University of California.
467 * All rights reserved.
469 * Redistribution and use in source and binary forms, with or without
470 * modification, are permitted provided that the following conditions
472 * 1. Redistributions of source code must retain the above copyright
473 * notice, this list of conditions and the following disclaimer.
474 * 2. Redistributions in binary form must reproduce the above copyright
475 * notice, this list of conditions and the following disclaimer in the
476 * documentation and/or other materials provided with the distribution.
477 * 3. All advertising materials mentioning features or use of this software
478 * must display the following acknowledgement:
479 * This product includes software developed by the University of
480 * California, Berkeley and its contributors.
481 * 4. Neither the name of the University nor the names of its contributors
482 * may be used to endorse or promote products derived from this software
483 * without specific prior written permission.
485 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
486 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
487 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
488 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
489 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
490 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
491 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
492 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
493 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
494 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
499 #ifndef BSD_DISKMAGIC
500 #define BSD_DISKMAGIC ((uint32_t) 0x82564557)
503 #ifndef BSD_MAXPARTITIONS
504 #define BSD_MAXPARTITIONS 16
507 #define BSD_LINUX_BOOTDIR "/usr/ucb/mdec"
509 #if defined (i386) || defined (__sparc__) || defined (__arm__) || defined (__mips__) || defined (__s390__) || defined (__sh__) || defined(__x86_64__)
510 #define BSD_LABELSECTOR 1
511 #define BSD_LABELOFFSET 0
512 #elif defined (__alpha__) || defined (__powerpc__) || defined (__ia64__) || defined (__hppa__)
513 #define BSD_LABELSECTOR 0
514 #define BSD_LABELOFFSET 64
515 #elif defined (__s390__) || defined (__s390x__)
516 #define BSD_LABELSECTOR 1
517 #define BSD_LABELOFFSET 0
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 */
834 #define SUN_LABEL_MAGIC 0xDABE
835 #define SUN_LABEL_MAGIC_SWAPPED 0xBEDA
836 #define sunlabel ((sun_partition *)MBRbuffer)
837 #define SUN_SSWAP16(x) (sun_other_endian ? __swap16(x) \
839 #define SUN_SSWAP32(x) (sun_other_endian ? __swap32(x) \
843 #ifdef CONFIG_FEATURE_OSF_LABEL
846 19990319 - Arnaldo Carvalho de Melo <acme@conectiva.com.br> - i18n/nls
848 20000101 - David Huggins-Daines <dhuggins@linuxcare.com> - Better
849 support for OSF/1 disklabels on Alpha.
850 Also fixed unaligned accesses in alpha_bootblock_checksum()
853 #define FREEBSD_PARTITION 0xa5
854 #define NETBSD_PARTITION 0xa9
856 static void xbsd_delete_part (void);
857 static void xbsd_new_part (void);
858 static void xbsd_write_disklabel (void);
859 static int xbsd_create_disklabel (void);
860 static void xbsd_edit_disklabel (void);
861 static void xbsd_write_bootstrap (void);
862 static void xbsd_change_fstype (void);
863 static int xbsd_get_part_index (int max);
864 static int xbsd_check_new_partition (int *i);
865 static void xbsd_list_types (void);
866 static u_short xbsd_dkcksum (struct xbsd_disklabel *lp);
867 static int xbsd_initlabel (struct partition *p, struct xbsd_disklabel *d,
869 static int xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d);
870 static int xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d);
872 #if defined (__alpha__)
873 static void alpha_bootblock_checksum (char *boot);
876 #if !defined (__alpha__)
877 static int xbsd_translate_fstype (int linux_type);
878 static void xbsd_link_part (void);
879 static struct partition *xbsd_part;
880 static int xbsd_part_index;
883 #if defined (__alpha__)
884 /* We access this through a uint64_t * when checksumming */
885 static char disklabelbuffer[BSD_BBSIZE] __attribute__((aligned(8)));
887 static char disklabelbuffer[BSD_BBSIZE];
890 static struct xbsd_disklabel xbsd_dlabel;
892 #define bsd_cround(n) \
893 (display_in_cyl_units ? ((n)/xbsd_dlabel.d_secpercyl) + 1 : (n))
896 * Test whether the whole disk has BSD disk label magic.
898 * Note: often reformatting with DOS-type label leaves the BSD magic,
899 * so this does not mean that there is a BSD disk label.
902 check_osf_label(void) {
903 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
908 static void xbsd_print_disklabel(int);
911 btrydev (const char * dev) {
912 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
914 printf(_("\nBSD label for device: %s\n"), dev);
915 xbsd_print_disklabel (0);
921 puts (_("Command action"));
922 puts (_("\td\tdelete a BSD partition"));
923 puts (_("\te\tedit drive data"));
924 puts (_("\ti\tinstall bootstrap"));
925 puts (_("\tl\tlist known filesystem types"));
926 puts (_("\tm\tprint this menu"));
927 puts (_("\tn\tadd a new BSD partition"));
928 puts (_("\tp\tprint BSD partition table"));
929 puts (_("\tq\tquit without saving changes"));
930 puts (_("\tr\treturn to main menu"));
931 puts (_("\ts\tshow complete disklabel"));
932 puts (_("\tt\tchange a partition's filesystem id"));
933 puts (_("\tu\tchange units (cylinders/sectors)"));
934 puts (_("\tw\twrite disklabel to disk"));
935 #if !defined (__alpha__)
936 puts (_("\tx\tlink BSD partition to non-BSD partition"));
940 #if !defined (__alpha__)
947 is_bsd_partition_type(int type) {
948 return (type == FREEBSD_PARTITION ||
949 type == hidden(FREEBSD_PARTITION) ||
950 type == NETBSD_PARTITION ||
951 type == hidden(NETBSD_PARTITION));
957 #if !defined (__alpha__)
961 for (t=0; t<4; t++) {
962 p = get_part_table(t);
963 if (p && is_bsd_partition_type(p->sys_ind)) {
966 ss = get_start_sect(xbsd_part);
968 fprintf (stderr, _("Partition %s has invalid starting sector 0.\n"),
969 partname(disk_device, t+1, 0));
972 printf (_("Reading disklabel of %s at sector %d.\n"),
973 partname(disk_device, t+1, 0), ss + BSD_LABELSECTOR);
974 if (xbsd_readlabel (xbsd_part, &xbsd_dlabel) == 0)
975 if (xbsd_create_disklabel () == 0)
982 printf (_("There is no *BSD partition on %s.\n"), disk_device);
986 #elif defined (__alpha__)
988 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
989 if (xbsd_create_disklabel () == 0)
990 exit ( EXIT_SUCCESS );
996 switch (tolower (read_char (_("BSD disklabel command (m for help): ")))) {
1001 xbsd_edit_disklabel ();
1004 xbsd_write_bootstrap ();
1013 xbsd_print_disklabel (0);
1017 exit ( EXIT_SUCCESS );
1021 xbsd_print_disklabel (1);
1024 xbsd_change_fstype ();
1030 xbsd_write_disklabel ();
1032 #if !defined (__alpha__)
1045 xbsd_delete_part (void)
1049 i = xbsd_get_part_index (xbsd_dlabel.d_npartitions);
1050 xbsd_dlabel.d_partitions[i].p_size = 0;
1051 xbsd_dlabel.d_partitions[i].p_offset = 0;
1052 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
1053 if (xbsd_dlabel.d_npartitions == i + 1)
1054 while (xbsd_dlabel.d_partitions[xbsd_dlabel.d_npartitions-1].p_size == 0)
1055 xbsd_dlabel.d_npartitions--;
1059 xbsd_new_part (void)
1065 if (!xbsd_check_new_partition (&i))
1068 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
1069 begin = get_start_sect(xbsd_part);
1070 end = begin + get_nr_sects(xbsd_part) - 1;
1073 end = xbsd_dlabel.d_secperunit - 1;
1076 snprintf (mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
1077 begin = read_int (bsd_cround (begin), bsd_cround (begin), bsd_cround (end),
1080 if (display_in_cyl_units)
1081 begin = (begin - 1) * xbsd_dlabel.d_secpercyl;
1083 snprintf (mesg, sizeof(mesg), _("Last %s or +size or +sizeM or +sizeK"),
1084 str_units(SINGULAR));
1085 end = read_int (bsd_cround (begin), bsd_cround (end), bsd_cround (end),
1086 bsd_cround (begin), mesg);
1088 if (display_in_cyl_units)
1089 end = end * xbsd_dlabel.d_secpercyl - 1;
1091 xbsd_dlabel.d_partitions[i].p_size = end - begin + 1;
1092 xbsd_dlabel.d_partitions[i].p_offset = begin;
1093 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
1097 xbsd_print_disklabel (int show_all) {
1098 struct xbsd_disklabel *lp = &xbsd_dlabel;
1099 struct xbsd_partition *pp;
1103 #if defined (__alpha__)
1104 printf("# %s:\n", disk_device);
1106 printf("# %s:\n", partname(disk_device, xbsd_part_index+1, 0));
1108 if ((unsigned) lp->d_type < BSD_DKMAXTYPES)
1109 printf(_("type: %s\n"), xbsd_dktypenames[lp->d_type]);
1111 printf(_("type: %d\n"), lp->d_type);
1112 printf(_("disk: %.*s\n"), (int) sizeof(lp->d_typename), lp->d_typename);
1113 printf(_("label: %.*s\n"), (int) sizeof(lp->d_packname), lp->d_packname);
1114 printf(_("flags:"));
1115 if (lp->d_flags & BSD_D_REMOVABLE)
1116 printf(_(" removable"));
1117 if (lp->d_flags & BSD_D_ECC)
1119 if (lp->d_flags & BSD_D_BADSECT)
1120 printf(_(" badsect"));
1122 /* On various machines the fields of *lp are short/int/long */
1123 /* In order to avoid problems, we cast them all to long. */
1124 printf(_("bytes/sector: %ld\n"), (long) lp->d_secsize);
1125 printf(_("sectors/track: %ld\n"), (long) lp->d_nsectors);
1126 printf(_("tracks/cylinder: %ld\n"), (long) lp->d_ntracks);
1127 printf(_("sectors/cylinder: %ld\n"), (long) lp->d_secpercyl);
1128 printf(_("cylinders: %ld\n"), (long) lp->d_ncylinders);
1129 printf(_("rpm: %d\n"), lp->d_rpm);
1130 printf(_("interleave: %d\n"), lp->d_interleave);
1131 printf(_("trackskew: %d\n"), lp->d_trackskew);
1132 printf(_("cylinderskew: %d\n"), lp->d_cylskew);
1133 printf(_("headswitch: %ld\t\t# milliseconds\n"),
1134 (long) lp->d_headswitch);
1135 printf(_("track-to-track seek: %ld\t# milliseconds\n"),
1136 (long) lp->d_trkseek);
1137 printf(_("drivedata: "));
1138 for (i = NDDATA - 1; i >= 0; i--)
1139 if (lp->d_drivedata[i])
1143 for (j = 0; j <= i; j++)
1144 printf("%ld ", (long) lp->d_drivedata[j]);
1146 printf(_("\n%d partitions:\n"), lp->d_npartitions);
1147 printf(_("# start end size fstype [fsize bsize cpg]\n"));
1148 pp = lp->d_partitions;
1149 for (i = 0; i < lp->d_npartitions; i++, pp++) {
1151 if (display_in_cyl_units && lp->d_secpercyl) {
1152 printf(" %c: %8ld%c %8ld%c %8ld%c ",
1154 (long) pp->p_offset / lp->d_secpercyl + 1,
1155 (pp->p_offset % lp->d_secpercyl) ? '*' : ' ',
1156 (long) (pp->p_offset + pp->p_size + lp->d_secpercyl - 1)
1158 ((pp->p_offset + pp->p_size) % lp->d_secpercyl) ? '*' : ' ',
1159 (long) pp->p_size / lp->d_secpercyl,
1160 (pp->p_size % lp->d_secpercyl) ? '*' : ' ');
1162 printf(" %c: %8ld %8ld %8ld ",
1164 (long) pp->p_offset,
1165 (long) pp->p_offset + pp->p_size - 1,
1168 if ((unsigned) pp->p_fstype < BSD_FSMAXTYPES)
1169 printf("%8.8s", xbsd_fstypes[pp->p_fstype].name);
1171 printf("%8x", pp->p_fstype);
1172 switch (pp->p_fstype) {
1174 printf(" %5ld %5ld %5.5s ",
1175 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, "");
1179 printf(" %5ld %5ld %5d ",
1180 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag,
1185 printf("%22.22s", "");
1194 xbsd_write_disklabel (void) {
1195 #if defined (__alpha__)
1196 printf (_("Writing disklabel to %s.\n"), disk_device);
1197 xbsd_writelabel (NULL, &xbsd_dlabel);
1199 printf (_("Writing disklabel to %s.\n"),
1200 partname(disk_device, xbsd_part_index+1, 0));
1201 xbsd_writelabel (xbsd_part, &xbsd_dlabel);
1203 reread_partition_table(0); /* no exit yet */
1207 xbsd_create_disklabel (void) {
1210 #if defined (__alpha__)
1211 fprintf (stderr, _("%s contains no disklabel.\n"), disk_device);
1213 fprintf (stderr, _("%s contains no disklabel.\n"),
1214 partname(disk_device, xbsd_part_index+1, 0));
1218 c = read_char (_("Do you want to create a disklabel? (y/n) "));
1219 if (c == 'y' || c == 'Y') {
1220 if (xbsd_initlabel (
1221 #if defined (__alpha__) || defined (__powerpc__) || defined (__hppa__) || \
1222 defined (__s390__) || defined (__s390x__)
1223 NULL, &xbsd_dlabel, 0
1225 xbsd_part, &xbsd_dlabel, xbsd_part_index
1228 xbsd_print_disklabel (1);
1232 } else if (c == 'n')
1238 edit_int (int def, char *mesg)
1241 fputs (mesg, stdout);
1242 printf (" (%d): ", def);
1246 while (!isdigit (*line_ptr));
1247 return atoi (line_ptr);
1251 xbsd_edit_disklabel (void)
1253 struct xbsd_disklabel *d;
1257 #if defined (__alpha__) || defined (__ia64__)
1258 d -> d_secsize = (u_long) edit_int ((u_long) d -> d_secsize ,_("bytes/sector"));
1259 d -> d_nsectors = (u_long) edit_int ((u_long) d -> d_nsectors ,_("sectors/track"));
1260 d -> d_ntracks = (u_long) edit_int ((u_long) d -> d_ntracks ,_("tracks/cylinder"));
1261 d -> d_ncylinders = (u_long) edit_int ((u_long) d -> d_ncylinders ,_("cylinders"));
1264 /* d -> d_secpercyl can be != d -> d_nsectors * d -> d_ntracks */
1267 d -> d_secpercyl = (u_long) edit_int ((u_long) d -> d_nsectors * d -> d_ntracks,
1268 _("sectors/cylinder"));
1269 if (d -> d_secpercyl <= d -> d_nsectors * d -> d_ntracks)
1272 printf (_("Must be <= sectors/track * tracks/cylinder (default).\n"));
1274 d -> d_rpm = (u_short) edit_int ((u_short) d -> d_rpm ,_("rpm"));
1275 d -> d_interleave = (u_short) edit_int ((u_short) d -> d_interleave,_("interleave"));
1276 d -> d_trackskew = (u_short) edit_int ((u_short) d -> d_trackskew ,_("trackskew"));
1277 d -> d_cylskew = (u_short) edit_int ((u_short) d -> d_cylskew ,_("cylinderskew"));
1278 d -> d_headswitch = (u_long) edit_int ((u_long) d -> d_headswitch ,_("headswitch"));
1279 d -> d_trkseek = (u_long) edit_int ((u_long) d -> d_trkseek ,_("track-to-track seek"));
1281 d -> d_secperunit = d -> d_secpercyl * d -> d_ncylinders;
1285 xbsd_get_bootstrap (char *path, void *ptr, int size)
1289 if ((fdb = open (path, O_RDONLY)) < 0)
1294 if (read (fdb, ptr, size) < 0)
1300 printf (" ... %s\n", path);
1308 printf (_("\nSyncing disks.\n"));
1314 xbsd_write_bootstrap (void)
1316 char *bootdir = BSD_LINUX_BOOTDIR;
1317 char path[MAXPATHLEN];
1319 struct xbsd_disklabel dl;
1323 if (xbsd_dlabel.d_type == BSD_DTYPE_SCSI)
1328 printf (_("Bootstrap: %sboot -> boot%s (%s): "),
1329 dkbasename, dkbasename, dkbasename);
1331 line_ptr[strlen (line_ptr)-1] = '\0';
1332 dkbasename = line_ptr;
1334 snprintf (path, sizeof(path), "%s/%sboot", bootdir, dkbasename);
1335 if (!xbsd_get_bootstrap (path, disklabelbuffer, (int) xbsd_dlabel.d_secsize))
1338 /* We need a backup of the disklabel (xbsd_dlabel might have changed). */
1339 d = &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE];
1340 bcopy (d, &dl, sizeof (struct xbsd_disklabel));
1342 /* The disklabel will be overwritten by 0's from bootxx anyway */
1343 bzero (d, sizeof (struct xbsd_disklabel));
1345 snprintf (path, sizeof(path), "%s/boot%s", bootdir, dkbasename);
1346 if (!xbsd_get_bootstrap (path, &disklabelbuffer[xbsd_dlabel.d_secsize],
1347 (int) xbsd_dlabel.d_bbsize - xbsd_dlabel.d_secsize))
1350 e = d + sizeof (struct xbsd_disklabel);
1351 for (p=d; p < e; p++)
1353 fprintf (stderr, _("Bootstrap overlaps with disk label!\n"));
1354 exit ( EXIT_FAILURE );
1357 bcopy (&dl, d, sizeof (struct xbsd_disklabel));
1359 #if defined (__powerpc__) || defined (__hppa__)
1361 #elif defined (__alpha__)
1363 alpha_bootblock_checksum (disklabelbuffer);
1365 sector = get_start_sect(xbsd_part);
1368 if (lseek (fd, sector * SECTOR_SIZE, SEEK_SET) == -1)
1369 fdisk_fatal (unable_to_seek);
1370 if (BSD_BBSIZE != write (fd, disklabelbuffer, BSD_BBSIZE))
1371 fdisk_fatal (unable_to_write);
1373 #if defined (__alpha__)
1374 printf (_("Bootstrap installed on %s.\n"), disk_device);
1376 printf (_("Bootstrap installed on %s.\n"),
1377 partname (disk_device, xbsd_part_index+1, 0));
1384 xbsd_change_fstype (void)
1388 i = xbsd_get_part_index (xbsd_dlabel.d_npartitions);
1389 xbsd_dlabel.d_partitions[i].p_fstype = read_hex (xbsd_fstypes);
1393 xbsd_get_part_index (int max)
1398 snprintf (prompt, sizeof(prompt), _("Partition (a-%c): "), 'a' + max - 1);
1400 l = tolower (read_char (prompt));
1401 while (l < 'a' || l > 'a' + max - 1);
1406 xbsd_check_new_partition (int *i) {
1408 /* room for more? various BSD flavours have different maxima */
1409 if (xbsd_dlabel.d_npartitions == BSD_MAXPARTITIONS) {
1412 for (t = 0; t < BSD_MAXPARTITIONS; t++)
1413 if (xbsd_dlabel.d_partitions[t].p_size == 0)
1416 if (t == BSD_MAXPARTITIONS) {
1417 fprintf (stderr, _("The maximum number of partitions "
1418 "has been created\n"));
1423 *i = xbsd_get_part_index (BSD_MAXPARTITIONS);
1425 if (*i >= xbsd_dlabel.d_npartitions)
1426 xbsd_dlabel.d_npartitions = (*i) + 1;
1428 if (xbsd_dlabel.d_partitions[*i].p_size != 0) {
1429 fprintf (stderr, _("This partition already exists.\n"));
1437 xbsd_list_types (void) {
1438 list_types (xbsd_fstypes);
1442 xbsd_dkcksum (struct xbsd_disklabel *lp) {
1443 u_short *start, *end;
1446 start = (u_short *) lp;
1447 end = (u_short *) &lp->d_partitions[lp->d_npartitions];
1454 xbsd_initlabel (struct partition *p, struct xbsd_disklabel *d, int pindex) {
1455 struct xbsd_partition *pp;
1458 bzero (d, sizeof (struct xbsd_disklabel));
1460 d -> d_magic = BSD_DISKMAGIC;
1462 if (strncmp (disk_device, "/dev/sd", 7) == 0)
1463 d -> d_type = BSD_DTYPE_SCSI;
1465 d -> d_type = BSD_DTYPE_ST506;
1467 #if 0 /* not used (at least not written to disk) by NetBSD/i386 1.0 */
1468 d -> d_subtype = BSD_DSTYPE_INDOSPART & pindex;
1471 #if !defined (__alpha__)
1472 d -> d_flags = BSD_D_DOSPART;
1476 d -> d_secsize = SECTOR_SIZE; /* bytes/sector */
1477 d -> d_nsectors = sectors; /* sectors/track */
1478 d -> d_ntracks = heads; /* tracks/cylinder (heads) */
1479 d -> d_ncylinders = cylinders;
1480 d -> d_secpercyl = sectors * heads;/* sectors/cylinder */
1481 if (d -> d_secpercyl == 0)
1482 d -> d_secpercyl = 1; /* avoid segfaults */
1483 d -> d_secperunit = d -> d_secpercyl * d -> d_ncylinders;
1486 d -> d_interleave = 1;
1487 d -> d_trackskew = 0;
1489 d -> d_headswitch = 0;
1492 d -> d_magic2 = BSD_DISKMAGIC;
1493 d -> d_bbsize = BSD_BBSIZE;
1494 d -> d_sbsize = BSD_SBSIZE;
1496 #if !defined (__alpha__)
1497 d -> d_npartitions = 4;
1498 pp = &d -> d_partitions[2]; /* Partition C should be
1499 the NetBSD partition */
1500 pp -> p_offset = get_start_sect(p);
1501 pp -> p_size = get_nr_sects(p);
1502 pp -> p_fstype = BSD_FS_UNUSED;
1503 pp = &d -> d_partitions[3]; /* Partition D should be
1506 pp -> p_size = d -> d_secperunit;
1507 pp -> p_fstype = BSD_FS_UNUSED;
1508 #elif defined (__alpha__)
1509 d -> d_npartitions = 3;
1510 pp = &d -> d_partitions[2]; /* Partition C should be
1513 pp -> p_size = d -> d_secperunit;
1514 pp -> p_fstype = BSD_FS_UNUSED;
1521 * Read a xbsd_disklabel from sector 0 or from the starting sector of p.
1522 * If it has the right magic, return 1.
1525 xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d)
1529 /* p is used only to get the starting sector */
1530 #if !defined (__alpha__)
1531 sector = (p ? get_start_sect(p) : 0);
1532 #elif defined (__alpha__)
1536 if (lseek (fd, sector * SECTOR_SIZE, SEEK_SET) == -1)
1537 fdisk_fatal (unable_to_seek);
1538 if (BSD_BBSIZE != read (fd, disklabelbuffer, BSD_BBSIZE))
1539 fdisk_fatal (unable_to_read);
1541 bcopy (&disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
1542 d, sizeof (struct xbsd_disklabel));
1544 if (d -> d_magic != BSD_DISKMAGIC || d -> d_magic2 != BSD_DISKMAGIC)
1547 for (t = d -> d_npartitions; t < BSD_MAXPARTITIONS; t++) {
1548 d -> d_partitions[t].p_size = 0;
1549 d -> d_partitions[t].p_offset = 0;
1550 d -> d_partitions[t].p_fstype = BSD_FS_UNUSED;
1553 if (d -> d_npartitions > BSD_MAXPARTITIONS)
1554 fprintf (stderr, _("Warning: too many partitions "
1555 "(%d, maximum is %d).\n"),
1556 d -> d_npartitions, BSD_MAXPARTITIONS);
1561 xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d)
1563 unsigned int sector;
1565 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
1566 sector = get_start_sect(p) + BSD_LABELSECTOR;
1568 sector = BSD_LABELSECTOR;
1571 d -> d_checksum = 0;
1572 d -> d_checksum = xbsd_dkcksum (d);
1574 /* This is necessary if we want to write the bootstrap later,
1575 otherwise we'd write the old disklabel with the bootstrap.
1577 bcopy (d, &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
1578 sizeof (struct xbsd_disklabel));
1580 #if defined (__alpha__) && BSD_LABELSECTOR == 0
1581 alpha_bootblock_checksum (disklabelbuffer);
1582 if (lseek (fd, 0, SEEK_SET) == -1)
1583 fdisk_fatal (unable_to_seek);
1584 if (BSD_BBSIZE != write (fd, disklabelbuffer, BSD_BBSIZE))
1585 fdisk_fatal (unable_to_write);
1587 if (lseek (fd, sector * SECTOR_SIZE + BSD_LABELOFFSET,
1589 fdisk_fatal (unable_to_seek);
1590 if (sizeof (struct xbsd_disklabel) != write (fd, d, sizeof (struct xbsd_disklabel)))
1591 fdisk_fatal (unable_to_write);
1600 #if !defined (__alpha__)
1602 xbsd_translate_fstype (int linux_type)
1606 case 0x01: /* DOS 12-bit FAT */
1607 case 0x04: /* DOS 16-bit <32M */
1608 case 0x06: /* DOS 16-bit >=32M */
1609 case 0xe1: /* DOS access */
1610 case 0xe3: /* DOS R/O */
1611 case 0xf2: /* DOS secondary */
1612 return BSD_FS_MSDOS;
1613 case 0x07: /* OS/2 HPFS */
1616 return BSD_FS_OTHER;
1621 xbsd_link_part (void)
1624 struct partition *p;
1626 k = get_partition (1, partitions);
1628 if (!xbsd_check_new_partition (&i))
1631 p = get_part_table(k);
1633 xbsd_dlabel.d_partitions[i].p_size = get_nr_sects(p);
1634 xbsd_dlabel.d_partitions[i].p_offset = get_start_sect(p);
1635 xbsd_dlabel.d_partitions[i].p_fstype = xbsd_translate_fstype(p->sys_ind);
1639 #if defined (__alpha__)
1641 #if !defined(__GLIBC__)
1642 typedef unsigned long long uint64_t;
1646 alpha_bootblock_checksum (char *boot)
1651 dp = (uint64_t *)boot;
1653 for (i = 0; i < 63; i++)
1657 #endif /* __alpha__ */
1659 #endif /* OSF_LABEL */
1661 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
1662 static inline unsigned short
1663 __swap16(unsigned short x) {
1664 return (((uint16_t)(x) & 0xFF) << 8) | (((uint16_t)(x) & 0xFF00) >> 8);
1667 static inline uint32_t
1668 __swap32(uint32_t x) {
1669 return (((x & 0xFF) << 24) |
1670 ((x & 0xFF00) << 8) |
1671 ((x & 0xFF0000) >> 8) |
1672 ((x & 0xFF000000) >> 24));
1676 #ifdef CONFIG_FEATURE_SGI_LABEL
1681 * Copyright (C) Andreas Neuper, Sep 1998.
1682 * This file may be modified and redistributed under
1683 * the terms of the GNU Public License.
1685 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
1686 * Internationalization
1690 static int sgi_other_endian;
1692 static short sgi_volumes=1;
1695 * only dealing with free blocks here
1698 typedef struct { unsigned int first; unsigned int last; } freeblocks;
1699 static freeblocks freelist[17]; /* 16 partitions can produce 17 vacant slots */
1702 setfreelist(int i, unsigned int f, unsigned int l) {
1703 freelist[i].first = f;
1704 freelist[i].last = l;
1708 add2freelist(unsigned int f, unsigned int l) {
1710 for ( ; i < 17 ; i++)
1711 if (freelist[i].last == 0)
1713 setfreelist(i, f, l);
1717 clearfreelist(void) {
1720 for (i = 0; i < 17 ; i++)
1721 setfreelist(i, 0, 0);
1725 isinfreelist(unsigned int b) {
1728 for (i = 0; i < 17 ; i++)
1729 if (freelist[i].first <= b && freelist[i].last >= b)
1730 return freelist[i].last;
1733 /* return last vacant block of this stride (never 0). */
1734 /* the '>=' is not quite correct, but simplifies the code */
1736 * end of free blocks section
1739 static const struct systypes sgi_sys_types[] = {
1740 /* SGI_VOLHDR */ {"\x00" "SGI volhdr" },
1741 /* 0x01 */ {"\x01" "SGI trkrepl" },
1742 /* 0x02 */ {"\x02" "SGI secrepl" },
1743 /* SGI_SWAP */ {"\x03" "SGI raw" },
1744 /* 0x04 */ {"\x04" "SGI bsd" },
1745 /* 0x05 */ {"\x05" "SGI sysv" },
1746 /* ENTIRE_DISK */ {"\x06" "SGI volume" },
1747 /* SGI_EFS */ {"\x07" "SGI efs" },
1748 /* 0x08 */ {"\x08" "SGI lvol" },
1749 /* 0x09 */ {"\x09" "SGI rlvol" },
1750 /* SGI_XFS */ {"\x0a" "SGI xfs" },
1751 /* SGI_XFSLOG */ {"\x0b" "SGI xfslog" },
1752 /* SGI_XLV */ {"\x0c" "SGI xlv" },
1753 /* SGI_XVM */ {"\x0d" "SGI xvm" },
1754 /* LINUX_SWAP */ {"\x82" "Linux swap" },
1755 /* LINUX_NATIVE */ {"\x83" "Linux native" },
1756 /* LINUX_LVM */ {"\x8d" "Linux LVM" },
1757 /* LINUX_RAID */ {"\xfd" "Linux RAID" },
1763 sgi_get_nsect(void) {
1764 return SGI_SSWAP16(sgilabel->devparam.nsect);
1768 sgi_get_ntrks(void) {
1769 return SGI_SSWAP16(sgilabel->devparam.ntrks);
1774 sgilabel->magic = 0;
1780 two_s_complement_32bit_sum(unsigned int* base, int size /* in bytes */) {
1784 size /= sizeof(unsigned int);
1785 for (i = 0; i < size; i++)
1786 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 _("Detected sgi disklabel with wrong checksum.\n"));
1823 sgi_get_start_sector(int i) {
1824 return SGI_SSWAP32(sgilabel->partitions[i].start_sector);
1828 sgi_get_num_sectors(int i) {
1829 return SGI_SSWAP32(sgilabel->partitions[i].num_sectors);
1833 sgi_get_sysid(int i)
1835 return SGI_SSWAP32(sgilabel->partitions[i].id);
1839 sgi_get_bootpartition(void)
1841 return SGI_SSWAP16(sgilabel->boot_part);
1845 sgi_get_swappartition(void)
1847 return SGI_SSWAP16(sgilabel->swap_part);
1851 sgi_list_table(int xtra) {
1853 int kpi = 0; /* kernel partition ID */
1856 printf(_("\nDisk %s (SGI disk label): %d heads, %d sectors\n"
1857 "%d cylinders, %d physical cylinders\n"
1858 "%d extra sects/cyl, interleave %d:1\n"
1860 "Units = %s of %d * 512 bytes\n\n"),
1861 disk_device, heads, sectors, cylinders,
1862 SGI_SSWAP16(sgiparam.pcylcount),
1863 SGI_SSWAP16(sgiparam.sparecyl),
1864 SGI_SSWAP16(sgiparam.ilfact),
1866 str_units(PLURAL), units_per_sector);
1868 printf( _("\nDisk %s (SGI disk label): "
1869 "%d heads, %d sectors, %d cylinders\n"
1870 "Units = %s of %d * 512 bytes\n\n"),
1871 disk_device, heads, sectors, cylinders,
1872 str_units(PLURAL), units_per_sector );
1875 w = strlen(disk_device);
1876 wd = strlen(_("Device"));
1880 printf(_("----- partitions -----\n"
1881 "Pt# %*s Info Start End Sectors Id System\n"),
1882 w + 2, _("Device"));
1883 for (i = 0 ; i < partitions; i++) {
1884 if( sgi_get_num_sectors(i) || debug ) {
1885 uint32_t start = sgi_get_start_sector(i);
1886 uint32_t len = sgi_get_num_sectors(i);
1887 kpi++; /* only count nonempty partitions */
1889 "%2d: %s %4s %9ld %9ld %9ld %2x %s\n",
1890 /* fdisk part number */ i+1,
1891 /* device */ partname(disk_device, kpi, w+3),
1892 /* flags */ (sgi_get_swappartition() == i) ? "swap" :
1893 /* flags */ (sgi_get_bootpartition() == i) ? "boot" : " ",
1894 /* start */ (long) scround(start),
1895 /* end */ (long) scround(start+len)-1,
1896 /* no odd flag on end */ (long) len,
1897 /* type id */ sgi_get_sysid(i),
1898 /* type name */ partition_type(sgi_get_sysid(i)));
1901 printf(_("----- Bootinfo -----\nBootfile: %s\n"
1902 "----- Directory Entries -----\n"),
1903 sgilabel->boot_file);
1904 for (i = 0 ; i < sgi_volumes; i++) {
1905 if (sgilabel->directory[i].vol_file_size) {
1906 uint32_t start = SGI_SSWAP32(sgilabel->directory[i].vol_file_start);
1907 uint32_t len = SGI_SSWAP32(sgilabel->directory[i].vol_file_size);
1908 char*name = sgilabel->directory[i].vol_file_name;
1910 printf(_("%2d: %-10s sector%5u size%8u\n"),
1911 i, name, (unsigned int) start, (unsigned int) len);
1917 sgi_set_bootpartition( int i )
1919 sgilabel->boot_part = SGI_SSWAP16(((short)i));
1923 sgi_get_lastblock(void) {
1924 return heads * sectors * cylinders;
1928 sgi_set_swappartition( int i ) {
1929 sgilabel->swap_part = SGI_SSWAP16(((short)i));
1933 sgi_check_bootfile(const char* aFile) {
1935 if (strlen(aFile) < 3) /* "/a\n" is minimum */ {
1936 printf(_("\nInvalid Bootfile!\n"
1937 "\tThe bootfile must be an absolute non-zero pathname,\n"
1938 "\te.g. \"/unix\" or \"/unix.save\".\n"));
1941 if (strlen(aFile) > 16) {
1942 printf(_("\n\tName of Bootfile too long: "
1943 "16 bytes maximum.\n"));
1946 if (aFile[0] != '/') {
1947 printf(_("\n\tBootfile must have a "
1948 "fully qualified pathname.\n"));
1953 if (strncmp(aFile, sgilabel->boot_file, 16)) {
1954 printf(_("\n\tBe aware, that the bootfile is not checked for existence.\n\t"
1955 "SGI's default is \"/unix\" and for backup \"/unix.save\".\n"));
1956 /* filename is correct and did change */
1959 return 0; /* filename did not change */
1963 sgi_get_bootfile(void) {
1964 return sgilabel->boot_file;
1968 sgi_set_bootfile(const char* aFile) {
1971 if (sgi_check_bootfile(aFile)) {
1973 if ((aFile[i] != '\n') /* in principle caught again by next line */
1974 && (strlen(aFile) > i))
1975 sgilabel->boot_file[i] = aFile[i];
1977 sgilabel->boot_file[i] = 0;
1980 printf(_("\n\tBootfile is changed to \"%s\".\n"), sgilabel->boot_file);
1985 create_sgiinfo(void)
1987 /* I keep SGI's habit to write the sgilabel to the second block */
1988 sgilabel->directory[0].vol_file_start = SGI_SSWAP32(2);
1989 sgilabel->directory[0].vol_file_size = SGI_SSWAP32(sizeof(sgiinfo));
1990 strncpy(sgilabel->directory[0].vol_file_name, "sgilabel", 8);
1993 static sgiinfo *fill_sgiinfo(void);
1996 sgi_write_table(void) {
1998 sgilabel->csum = SGI_SSWAP32(two_s_complement_32bit_sum(
1999 (unsigned int*)sgilabel,
2000 sizeof(*sgilabel)));
2001 assert(two_s_complement_32bit_sum(
2002 (unsigned int*)sgilabel, sizeof(*sgilabel)) == 0);
2003 if (lseek(fd, 0, SEEK_SET) < 0)
2004 fdisk_fatal(unable_to_seek);
2005 if (write(fd, sgilabel, SECTOR_SIZE) != SECTOR_SIZE)
2006 fdisk_fatal(unable_to_write);
2007 if (! strncmp(sgilabel->directory[0].vol_file_name, "sgilabel", 8)) {
2009 * keep this habit of first writing the "sgilabel".
2010 * I never tested whether it works without (AN 981002).
2012 sgiinfo *info = fill_sgiinfo();
2013 int infostartblock = SGI_SSWAP32(sgilabel->directory[0].vol_file_start);
2014 if (lseek(fd, infostartblock*SECTOR_SIZE, SEEK_SET) < 0)
2015 fdisk_fatal(unable_to_seek);
2016 if (write(fd, info, SECTOR_SIZE) != SECTOR_SIZE)
2017 fdisk_fatal(unable_to_write);
2023 compare_start(int *x, int *y) {
2025 * sort according to start sectors
2026 * and prefers largest partition:
2027 * entry zero is entire disk entry
2029 unsigned int i = *x;
2030 unsigned int j = *y;
2031 unsigned int a = sgi_get_start_sector(i);
2032 unsigned int b = sgi_get_start_sector(j);
2033 unsigned int c = sgi_get_num_sectors(i);
2034 unsigned int d = sgi_get_num_sectors(j);
2037 return (d > c) ? 1 : (d == c) ? 0 : -1;
2038 return (a > b) ? 1 : -1;
2043 verify_sgi(int verbose)
2045 int Index[16]; /* list of valid partitions */
2046 int sortcount = 0; /* number of used partitions, i.e. non-zero lengths */
2047 int entire = 0, i = 0;
2048 unsigned int start = 0;
2049 long long gap = 0; /* count unused blocks */
2050 unsigned int lastblock = sgi_get_lastblock();
2053 for (i=0; i<16; i++) {
2054 if (sgi_get_num_sectors(i) != 0) {
2055 Index[sortcount++]=i;
2056 if (sgi_get_sysid(i) == ENTIRE_DISK) {
2057 if (entire++ == 1) {
2059 printf(_("More than one entire disk entry present.\n"));
2064 if (sortcount == 0) {
2066 printf(_("No partitions defined\n"));
2067 return (lastblock > 0) ? 1 : (lastblock == 0) ? 0 : -1;
2069 qsort(Index, sortcount, sizeof(Index[0]), (void*)compare_start);
2070 if (sgi_get_sysid(Index[0]) == ENTIRE_DISK) {
2071 if ((Index[0] != 10) && verbose)
2072 printf(_("IRIX likes when Partition 11 covers the entire disk.\n"));
2073 if ((sgi_get_start_sector(Index[0]) != 0) && verbose)
2074 printf(_("The entire disk partition should start "
2076 "not at diskblock %d.\n"),
2077 sgi_get_start_sector(Index[0]));
2078 if (debug) /* I do not understand how some disks fulfil it */
2079 if ((sgi_get_num_sectors(Index[0]) != lastblock) && verbose)
2080 printf(_("The entire disk partition is only %d diskblock large,\n"
2081 "but the disk is %d diskblocks long.\n"),
2082 sgi_get_num_sectors(Index[0]), lastblock);
2083 lastblock = sgi_get_num_sectors(Index[0]);
2086 printf(_("One Partition (#11) should cover the entire disk.\n"));
2088 printf("sysid=%d\tpartition=%d\n",
2089 sgi_get_sysid(Index[0]), Index[0]+1);
2091 for (i=1, start=0; i<sortcount; i++) {
2092 int cylsize = sgi_get_nsect() * sgi_get_ntrks();
2094 if ((sgi_get_start_sector(Index[i]) % cylsize) != 0) {
2095 if (debug) /* I do not understand how some disks fulfil it */
2097 printf(_("Partition %d does not start on cylinder boundary.\n"),
2100 if (sgi_get_num_sectors(Index[i]) % cylsize != 0) {
2101 if (debug) /* I do not understand how some disks fulfil it */
2103 printf(_("Partition %d does not end on cylinder boundary.\n"),
2106 /* We cannot handle several "entire disk" entries. */
2107 if (sgi_get_sysid(Index[i]) == ENTIRE_DISK) continue;
2108 if (start > sgi_get_start_sector(Index[i])) {
2110 printf(_("The Partition %d and %d overlap by %d sectors.\n"),
2111 Index[i-1]+1, Index[i]+1,
2112 start - sgi_get_start_sector(Index[i]));
2113 if (gap > 0) gap = -gap;
2114 if (gap == 0) gap = -1;
2116 if (start < sgi_get_start_sector(Index[i])) {
2118 printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"),
2119 sgi_get_start_sector(Index[i]) - start,
2120 start, sgi_get_start_sector(Index[i])-1);
2121 gap += sgi_get_start_sector(Index[i]) - start;
2122 add2freelist(start, sgi_get_start_sector(Index[i]));
2124 start = sgi_get_start_sector(Index[i])
2125 + sgi_get_num_sectors(Index[i]);
2128 printf("%2d:%12d\t%12d\t%12d\n", Index[i],
2129 sgi_get_start_sector(Index[i]),
2130 sgi_get_num_sectors(Index[i]),
2131 sgi_get_sysid(Index[i]));
2134 if (start < lastblock) {
2136 printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"),
2137 lastblock - start, start, lastblock-1);
2138 gap += lastblock - start;
2139 add2freelist(start, lastblock);
2142 * Done with arithmetics
2143 * Go for details now
2146 if (!sgi_get_num_sectors(sgi_get_bootpartition())) {
2147 printf(_("\nThe boot partition does not exist.\n"));
2149 if (!sgi_get_num_sectors(sgi_get_swappartition())) {
2150 printf(_("\nThe swap partition does not exist.\n"));
2152 if ((sgi_get_sysid(sgi_get_swappartition()) != SGI_SWAP)
2153 && (sgi_get_sysid(sgi_get_swappartition()) != LINUX_SWAP))
2154 printf(_("\nThe swap partition has no swap type.\n"));
2156 if (sgi_check_bootfile("/unix"))
2157 printf(_("\tYou have chosen an unusual boot file name.\n"));
2159 return (gap > 0) ? 1 : (gap == 0) ? 0 : -1;
2165 * returned value is:
2166 * = 0 : disk is properly filled to the rim
2167 * < 0 : there is an overlap
2168 * > 0 : there is still some vacant space
2170 return verify_sgi(0);
2174 sgi_change_sysid( int i, int sys )
2176 if( sgi_get_num_sectors(i) == 0 ) /* caught already before, ... */
2178 printf(_("Sorry You may change the Tag of non-empty partitions.\n"));
2181 if( ((sys != ENTIRE_DISK ) && (sys != SGI_VOLHDR))
2182 && (sgi_get_start_sector(i)<1) )
2185 _("It is highly recommended that the partition at offset 0\n"
2186 "is of type \"SGI volhdr\", the IRIX system will rely on it to\n"
2187 "retrieve from its directory standalone tools like sash and fx.\n"
2188 "Only the \"SGI volume\" entire disk section may violate this.\n"
2189 "Type YES if you are sure about tagging this partition differently.\n"));
2190 if (strcmp (line_ptr, _("YES\n")))
2193 sgilabel->partitions[i].id = SGI_SSWAP32(sys);
2196 /* returns partition index of first entry marked as entire disk */
2202 if(sgi_get_sysid(i) == SGI_VOLUME)
2208 sgi_set_partition(int i, unsigned int start, unsigned int length, int sys) {
2210 sgilabel->partitions[i].id = SGI_SSWAP32(sys);
2211 sgilabel->partitions[i].num_sectors = SGI_SSWAP32(length);
2212 sgilabel->partitions[i].start_sector = SGI_SSWAP32(start);
2214 if (sgi_gaps() < 0) /* rebuild freelist */
2215 printf(_("Do You know, You got a partition overlap on the disk?\n"));
2219 sgi_set_entire(void) {
2222 for(n=10; n < partitions; n++) {
2223 if(!sgi_get_num_sectors(n) ) {
2224 sgi_set_partition(n, 0, sgi_get_lastblock(), SGI_VOLUME);
2231 sgi_set_volhdr(void)
2234 for( n=8; n<partitions; n++ )
2236 if(!sgi_get_num_sectors( n ) )
2239 * 5 cylinders is an arbitrary value I like
2240 * IRIX 5.3 stored files in the volume header
2241 * (like sash, symmon, fx, ide) with ca. 3200
2244 if( heads * sectors * 5 < sgi_get_lastblock() )
2245 sgi_set_partition( n, 0, heads * sectors * 5, SGI_VOLHDR );
2252 sgi_delete_partition( int i )
2254 sgi_set_partition( i, 0, 0, 0 );
2258 sgi_add_partition( int n, int sys )
2261 unsigned int first=0, last=0;
2265 } else if ( n == 8 ) {
2268 if(sgi_get_num_sectors(n)) {
2269 printf(_("Partition %d is already defined. Delete "
2270 "it before re-adding it.\n"), n + 1);
2273 if( (sgi_entire() == -1) && (sys != SGI_VOLUME) ) {
2274 printf(_("Attempting to generate entire disk entry automatically.\n"));
2278 if( (sgi_gaps() == 0) && (sys != SGI_VOLUME) ) {
2279 printf(_("The entire disk is already covered with partitions.\n"));
2282 if(sgi_gaps() < 0) {
2283 printf(_("You got a partition overlap on the disk. Fix it first!\n"));
2286 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
2288 if(sys == SGI_VOLUME) {
2289 last = sgi_get_lastblock();
2290 first = read_int(0, 0, last-1, 0, mesg);
2292 printf(_("It is highly recommended that eleventh partition\n"
2293 "covers the entire disk and is of type `SGI volume'\n"));
2296 first = freelist[0].first;
2297 last = freelist[0].last;
2298 first = read_int(scround(first), scround(first), scround(last)-1,
2301 if (display_in_cyl_units)
2302 first *= units_per_sector;
2304 first = first; /* align to cylinder if you know how ... */
2306 last = isinfreelist(first);
2308 printf(_("You will get a partition overlap on the disk. "
2309 "Fix it first!\n"));
2313 snprintf(mesg, sizeof(mesg), _(" Last %s"), str_units(SINGULAR));
2314 last = read_int(scround(first), scround(last)-1, scround(last)-1,
2315 scround(first), mesg)+1;
2316 if (display_in_cyl_units)
2317 last *= units_per_sector;
2319 last = last; /* align to cylinder if You know how ... */
2320 if( (sys == SGI_VOLUME) && ( first != 0 || last != sgi_get_lastblock() ) )
2321 printf(_("It is highly recommended that eleventh partition\n"
2322 "covers the entire disk and is of type `SGI volume'\n"));
2323 sgi_set_partition( n, first, last-first, sys );
2326 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
2328 create_sgilabel(void)
2330 struct hd_geometry geometry;
2337 long longsectors; /* the number of sectors on the device */
2338 int res; /* the result from the ioctl */
2339 int sec_fac; /* the sector factor */
2341 sec_fac = sector_size / 512; /* determine the sector factor */
2344 _("Building a new SGI disklabel. Changes will remain in memory only,\n"
2345 "until you decide to write them. After that, of course, the previous\n"
2346 "content will be unrecoverably lost.\n\n"));
2348 sgi_other_endian = (BYTE_ORDER == LITTLE_ENDIAN);
2349 res = ioctl(fd, BLKGETSIZE, &longsectors);
2350 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
2351 heads = geometry.heads;
2352 sectors = geometry.sectors;
2354 /* the get device size ioctl was successful */
2355 cylinders = longsectors / (heads * sectors);
2356 cylinders /= sec_fac;
2358 /* otherwise print error and use truncated version */
2359 cylinders = geometry.cylinders;
2361 _("Warning: BLKGETSIZE ioctl failed on %s. "
2362 "Using geometry cylinder value of %d.\n"
2363 "This value may be truncated for devices"
2364 " > 33.8 GB.\n"), disk_device, cylinders);
2367 for (i = 0; i < 4; i++) {
2369 if(valid_part_table_flag(MBRbuffer)) {
2370 if(get_part_table(i)->sys_ind) {
2371 old[i].sysid = get_part_table(i)->sys_ind;
2372 old[i].start = get_start_sect(get_part_table(i));
2373 old[i].nsect = get_nr_sects(get_part_table(i));
2374 printf(_("Trying to keep parameters of partition %d.\n"), i);
2376 printf(_("ID=%02x\tSTART=%d\tLENGTH=%d\n"),
2377 old[i].sysid, old[i].start, old[i].nsect);
2382 memset(MBRbuffer, 0, sizeof(MBRbuffer));
2383 sgilabel->magic = SGI_SSWAP32(SGI_LABEL_MAGIC);
2384 sgilabel->boot_part = SGI_SSWAP16(0);
2385 sgilabel->swap_part = SGI_SSWAP16(1);
2387 /* sizeof(sgilabel->boot_file) = 16 > 6 */
2388 memset(sgilabel->boot_file, 0, 16);
2389 strcpy(sgilabel->boot_file, "/unix");
2391 sgilabel->devparam.skew = (0);
2392 sgilabel->devparam.gap1 = (0);
2393 sgilabel->devparam.gap2 = (0);
2394 sgilabel->devparam.sparecyl = (0);
2395 sgilabel->devparam.pcylcount = SGI_SSWAP16(geometry.cylinders);
2396 sgilabel->devparam.head_vol0 = SGI_SSWAP16(0);
2397 sgilabel->devparam.ntrks = SGI_SSWAP16(geometry.heads);
2398 /* tracks/cylinder (heads) */
2399 sgilabel->devparam.cmd_tag_queue_depth = (0);
2400 sgilabel->devparam.unused0 = (0);
2401 sgilabel->devparam.unused1 = SGI_SSWAP16(0);
2402 sgilabel->devparam.nsect = SGI_SSWAP16(geometry.sectors);
2404 sgilabel->devparam.bytes = SGI_SSWAP16(512);
2405 sgilabel->devparam.ilfact = SGI_SSWAP16(1);
2406 sgilabel->devparam.flags = SGI_SSWAP32(TRACK_FWD|
2407 IGNORE_ERRORS|RESEEK);
2408 sgilabel->devparam.datarate = SGI_SSWAP32(0);
2409 sgilabel->devparam.retries_on_error = SGI_SSWAP32(1);
2410 sgilabel->devparam.ms_per_word = SGI_SSWAP32(0);
2411 sgilabel->devparam.xylogics_gap1 = SGI_SSWAP16(0);
2412 sgilabel->devparam.xylogics_syncdelay = SGI_SSWAP16(0);
2413 sgilabel->devparam.xylogics_readdelay = SGI_SSWAP16(0);
2414 sgilabel->devparam.xylogics_gap2 = SGI_SSWAP16(0);
2415 sgilabel->devparam.xylogics_readgate = SGI_SSWAP16(0);
2416 sgilabel->devparam.xylogics_writecont = SGI_SSWAP16(0);
2417 memset( &(sgilabel->directory), 0, sizeof(struct volume_directory)*15 );
2418 memset( &(sgilabel->partitions), 0, sizeof(struct sgi_partition)*16 );
2424 for (i = 0; i < 4; i++) {
2426 sgi_set_partition(i, old[i].start, old[i].nsect, old[i].sysid);
2434 /* do nothing in the beginning */
2436 #endif /* CONFIG_FEATURE_FDISK_ADVANCED */
2438 /* _____________________________________________________________
2444 sgiinfo *info = calloc(1, sizeof(sgiinfo));
2446 info->magic=SGI_SSWAP32(SGI_INFO_MAGIC);
2447 info->b1=SGI_SSWAP32(-1);
2448 info->b2=SGI_SSWAP16(-1);
2449 info->b3=SGI_SSWAP16(1);
2450 /* You may want to replace this string !!!!!!! */
2451 strcpy( info->scsi_string, "IBM OEM 0662S12 3 30" );
2452 strcpy( info->serial, "0000" );
2453 info->check1816 = SGI_SSWAP16(18*256 +16 );
2454 strcpy( info->installer, "Sfx version 5.3, Oct 18, 1994" );
2457 #endif /* SGI_LABEL */
2460 #ifdef CONFIG_FEATURE_SUN_LABEL
2464 * I think this is mostly, or entirely, due to
2465 * Jakub Jelinek (jj@sunsite.mff.cuni.cz), July 1996
2467 * Merged with fdisk for other architectures, aeb, June 1998.
2469 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
2470 * Internationalization
2474 static int sun_other_endian;
2475 static int scsi_disk;
2479 #define IDE0_MAJOR 3
2482 #define IDE1_MAJOR 22
2485 static void guess_device_type(void) {
2486 struct stat bootstat;
2488 if (fstat (fd, &bootstat) < 0) {
2491 } else if (S_ISBLK(bootstat.st_mode)
2492 && (major(bootstat.st_rdev) == IDE0_MAJOR ||
2493 major(bootstat.st_rdev) == IDE1_MAJOR)) {
2496 } else if (S_ISBLK(bootstat.st_mode)
2497 && major(bootstat.st_rdev) == FLOPPY_MAJOR) {
2506 static const struct systypes sun_sys_types[] = {
2507 /* 0 */ {"\x00" "Empty" },
2508 /* 1 */ {"\x01" "Boot" },
2509 /* 2 */ {"\x02" "SunOS root" },
2510 /* SUNOS_SWAP */ {"\x03" "SunOS swap" },
2511 /* 4 */ {"\x04" "SunOS usr" },
2512 /* WHOLE_DISK */ {"\x05" "Whole disk" },
2513 /* 6 */ {"\x06" "SunOS stand" },
2514 /* 7 */ {"\x07" "SunOS var" },
2515 /* 8 */ {"\x08" "SunOS home" },
2516 /* LINUX_SWAP */ {"\x82" "Linux swap" },
2517 /* LINUX_NATIVE */ {"\x83" "Linux native" },
2518 /* 0x8e */ {"\x8e" "Linux LVM" },
2519 /* New (2.2.x) raid partition with autodetect using persistent superblock */
2520 /* 0xfd */ {"\xfd" "Linux raid autodetect" },
2526 set_sun_partition(int i, uint start, uint stop, int sysid) {
2527 sunlabel->infos[i].id = sysid;
2528 sunlabel->partitions[i].start_cylinder =
2529 SUN_SSWAP32(start / (heads * sectors));
2530 sunlabel->partitions[i].num_sectors =
2531 SUN_SSWAP32(stop - start);
2538 sunlabel->magic = 0;
2543 check_sun_label(void) {
2544 unsigned short *ush;
2547 if (sunlabel->magic != SUN_LABEL_MAGIC &&
2548 sunlabel->magic != SUN_LABEL_MAGIC_SWAPPED) {
2550 sun_other_endian = 0;
2553 sun_other_endian = (sunlabel->magic == SUN_LABEL_MAGIC_SWAPPED);
2554 ush = ((unsigned short *) (sunlabel + 1)) - 1;
2555 for (csum = 0; ush >= (unsigned short *)sunlabel;) csum ^= *ush--;
2557 fprintf(stderr,_("Detected sun disklabel with wrong checksum.\n"
2558 "Probably you'll have to set all the values,\n"
2559 "e.g. heads, sectors, cylinders and partitions\n"
2560 "or force a fresh label (s command in main menu)\n"));
2562 heads = SUN_SSWAP16(sunlabel->ntrks);
2563 cylinders = SUN_SSWAP16(sunlabel->ncyl);
2564 sectors = SUN_SSWAP16(sunlabel->nsect);
2572 static const struct sun_predefined_drives {
2575 unsigned short sparecyl;
2576 unsigned short ncyl;
2577 unsigned short nacyl;
2578 unsigned short pcylcount;
2579 unsigned short ntrks;
2580 unsigned short nsect;
2581 unsigned short rspeed;
2583 {"Quantum","ProDrive 80S",1,832,2,834,6,34,3662},
2584 {"Quantum","ProDrive 105S",1,974,2,1019,6,35,3662},
2585 {"CDC","Wren IV 94171-344",3,1545,2,1549,9,46,3600},
2586 {"IBM","DPES-31080",0,4901,2,4903,4,108,5400},
2587 {"IBM","DORS-32160",0,1015,2,1017,67,62,5400},
2588 {"IBM","DNES-318350",0,11199,2,11474,10,320,7200},
2589 {"SEAGATE","ST34371",0,3880,2,3882,16,135,7228},
2590 {"","SUN0104",1,974,2,1019,6,35,3662},
2591 {"","SUN0207",4,1254,2,1272,9,36,3600},
2592 {"","SUN0327",3,1545,2,1549,9,46,3600},
2593 {"","SUN0340",0,1538,2,1544,6,72,4200},
2594 {"","SUN0424",2,1151,2,2500,9,80,4400},
2595 {"","SUN0535",0,1866,2,2500,7,80,5400},
2596 {"","SUN0669",5,1614,2,1632,15,54,3600},
2597 {"","SUN1.0G",5,1703,2,1931,15,80,3597},
2598 {"","SUN1.05",0,2036,2,2038,14,72,5400},
2599 {"","SUN1.3G",6,1965,2,3500,17,80,5400},
2600 {"","SUN2.1G",0,2733,2,3500,19,80,5400},
2601 {"IOMEGA","Jaz",0,1019,2,1021,64,32,5394},
2604 static const struct sun_predefined_drives *
2605 sun_autoconfigure_scsi(void) {
2606 const struct sun_predefined_drives *p = NULL;
2608 #ifdef SCSI_IOCTL_GET_IDLUN
2618 if (!ioctl(fd, SCSI_IOCTL_GET_IDLUN, &id)) {
2620 "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n",
2622 ((id[0]>>24)&0xff)-/*PROC_SCSI_SCSI+PROC_SCSI_FILE*/33,
2624 /* This is very wrong (works only if you have one HBA),
2625 but I haven't found a way how to get hostno
2626 from the current kernel */
2632 pfd = fopen("/proc/scsi/scsi","r");
2634 while (fgets(buffer2,2048,pfd)) {
2635 if (!strcmp(buffer, buffer2)) {
2636 if (fgets(buffer2,2048,pfd)) {
2637 q = strstr(buffer2,"Vendor: ");
2642 *q++ = 0; /* truncate vendor name */
2643 q = strstr(q,"Model: ");
2648 q = strstr(q," Rev: ");
2651 for (i = 0; i < SIZE(sun_drives); i++) {
2652 if (*sun_drives[i].vendor && strcasecmp(sun_drives[i].vendor, vendor))
2654 if (!strstr(model, sun_drives[i].model))
2656 printf(_("Autoconfigure found a %s%s%s\n"),sun_drives[i].vendor,(*sun_drives[i].vendor) ? " " : "",sun_drives[i].model);
2674 static void create_sunlabel(void)
2676 struct hd_geometry geometry;
2680 const struct sun_predefined_drives *p = NULL;
2683 _("Building a new sun disklabel. Changes will remain in memory only,\n"
2684 "until you decide to write them. After that, of course, the previous\n"
2685 "content won't be recoverable.\n\n"));
2686 #if BYTE_ORDER == LITTLE_ENDIAN
2687 sun_other_endian = 1;
2689 sun_other_endian = 0;
2691 memset(MBRbuffer, 0, sizeof(MBRbuffer));
2692 sunlabel->magic = SUN_SSWAP16(SUN_LABEL_MAGIC);
2694 puts(_("Drive type\n"
2695 " ? auto configure\n"
2696 " 0 custom (with hardware detected defaults)"));
2697 for (i = 0; i < SIZE(sun_drives); i++) {
2698 printf(" %c %s%s%s\n",
2699 i + 'a', sun_drives[i].vendor,
2700 (*sun_drives[i].vendor) ? " " : "",
2701 sun_drives[i].model);
2704 c = read_char(_("Select type (? for auto, 0 for custom): "));
2705 if (c >= 'a' && c < 'a' + SIZE(sun_drives)) {
2706 p = sun_drives + c - 'a';
2708 } else if (c >= 'A' && c < 'A' + SIZE(sun_drives)) {
2709 p = sun_drives + c - 'A';
2711 } else if (c == '0') {
2713 } else if (c == '?' && scsi_disk) {
2714 p = sun_autoconfigure_scsi();
2716 printf(_("Autoconfigure failed.\n"));
2723 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
2724 heads = geometry.heads;
2725 sectors = geometry.sectors;
2726 cylinders = geometry.cylinders;
2733 sunlabel->nacyl = 0;
2734 sunlabel->pcylcount = SUN_SSWAP16(cylinders);
2735 sunlabel->rspeed = SUN_SSWAP16(300);
2736 sunlabel->ilfact = SUN_SSWAP16(1);
2737 sunlabel->sparecyl = 0;
2739 heads = read_int(1,heads,1024,0,_("Heads"));
2740 sectors = read_int(1,sectors,1024,0,_("Sectors/track"));
2742 cylinders = read_int(1,cylinders-2,65535,0,_("Cylinders"));
2744 cylinders = read_int(1,0,65535,0,_("Cylinders"));
2746 SUN_SSWAP16(read_int(0,2,65535,0,
2747 _("Alternate cylinders")));
2748 sunlabel->pcylcount =
2749 SUN_SSWAP16(read_int(0,cylinders+SUN_SSWAP16(sunlabel->nacyl),
2750 65535,0,_("Physical cylinders")));
2752 SUN_SSWAP16(read_int(1,5400,100000,0,
2753 _("Rotation speed (rpm)")));
2755 SUN_SSWAP16(read_int(1,1,32,0,_("Interleave factor")));
2756 sunlabel->sparecyl =
2757 SUN_SSWAP16(read_int(0,0,sectors,0,
2758 _("Extra sectors per cylinder")));
2761 sunlabel->sparecyl = SUN_SSWAP16(p->sparecyl);
2762 sunlabel->ncyl = SUN_SSWAP16(p->ncyl);
2763 sunlabel->nacyl = SUN_SSWAP16(p->nacyl);
2764 sunlabel->pcylcount = SUN_SSWAP16(p->pcylcount);
2765 sunlabel->ntrks = SUN_SSWAP16(p->ntrks);
2766 sunlabel->nsect = SUN_SSWAP16(p->nsect);
2767 sunlabel->rspeed = SUN_SSWAP16(p->rspeed);
2768 sunlabel->ilfact = SUN_SSWAP16(1);
2769 cylinders = p->ncyl;
2772 puts(_("You may change all the disk params from the x menu"));
2775 snprintf(sunlabel->info, sizeof(sunlabel->info),
2776 "%s%s%s cyl %d alt %d hd %d sec %d",
2777 p ? p->vendor : "", (p && *p->vendor) ? " " : "",
2779 : (floppy ? _("3,5\" floppy") : _("Linux custom")),
2780 cylinders, SUN_SSWAP16(sunlabel->nacyl), heads, sectors);
2782 sunlabel->ntrks = SUN_SSWAP16(heads);
2783 sunlabel->nsect = SUN_SSWAP16(sectors);
2784 sunlabel->ncyl = SUN_SSWAP16(cylinders);
2786 set_sun_partition(0, 0, cylinders * heads * sectors, LINUX_NATIVE);
2788 if (cylinders * heads * sectors >= 150 * 2048) {
2789 ndiv = cylinders - (50 * 2048 / (heads * sectors)); /* 50M swap */
2791 ndiv = cylinders * 2 / 3;
2792 set_sun_partition(0, 0, ndiv * heads * sectors, LINUX_NATIVE);
2793 set_sun_partition(1, ndiv * heads * sectors, cylinders * heads * sectors, LINUX_SWAP);
2794 sunlabel->infos[1].flags |= 0x01; /* Not mountable */
2796 set_sun_partition(2, 0, cylinders * heads * sectors, WHOLE_DISK);
2798 unsigned short *ush = (unsigned short *)sunlabel;
2799 unsigned short csum = 0;
2800 while(ush < (unsigned short *)(&sunlabel->csum))
2802 sunlabel->csum = csum;
2805 set_all_unchanged();
2807 get_boot(create_empty_sun);
2811 toggle_sunflags(int i, unsigned char mask) {
2812 if (sunlabel->infos[i].flags & mask)
2813 sunlabel->infos[i].flags &= ~mask;
2814 else sunlabel->infos[i].flags |= mask;
2819 fetch_sun(uint *starts, uint *lens, uint *start, uint *stop) {
2820 int i, continuous = 1;
2821 *start = 0; *stop = cylinders * heads * sectors;
2822 for (i = 0; i < partitions; i++) {
2823 if (sunlabel->partitions[i].num_sectors
2824 && sunlabel->infos[i].id
2825 && sunlabel->infos[i].id != WHOLE_DISK) {
2826 starts[i] = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
2827 lens[i] = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
2829 if (starts[i] == *start)
2831 else if (starts[i] + lens[i] >= *stop)
2835 /* There will be probably more gaps
2836 than one, so lets check afterwards */
2845 static uint *verify_sun_starts;
2848 verify_sun_cmp(int *a, int *b) {
2849 if (*a == -1) return 1;
2850 if (*b == -1) return -1;
2851 if (verify_sun_starts[*a] > verify_sun_starts[*b]) return 1;
2857 uint starts[8], lens[8], start, stop;
2858 int i,j,k,starto,endo;
2861 verify_sun_starts = starts;
2862 fetch_sun(starts,lens,&start,&stop);
2863 for (k = 0; k < 7; k++) {
2864 for (i = 0; i < 8; i++) {
2865 if (k && (lens[i] % (heads * sectors))) {
2866 printf(_("Partition %d doesn't end on cylinder boundary\n"), i+1);
2869 for (j = 0; j < i; j++)
2871 if (starts[j] == starts[i]+lens[i]) {
2872 starts[j] = starts[i]; lens[j] += lens[i];
2874 } else if (starts[i] == starts[j]+lens[j]){
2878 if (starts[i] < starts[j]+lens[j] &&
2879 starts[j] < starts[i]+lens[i]) {
2881 if (starts[j] > starto)
2883 endo = starts[i]+lens[i];
2884 if (starts[j]+lens[j] < endo)
2885 endo = starts[j]+lens[j];
2886 printf(_("Partition %d overlaps with others in "
2887 "sectors %d-%d\n"), i+1, starto, endo);
2894 for (i = 0; i < 8; i++) {
2900 qsort(array,SIZE(array),sizeof(array[0]),
2901 (int (*)(const void *,const void *)) verify_sun_cmp);
2902 if (array[0] == -1) {
2903 printf(_("No partitions defined\n"));
2906 stop = cylinders * heads * sectors;
2907 if (starts[array[0]])
2908 printf(_("Unused gap - sectors 0-%d\n"),starts[array[0]]);
2909 for (i = 0; i < 7 && array[i+1] != -1; i++) {
2910 printf(_("Unused gap - sectors %d-%d\n"),starts[array[i]]+lens[array[i]],starts[array[i+1]]);
2912 start = starts[array[i]]+lens[array[i]];
2914 printf(_("Unused gap - sectors %d-%d\n"),start,stop);
2918 add_sun_partition(int n, int sys) {
2919 uint start, stop, stop2;
2920 uint starts[8], lens[8];
2926 if (sunlabel->partitions[n].num_sectors && sunlabel->infos[n].id) {
2927 printf(_("Partition %d is already defined. Delete "
2928 "it before re-adding it.\n"), n + 1);
2932 fetch_sun(starts,lens,&start,&stop);
2933 if (stop <= start) {
2937 printf(_("Other partitions already cover the whole disk.\nDelete "
2938 "some/shrink them before retry.\n"));
2942 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
2945 first = read_int(0, 0, 0, 0, mesg);
2947 first = read_int(scround(start), scround(stop)+1,
2948 scround(stop), 0, mesg);
2949 if (display_in_cyl_units)
2950 first *= units_per_sector;
2952 /* Starting sector has to be properly aligned */
2953 first = (first + heads * sectors - 1) / (heads * sectors);
2954 if (n == 2 && first != 0)
2956 It is highly recommended that the third partition covers the whole disk\n\
2957 and is of type `Whole disk'\n");
2958 /* ewt asks to add: "don't start a partition at cyl 0"
2959 However, edmundo@rano.demon.co.uk writes:
2960 "In addition to having a Sun partition table, to be able to
2961 boot from the disc, the first partition, /dev/sdX1, must
2962 start at cylinder 0. This means that /dev/sdX1 contains
2963 the partition table and the boot block, as these are the
2964 first two sectors of the disc. Therefore you must be
2965 careful what you use /dev/sdX1 for. In particular, you must
2966 not use a partition starting at cylinder 0 for Linux swap,
2967 as that would overwrite the partition table and the boot
2968 block. You may, however, use such a partition for a UFS
2969 or EXT2 file system, as these file systems leave the first
2970 1024 bytes undisturbed. */
2971 /* On the other hand, one should not use partitions
2972 starting at block 0 in an md, or the label will
2974 for (i = 0; i < partitions; i++)
2975 if (lens[i] && starts[i] <= first
2976 && starts[i] + lens[i] > first)
2978 if (i < partitions && !whole_disk) {
2979 if (n == 2 && !first) {
2983 printf(_("Sector %d is already allocated\n"), first);
2987 stop = cylinders * heads * sectors;
2989 for (i = 0; i < partitions; i++) {
2990 if (starts[i] > first && starts[i] < stop)
2993 snprintf(mesg, sizeof(mesg),
2994 _("Last %s or +size or +sizeM or +sizeK"),
2995 str_units(SINGULAR));
2997 last = read_int(scround(stop2), scround(stop2), scround(stop2),
2999 else if (n == 2 && !first)
3000 last = read_int(scround(first), scround(stop2), scround(stop2),
3001 scround(first), mesg);
3003 last = read_int(scround(first), scround(stop), scround(stop),
3004 scround(first), mesg);
3005 if (display_in_cyl_units)
3006 last *= units_per_sector;
3007 if (n == 2 && !first) {
3008 if (last >= stop2) {
3011 } else if (last > stop) {
3013 _("You haven't covered the whole disk with the 3rd partition, but your value\n"
3014 "%d %s covers some other partition. Your entry has been changed\n"
3016 scround(last), str_units(SINGULAR),
3017 scround(stop), str_units(SINGULAR));
3020 } else if (!whole_disk && last > stop)
3023 if (whole_disk) sys = WHOLE_DISK;
3024 set_sun_partition(n, first, last, sys);
3028 sun_delete_partition(int i) {
3031 if (i == 2 && sunlabel->infos[i].id == WHOLE_DISK &&
3032 !sunlabel->partitions[i].start_cylinder &&
3033 (nsec = SUN_SSWAP32(sunlabel->partitions[i].num_sectors))
3034 == heads * sectors * cylinders)
3035 printf(_("If you want to maintain SunOS/Solaris compatibility, "
3036 "consider leaving this\n"
3037 "partition as Whole disk (5), starting at 0, with %u "
3038 "sectors\n"), nsec);
3039 sunlabel->infos[i].id = 0;
3040 sunlabel->partitions[i].num_sectors = 0;
3044 sun_change_sysid(int i, int sys) {
3045 if (sys == LINUX_SWAP && !sunlabel->partitions[i].start_cylinder) {
3047 _("It is highly recommended that the partition at offset 0\n"
3048 "is UFS, EXT2FS filesystem or SunOS swap. Putting Linux swap\n"
3049 "there may destroy your partition table and bootblock.\n"
3050 "Type YES if you're very sure you would like that partition\n"
3051 "tagged with 82 (Linux swap): "));
3052 if (strcmp (line_ptr, _("YES\n")))
3058 /* swaps are not mountable by default */
3059 sunlabel->infos[i].flags |= 0x01;
3062 /* assume other types are mountable;
3063 user can change it anyway */
3064 sunlabel->infos[i].flags &= ~0x01;
3067 sunlabel->infos[i].id = sys;
3071 sun_list_table(int xtra) {
3074 w = strlen(disk_device);
3077 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d rpm\n"
3078 "%d cylinders, %d alternate cylinders, %d physical cylinders\n"
3079 "%d extra sects/cyl, interleave %d:1\n"
3081 "Units = %s of %d * 512 bytes\n\n"),
3082 disk_device, heads, sectors, SUN_SSWAP16(sunlabel->rspeed),
3083 cylinders, SUN_SSWAP16(sunlabel->nacyl),
3084 SUN_SSWAP16(sunlabel->pcylcount),
3085 SUN_SSWAP16(sunlabel->sparecyl),
3086 SUN_SSWAP16(sunlabel->ilfact),
3088 str_units(PLURAL), units_per_sector);
3091 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d cylinders\n"
3092 "Units = %s of %d * 512 bytes\n\n"),
3093 disk_device, heads, sectors, cylinders,
3094 str_units(PLURAL), units_per_sector);
3096 printf(_("%*s Flag Start End Blocks Id System\n"),
3097 w + 1, _("Device"));
3098 for (i = 0 ; i < partitions; i++) {
3099 if (sunlabel->partitions[i].num_sectors) {
3100 uint32_t start = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
3101 uint32_t len = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
3103 "%s %c%c %9ld %9ld %9ld%c %2x %s\n",
3104 /* device */ partname(disk_device, i+1, w),
3105 /* flags */ (sunlabel->infos[i].flags & 0x01) ? 'u' : ' ',
3106 (sunlabel->infos[i].flags & 0x10) ? 'r' : ' ',
3107 /* start */ (long) scround(start),
3108 /* end */ (long) scround(start+len),
3109 /* odd flag on end */ (long) len / 2, len & 1 ? '+' : ' ',
3110 /* type id */ sunlabel->infos[i].id,
3111 /* type name */ partition_type(sunlabel->infos[i].id));
3116 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3119 sun_set_alt_cyl(void) {
3121 SUN_SSWAP16(read_int(0,SUN_SSWAP16(sunlabel->nacyl), 65535, 0,
3122 _("Number of alternate cylinders")));
3126 sun_set_ncyl(int cyl) {
3127 sunlabel->ncyl = SUN_SSWAP16(cyl);
3131 sun_set_xcyl(void) {
3132 sunlabel->sparecyl =
3133 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->sparecyl), sectors, 0,
3134 _("Extra sectors per cylinder")));
3138 sun_set_ilfact(void) {
3140 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->ilfact), 32, 0,
3141 _("Interleave factor")));
3145 sun_set_rspeed(void) {
3147 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->rspeed), 100000, 0,
3148 _("Rotation speed (rpm)")));
3152 sun_set_pcylcount(void) {
3153 sunlabel->pcylcount =
3154 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->pcylcount), 65535, 0,
3155 _("Number of physical cylinders")));
3157 #endif /* CONFIG_FEATURE_FDISK_ADVANCED */
3160 sun_write_table(void) {
3161 unsigned short *ush = (unsigned short *)sunlabel;
3162 unsigned short csum = 0;
3164 while(ush < (unsigned short *)(&sunlabel->csum))
3166 sunlabel->csum = csum;
3167 if (lseek(fd, 0, SEEK_SET) < 0)
3168 fdisk_fatal(unable_to_seek);
3169 if (write(fd, sunlabel, SECTOR_SIZE) != SECTOR_SIZE)
3170 fdisk_fatal(unable_to_write);
3172 #endif /* SUN_LABEL */
3174 /* DOS partition types */
3176 static const struct systypes i386_sys_types[] = {
3179 {"\x04" "FAT16 <32M"},
3180 {"\x05" "Extended"}, /* DOS 3.3+ extended partition */
3181 {"\x06" "FAT16"}, /* DOS 16-bit >=32M */
3182 {"\x07" "HPFS/NTFS"}, /* OS/2 IFS, eg, HPFS or NTFS or QNX */
3183 {"\x0a" "OS/2 Boot Manager"},/* OS/2 Boot Manager */
3184 {"\x0b" "Win95 FAT32"},
3185 {"\x0c" "Win95 FAT32 (LBA)"},/* LBA really is `Extended Int 13h' */
3186 {"\x0e" "Win95 FAT16 (LBA)"},
3187 {"\x0f" "Win95 Ext'd (LBA)"},
3188 {"\x11" "Hidden FAT12"},
3189 {"\x12" "Compaq diagnostics"},
3190 {"\x14" "Hidden FAT16 <32M"},
3191 {"\x16" "Hidden FAT16"},
3192 {"\x17" "Hidden HPFS/NTFS"},
3193 {"\x1b" "Hidden Win95 FAT32"},
3194 {"\x1c" "Hidden Win95 FAT32 (LBA)"},
3195 {"\x1e" "Hidden Win95 FAT16 (LBA)"},
3196 {"\x3c" "PartitionMagic recovery"},
3197 {"\x41" "PPC PReP Boot"},
3199 {"\x63" "GNU HURD or SysV"}, /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */
3200 {"\x80" "Old Minix"}, /* Minix 1.4a and earlier */
3201 {"\x81" "Minix / old Linux"},/* Minix 1.4b and later */
3202 {"\x82" "Linux swap"}, /* also Solaris */
3204 {"\x84" "OS/2 hidden C: drive"},
3205 {"\x85" "Linux extended"},
3206 {"\x86" "NTFS volume set"},
3207 {"\x87" "NTFS volume set"},
3208 {"\x8e" "Linux LVM"},
3209 {"\x9f" "BSD/OS"}, /* BSDI */
3210 {"\xa0" "IBM Thinkpad hibernation"},
3211 {"\xa5" "FreeBSD"}, /* various BSD flavours */
3213 {"\xa8" "Darwin UFS"},
3215 {"\xab" "Darwin boot"},
3217 {"\xb8" "BSDI swap"},
3218 {"\xbe" "Solaris boot"},
3220 {"\xee" "EFI GPT"}, /* Intel EFI GUID Partition Table */
3221 {"\xef" "EFI (FAT-12/16/32)"},/* Intel EFI System Partition */
3222 {"\xf0" "Linux/PA-RISC boot"},/* Linux/PA-RISC boot loader */
3223 {"\xf2" "DOS secondary"}, /* DOS 3.3+ secondary */
3224 {"\xfd" "Linux raid autodetect"},/* New (2.2.x) raid partition with
3225 autodetect using persistent
3227 #ifdef CONFIG_WEIRD_PARTITION_TYPES
3228 {"\x02" "XENIX root"},
3229 {"\x03" "XENIX usr"},
3230 {"\x08" "AIX"}, /* AIX boot (AIX -- PS/2 port) or SplitDrive */
3231 {"\x09" "AIX bootable"}, /* AIX data or Coherent */
3233 {"\x18" "AST SmartSleep"},
3236 {"\x40" "Venix 80286"},
3238 {"\x4e" "QNX4.x 2nd part"},
3239 {"\x4f" "QNX4.x 3rd part"},
3240 {"\x50" "OnTrack DM"},
3241 {"\x51" "OnTrack DM6 Aux1"}, /* (or Novell) */
3242 {"\x52" "CP/M"}, /* CP/M or Microport SysV/AT */
3243 {"\x53" "OnTrack DM6 Aux3"},
3244 {"\x54" "OnTrackDM6"},
3245 {"\x55" "EZ-Drive"},
3246 {"\x56" "Golden Bow"},
3247 {"\x5c" "Priam Edisk"},
3248 {"\x61" "SpeedStor"},
3249 {"\x64" "Novell Netware 286"},
3250 {"\x65" "Novell Netware 386"},
3251 {"\x70" "DiskSecure Multi-Boot"},
3254 {"\x94" "Amoeba BBT"}, /* (bad block table) */
3255 {"\xa7" "NeXTSTEP"},
3256 {"\xbb" "Boot Wizard hidden"},
3257 {"\xc1" "DRDOS/sec (FAT-12)"},
3258 {"\xc4" "DRDOS/sec (FAT-16 < 32M)"},
3259 {"\xc6" "DRDOS/sec (FAT-16)"},
3261 {"\xda" "Non-FS data"},
3262 {"\xdb" "CP/M / CTOS / ..."},/* CP/M or Concurrent CP/M or
3263 Concurrent DOS or CTOS */
3264 {"\xde" "Dell Utility"}, /* Dell PowerEdge Server utilities */
3265 {"\xdf" "BootIt"}, /* BootIt EMBRM */
3266 {"\xe1" "DOS access"}, /* DOS access or SpeedStor 12-bit FAT
3267 extended partition */
3268 {"\xe3" "DOS R/O"}, /* DOS R/O or SpeedStor */
3269 {"\xe4" "SpeedStor"}, /* SpeedStor 16-bit FAT extended
3270 partition < 1024 cyl. */
3271 {"\xf1" "SpeedStor"},
3272 {"\xf4" "SpeedStor"}, /* SpeedStor large partition */
3273 {"\xfe" "LANstep"}, /* SpeedStor >1024 cyl. or LANstep */
3274 {"\xff" "BBT"}, /* Xenix Bad Block Table */
3281 /* A valid partition table sector ends in 0x55 0xaa */
3283 part_table_flag(const char *b) {
3284 return ((uint) b[510]) + (((uint) b[511]) << 8);
3288 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3290 write_part_table_flag(char *b) {
3295 /* start_sect and nr_sects are stored little endian on all machines */
3296 /* moreover, they are not aligned correctly */
3298 store4_little_endian(unsigned char *cp, unsigned int val) {
3299 cp[0] = (val & 0xff);
3300 cp[1] = ((val >> 8) & 0xff);
3301 cp[2] = ((val >> 16) & 0xff);
3302 cp[3] = ((val >> 24) & 0xff);
3304 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3307 read4_little_endian(const unsigned char *cp) {
3308 return (uint)(cp[0]) + ((uint)(cp[1]) << 8)
3309 + ((uint)(cp[2]) << 16) + ((uint)(cp[3]) << 24);
3312 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3314 set_start_sect(struct partition *p, unsigned int start_sect) {
3315 store4_little_endian(p->start4, start_sect);
3320 get_start_sect(const struct partition *p) {
3321 return read4_little_endian(p->start4);
3324 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3326 set_nr_sects(struct partition *p, unsigned int nr_sects) {
3327 store4_little_endian(p->size4, nr_sects);
3332 get_nr_sects(const struct partition *p) {
3333 return read4_little_endian(p->size4);
3336 /* normally O_RDWR, -l option gives O_RDONLY */
3337 static int type_open = O_RDWR;
3340 static int ext_index, /* the prime extended partition */
3341 listing, /* no aborts for fdisk -l */
3342 dos_compatible_flag = ~0;
3343 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3344 static int dos_changed;
3345 static int nowarn; /* no warnings for fdisk -l/-s */
3350 static uint user_cylinders, user_heads, user_sectors;
3351 static uint pt_heads, pt_sectors;
3352 static uint kern_heads, kern_sectors;
3354 static uint extended_offset; /* offset of link pointers */
3356 static unsigned long long total_number_of_sectors;
3359 static jmp_buf listingbuf;
3361 static void fdisk_fatal(enum failure why) {
3362 const char *message;
3366 longjmp(listingbuf, 1);
3370 case unable_to_open:
3371 message = "Unable to open %s\n";
3373 case unable_to_read:
3374 message = "Unable to read %s\n";
3376 case unable_to_seek:
3377 message = "Unable to seek on %s\n";
3379 case unable_to_write:
3380 message = "Unable to write %s\n";
3383 message = "BLKGETSIZE ioctl failed on %s\n";
3386 message = "Fatal error\n";
3389 fputc('\n', stderr);
3390 fprintf(stderr, message, disk_device);
3395 seek_sector(uint secno) {
3396 off_t offset = secno * sector_size;
3397 if (lseek(fd, offset, SEEK_SET) == (off_t) -1)
3398 fdisk_fatal(unable_to_seek);
3401 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3403 write_sector(uint secno, char *buf) {
3405 if (write(fd, buf, sector_size) != sector_size)
3406 fdisk_fatal(unable_to_write);
3410 /* Allocate a buffer and read a partition table sector */
3412 read_pte(struct pte *pe, uint offset) {
3414 pe->offset = offset;
3415 pe->sectorbuffer = (char *) xmalloc(sector_size);
3416 seek_sector(offset);
3417 if (read(fd, pe->sectorbuffer, sector_size) != sector_size)
3418 fdisk_fatal(unable_to_read);
3419 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3422 pe->part_table = pe->ext_pointer = NULL;
3426 get_partition_start(const struct pte *pe) {
3427 return pe->offset + get_start_sect(pe->part_table);
3430 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3432 * Avoid warning about DOS partitions when no DOS partition was changed.
3433 * Here a heuristic "is probably dos partition".
3434 * We might also do the opposite and warn in all cases except
3435 * for "is probably nondos partition".
3438 is_dos_partition(int t) {
3439 return (t == 1 || t == 4 || t == 6 ||
3440 t == 0x0b || t == 0x0c || t == 0x0e ||
3441 t == 0x11 || t == 0x12 || t == 0x14 || t == 0x16 ||
3442 t == 0x1b || t == 0x1c || t == 0x1e || t == 0x24 ||
3443 t == 0xc1 || t == 0xc4 || t == 0xc6);
3448 #ifdef CONFIG_FEATURE_SUN_LABEL
3450 puts(_("Command action"));
3451 puts(_("\ta\ttoggle a read only flag")); /* sun */
3452 puts(_("\tb\tedit bsd disklabel"));
3453 puts(_("\tc\ttoggle the mountable flag")); /* sun */
3454 puts(_("\td\tdelete a partition"));
3455 puts(_("\tl\tlist known partition types"));
3456 puts(_("\tm\tprint this menu"));
3457 puts(_("\tn\tadd a new partition"));
3458 puts(_("\to\tcreate a new empty DOS partition table"));
3459 puts(_("\tp\tprint the partition table"));
3460 puts(_("\tq\tquit without saving changes"));
3461 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3462 puts(_("\tt\tchange a partition's system id"));
3463 puts(_("\tu\tchange display/entry units"));
3464 puts(_("\tv\tverify the partition table"));
3465 puts(_("\tw\twrite table to disk and exit"));
3466 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3467 puts(_("\tx\textra functionality (experts only)"));
3471 #ifdef CONFIG_FEATURE_SGI_LABEL
3473 puts(_("Command action"));
3474 puts(_("\ta\tselect bootable partition")); /* sgi flavour */
3475 puts(_("\tb\tedit bootfile entry")); /* sgi */
3476 puts(_("\tc\tselect sgi swap partition")); /* sgi flavour */
3477 puts(_("\td\tdelete a partition"));
3478 puts(_("\tl\tlist known partition types"));
3479 puts(_("\tm\tprint this menu"));
3480 puts(_("\tn\tadd a new partition"));
3481 puts(_("\to\tcreate a new empty DOS partition table"));
3482 puts(_("\tp\tprint the partition table"));
3483 puts(_("\tq\tquit without saving changes"));
3484 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3485 puts(_("\tt\tchange a partition's system id"));
3486 puts(_("\tu\tchange display/entry units"));
3487 puts(_("\tv\tverify the partition table"));
3488 puts(_("\tw\twrite table to disk and exit"));
3491 #ifdef CONFIG_FEATURE_AIX_LABEL
3493 puts(_("Command action"));
3494 puts(_("\tm\tprint this menu"));
3495 puts(_("\to\tcreate a new empty DOS partition table"));
3496 puts(_("\tq\tquit without saving changes"));
3497 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3501 puts(_("Command action"));
3502 puts(_("\ta\ttoggle a bootable flag"));
3503 puts(_("\tb\tedit bsd disklabel"));
3504 puts(_("\tc\ttoggle the dos compatibility flag"));
3505 puts(_("\td\tdelete a partition"));
3506 puts(_("\tl\tlist known partition types"));
3507 puts(_("\tm\tprint this menu"));
3508 puts(_("\tn\tadd a new partition"));
3509 puts(_("\to\tcreate a new empty DOS partition table"));
3510 puts(_("\tp\tprint the partition table"));
3511 puts(_("\tq\tquit without saving changes"));
3512 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3513 puts(_("\tt\tchange a partition's system id"));
3514 puts(_("\tu\tchange display/entry units"));
3515 puts(_("\tv\tverify the partition table"));
3516 puts(_("\tw\twrite table to disk and exit"));
3517 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3518 puts(_("\tx\textra functionality (experts only)"));
3522 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3525 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3528 #ifdef CONFIG_FEATURE_SUN_LABEL
3530 puts(_("Command action"));
3531 puts(_("\ta\tchange number of alternate cylinders")); /*sun*/
3532 puts(_("\tc\tchange number of cylinders"));
3533 puts(_("\td\tprint the raw data in the partition table"));
3534 puts(_("\te\tchange number of extra sectors per cylinder"));/*sun*/
3535 puts(_("\th\tchange number of heads"));
3536 puts(_("\ti\tchange interleave factor")); /*sun*/
3537 puts(_("\to\tchange rotation speed (rpm)")); /*sun*/
3538 puts(_("\tm\tprint this menu"));
3539 puts(_("\tp\tprint the partition table"));
3540 puts(_("\tq\tquit without saving changes"));
3541 puts(_("\tr\treturn to main menu"));
3542 puts(_("\ts\tchange number of sectors/track"));
3543 puts(_("\tv\tverify the partition table"));
3544 puts(_("\tw\twrite table to disk and exit"));
3545 puts(_("\ty\tchange number of physical cylinders")); /*sun*/
3548 #ifdef CONFIG_FEATURE_SGI_LABEL
3550 puts(_("Command action"));
3551 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3552 puts(_("\tc\tchange number of cylinders"));
3553 puts(_("\td\tprint the raw data in the partition table"));
3554 puts(_("\te\tlist extended partitions")); /* !sun */
3555 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3556 puts(_("\th\tchange number of heads"));
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"));
3566 #ifdef CONFIG_FEATURE_AIX_LABEL
3568 puts(_("Command action"));
3569 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3570 puts(_("\tc\tchange number of cylinders"));
3571 puts(_("\td\tprint the raw data in the partition table"));
3572 puts(_("\te\tlist extended partitions")); /* !sun */
3573 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3574 puts(_("\th\tchange number of heads"));
3575 puts(_("\tm\tprint this menu"));
3576 puts(_("\tp\tprint the partition table"));
3577 puts(_("\tq\tquit without saving changes"));
3578 puts(_("\tr\treturn to main menu"));
3579 puts(_("\ts\tchange number of sectors/track"));
3580 puts(_("\tv\tverify the partition table"));
3581 puts(_("\tw\twrite table to disk and exit"));
3585 puts(_("Command action"));
3586 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3587 puts(_("\tc\tchange number of cylinders"));
3588 puts(_("\td\tprint the raw data in the partition table"));
3589 puts(_("\te\tlist extended partitions")); /* !sun */
3590 puts(_("\tf\tfix partition order")); /* !sun, !aix, !sgi */
3591 #ifdef CONFIG_FEATURE_SGI_LABEL
3592 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3594 puts(_("\th\tchange number of heads"));
3595 puts(_("\tm\tprint this menu"));
3596 puts(_("\tp\tprint the partition table"));
3597 puts(_("\tq\tquit without saving changes"));
3598 puts(_("\tr\treturn to main menu"));
3599 puts(_("\ts\tchange number of sectors/track"));
3600 puts(_("\tv\tverify the partition table"));
3601 puts(_("\tw\twrite table to disk and exit"));
3604 #endif /* ADVANCED mode */
3606 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3607 static const struct systypes *
3608 get_sys_types(void) {
3610 #ifdef CONFIG_FEATURE_SUN_LABEL
3611 sun_label ? sun_sys_types :
3613 #ifdef CONFIG_FEATURE_SGI_LABEL
3614 sgi_label ? sgi_sys_types :
3619 #define get_sys_types() i386_sys_types
3620 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3622 static const char *partition_type(unsigned char type)
3625 const struct systypes *types = get_sys_types();
3627 for (i=0; types[i].name; i++)
3628 if (types[i].name[0] == type)
3629 return types[i].name + 1;
3631 return _("Unknown");
3635 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3639 #ifdef CONFIG_FEATURE_SUN_LABEL
3640 sun_label ? sunlabel->infos[i].id :
3642 #ifdef CONFIG_FEATURE_SGI_LABEL
3643 sgi_label ? sgi_get_sysid(i) :
3645 ptes[i].part_table->sys_ind);
3648 void list_types(const struct systypes *sys)
3650 uint last[4], done = 0, next = 0, size;
3653 for (i = 0; sys[i].name; i++);
3656 for (i = 3; i >= 0; i--)
3657 last[3 - i] = done += (size + i - done) / (i + 1);
3661 printf("%c%2x %-15.15s", i ? ' ' : '\n',
3662 sys[next].name[0], partition_type(sys[next].name[0]));
3663 next = last[i++] + done;
3664 if (i > 3 || next >= last[i]) {
3668 } while (done < last[0]);
3671 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3674 is_cleared_partition(const struct partition *p) {
3675 return !(!p || p->boot_ind || p->head || p->sector || p->cyl ||
3676 p->sys_ind || p->end_head || p->end_sector || p->end_cyl ||
3677 get_start_sect(p) || get_nr_sects(p));
3681 clear_partition(struct partition *p) {
3684 memset(p, 0, sizeof(struct partition));
3687 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3689 set_partition(int i, int doext, uint start, uint stop, int sysid) {
3690 struct partition *p;
3694 p = ptes[i].ext_pointer;
3695 offset = extended_offset;
3697 p = ptes[i].part_table;
3698 offset = ptes[i].offset;
3702 set_start_sect(p, start - offset);
3703 set_nr_sects(p, stop - start + 1);
3704 if (dos_compatible_flag && (start/(sectors*heads) > 1023))
3705 start = heads*sectors*1024 - 1;
3706 set_hsc(p->head, p->sector, p->cyl, start);
3707 if (dos_compatible_flag && (stop/(sectors*heads) > 1023))
3708 stop = heads*sectors*1024 - 1;
3709 set_hsc(p->end_head, p->end_sector, p->end_cyl, stop);
3710 ptes[i].changed = 1;
3715 test_c(const char **m, const char *mesg) {
3718 fprintf(stderr, _("You must set"));
3720 fprintf(stderr, " %s", *m);
3728 warn_geometry(void) {
3729 const char *m = NULL;
3733 prev = test_c(&m, _("heads"));
3735 prev = test_c(&m, _("sectors"));
3737 prev = test_c(&m, _("cylinders"));
3741 fprintf(stderr, "%s%s.\n"
3742 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3743 "You can do this from the extra functions menu.\n"
3745 , prev ? _(" and ") : " ", m);
3750 static void update_units(void)
3752 int cyl_units = heads * sectors;
3754 if (display_in_cyl_units && cyl_units)
3755 units_per_sector = cyl_units;
3757 units_per_sector = 1; /* in sectors */
3760 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3762 warn_cylinders(void) {
3763 if (dos_label && cylinders > 1024 && !nowarn)
3764 fprintf(stderr, _("\n"
3765 "The number of cylinders for this disk is set to %d.\n"
3766 "There is nothing wrong with that, but this is larger than 1024,\n"
3767 "and could in certain setups cause problems with:\n"
3768 "1) software that runs at boot time (e.g., old versions of LILO)\n"
3769 "2) booting and partitioning software from other OSs\n"
3770 " (e.g., DOS FDISK, OS/2 FDISK)\n"),
3776 read_extended(int ext) {
3779 struct partition *p, *q;
3783 pex->ext_pointer = pex->part_table;
3785 p = pex->part_table;
3786 if (!get_start_sect(p)) {
3788 _("Bad offset in primary extended partition\n"));
3792 while (IS_EXTENDED (p->sys_ind)) {
3793 struct pte *pe = &ptes[partitions];
3795 if (partitions >= MAXIMUM_PARTS) {
3796 /* This is not a Linux restriction, but
3797 this program uses arrays of size MAXIMUM_PARTS.
3798 Do not try to `improve' this test. */
3799 struct pte *pre = &ptes[partitions-1];
3800 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3802 _("Warning: deleting partitions after %d\n"),
3806 clear_partition(pre->ext_pointer);
3810 read_pte(pe, extended_offset + get_start_sect(p));
3812 if (!extended_offset)
3813 extended_offset = get_start_sect(p);
3815 q = p = pt_offset(pe->sectorbuffer, 0);
3816 for (i = 0; i < 4; i++, p++) if (get_nr_sects(p)) {
3817 if (IS_EXTENDED (p->sys_ind)) {
3818 if (pe->ext_pointer)
3820 _("Warning: extra link "
3821 "pointer in partition table"
3822 " %d\n"), partitions + 1);
3824 pe->ext_pointer = p;
3825 } else if (p->sys_ind) {
3828 _("Warning: ignoring extra "
3829 "data in partition table"
3830 " %d\n"), partitions + 1);
3836 /* very strange code here... */
3837 if (!pe->part_table) {
3838 if (q != pe->ext_pointer)
3841 pe->part_table = q + 1;
3843 if (!pe->ext_pointer) {
3844 if (q != pe->part_table)
3845 pe->ext_pointer = q;
3847 pe->ext_pointer = q + 1;
3850 p = pe->ext_pointer;
3854 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3855 /* remove empty links */
3857 for (i = 4; i < partitions; i++) {
3858 struct pte *pe = &ptes[i];
3860 if (!get_nr_sects(pe->part_table) &&
3861 (partitions > 5 || ptes[4].part_table->sys_ind)) {
3862 printf("omitting empty partition (%d)\n", i+1);
3863 delete_partition(i);
3864 goto remove; /* numbering changed */
3870 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3872 create_doslabel(void) {
3876 _("Building a new DOS disklabel. Changes will remain in memory only,\n"
3877 "until you decide to write them. After that, of course, the previous\n"
3878 "content won't be recoverable.\n\n"));
3879 #ifdef CONFIG_FEATURE_SUN_LABEL
3880 sun_nolabel(); /* otherwise always recognised as sun */
3882 #ifdef CONFIG_FEATURE_SGI_LABEL
3883 sgi_nolabel(); /* otherwise always recognised as sgi */
3885 #ifdef CONFIG_FEATURE_AIX_LABEL
3888 #ifdef CONFIG_FEATURE_OSF_LABEL
3890 possibly_osf_label = 0;
3894 for (i = 510-64; i < 510; i++)
3896 write_part_table_flag(MBRbuffer);
3897 extended_offset = 0;
3898 set_all_unchanged();
3900 get_boot(create_empty_dos);
3902 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3905 get_sectorsize(void) {
3906 if (!user_set_sector_size &&
3907 get_kernel_revision() >= MAKE_VERSION(2,3,3)) {
3909 if (ioctl(fd, BLKSSZGET, &arg) == 0)
3911 if (sector_size != DEFAULT_SECTOR_SIZE)
3912 printf(_("Note: sector size is %d (not %d)\n"),
3913 sector_size, DEFAULT_SECTOR_SIZE);
3918 get_kernel_geometry(void) {
3919 struct hd_geometry geometry;
3921 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
3922 kern_heads = geometry.heads;
3923 kern_sectors = geometry.sectors;
3924 /* never use geometry.cylinders - it is truncated */
3929 get_partition_table_geometry(void) {
3930 const unsigned char *bufp = MBRbuffer;
3931 struct partition *p;
3932 int i, h, s, hh, ss;
3936 if (!(valid_part_table_flag(bufp)))
3940 for (i=0; i<4; i++) {
3941 p = pt_offset(bufp, i);
3942 if (p->sys_ind != 0) {
3943 h = p->end_head + 1;
3944 s = (p->end_sector & 077);
3949 } else if (hh != h || ss != s)
3954 if (!first && !bad) {
3961 get_geometry(void) {
3963 unsigned long long bytes; /* really u64 */
3966 sec_fac = sector_size / 512;
3967 #ifdef CONFIG_FEATURE_SUN_LABEL
3968 guess_device_type();
3970 heads = cylinders = sectors = 0;
3971 kern_heads = kern_sectors = 0;
3972 pt_heads = pt_sectors = 0;
3974 get_kernel_geometry();
3975 get_partition_table_geometry();
3977 heads = user_heads ? user_heads :
3978 pt_heads ? pt_heads :
3979 kern_heads ? kern_heads : 255;
3980 sectors = user_sectors ? user_sectors :
3981 pt_sectors ? pt_sectors :
3982 kern_sectors ? kern_sectors : 63;
3983 if (ioctl(fd, BLKGETSIZE64, &bytes) == 0) {
3986 unsigned long longsectors;
3988 if (ioctl(fd, BLKGETSIZE, &longsectors))
3990 bytes = ((unsigned long long) longsectors) << 9;
3993 total_number_of_sectors = (bytes >> 9);
3996 if (dos_compatible_flag)
3997 sector_offset = sectors;
3999 cylinders = total_number_of_sectors / (heads * sectors * sec_fac);
4001 cylinders = user_cylinders;
4005 * Read MBR. Returns:
4006 * -1: no 0xaa55 flag present (possibly entire disk BSD)
4007 * 0: found or created label
4011 get_boot(enum action what) {
4016 for (i = 0; i < 4; i++) {
4017 struct pte *pe = &ptes[i];
4019 pe->part_table = pt_offset(MBRbuffer, i);
4020 pe->ext_pointer = NULL;
4022 pe->sectorbuffer = MBRbuffer;
4023 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4024 pe->changed = (what == create_empty_dos);
4028 #ifdef CONFIG_FEATURE_SUN_LABEL
4029 if (what == create_empty_sun && check_sun_label())
4033 memset(MBRbuffer, 0, 512);
4035 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4036 if (what == create_empty_dos)
4037 goto got_dos_table; /* skip reading disk */
4039 if ((fd = open(disk_device, type_open)) < 0) {
4040 if ((fd = open(disk_device, O_RDONLY)) < 0) {
4041 if (what == try_only)
4043 fdisk_fatal(unable_to_open);
4045 printf(_("You will not be able to write "
4046 "the partition table.\n"));
4049 if (512 != read(fd, MBRbuffer, 512)) {
4050 if (what == try_only)
4052 fdisk_fatal(unable_to_read);
4055 if ((fd = open(disk_device, O_RDONLY)) < 0)
4057 if (512 != read(fd, MBRbuffer, 512))
4065 #ifdef CONFIG_FEATURE_SUN_LABEL
4066 if (check_sun_label())
4070 #ifdef CONFIG_FEATURE_SGI_LABEL
4071 if (check_sgi_label())
4075 #ifdef CONFIG_FEATURE_AIX_LABEL
4076 if (check_aix_label())
4080 #ifdef CONFIG_FEATURE_OSF_LABEL
4081 if (check_osf_label()) {
4082 possibly_osf_label = 1;
4083 if (!valid_part_table_flag(MBRbuffer)) {
4087 printf(_("This disk has both DOS and BSD magic.\n"
4088 "Give the 'b' command to go to BSD mode.\n"));
4092 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4096 if (!valid_part_table_flag(MBRbuffer)) {
4097 #ifndef CONFIG_FEATURE_FDISK_WRITABLE
4103 _("Device contains neither a valid DOS "
4104 "partition table, nor Sun, SGI or OSF "
4107 #ifdef CONFIG_FEATURE_SUN_LABEL
4116 case create_empty_dos:
4117 #ifdef CONFIG_FEATURE_SUN_LABEL
4118 case create_empty_sun:
4122 fprintf(stderr, _("Internal error\n"));
4125 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
4128 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4133 for (i = 0; i < 4; i++) {
4134 struct pte *pe = &ptes[i];
4136 if (IS_EXTENDED (pe->part_table->sys_ind)) {
4137 if (partitions != 4)
4138 fprintf(stderr, _("Ignoring extra extended "
4139 "partition %d\n"), i + 1);
4145 for (i = 3; i < partitions; i++) {
4146 struct pte *pe = &ptes[i];
4148 if (!valid_part_table_flag(pe->sectorbuffer)) {
4150 _("Warning: invalid flag 0x%04x of partition "
4151 "table %d will be corrected by w(rite)\n"),
4152 part_table_flag(pe->sectorbuffer), i + 1);
4153 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4162 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4164 * Print the message MESG, then read an integer between LOW and HIGH (inclusive).
4165 * If the user hits Enter, DFLT is returned.
4166 * Answers like +10 are interpreted as offsets from BASE.
4168 * There is no default if DFLT is not between LOW and HIGH.
4171 read_int(uint low, uint dflt, uint high, uint base, char *mesg)
4175 static char *ms = NULL;
4176 static int mslen = 0;
4178 if (!ms || strlen(mesg)+100 > mslen) {
4179 mslen = strlen(mesg)+200;
4180 ms = xrealloc(ms,mslen);
4183 if (dflt < low || dflt > high)
4187 snprintf(ms, mslen, _("%s (%u-%u, default %u): "),
4188 mesg, low, high, dflt);
4190 snprintf(ms, mslen, "%s (%u-%u): ",
4194 int use_default = default_ok;
4196 /* ask question and read answer */
4197 while (read_chars(ms) != '\n' && !isdigit(*line_ptr)
4198 && *line_ptr != '-' && *line_ptr != '+')
4201 if (*line_ptr == '+' || *line_ptr == '-') {
4202 int minus = (*line_ptr == '-');
4205 i = atoi(line_ptr+1);
4207 while (isdigit(*++line_ptr))
4210 switch (*line_ptr) {
4213 if (!display_in_cyl_units)
4214 i *= heads * sectors;
4228 absolute = 1000000000;
4234 unsigned long long bytes;
4237 bytes = (unsigned long long) i * absolute;
4238 unit = sector_size * units_per_sector;
4239 bytes += unit/2; /* round */
4248 while (isdigit(*line_ptr)) {
4254 printf(_("Using default value %u\n"), i = dflt);
4255 if (i >= low && i <= high)
4258 printf(_("Value out of range.\n"));
4264 get_partition(int warn, int max) {
4268 i = read_int(1, 0, max, 0, _("Partition number")) - 1;
4272 if ((!sun_label && !sgi_label && !pe->part_table->sys_ind)
4273 #ifdef CONFIG_FEATURE_SUN_LABEL
4275 (!sunlabel->partitions[i].num_sectors ||
4276 !sunlabel->infos[i].id))
4278 #ifdef CONFIG_FEATURE_SGI_LABEL
4279 || (sgi_label && (!sgi_get_num_sectors(i)))
4283 _("Warning: partition %d has empty type\n"),
4290 get_existing_partition(int warn, int max) {
4294 for (i = 0; i < max; i++) {
4295 struct pte *pe = &ptes[i];
4296 struct partition *p = pe->part_table;
4298 if (p && !is_cleared_partition(p)) {
4305 printf(_("Selected partition %d\n"), pno+1);
4308 printf(_("No partition is defined yet!\n"));
4312 return get_partition(warn, max);
4316 get_nonexisting_partition(int warn, int max) {
4320 for (i = 0; i < max; i++) {
4321 struct pte *pe = &ptes[i];
4322 struct partition *p = pe->part_table;
4324 if (p && is_cleared_partition(p)) {
4331 printf(_("Selected partition %d\n"), pno+1);
4334 printf(_("All primary partitions have been defined already!\n"));
4338 return get_partition(warn, max);
4342 void change_units(void)
4344 display_in_cyl_units = !display_in_cyl_units;
4346 printf(_("Changing display/entry units to %s\n"),
4351 toggle_active(int i) {
4352 struct pte *pe = &ptes[i];
4353 struct partition *p = pe->part_table;
4355 if (IS_EXTENDED (p->sys_ind) && !p->boot_ind)
4357 _("WARNING: Partition %d is an extended partition\n"),
4359 p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG);
4364 toggle_dos_compatibility_flag(void) {
4365 dos_compatible_flag = ~dos_compatible_flag;
4366 if (dos_compatible_flag) {
4367 sector_offset = sectors;
4368 printf(_("DOS Compatibility flag is set\n"));
4372 printf(_("DOS Compatibility flag is not set\n"));
4377 delete_partition(int i) {
4378 struct pte *pe = &ptes[i];
4379 struct partition *p = pe->part_table;
4380 struct partition *q = pe->ext_pointer;
4382 /* Note that for the fifth partition (i == 4) we don't actually
4383 * decrement partitions.
4386 if (warn_geometry())
4387 return; /* C/H/S not set */
4390 #ifdef CONFIG_FEATURE_SUN_LABEL
4392 sun_delete_partition(i);
4396 #ifdef CONFIG_FEATURE_SGI_LABEL
4398 sgi_delete_partition(i);
4404 if (IS_EXTENDED (p->sys_ind) && i == ext_index) {
4406 ptes[ext_index].ext_pointer = NULL;
4407 extended_offset = 0;
4413 if (!q->sys_ind && i > 4) {
4414 /* the last one in the chain - just delete */
4417 clear_partition(ptes[i].ext_pointer);
4418 ptes[i].changed = 1;
4420 /* not the last one - further ones will be moved down */
4422 /* delete this link in the chain */
4423 p = ptes[i-1].ext_pointer;
4425 set_start_sect(p, get_start_sect(q));
4426 set_nr_sects(p, get_nr_sects(q));
4427 ptes[i-1].changed = 1;
4428 } else if (partitions > 5) { /* 5 will be moved to 4 */
4429 /* the first logical in a longer chain */
4432 if (pe->part_table) /* prevent SEGFAULT */
4433 set_start_sect(pe->part_table,
4434 get_partition_start(pe) -
4436 pe->offset = extended_offset;
4440 if (partitions > 5) {
4442 while (i < partitions) {
4443 ptes[i] = ptes[i+1];
4447 /* the only logical: clear only */
4448 clear_partition(ptes[i].part_table);
4453 change_sysid(void) {
4454 int i, sys, origsys;
4455 struct partition *p;
4457 #ifdef CONFIG_FEATURE_SGI_LABEL
4458 /* If sgi_label then don't use get_existing_partition,
4459 let the user select a partition, since get_existing_partition()
4460 only works for Linux like partition tables. */
4462 i = get_existing_partition(0, partitions);
4464 i = get_partition(0, partitions);
4467 i = get_existing_partition(0, partitions);
4471 p = ptes[i].part_table;
4472 origsys = sys = get_sysid(i);
4474 /* if changing types T to 0 is allowed, then
4475 the reverse change must be allowed, too */
4476 if (!sys && !sgi_label && !sun_label && !get_nr_sects(p))
4477 printf(_("Partition %d does not exist yet!\n"), i + 1);
4479 sys = read_hex (get_sys_types());
4481 if (!sys && !sgi_label && !sun_label) {
4482 printf(_("Type 0 means free space to many systems\n"
4483 "(but not to Linux). Having partitions of\n"
4484 "type 0 is probably unwise. You can delete\n"
4485 "a partition using the `d' command.\n"));
4489 if (!sun_label && !sgi_label) {
4490 if (IS_EXTENDED (sys) != IS_EXTENDED (p->sys_ind)) {
4491 printf(_("You cannot change a partition into"
4492 " an extended one or vice versa\n"
4493 "Delete it first.\n"));
4499 #ifdef CONFIG_FEATURE_SUN_LABEL
4500 if (sun_label && i == 2 && sys != WHOLE_DISK)
4501 printf(_("Consider leaving partition 3 "
4502 "as Whole disk (5),\n"
4503 "as SunOS/Solaris expects it and "
4504 "even Linux likes it.\n\n"));
4506 #ifdef CONFIG_FEATURE_SGI_LABEL
4507 if (sgi_label && ((i == 10 && sys != ENTIRE_DISK)
4508 || (i == 8 && sys != 0)))
4509 printf(_("Consider leaving partition 9 "
4510 "as volume header (0),\nand "
4511 "partition 11 as entire volume (6)"
4512 "as IRIX expects it.\n\n"));
4516 #ifdef CONFIG_FEATURE_SUN_LABEL
4518 sun_change_sysid(i, sys);
4521 #ifdef CONFIG_FEATURE_SGI_LABEL
4523 sgi_change_sysid(i, sys);
4527 printf (_("Changed system type of partition %d "
4528 "to %x (%s)\n"), i + 1, sys,
4529 partition_type(sys));
4530 ptes[i].changed = 1;
4531 if (is_dos_partition(origsys) ||
4532 is_dos_partition(sys))
4538 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
4541 /* check_consistency() and long2chs() added Sat Mar 6 12:28:16 1993,
4542 * faith@cs.unc.edu, based on code fragments from pfdisk by Gordon W. Ross,
4543 * Jan. 1990 (version 1.2.1 by Gordon W. Ross Aug. 1990; Modified by S.
4544 * Lubkin Oct. 1991). */
4546 static void long2chs(ulong ls, uint *c, uint *h, uint *s) {
4547 int spc = heads * sectors;
4552 *s = ls % sectors + 1; /* sectors count from 1 */
4555 static void check_consistency(const struct partition *p, int partition) {
4556 uint pbc, pbh, pbs; /* physical beginning c, h, s */
4557 uint pec, peh, pes; /* physical ending c, h, s */
4558 uint lbc, lbh, lbs; /* logical beginning c, h, s */
4559 uint lec, leh, les; /* logical ending c, h, s */
4561 if (!heads || !sectors || (partition >= 4))
4562 return; /* do not check extended partitions */
4564 /* physical beginning c, h, s */
4565 pbc = (p->cyl & 0xff) | ((p->sector << 2) & 0x300);
4567 pbs = p->sector & 0x3f;
4569 /* physical ending c, h, s */
4570 pec = (p->end_cyl & 0xff) | ((p->end_sector << 2) & 0x300);
4572 pes = p->end_sector & 0x3f;
4574 /* compute logical beginning (c, h, s) */
4575 long2chs(get_start_sect(p), &lbc, &lbh, &lbs);
4577 /* compute logical ending (c, h, s) */
4578 long2chs(get_start_sect(p) + get_nr_sects(p) - 1, &lec, &leh, &les);
4580 /* Same physical / logical beginning? */
4581 if (cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) {
4582 printf(_("Partition %d has different physical/logical "
4583 "beginnings (non-Linux?):\n"), partition + 1);
4584 printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs);
4585 printf(_("logical=(%d, %d, %d)\n"),lbc, lbh, lbs);
4588 /* Same physical / logical ending? */
4589 if (cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) {
4590 printf(_("Partition %d has different physical/logical "
4591 "endings:\n"), partition + 1);
4592 printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
4593 printf(_("logical=(%d, %d, %d)\n"),lec, leh, les);
4597 /* Beginning on cylinder boundary? */
4598 if (pbh != !pbc || pbs != 1) {
4599 printf(_("Partition %i does not start on cylinder "
4600 "boundary:\n"), partition + 1);
4601 printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs);
4602 printf(_("should be (%d, %d, 1)\n"), pbc, !pbc);
4606 /* Ending on cylinder boundary? */
4607 if (peh != (heads - 1) || pes != sectors) {
4608 printf(_("Partition %i does not end on cylinder boundary.\n"),
4611 printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
4612 printf(_("should be (%d, %d, %d)\n"),
4613 pec, heads - 1, sectors);
4619 list_disk_geometry(void) {
4620 long long bytes = (total_number_of_sectors << 9);
4621 long megabytes = bytes/1000000;
4623 if (megabytes < 10000)
4624 printf(_("\nDisk %s: %ld MB, %lld bytes\n"),
4625 disk_device, megabytes, bytes);
4627 printf(_("\nDisk %s: %ld.%ld GB, %lld bytes\n"),
4628 disk_device, megabytes/1000, (megabytes/100)%10, bytes);
4629 printf(_("%d heads, %d sectors/track, %d cylinders"),
4630 heads, sectors, cylinders);
4631 if (units_per_sector == 1)
4632 printf(_(", total %llu sectors"),
4633 total_number_of_sectors / (sector_size/512));
4634 printf(_("\nUnits = %s of %d * %d = %d bytes\n\n"),
4636 units_per_sector, sector_size, units_per_sector * sector_size);
4640 * Check whether partition entries are ordered by their starting positions.
4641 * Return 0 if OK. Return i if partition i should have been earlier.
4642 * Two separate checks: primary and logical partitions.
4645 wrong_p_order(int *prev) {
4646 const struct pte *pe;
4647 const struct partition *p;
4648 uint last_p_start_pos = 0, p_start_pos;
4651 for (i = 0 ; i < partitions; i++) {
4654 last_p_start_pos = 0;
4657 if ((p = pe->part_table)->sys_ind) {
4658 p_start_pos = get_partition_start(pe);
4660 if (last_p_start_pos > p_start_pos) {
4666 last_p_start_pos = p_start_pos;
4673 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
4675 * Fix the chain of logicals.
4676 * extended_offset is unchanged, the set of sectors used is unchanged
4677 * The chain is sorted so that sectors increase, and so that
4678 * starting sectors increase.
4680 * After this it may still be that cfdisk doesnt like the table.
4681 * (This is because cfdisk considers expanded parts, from link to
4682 * end of partition, and these may still overlap.)
4684 * sfdisk /dev/hda > ohda; sfdisk /dev/hda < ohda
4688 fix_chain_of_logicals(void) {
4689 int j, oj, ojj, sj, sjj;
4690 struct partition *pj,*pjj,tmp;
4692 /* Stage 1: sort sectors but leave sector of part 4 */
4693 /* (Its sector is the global extended_offset.) */
4695 for (j = 5; j < partitions-1; j++) {
4696 oj = ptes[j].offset;
4697 ojj = ptes[j+1].offset;
4699 ptes[j].offset = ojj;
4700 ptes[j+1].offset = oj;
4701 pj = ptes[j].part_table;
4702 set_start_sect(pj, get_start_sect(pj)+oj-ojj);
4703 pjj = ptes[j+1].part_table;
4704 set_start_sect(pjj, get_start_sect(pjj)+ojj-oj);
4705 set_start_sect(ptes[j-1].ext_pointer,
4706 ojj-extended_offset);
4707 set_start_sect(ptes[j].ext_pointer,
4708 oj-extended_offset);
4713 /* Stage 2: sort starting sectors */
4715 for (j = 4; j < partitions-1; j++) {
4716 pj = ptes[j].part_table;
4717 pjj = ptes[j+1].part_table;
4718 sj = get_start_sect(pj);
4719 sjj = get_start_sect(pjj);
4720 oj = ptes[j].offset;
4721 ojj = ptes[j+1].offset;
4722 if (oj+sj > ojj+sjj) {
4726 set_start_sect(pj, ojj+sjj-oj);
4727 set_start_sect(pjj, oj+sj-ojj);
4732 /* Probably something was changed */
4733 for (j = 4; j < partitions; j++)
4734 ptes[j].changed = 1;
4739 fix_partition_table_order(void) {
4740 struct pte *pei, *pek;
4743 if (!wrong_p_order(NULL)) {
4744 printf(_("Nothing to do. Ordering is correct already.\n\n"));
4748 while ((i = wrong_p_order(&k)) != 0 && i < 4) {
4749 /* partition i should have come earlier, move it */
4750 /* We have to move data in the MBR */
4751 struct partition *pi, *pk, *pe, pbuf;
4755 pe = pei->ext_pointer;
4756 pei->ext_pointer = pek->ext_pointer;
4757 pek->ext_pointer = pe;
4759 pi = pei->part_table;
4760 pk = pek->part_table;
4762 memmove(&pbuf, pi, sizeof(struct partition));
4763 memmove(pi, pk, sizeof(struct partition));
4764 memmove(pk, &pbuf, sizeof(struct partition));
4766 pei->changed = pek->changed = 1;
4770 fix_chain_of_logicals();
4778 list_table(int xtra) {
4779 const struct partition *p;
4782 #ifdef CONFIG_FEATURE_SUN_LABEL
4784 sun_list_table(xtra);
4789 #ifdef CONFIG_FEATURE_SGI_LABEL
4791 sgi_list_table(xtra);
4796 list_disk_geometry();
4798 #ifdef CONFIG_FEATURE_OSF_LABEL
4800 xbsd_print_disklabel(xtra);
4805 /* Heuristic: we list partition 3 of /dev/foo as /dev/foo3,
4806 but if the device name ends in a digit, say /dev/foo1,
4807 then the partition is called /dev/foo1p3. */
4808 w = strlen(disk_device);
4809 if (w && isdigit(disk_device[w-1]))
4814 printf(_("%*s Boot Start End Blocks Id System\n"),
4817 for (i = 0; i < partitions; i++) {
4818 const struct pte *pe = &ptes[i];
4821 if (p && !is_cleared_partition(p)) {
4822 unsigned int psects = get_nr_sects(p);
4823 unsigned int pblocks = psects;
4824 unsigned int podd = 0;
4826 if (sector_size < 1024) {
4827 pblocks /= (1024 / sector_size);
4828 podd = psects % (1024 / sector_size);
4830 if (sector_size > 1024)
4831 pblocks *= (sector_size / 1024);
4833 "%s %c %11lu %11lu %11lu%c %2x %s\n",
4834 partname(disk_device, i+1, w+2),
4835 /* boot flag */ !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG
4837 /* start */ (unsigned long) cround(get_partition_start(pe)),
4838 /* end */ (unsigned long) cround(get_partition_start(pe) + psects
4839 - (psects ? 1 : 0)),
4840 /* odd flag on end */ (unsigned long) pblocks, podd ? '+' : ' ',
4841 /* type id */ p->sys_ind,
4842 /* type name */ partition_type(p->sys_ind));
4843 check_consistency(p, i);
4847 /* Is partition table in disk order? It need not be, but... */
4848 /* partition table entries are not checked for correct order if this
4849 is a sgi, sun or aix labeled disk... */
4850 if (dos_label && wrong_p_order(NULL)) {
4851 printf(_("\nPartition table entries are not in disk order\n"));
4855 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
4857 x_list_table(int extend) {
4858 const struct pte *pe;
4859 const struct partition *p;
4862 printf(_("\nDisk %s: %d heads, %d sectors, %d cylinders\n\n"),
4863 disk_device, heads, sectors, cylinders);
4864 printf(_("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n"));
4865 for (i = 0 ; i < partitions; i++) {
4867 p = (extend ? pe->ext_pointer : pe->part_table);
4869 printf("%2d %02x%4d%4d%5d%4d%4d%5d%11u%11u %02x\n",
4870 i + 1, p->boot_ind, p->head,
4872 cylinder(p->sector, p->cyl), p->end_head,
4873 sector(p->end_sector),
4874 cylinder(p->end_sector, p->end_cyl),
4875 get_start_sect(p), get_nr_sects(p), p->sys_ind);
4877 check_consistency(p, i);
4883 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4885 fill_bounds(uint *first, uint *last) {
4887 const struct pte *pe = &ptes[0];
4888 const struct partition *p;
4890 for (i = 0; i < partitions; pe++,i++) {
4892 if (!p->sys_ind || IS_EXTENDED (p->sys_ind)) {
4893 first[i] = 0xffffffff;
4896 first[i] = get_partition_start(pe);
4897 last[i] = first[i] + get_nr_sects(p) - 1;
4903 check(int n, uint h, uint s, uint c, uint start) {
4904 uint total, real_s, real_c;
4906 real_s = sector(s) - 1;
4907 real_c = cylinder(s, c);
4908 total = (real_c * sectors + real_s) * heads + h;
4910 fprintf(stderr, _("Warning: partition %d contains sector 0\n"), n);
4913 _("Partition %d: head %d greater than maximum %d\n"),
4915 if (real_s >= sectors)
4916 fprintf(stderr, _("Partition %d: sector %d greater than "
4917 "maximum %d\n"), n, s, sectors);
4918 if (real_c >= cylinders)
4919 fprintf(stderr, _("Partitions %d: cylinder %d greater than "
4920 "maximum %d\n"), n, real_c + 1, cylinders);
4921 if (cylinders <= 1024 && start != total)
4923 _("Partition %d: previous sectors %d disagrees with "
4924 "total %d\n"), n, start, total);
4931 uint first[partitions], last[partitions];
4932 struct partition *p;
4934 if (warn_geometry())
4937 #ifdef CONFIG_FEATURE_SUN_LABEL
4943 #ifdef CONFIG_FEATURE_SGI_LABEL
4950 fill_bounds(first, last);
4951 for (i = 0; i < partitions; i++) {
4952 struct pte *pe = &ptes[i];
4955 if (p->sys_ind && !IS_EXTENDED (p->sys_ind)) {
4956 check_consistency(p, i);
4957 if (get_partition_start(pe) < first[i])
4958 printf(_("Warning: bad start-of-data in "
4959 "partition %d\n"), i + 1);
4960 check(i + 1, p->end_head, p->end_sector, p->end_cyl,
4962 total += last[i] + 1 - first[i];
4963 for (j = 0; j < i; j++)
4964 if ((first[i] >= first[j] && first[i] <= last[j])
4965 || ((last[i] <= last[j] && last[i] >= first[j]))) {
4966 printf(_("Warning: partition %d overlaps "
4967 "partition %d.\n"), j + 1, i + 1);
4968 total += first[i] >= first[j] ?
4969 first[i] : first[j];
4970 total -= last[i] <= last[j] ?
4976 if (extended_offset) {
4977 struct pte *pex = &ptes[ext_index];
4978 uint e_last = get_start_sect(pex->part_table) +
4979 get_nr_sects(pex->part_table) - 1;
4981 for (i = 4; i < partitions; i++) {
4983 p = ptes[i].part_table;
4985 if (i != 4 || i + 1 < partitions)
4986 printf(_("Warning: partition %d "
4987 "is empty\n"), i + 1);
4989 else if (first[i] < extended_offset ||
4991 printf(_("Logical partition %d not entirely in "
4992 "partition %d\n"), i + 1, ext_index + 1);
4996 if (total > heads * sectors * cylinders)
4997 printf(_("Total allocated sectors %d greater than the maximum "
4998 "%d\n"), total, heads * sectors * cylinders);
4999 else if ((total = heads * sectors * cylinders - total) != 0)
5000 printf(_("%d unallocated sectors\n"), total);
5004 add_partition(int n, int sys) {
5005 char mesg[256]; /* 48 does not suffice in Japanese */
5007 struct partition *p = ptes[n].part_table;
5008 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 || !total_number_of_sectors)
5022 llimit = heads * sectors * cylinders - 1;
5024 llimit = total_number_of_sectors - 1;
5026 if (limit != llimit)
5028 if (extended_offset) {
5029 first[ext_index] = extended_offset;
5030 last[ext_index] = get_start_sect(q) +
5031 get_nr_sects(q) - 1;
5034 start = extended_offset + sector_offset;
5035 limit = get_start_sect(q) + get_nr_sects(q) - 1;
5037 if (display_in_cyl_units)
5038 for (i = 0; i < partitions; i++)
5039 first[i] = (cround(first[i]) - 1) * units_per_sector;
5041 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
5044 for (i = 0; i < partitions; i++) {
5047 if (start == ptes[i].offset)
5048 start += sector_offset;
5049 lastplusoff = last[i] + ((n<4) ? 0 : sector_offset);
5050 if (start >= first[i] && start <= lastplusoff)
5051 start = lastplusoff + 1;
5055 if (start >= temp+units_per_sector && readed) {
5056 printf(_("Sector %d is already allocated\n"), temp);
5060 if (!readed && start == temp) {
5063 saved_start = start;
5064 start = read_int(cround(saved_start), cround(saved_start), cround(limit),
5066 if (display_in_cyl_units) {
5067 start = (start - 1) * units_per_sector;
5068 if (start < saved_start) start = saved_start;
5072 } while (start != temp || !readed);
5073 if (n > 4) { /* NOT for fifth partition */
5074 struct pte *pe = &ptes[n];
5076 pe->offset = start - sector_offset;
5077 if (pe->offset == extended_offset) { /* must be corrected */
5079 if (sector_offset == 1)
5084 for (i = 0; i < partitions; i++) {
5085 struct pte *pe = &ptes[i];
5087 if (start < pe->offset && limit >= pe->offset)
5088 limit = pe->offset - 1;
5089 if (start < first[i] && limit >= first[i])
5090 limit = first[i] - 1;
5092 if (start > limit) {
5093 printf(_("No free sectors available\n"));
5098 if (cround(start) == cround(limit)) {
5101 snprintf(mesg, sizeof(mesg),
5102 _("Last %s or +size or +sizeM or +sizeK"),
5103 str_units(SINGULAR));
5104 stop = read_int(cround(start), cround(limit), cround(limit),
5105 cround(start), mesg);
5106 if (display_in_cyl_units) {
5107 stop = stop * units_per_sector - 1;
5113 set_partition(n, 0, start, stop, sys);
5115 set_partition(n - 1, 1, ptes[n].offset, stop, EXTENDED);
5117 if (IS_EXTENDED (sys)) {
5118 struct pte *pe4 = &ptes[4];
5119 struct pte *pen = &ptes[n];
5122 pen->ext_pointer = p;
5123 pe4->offset = extended_offset = start;
5124 pe4->sectorbuffer = xcalloc(1, sector_size);
5125 pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
5126 pe4->ext_pointer = pe4->part_table + 1;
5134 if (partitions > 5 || ptes[4].part_table->sys_ind) {
5135 struct pte *pe = &ptes[partitions];
5137 pe->sectorbuffer = xcalloc(1, sector_size);
5138 pe->part_table = pt_offset(pe->sectorbuffer, 0);
5139 pe->ext_pointer = pe->part_table + 1;
5144 add_partition(partitions - 1, LINUX_NATIVE);
5148 new_partition(void) {
5149 int i, free_primary = 0;
5151 if (warn_geometry())
5154 #ifdef CONFIG_FEATURE_SUN_LABEL
5156 add_sun_partition(get_partition(0, partitions), LINUX_NATIVE);
5160 #ifdef CONFIG_FEATURE_SGI_LABEL
5162 sgi_add_partition(get_partition(0, partitions), LINUX_NATIVE);
5166 #ifdef CONFIG_FEATURE_AIX_LABEL
5168 printf(_("\tSorry - this fdisk cannot handle AIX disk labels."
5169 "\n\tIf you want to add DOS-type partitions, create"
5170 "\n\ta new empty DOS partition table first. (Use o.)"
5172 "This will destroy the present disk contents.\n"));
5177 for (i = 0; i < 4; i++)
5178 free_primary += !ptes[i].part_table->sys_ind;
5180 if (!free_primary && partitions >= MAXIMUM_PARTS) {
5181 printf(_("The maximum number of partitions has been created\n"));
5185 if (!free_primary) {
5186 if (extended_offset)
5189 printf(_("You must delete some partition and add "
5190 "an extended partition first\n"));
5192 char c, line[LINE_LENGTH];
5193 snprintf(line, sizeof(line), "%s\n %s\n p primary "
5194 "partition (1-4)\n",
5195 "Command action", (extended_offset ?
5196 "l logical (5 or over)" : "e extended"));
5198 if ((c = read_char(line)) == 'p' || c == 'P') {
5199 i = get_nonexisting_partition(0, 4);
5201 add_partition(i, LINUX_NATIVE);
5204 else if (c == 'l' && extended_offset) {
5208 else if (c == 'e' && !extended_offset) {
5209 i = get_nonexisting_partition(0, 4);
5211 add_partition(i, EXTENDED);
5215 printf(_("Invalid partition number "
5216 "for type `%c'\n"), c);
5227 if (ptes[i].changed)
5228 ptes[3].changed = 1;
5229 for (i = 3; i < partitions; i++) {
5230 struct pte *pe = &ptes[i];
5233 write_part_table_flag(pe->sectorbuffer);
5234 write_sector(pe->offset, pe->sectorbuffer);
5238 #ifdef CONFIG_FEATURE_SGI_LABEL
5239 else if (sgi_label) {
5240 /* no test on change? the printf below might be mistaken */
5244 #ifdef CONFIG_FEATURE_SUN_LABEL
5245 else if (sun_label) {
5249 if (ptes[i].changed)
5256 printf(_("The partition table has been altered!\n\n"));
5257 reread_partition_table(1);
5261 reread_partition_table(int leave) {
5265 printf(_("Calling ioctl() to re-read partition table.\n"));
5268 if ((i = ioctl(fd, BLKRRPART)) != 0) {
5271 /* some kernel versions (1.2.x) seem to have trouble
5272 rereading the partition table, but if asked to do it
5273 twice, the second time works. - biro@yggdrasil.com */
5276 if ((i = ioctl(fd, BLKRRPART)) != 0)
5281 printf(_("\nWARNING: Re-reading the partition table "
5282 "failed with error %d: %s.\n"
5283 "The kernel still uses the old table.\n"
5284 "The new table will be used "
5285 "at the next reboot.\n"),
5286 error, strerror(error));
5291 _("\nWARNING: If you have created or modified any DOS 6.x\n"
5292 "partitions, please see the fdisk manual page for additional\n"
5298 printf(_("Syncing disks.\n"));
5300 sleep(4); /* for sync() */
5304 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
5306 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
5307 #define MAX_PER_LINE 16
5309 print_buffer(char pbuffer[]) {
5313 for (i = 0, l = 0; i < sector_size; i++, l++) {
5315 printf("0x%03X:", i);
5316 printf(" %02X", (unsigned char) pbuffer[i]);
5317 if (l == MAX_PER_LINE - 1) {
5332 printf(_("Device: %s\n"), disk_device);
5333 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
5334 if (sun_label || sgi_label)
5335 print_buffer(MBRbuffer);
5338 for (i = 3; i < partitions; i++)
5339 print_buffer(ptes[i].sectorbuffer);
5344 struct pte *pe = &ptes[i];
5345 struct partition *p = pe->part_table;
5348 if (warn_geometry())
5350 if (!p->sys_ind || !get_nr_sects(p) || IS_EXTENDED (p->sys_ind)) {
5351 printf(_("Partition %d has no data area\n"), i + 1);
5354 first = get_partition_start(pe);
5355 new = read_int(first, first, first + get_nr_sects(p) - 1, first,
5356 _("New beginning of data")) - pe->offset;
5358 if (new != get_nr_sects(p)) {
5359 first = get_nr_sects(p) + get_start_sect(p) - new;
5360 set_nr_sects(p, first);
5361 set_start_sect(p, new);
5372 c = tolower(read_char(_("Expert command (m for help): ")));
5375 #ifdef CONFIG_FEATURE_SUN_LABEL
5382 move_begin(get_partition(0, partitions));
5385 user_cylinders = cylinders =
5386 read_int(1, cylinders, 1048576, 0,
5387 _("Number of cylinders"));
5388 #ifdef CONFIG_FEATURE_SUN_LABEL
5390 sun_set_ncyl(cylinders);
5399 #ifdef CONFIG_FEATURE_SGI_LABEL
5404 #ifdef CONFIG_FEATURE_SUN_LABEL
5414 fix_partition_table_order();
5417 #ifdef CONFIG_FEATURE_SGI_LABEL
5422 user_heads = heads = read_int(1, heads, 256, 0,
5423 _("Number of heads"));
5427 #ifdef CONFIG_FEATURE_SUN_LABEL
5433 #ifdef CONFIG_FEATURE_SUN_LABEL
5439 #ifdef CONFIG_FEATURE_SUN_LABEL
5453 user_sectors = sectors = read_int(1, sectors, 63, 0,
5454 _("Number of sectors"));
5455 if (dos_compatible_flag) {
5456 sector_offset = sectors;
5457 fprintf(stderr, _("Warning: setting "
5458 "sector offset for DOS "
5467 write_table(); /* does not return */
5470 #ifdef CONFIG_FEATURE_SUN_LABEL
5472 sun_set_pcylcount();
5480 #endif /* ADVANCED mode */
5483 is_ide_cdrom_or_tape(const char *device) {
5486 struct stat statbuf;
5489 /* No device was given explicitly, and we are trying some
5490 likely things. But opening /dev/hdc may produce errors like
5491 "hdc: tray open or drive not ready"
5492 if it happens to be a CD-ROM drive. It even happens that
5493 the process hangs on the attempt to read a music CD.
5494 So try to be careful. This only works since 2.1.73. */
5496 if (strncmp("/dev/hd", device, 7))
5499 snprintf(buf, sizeof(buf), "/proc/ide/%s/media", device+5);
5500 procf = fopen(buf, "r");
5501 if (procf != NULL && fgets(buf, sizeof(buf), procf))
5502 is_ide = (!strncmp(buf, "cdrom", 5) ||
5503 !strncmp(buf, "tape", 4));
5505 /* Now when this proc file does not exist, skip the
5506 device when it is read-only. */
5507 if (stat(device, &statbuf) == 0)
5508 is_ide = ((statbuf.st_mode & 0222) == 0);
5516 try(const char *device, int user_specified) {
5519 disk_device = device;
5520 if (setjmp(listingbuf))
5522 if (!user_specified)
5523 if (is_ide_cdrom_or_tape(device))
5525 if ((fd = open(disk_device, type_open)) >= 0) {
5526 gb = get_boot(try_only);
5527 if (gb > 0) { /* I/O error */
5529 } else if (gb < 0) { /* no DOS signature */
5530 list_disk_geometry();
5533 #ifdef CONFIG_FEATURE_OSF_LABEL
5534 if (btrydev(device) < 0)
5537 _("Disk %s doesn't contain a valid "
5538 "partition table\n"), device);
5543 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5544 if (!sun_label && partitions > 4)
5545 delete_partition(ext_index);
5549 /* Ignore other errors, since we try IDE
5550 and SCSI hard disks which may not be
5551 installed on the system. */
5552 if (errno == EACCES) {
5553 fprintf(stderr, _("Cannot open %s\n"), device);
5559 /* for fdisk -l: try all things in /proc/partitions
5560 that look like a partition name (do not end in a digit) */
5564 char line[100], ptname[100], devname[120], *s;
5567 procpt = bb_wfopen(PROC_PARTITIONS, "r");
5569 while (fgets(line, sizeof(line), procpt)) {
5570 if (sscanf (line, " %d %d %d %[^\n ]",
5571 &ma, &mi, &sz, ptname) != 4)
5573 for (s = ptname; *s; s++);
5576 sprintf(devname, "/dev/%s", ptname);
5579 #ifdef CONFIG_FEATURE_CLEAN_UP
5584 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5586 unknown_command(int c) {
5587 printf(_("%c: unknown command\n"), c);
5591 int fdisk_main(int argc, char **argv) {
5593 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5596 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5602 * fdisk -l [-b sectorsize] [-u] device ...
5603 * fdisk -s [partition] ...
5604 * fdisk [-b sectorsize] [-u] device
5606 * Options -C, -H, -S set the geometry.
5609 while ((c = getopt(argc, argv, "b:C:H:lS:uvV"
5610 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5616 /* Ugly: this sector size is really per device,
5617 so cannot be combined with multiple disks,
5618 and te same goes for the C/H/S options.
5620 sector_size = atoi(optarg);
5621 if (sector_size != 512 && sector_size != 1024 &&
5622 sector_size != 2048)
5625 user_set_sector_size = 1;
5628 user_cylinders = atoi(optarg);
5631 user_heads = atoi(optarg);
5632 if (user_heads <= 0 || user_heads >= 256)
5636 user_sectors = atoi(optarg);
5637 if (user_sectors <= 0 || user_sectors >= 64)
5641 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5645 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5651 display_in_cyl_units = 0;
5655 printf("fdisk v" UTIL_LINUX_VERSION "\n");
5663 printf(_("This kernel finds the sector size itself - "
5664 "-b option ignored\n"));
5666 if (user_set_sector_size && argc-optind != 1)
5667 printf(_("Warning: the -b (set sector size) option should"
5668 " be used with one specified device\n"));
5671 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5675 type_open = O_RDONLY;
5676 if (argc > optind) {
5679 /* avoid gcc warning:
5680 variable `k' might be clobbered by `longjmp' */
5684 for (k=optind; k<argc; k++)
5687 /* we no longer have default device names */
5688 /* but, we can use /proc/partitions instead */
5692 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5696 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5702 type_open = O_RDONLY;
5704 opts = argc - optind;
5708 for (j = optind; j < argc; j++) {
5709 disk_device = argv[j];
5710 if ((fd = open(disk_device, type_open)) < 0)
5711 fdisk_fatal(unable_to_open);
5712 if (ioctl(fd, BLKGETSIZE, &size))
5713 fdisk_fatal(ioctl_error);
5716 printf("%ld\n", size/2);
5718 printf("%s: %ld\n", argv[j], size/2);
5724 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5725 if (argc-optind == 1)
5726 disk_device = argv[optind];
5732 #ifdef CONFIG_FEATURE_OSF_LABEL
5734 /* OSF label, and no DOS label */
5735 printf(_("Detected an OSF/1 disklabel on %s, entering "
5736 "disklabel mode.\n"),
5740 /* If we return we may want to make an empty DOS label? */
5746 c = tolower(read_char(_("Command (m for help): ")));
5750 toggle_active(get_partition(1, partitions));
5751 #ifdef CONFIG_FEATURE_SUN_LABEL
5753 toggle_sunflags(get_partition(1, partitions),
5756 #ifdef CONFIG_FEATURE_SGI_LABEL
5758 sgi_set_bootpartition(
5759 get_partition(1, partitions));
5765 #ifdef CONFIG_FEATURE_SGI_LABEL
5767 printf(_("\nThe current boot file is: %s\n"),
5768 sgi_get_bootfile());
5769 if (read_chars(_("Please enter the name of the "
5770 "new boot file: ")) == '\n')
5771 printf(_("Boot file unchanged\n"));
5773 sgi_set_bootfile(line_ptr);
5776 #ifdef CONFIG_FEATURE_OSF_LABEL
5782 toggle_dos_compatibility_flag();
5783 #ifdef CONFIG_FEATURE_SUN_LABEL
5785 toggle_sunflags(get_partition(1, partitions),
5788 #ifdef CONFIG_FEATURE_SGI_LABEL
5790 sgi_set_swappartition(
5791 get_partition(1, partitions));
5799 #ifdef CONFIG_FEATURE_SGI_LABEL
5800 /* If sgi_label then don't use get_existing_partition,
5801 let the user select a partition, since
5802 get_existing_partition() only works for Linux-like
5805 j = get_existing_partition(1, partitions);
5807 j = get_partition(1, partitions);
5810 j = get_existing_partition(1, partitions);
5813 delete_partition(j);
5817 #ifdef CONFIG_FEATURE_SGI_LABEL
5824 list_types(get_sys_types());
5843 #ifdef CONFIG_FEATURE_SUN_LABEL
5857 write_table(); /* does not return */
5859 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
5861 #ifdef CONFIG_FEATURE_SGI_LABEL
5864 _("\n\tSorry, no experts menu for SGI "
5865 "partition tables available.\n\n"));
5878 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */