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"
18 /* Force fdisk to transparently remap 32-bit interfaces
19 * to instead really use 64 bit interfaces, at least for
20 * glibc and uClibc... */
21 #ifndef __USE_FILE_OFFSET64
22 # define __USE_FILE_OFFSET64 1
25 #include <sys/types.h>
26 #include <sys/stat.h> /* stat */
35 #include <assert.h> /* assert */
38 #include <sys/ioctl.h>
39 #include <sys/param.h>
40 #include <sys/sysmacros.h> /* major */
42 #include <stdint.h> /* for uint32_t, uint16_t, uint8_t, int16_t, etc */
44 /* Copied from linux/major.h */
45 #define FLOPPY_MAJOR 2
47 #include <sys/utsname.h>
51 #define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r))
57 #define BLKRRPART _IO(0x12,95) /* re-read partition table */
58 #define BLKGETSIZE _IO(0x12,96) /* return device size */
59 #define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */
60 #define BLKSSZGET _IO(0x12,104) /* get block device sector size */
62 /* Avoid conflicts with the 2.6 kernel headers, which define
63 * _IOR rather differently */
65 #define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size))
66 #define BLKGETSIZE64 _IOR(0x12,114,uint64_t)
72 #define DEFAULT_SECTOR_SIZE 512
73 #define MAX_SECTOR_SIZE 2048
74 #define SECTOR_SIZE 512 /* still used in BSD code */
75 #define MAXIMUM_PARTS 60
77 #define ACTIVE_FLAG 0x80
80 #define WIN98_EXTENDED 0x0f
81 #define LINUX_PARTITION 0x81
82 #define LINUX_SWAP 0x82
83 #define LINUX_NATIVE 0x83
84 #define LINUX_EXTENDED 0x85
85 #define LINUX_LVM 0x8e
86 #define LINUX_RAID 0xfd
91 #define IS_EXTENDED(i) \
92 ((i) == EXTENDED || (i) == WIN98_EXTENDED || (i) == LINUX_EXTENDED)
94 #define SIZE(a) (sizeof(a)/sizeof((a)[0]))
96 #define cround(n) (display_in_cyl_units ? ((n)/units_per_sector)+1 : (n))
97 #define scround(x) (((x)+units_per_sector-1)/units_per_sector)
99 #ifdef CONFIG_FEATURE_SUN_LABEL
100 #define SCSI_IOCTL_GET_IDLUN 0x5382
104 /* including <linux/hdreg.h> also fails */
107 unsigned char sectors;
108 unsigned short cylinders;
112 #define HDIO_GETGEO 0x0301 /* get device geometry */
116 const unsigned char *name;
119 static uint sector_size = DEFAULT_SECTOR_SIZE,
120 user_set_sector_size,
124 * Raw disk label. For DOS-type partition tables the MBR,
125 * with descriptions of the primary partitions.
127 static char MBRbuffer[MAX_SECTOR_SIZE];
129 #ifdef CONFIG_FEATURE_SUN_LABEL
130 static int sun_label; /* looking at sun disklabel */
134 #ifdef CONFIG_FEATURE_SGI_LABEL
135 static int sgi_label; /* looking at sgi disklabel */
139 #ifdef CONFIG_FEATURE_AIX_LABEL
140 static int aix_label; /* looking at aix disklabel */
144 #ifdef CONFIG_FEATURE_OSF_LABEL
145 static int osf_label; /* looking at OSF/1 disklabel */
146 static int possibly_osf_label;
151 #define dos_label (!sun_label && !sgi_label && !aix_label && !osf_label)
153 static uint heads, sectors, cylinders;
154 static void update_units(void);
158 * return partition name - uses static storage unless buf is supplied
161 partname(const char *dev, int pno, int lth) {
162 static char buffer[80];
169 bufsiz = sizeof(buffer);
174 if (isdigit(dev[w-1]))
177 /* devfs kludge - note: fdisk partition names are not supposed
178 to equal kernel names, so there is no reason to do this */
179 if (strcmp (dev + w - 4, "disc") == 0) {
187 snprintf(bufp, bufsiz, "%*.*s%s%-2u",
188 lth-wp-2, w, dev, p, pno);
190 snprintf(bufp, bufsiz, "%.*s%s%-2u", w, dev, p, pno);
196 unsigned char boot_ind; /* 0x80 - active */
197 unsigned char head; /* starting head */
198 unsigned char sector; /* starting sector */
199 unsigned char cyl; /* starting cylinder */
200 unsigned char sys_ind; /* What partition type */
201 unsigned char end_head; /* end head */
202 unsigned char end_sector; /* end sector */
203 unsigned char end_cyl; /* end cylinder */
204 unsigned char start4[4]; /* starting sector counting from 0 */
205 unsigned char size4[4]; /* nr of sectors in partition */
206 } __attribute__((__packed__));
209 ioctl_error, unable_to_open, unable_to_read, unable_to_seek,
213 enum action {fdisk, require, try_only, create_empty_dos, create_empty_sun};
215 static const char *disk_device;
216 static int fd; /* the disk */
217 static int partitions = 4; /* maximum partition + 1 */
218 static uint display_in_cyl_units = 1;
219 static uint units_per_sector = 1;
220 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
221 static char *line_ptr;
222 static void change_units(void);
223 static void reread_partition_table(int leave);
224 static void delete_partition(int i);
225 static int get_partition(int warn, int max);
226 static void list_types(const struct systypes *sys);
227 static uint read_int(uint low, uint dflt, uint high, uint base, char *mesg);
229 static const char *partition_type(unsigned char type);
230 static void fdisk_fatal(enum failure why) __attribute__ ((noreturn));
231 static void get_geometry(void);
232 static int get_boot(enum action what);
237 #define hex_val(c) ({ \
239 isdigit(_c) ? _c - '0' : \
240 tolower(_c) + 10 - 'a'; \
244 #define LINE_LENGTH 800
245 #define pt_offset(b, n) ((struct partition *)((b) + 0x1be + \
246 (n) * sizeof(struct partition)))
247 #define sector(s) ((s) & 0x3f)
248 #define cylinder(s, c) ((c) | (((s) & 0xc0) << 2))
250 #define hsc2sector(h,s,c) (sector(s) - 1 + sectors * \
251 ((h) + heads * cylinder(s,c)))
252 #define set_hsc(h,s,c,sector) { \
253 s = sector % sectors + 1; \
255 h = sector % heads; \
258 s |= (sector >> 2) & 0xc0; \
262 static unsigned int get_start_sect(const struct partition *p);
263 static unsigned int get_nr_sects(const struct partition *p);
266 * per partition table entry data
268 * The four primary partitions have the same sectorbuffer (MBRbuffer)
269 * and have NULL ext_pointer.
270 * Each logical partition table entry has two pointers, one for the
271 * partition and one link to the next one.
274 struct partition *part_table; /* points into sectorbuffer */
275 struct partition *ext_pointer; /* points into sectorbuffer */
276 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
277 char changed; /* boolean */
279 uint offset; /* disk sector number */
280 char *sectorbuffer; /* disk sector contents */
281 } ptes[MAXIMUM_PARTS];
284 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
286 set_all_unchanged(void) {
289 for (i = 0; i < MAXIMUM_PARTS; i++)
297 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
299 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_OSF_LABEL)
300 static struct partition *
301 get_part_table(int i) {
302 return ptes[i].part_table;
307 str_units(int n) { /* n==1: use singular */
309 return display_in_cyl_units ? _("cylinder") : _("sector");
311 return display_in_cyl_units ? _("cylinders") : _("sectors");
315 valid_part_table_flag(const unsigned char *b) {
316 return (b[510] == 0x55 && b[511] == 0xaa);
319 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
320 static char line_buffer[LINE_LENGTH];
322 /* read line; return 0 or first char */
326 static int got_eof = 0;
328 fflush (stdout); /* requested by niles@scyld.com */
329 line_ptr = line_buffer;
330 if (!fgets(line_buffer, LINE_LENGTH, stdin)) {
332 got_eof++; /* user typed ^D ? */
334 fprintf(stderr, _("\ngot EOF thrice - exiting..\n"));
339 while (*line_ptr && !isgraph(*line_ptr))
345 read_char(const char *mesg)
349 } while (!read_line());
354 read_chars(const char *mesg)
365 read_hex(const struct systypes *sys)
371 read_char(_("Hex code (type L to list codes): "));
372 if (*line_ptr == 'l' || *line_ptr == 'L')
374 else if (isxdigit (*line_ptr))
378 hex = hex << 4 | hex_val(*line_ptr++);
379 while (isxdigit(*line_ptr));
384 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
386 #ifdef CONFIG_FEATURE_AIX_LABEL
388 * Copyright (C) Andreas Neuper, Sep 1998.
389 * This file may be redistributed under
390 * the terms of the GNU Public License.
394 unsigned int magic; /* expect AIX_LABEL_MAGIC */
395 unsigned int fillbytes1[124];
396 unsigned int physical_volume_id;
397 unsigned int fillbytes2[124];
400 #define AIX_LABEL_MAGIC 0xc9c2d4c1
401 #define AIX_LABEL_MAGIC_SWAPPED 0xc1d4c2c9
402 #define AIX_INFO_MAGIC 0x00072959
403 #define AIX_INFO_MAGIC_SWAPPED 0x59290700
405 #define aixlabel ((aix_partition *)MBRbuffer)
410 * 1999-03-20 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
411 * Internationalization
413 * 2003-03-20 Phillip Kesling <pkesling@sgi.com>
417 static int aix_other_endian;
418 static short aix_volumes=1;
421 * only dealing with free blocks here
427 _("\n\tThere is a valid AIX label on this disk.\n"
428 "\tUnfortunately Linux cannot handle these\n"
429 "\tdisks at the moment. Nevertheless some\n"
431 "\t1. fdisk will destroy its contents on write.\n"
432 "\t2. Be sure that this disk is NOT a still vital\n"
433 "\t part of a volume group. (Otherwise you may\n"
434 "\t erase the other disks as well, if unmirrored.)\n"
435 "\t3. Before deleting this physical volume be sure\n"
436 "\t to remove the disk logically from your AIX\n"
437 "\t machine. (Otherwise you become an AIXpert).")
447 memset( MBRbuffer, 0, sizeof(MBRbuffer) ); /* avoid fdisk cores */
452 check_aix_label( void )
454 if (aixlabel->magic != AIX_LABEL_MAGIC &&
455 aixlabel->magic != AIX_LABEL_MAGIC_SWAPPED) {
457 aix_other_endian = 0;
460 aix_other_endian = (aixlabel->magic == AIX_LABEL_MAGIC_SWAPPED);
466 aix_nolabel(); /* %% */
467 aix_label = 1; /* %% */
470 #endif /* AIX_LABEL */
472 #ifdef CONFIG_FEATURE_OSF_LABEL
474 * Copyright (c) 1987, 1988 Regents of the University of California.
475 * All rights reserved.
477 * Redistribution and use in source and binary forms, with or without
478 * modification, are permitted provided that the following conditions
480 * 1. Redistributions of source code must retain the above copyright
481 * notice, this list of conditions and the following disclaimer.
482 * 2. Redistributions in binary form must reproduce the above copyright
483 * notice, this list of conditions and the following disclaimer in the
484 * documentation and/or other materials provided with the distribution.
485 * 3. All advertising materials mentioning features or use of this software
486 * must display the following acknowledgment:
487 * This product includes software developed by the University of
488 * California, Berkeley and its contributors.
489 * 4. Neither the name of the University nor the names of its contributors
490 * may be used to endorse or promote products derived from this software
491 * without specific prior written permission.
493 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
494 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
495 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
496 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
497 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
498 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
499 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
500 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
501 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
502 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
507 #ifndef BSD_DISKMAGIC
508 #define BSD_DISKMAGIC ((uint32_t) 0x82564557)
511 #ifndef BSD_MAXPARTITIONS
512 #define BSD_MAXPARTITIONS 16
515 #define BSD_LINUX_BOOTDIR "/usr/ucb/mdec"
517 #if defined (i386) || defined (__sparc__) || defined (__arm__) || defined (__mips__) || defined (__s390__) || defined (__sh__) || defined(__x86_64__)
518 #define BSD_LABELSECTOR 1
519 #define BSD_LABELOFFSET 0
520 #elif defined (__alpha__) || defined (__powerpc__) || defined (__ia64__) || defined (__hppa__)
521 #define BSD_LABELSECTOR 0
522 #define BSD_LABELOFFSET 64
523 #elif defined (__s390__) || defined (__s390x__)
524 #define BSD_LABELSECTOR 1
525 #define BSD_LABELOFFSET 0
527 #error unknown architecture
530 #define BSD_BBSIZE 8192 /* size of boot area, with label */
531 #define BSD_SBSIZE 8192 /* max size of fs superblock */
533 struct xbsd_disklabel {
534 uint32_t d_magic; /* the magic number */
535 int16_t d_type; /* drive type */
536 int16_t d_subtype; /* controller/d_type specific */
537 char d_typename[16]; /* type name, e.g. "eagle" */
538 char d_packname[16]; /* pack identifier */
540 uint32_t d_secsize; /* # of bytes per sector */
541 uint32_t d_nsectors; /* # of data sectors per track */
542 uint32_t d_ntracks; /* # of tracks per cylinder */
543 uint32_t d_ncylinders; /* # of data cylinders per unit */
544 uint32_t d_secpercyl; /* # of data sectors per cylinder */
545 uint32_t d_secperunit; /* # of data sectors per unit */
547 * Spares (bad sector replacements) below
548 * are not counted in d_nsectors or d_secpercyl.
549 * Spare sectors are assumed to be physical sectors
550 * which occupy space at the end of each track and/or cylinder.
552 uint16_t d_sparespertrack; /* # of spare sectors per track */
553 uint16_t d_sparespercyl; /* # of spare sectors per cylinder */
555 * Alternate cylinders include maintenance, replacement,
556 * configuration description areas, etc.
558 uint32_t d_acylinders; /* # of alt. cylinders per unit */
560 /* hardware characteristics: */
562 * d_interleave, d_trackskew and d_cylskew describe perturbations
563 * in the media format used to compensate for a slow controller.
564 * Interleave is physical sector interleave, set up by the formatter
565 * or controller when formatting. When interleaving is in use,
566 * logically adjacent sectors are not physically contiguous,
567 * but instead are separated by some number of sectors.
568 * It is specified as the ratio of physical sectors traversed
569 * per logical sector. Thus an interleave of 1:1 implies contiguous
570 * layout, while 2:1 implies that logical sector 0 is separated
571 * by one sector from logical sector 1.
572 * d_trackskew is the offset of sector 0 on track N
573 * relative to sector 0 on track N-1 on the same cylinder.
574 * Finally, d_cylskew is the offset of sector 0 on cylinder N
575 * relative to sector 0 on cylinder N-1.
577 uint16_t d_rpm; /* rotational speed */
578 uint16_t d_interleave; /* hardware sector interleave */
579 uint16_t d_trackskew; /* sector 0 skew, per track */
580 uint16_t d_cylskew; /* sector 0 skew, per cylinder */
581 uint32_t d_headswitch; /* head switch time, usec */
582 uint32_t d_trkseek; /* track-to-track seek, usec */
583 uint32_t d_flags; /* generic flags */
585 uint32_t d_drivedata[NDDATA]; /* drive-type specific information */
587 uint32_t d_spare[NSPARE]; /* reserved for future use */
588 uint32_t d_magic2; /* the magic number (again) */
589 uint16_t d_checksum; /* xor of data incl. partitions */
590 /* filesystem and partition information: */
591 uint16_t d_npartitions; /* number of partitions in following */
592 uint32_t d_bbsize; /* size of boot area at sn0, bytes */
593 uint32_t d_sbsize; /* max size of fs superblock, bytes */
594 struct xbsd_partition { /* the partition table */
595 uint32_t p_size; /* number of sectors in partition */
596 uint32_t p_offset; /* starting sector */
597 uint32_t p_fsize; /* filesystem basic fragment size */
598 uint8_t p_fstype; /* filesystem type, see below */
599 uint8_t p_frag; /* filesystem fragments per block */
600 uint16_t p_cpg; /* filesystem cylinders per group */
601 } d_partitions[BSD_MAXPARTITIONS]; /* actually may be more */
605 #define BSD_DTYPE_SMD 1 /* SMD, XSMD; VAX hp/up */
606 #define BSD_DTYPE_MSCP 2 /* MSCP */
607 #define BSD_DTYPE_DEC 3 /* other DEC (rk, rl) */
608 #define BSD_DTYPE_SCSI 4 /* SCSI */
609 #define BSD_DTYPE_ESDI 5 /* ESDI interface */
610 #define BSD_DTYPE_ST506 6 /* ST506 etc. */
611 #define BSD_DTYPE_HPIB 7 /* CS/80 on HP-IB */
612 #define BSD_DTYPE_HPFL 8 /* HP Fiber-link */
613 #define BSD_DTYPE_FLOPPY 10 /* floppy */
615 /* d_subtype values: */
616 #define BSD_DSTYPE_INDOSPART 0x8 /* is inside dos partition */
617 #define BSD_DSTYPE_DOSPART(s) ((s) & 3) /* dos partition number */
618 #define BSD_DSTYPE_GEOMETRY 0x10 /* drive params in label */
621 static const char * const xbsd_dktypenames[] = {
635 #define BSD_DKMAXTYPES (sizeof(xbsd_dktypenames) / sizeof(xbsd_dktypenames[0]) - 1)
639 * Filesystem type and version.
640 * Used to interpret other filesystem-specific
641 * per-partition information.
643 #define BSD_FS_UNUSED 0 /* unused */
644 #define BSD_FS_SWAP 1 /* swap */
645 #define BSD_FS_V6 2 /* Sixth Edition */
646 #define BSD_FS_V7 3 /* Seventh Edition */
647 #define BSD_FS_SYSV 4 /* System V */
648 #define BSD_FS_V71K 5 /* V7 with 1K blocks (4.1, 2.9) */
649 #define BSD_FS_V8 6 /* Eighth Edition, 4K blocks */
650 #define BSD_FS_BSDFFS 7 /* 4.2BSD fast file system */
651 #define BSD_FS_BSDLFS 9 /* 4.4BSD log-structured file system */
652 #define BSD_FS_OTHER 10 /* in use, but unknown/unsupported */
653 #define BSD_FS_HPFS 11 /* OS/2 high-performance file system */
654 #define BSD_FS_ISO9660 12 /* ISO-9660 filesystem (cdrom) */
655 #define BSD_FS_ISOFS BSD_FS_ISO9660
656 #define BSD_FS_BOOT 13 /* partition contains bootstrap */
657 #define BSD_FS_ADOS 14 /* AmigaDOS fast file system */
658 #define BSD_FS_HFS 15 /* Macintosh HFS */
659 #define BSD_FS_ADVFS 16 /* Digital Unix AdvFS */
661 /* this is annoying, but it's also the way it is :-( */
663 #define BSD_FS_EXT2 8 /* ext2 file system */
665 #define BSD_FS_MSDOS 8 /* MS-DOS file system */
669 static const struct systypes xbsd_fstypes[] = {
670 /* BSD_FS_UNUSED */ {"\x00" "unused"},
671 /* BSD_FS_SWAP */ {"\x01" "swap"},
672 /* BSD_FS_V6 */ {"\x02" "Version 6"},
673 /* BSD_FS_V7 */ {"\x03" "Version 7"},
674 /* BSD_FS_SYSV */ {"\x04" "System V"},
675 /* BSD_FS_V71K */ {"\x05" "4.1BSD"},
676 /* BSD_FS_V8 */ {"\x06" "Eighth Edition"},
677 /* BSD_FS_BSDFFS */ {"\x07" "4.2BSD"},
679 /* BSD_FS_EXT2 */ {"\x08" "ext2"},
681 /* BSD_FS_MSDOS */ {"\x08" "MS-DOS"},
683 /* BSD_FS_BSDLFS */ {"\x09" "4.4LFS"},
684 /* BSD_FS_OTHER */ {"\x0a" "unknown"},
685 /* BSD_FS_HPFS */ {"\x0b" "HPFS"},
686 /* BSD_FS_ISO9660 */ {"\x0c" "ISO-9660"},
687 /* BSD_FS_BOOT */ {"\x0d" "boot"},
688 /* BSD_FS_ADOS */ {"\x0e" "ADOS"},
689 /* BSD_FS_HFS */ {"\x0f" "HFS"},
690 /* BSD_FS_ADVFS */ {"\x10" "AdvFS"},
693 #define BSD_FSMAXTYPES (SIZE(xbsd_fstypes)-1)
698 * flags shared by various drives:
700 #define BSD_D_REMOVABLE 0x01 /* removable media */
701 #define BSD_D_ECC 0x02 /* supports ECC */
702 #define BSD_D_BADSECT 0x04 /* supports bad sector forw. */
703 #define BSD_D_RAMDISK 0x08 /* disk emulator */
704 #define BSD_D_CHAIN 0x10 /* can do back-back transfers */
705 #define BSD_D_DOSPART 0x20 /* within MSDOS partition */
707 #endif /* OSF_LABEL */
710 * Copyright (C) Andreas Neuper, Sep 1998.
711 * This file may be modified and redistributed under
712 * the terms of the GNU Public License.
715 struct device_parameter { /* 48 bytes */
719 unsigned char sparecyl;
720 unsigned short pcylcount;
721 unsigned short head_vol0;
722 unsigned short ntrks; /* tracks in cyl 0 or vol 0 */
723 unsigned char cmd_tag_queue_depth;
724 unsigned char unused0;
725 unsigned short unused1;
726 unsigned short nsect; /* sectors/tracks in cyl 0 or vol 0 */
727 unsigned short bytes;
728 unsigned short ilfact;
729 unsigned int flags; /* controller flags */
730 unsigned int datarate;
731 unsigned int retries_on_error;
732 unsigned int ms_per_word;
733 unsigned short xylogics_gap1;
734 unsigned short xylogics_syncdelay;
735 unsigned short xylogics_readdelay;
736 unsigned short xylogics_gap2;
737 unsigned short xylogics_readgate;
738 unsigned short xylogics_writecont;
741 #define SGI_VOLHDR 0x00
742 /* 1 and 2 were used for drive types no longer supported by SGI */
743 #define SGI_SWAP 0x03
744 /* 4 and 5 were for filesystem types SGI haven't ever supported on MIPS CPUs */
745 #define SGI_VOLUME 0x06
747 #define SGI_LVOL 0x08
748 #define SGI_RLVOL 0x09
750 #define SGI_XFSLOG 0x0b
753 #define ENTIRE_DISK SGI_VOLUME
757 #define SECTOR_SLIP 0x01
758 #define SECTOR_FWD 0x02
759 #define TRACK_FWD 0x04
760 #define TRACK_MULTIVOL 0x08
761 #define IGNORE_ERRORS 0x10
763 #define ENABLE_CMDTAGQ 0x40
766 unsigned int magic; /* expect SGI_LABEL_MAGIC */
767 unsigned short boot_part; /* active boot partition */
768 unsigned short swap_part; /* active swap partition */
769 unsigned char boot_file[16]; /* name of the bootfile */
770 struct device_parameter devparam; /* 1 * 48 bytes */
771 struct volume_directory { /* 15 * 16 bytes */
772 unsigned char vol_file_name[8]; /* a character array */
773 unsigned int vol_file_start; /* number of logical block */
774 unsigned int vol_file_size; /* number of bytes */
776 struct sgi_partition { /* 16 * 12 bytes */
777 unsigned int num_sectors; /* number of blocks */
778 unsigned int start_sector; /* must be cylinder aligned */
782 unsigned int fillbytes;
786 unsigned int magic; /* looks like a magic number */
795 unsigned char scsi_string[50];
796 unsigned char serial[137];
797 unsigned short check1816;
798 unsigned char installer[225];
801 #define SGI_LABEL_MAGIC 0x0be5a941
802 #define SGI_LABEL_MAGIC_SWAPPED 0x41a9e50b
803 #define SGI_INFO_MAGIC 0x00072959
804 #define SGI_INFO_MAGIC_SWAPPED 0x59290700
805 #define SGI_SSWAP16(x) (sgi_other_endian ? __swap16(x) \
807 #define SGI_SSWAP32(x) (sgi_other_endian ? __swap32(x) \
810 #define sgilabel ((sgi_partition *)MBRbuffer)
811 #define sgiparam (sgilabel->devparam)
814 unsigned char info[128]; /* Informative text string */
815 unsigned char spare0[14];
817 unsigned char spare1;
819 unsigned char spare2;
822 unsigned char spare1[246]; /* Boot information etc. */
823 unsigned short rspeed; /* Disk rotational speed */
824 unsigned short pcylcount; /* Physical cylinder count */
825 unsigned short sparecyl; /* extra sects per cylinder */
826 unsigned char spare2[4]; /* More magic... */
827 unsigned short ilfact; /* Interleave factor */
828 unsigned short ncyl; /* Data cylinder count */
829 unsigned short nacyl; /* Alt. cylinder count */
830 unsigned short ntrks; /* Tracks per cylinder */
831 unsigned short nsect; /* Sectors per track */
832 unsigned char spare3[4]; /* Even more magic... */
833 struct sun_partition {
834 uint32_t start_cylinder;
835 uint32_t num_sectors;
837 unsigned short magic; /* Magic number */
838 unsigned short csum; /* Label xor'd checksum */
842 #define SUN_LABEL_MAGIC 0xDABE
843 #define SUN_LABEL_MAGIC_SWAPPED 0xBEDA
844 #define sunlabel ((sun_partition *)MBRbuffer)
845 #define SUN_SSWAP16(x) (sun_other_endian ? __swap16(x) \
847 #define SUN_SSWAP32(x) (sun_other_endian ? __swap32(x) \
851 #ifdef CONFIG_FEATURE_OSF_LABEL
854 19990319 - Arnaldo Carvalho de Melo <acme@conectiva.com.br> - i18n/nls
856 20000101 - David Huggins-Daines <dhuggins@linuxcare.com> - Better
857 support for OSF/1 disklabels on Alpha.
858 Also fixed unaligned accesses in alpha_bootblock_checksum()
861 #define FREEBSD_PARTITION 0xa5
862 #define NETBSD_PARTITION 0xa9
864 static void xbsd_delete_part (void);
865 static void xbsd_new_part (void);
866 static void xbsd_write_disklabel (void);
867 static int xbsd_create_disklabel (void);
868 static void xbsd_edit_disklabel (void);
869 static void xbsd_write_bootstrap (void);
870 static void xbsd_change_fstype (void);
871 static int xbsd_get_part_index (int max);
872 static int xbsd_check_new_partition (int *i);
873 static void xbsd_list_types (void);
874 static u_short xbsd_dkcksum (struct xbsd_disklabel *lp);
875 static int xbsd_initlabel (struct partition *p, struct xbsd_disklabel *d,
877 static int xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d);
878 static int xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d);
880 #if defined (__alpha__)
881 static void alpha_bootblock_checksum (char *boot);
884 #if !defined (__alpha__)
885 static int xbsd_translate_fstype (int linux_type);
886 static void xbsd_link_part (void);
887 static struct partition *xbsd_part;
888 static int xbsd_part_index;
891 #if defined (__alpha__)
892 /* We access this through a uint64_t * when checksumming */
893 static char disklabelbuffer[BSD_BBSIZE] __attribute__((aligned(8)));
895 static char disklabelbuffer[BSD_BBSIZE];
898 static struct xbsd_disklabel xbsd_dlabel;
900 #define bsd_cround(n) \
901 (display_in_cyl_units ? ((n)/xbsd_dlabel.d_secpercyl) + 1 : (n))
904 * Test whether the whole disk has BSD disk label magic.
906 * Note: often reformatting with DOS-type label leaves the BSD magic,
907 * so this does not mean that there is a BSD disk label.
910 check_osf_label(void) {
911 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
916 static void xbsd_print_disklabel(int);
919 btrydev (const char * dev) {
920 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
922 printf(_("\nBSD label for device: %s\n"), dev);
923 xbsd_print_disklabel (0);
929 puts (_("Command action"));
930 puts (_("\td\tdelete a BSD partition"));
931 puts (_("\te\tedit drive data"));
932 puts (_("\ti\tinstall bootstrap"));
933 puts (_("\tl\tlist known filesystem types"));
934 puts (_("\tm\tprint this menu"));
935 puts (_("\tn\tadd a new BSD partition"));
936 puts (_("\tp\tprint BSD partition table"));
937 puts (_("\tq\tquit without saving changes"));
938 puts (_("\tr\treturn to main menu"));
939 puts (_("\ts\tshow complete disklabel"));
940 puts (_("\tt\tchange a partition's filesystem id"));
941 puts (_("\tu\tchange units (cylinders/sectors)"));
942 puts (_("\tw\twrite disklabel to disk"));
943 #if !defined (__alpha__)
944 puts (_("\tx\tlink BSD partition to non-BSD partition"));
948 #if !defined (__alpha__)
955 is_bsd_partition_type(int type) {
956 return (type == FREEBSD_PARTITION ||
957 type == hidden(FREEBSD_PARTITION) ||
958 type == NETBSD_PARTITION ||
959 type == hidden(NETBSD_PARTITION));
965 #if !defined (__alpha__)
969 for (t=0; t<4; t++) {
970 p = get_part_table(t);
971 if (p && is_bsd_partition_type(p->sys_ind)) {
974 ss = get_start_sect(xbsd_part);
976 fprintf (stderr, _("Partition %s has invalid starting sector 0.\n"),
977 partname(disk_device, t+1, 0));
980 printf (_("Reading disklabel of %s at sector %d.\n"),
981 partname(disk_device, t+1, 0), ss + BSD_LABELSECTOR);
982 if (xbsd_readlabel (xbsd_part, &xbsd_dlabel) == 0)
983 if (xbsd_create_disklabel () == 0)
990 printf (_("There is no *BSD partition on %s.\n"), disk_device);
994 #elif defined (__alpha__)
996 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
997 if (xbsd_create_disklabel () == 0)
998 exit ( EXIT_SUCCESS );
1004 switch (tolower (read_char (_("BSD disklabel command (m for help): ")))) {
1006 xbsd_delete_part ();
1009 xbsd_edit_disklabel ();
1012 xbsd_write_bootstrap ();
1021 xbsd_print_disklabel (0);
1025 exit ( EXIT_SUCCESS );
1029 xbsd_print_disklabel (1);
1032 xbsd_change_fstype ();
1038 xbsd_write_disklabel ();
1040 #if !defined (__alpha__)
1053 xbsd_delete_part (void)
1057 i = xbsd_get_part_index (xbsd_dlabel.d_npartitions);
1058 xbsd_dlabel.d_partitions[i].p_size = 0;
1059 xbsd_dlabel.d_partitions[i].p_offset = 0;
1060 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
1061 if (xbsd_dlabel.d_npartitions == i + 1)
1062 while (xbsd_dlabel.d_partitions[xbsd_dlabel.d_npartitions-1].p_size == 0)
1063 xbsd_dlabel.d_npartitions--;
1067 xbsd_new_part (void)
1073 if (!xbsd_check_new_partition (&i))
1076 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
1077 begin = get_start_sect(xbsd_part);
1078 end = begin + get_nr_sects(xbsd_part) - 1;
1081 end = xbsd_dlabel.d_secperunit - 1;
1084 snprintf (mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
1085 begin = read_int (bsd_cround (begin), bsd_cround (begin), bsd_cround (end),
1088 if (display_in_cyl_units)
1089 begin = (begin - 1) * xbsd_dlabel.d_secpercyl;
1091 snprintf (mesg, sizeof(mesg), _("Last %s or +size or +sizeM or +sizeK"),
1092 str_units(SINGULAR));
1093 end = read_int (bsd_cround (begin), bsd_cround (end), bsd_cround (end),
1094 bsd_cround (begin), mesg);
1096 if (display_in_cyl_units)
1097 end = end * xbsd_dlabel.d_secpercyl - 1;
1099 xbsd_dlabel.d_partitions[i].p_size = end - begin + 1;
1100 xbsd_dlabel.d_partitions[i].p_offset = begin;
1101 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
1105 xbsd_print_disklabel (int show_all) {
1106 struct xbsd_disklabel *lp = &xbsd_dlabel;
1107 struct xbsd_partition *pp;
1111 #if defined (__alpha__)
1112 printf("# %s:\n", disk_device);
1114 printf("# %s:\n", partname(disk_device, xbsd_part_index+1, 0));
1116 if ((unsigned) lp->d_type < BSD_DKMAXTYPES)
1117 printf(_("type: %s\n"), xbsd_dktypenames[lp->d_type]);
1119 printf(_("type: %d\n"), lp->d_type);
1120 printf(_("disk: %.*s\n"), (int) sizeof(lp->d_typename), lp->d_typename);
1121 printf(_("label: %.*s\n"), (int) sizeof(lp->d_packname), lp->d_packname);
1122 printf(_("flags:"));
1123 if (lp->d_flags & BSD_D_REMOVABLE)
1124 printf(_(" removable"));
1125 if (lp->d_flags & BSD_D_ECC)
1127 if (lp->d_flags & BSD_D_BADSECT)
1128 printf(_(" badsect"));
1130 /* On various machines the fields of *lp are short/int/long */
1131 /* In order to avoid problems, we cast them all to long. */
1132 printf(_("bytes/sector: %ld\n"), (long) lp->d_secsize);
1133 printf(_("sectors/track: %ld\n"), (long) lp->d_nsectors);
1134 printf(_("tracks/cylinder: %ld\n"), (long) lp->d_ntracks);
1135 printf(_("sectors/cylinder: %ld\n"), (long) lp->d_secpercyl);
1136 printf(_("cylinders: %ld\n"), (long) lp->d_ncylinders);
1137 printf(_("rpm: %d\n"), lp->d_rpm);
1138 printf(_("interleave: %d\n"), lp->d_interleave);
1139 printf(_("trackskew: %d\n"), lp->d_trackskew);
1140 printf(_("cylinderskew: %d\n"), lp->d_cylskew);
1141 printf(_("headswitch: %ld\t\t# milliseconds\n"),
1142 (long) lp->d_headswitch);
1143 printf(_("track-to-track seek: %ld\t# milliseconds\n"),
1144 (long) lp->d_trkseek);
1145 printf(_("drivedata: "));
1146 for (i = NDDATA - 1; i >= 0; i--)
1147 if (lp->d_drivedata[i])
1151 for (j = 0; j <= i; j++)
1152 printf("%ld ", (long) lp->d_drivedata[j]);
1154 printf(_("\n%d partitions:\n"), lp->d_npartitions);
1155 printf(_("# start end size fstype [fsize bsize cpg]\n"));
1156 pp = lp->d_partitions;
1157 for (i = 0; i < lp->d_npartitions; i++, pp++) {
1159 if (display_in_cyl_units && lp->d_secpercyl) {
1160 printf(" %c: %8ld%c %8ld%c %8ld%c ",
1162 (long) pp->p_offset / lp->d_secpercyl + 1,
1163 (pp->p_offset % lp->d_secpercyl) ? '*' : ' ',
1164 (long) (pp->p_offset + pp->p_size + lp->d_secpercyl - 1)
1166 ((pp->p_offset + pp->p_size) % lp->d_secpercyl) ? '*' : ' ',
1167 (long) pp->p_size / lp->d_secpercyl,
1168 (pp->p_size % lp->d_secpercyl) ? '*' : ' ');
1170 printf(" %c: %8ld %8ld %8ld ",
1172 (long) pp->p_offset,
1173 (long) pp->p_offset + pp->p_size - 1,
1176 if ((unsigned) pp->p_fstype < BSD_FSMAXTYPES)
1177 printf("%8.8s", xbsd_fstypes[pp->p_fstype].name);
1179 printf("%8x", pp->p_fstype);
1180 switch (pp->p_fstype) {
1182 printf(" %5ld %5ld %5.5s ",
1183 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, "");
1187 printf(" %5ld %5ld %5d ",
1188 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag,
1193 printf("%22.22s", "");
1202 xbsd_write_disklabel (void) {
1203 #if defined (__alpha__)
1204 printf (_("Writing disklabel to %s.\n"), disk_device);
1205 xbsd_writelabel (NULL, &xbsd_dlabel);
1207 printf (_("Writing disklabel to %s.\n"),
1208 partname(disk_device, xbsd_part_index+1, 0));
1209 xbsd_writelabel (xbsd_part, &xbsd_dlabel);
1211 reread_partition_table(0); /* no exit yet */
1215 xbsd_create_disklabel (void) {
1218 #if defined (__alpha__)
1219 fprintf (stderr, _("%s contains no disklabel.\n"), disk_device);
1221 fprintf (stderr, _("%s contains no disklabel.\n"),
1222 partname(disk_device, xbsd_part_index+1, 0));
1226 c = read_char (_("Do you want to create a disklabel? (y/n) "));
1227 if (c == 'y' || c == 'Y') {
1228 if (xbsd_initlabel (
1229 #if defined (__alpha__) || defined (__powerpc__) || defined (__hppa__) || \
1230 defined (__s390__) || defined (__s390x__)
1231 NULL, &xbsd_dlabel, 0
1233 xbsd_part, &xbsd_dlabel, xbsd_part_index
1236 xbsd_print_disklabel (1);
1240 } else if (c == 'n')
1246 edit_int (int def, char *mesg)
1249 fputs (mesg, stdout);
1250 printf (" (%d): ", def);
1254 while (!isdigit (*line_ptr));
1255 return atoi (line_ptr);
1259 xbsd_edit_disklabel (void)
1261 struct xbsd_disklabel *d;
1265 #if defined (__alpha__) || defined (__ia64__)
1266 d -> d_secsize = (u_long) edit_int ((u_long) d -> d_secsize ,_("bytes/sector"));
1267 d -> d_nsectors = (u_long) edit_int ((u_long) d -> d_nsectors ,_("sectors/track"));
1268 d -> d_ntracks = (u_long) edit_int ((u_long) d -> d_ntracks ,_("tracks/cylinder"));
1269 d -> d_ncylinders = (u_long) edit_int ((u_long) d -> d_ncylinders ,_("cylinders"));
1272 /* d -> d_secpercyl can be != d -> d_nsectors * d -> d_ntracks */
1275 d -> d_secpercyl = (u_long) edit_int ((u_long) d -> d_nsectors * d -> d_ntracks,
1276 _("sectors/cylinder"));
1277 if (d -> d_secpercyl <= d -> d_nsectors * d -> d_ntracks)
1280 printf (_("Must be <= sectors/track * tracks/cylinder (default).\n"));
1282 d -> d_rpm = (u_short) edit_int ((u_short) d -> d_rpm ,_("rpm"));
1283 d -> d_interleave = (u_short) edit_int ((u_short) d -> d_interleave,_("interleave"));
1284 d -> d_trackskew = (u_short) edit_int ((u_short) d -> d_trackskew ,_("trackskew"));
1285 d -> d_cylskew = (u_short) edit_int ((u_short) d -> d_cylskew ,_("cylinderskew"));
1286 d -> d_headswitch = (u_long) edit_int ((u_long) d -> d_headswitch ,_("headswitch"));
1287 d -> d_trkseek = (u_long) edit_int ((u_long) d -> d_trkseek ,_("track-to-track seek"));
1289 d -> d_secperunit = d -> d_secpercyl * d -> d_ncylinders;
1293 xbsd_get_bootstrap (char *path, void *ptr, int size)
1297 if ((fdb = open (path, O_RDONLY)) < 0)
1302 if (read (fdb, ptr, size) < 0)
1308 printf (" ... %s\n", path);
1316 printf (_("\nSyncing disks.\n"));
1322 xbsd_write_bootstrap (void)
1324 char *bootdir = BSD_LINUX_BOOTDIR;
1325 char path[MAXPATHLEN];
1327 struct xbsd_disklabel dl;
1331 if (xbsd_dlabel.d_type == BSD_DTYPE_SCSI)
1336 printf (_("Bootstrap: %sboot -> boot%s (%s): "),
1337 dkbasename, dkbasename, dkbasename);
1339 line_ptr[strlen (line_ptr)-1] = '\0';
1340 dkbasename = line_ptr;
1342 snprintf (path, sizeof(path), "%s/%sboot", bootdir, dkbasename);
1343 if (!xbsd_get_bootstrap (path, disklabelbuffer, (int) xbsd_dlabel.d_secsize))
1346 /* We need a backup of the disklabel (xbsd_dlabel might have changed). */
1347 d = &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE];
1348 bcopy (d, &dl, sizeof (struct xbsd_disklabel));
1350 /* The disklabel will be overwritten by 0's from bootxx anyway */
1351 bzero (d, sizeof (struct xbsd_disklabel));
1353 snprintf (path, sizeof(path), "%s/boot%s", bootdir, dkbasename);
1354 if (!xbsd_get_bootstrap (path, &disklabelbuffer[xbsd_dlabel.d_secsize],
1355 (int) xbsd_dlabel.d_bbsize - xbsd_dlabel.d_secsize))
1358 e = d + sizeof (struct xbsd_disklabel);
1359 for (p=d; p < e; p++)
1361 fprintf (stderr, _("Bootstrap overlaps with disk label!\n"));
1362 exit ( EXIT_FAILURE );
1365 bcopy (&dl, d, sizeof (struct xbsd_disklabel));
1367 #if defined (__powerpc__) || defined (__hppa__)
1369 #elif defined (__alpha__)
1371 alpha_bootblock_checksum (disklabelbuffer);
1373 sector = get_start_sect(xbsd_part);
1376 if (lseek (fd, sector * SECTOR_SIZE, SEEK_SET) == -1)
1377 fdisk_fatal (unable_to_seek);
1378 if (BSD_BBSIZE != write (fd, disklabelbuffer, BSD_BBSIZE))
1379 fdisk_fatal (unable_to_write);
1381 #if defined (__alpha__)
1382 printf (_("Bootstrap installed on %s.\n"), disk_device);
1384 printf (_("Bootstrap installed on %s.\n"),
1385 partname (disk_device, xbsd_part_index+1, 0));
1392 xbsd_change_fstype (void)
1396 i = xbsd_get_part_index (xbsd_dlabel.d_npartitions);
1397 xbsd_dlabel.d_partitions[i].p_fstype = read_hex (xbsd_fstypes);
1401 xbsd_get_part_index (int max)
1406 snprintf (prompt, sizeof(prompt), _("Partition (a-%c): "), 'a' + max - 1);
1408 l = tolower (read_char (prompt));
1409 while (l < 'a' || l > 'a' + max - 1);
1414 xbsd_check_new_partition (int *i) {
1416 /* room for more? various BSD flavours have different maxima */
1417 if (xbsd_dlabel.d_npartitions == BSD_MAXPARTITIONS) {
1420 for (t = 0; t < BSD_MAXPARTITIONS; t++)
1421 if (xbsd_dlabel.d_partitions[t].p_size == 0)
1424 if (t == BSD_MAXPARTITIONS) {
1425 fprintf (stderr, _("The maximum number of partitions "
1426 "has been created\n"));
1431 *i = xbsd_get_part_index (BSD_MAXPARTITIONS);
1433 if (*i >= xbsd_dlabel.d_npartitions)
1434 xbsd_dlabel.d_npartitions = (*i) + 1;
1436 if (xbsd_dlabel.d_partitions[*i].p_size != 0) {
1437 fprintf (stderr, _("This partition already exists.\n"));
1445 xbsd_list_types (void) {
1446 list_types (xbsd_fstypes);
1450 xbsd_dkcksum (struct xbsd_disklabel *lp) {
1451 u_short *start, *end;
1454 start = (u_short *) lp;
1455 end = (u_short *) &lp->d_partitions[lp->d_npartitions];
1462 xbsd_initlabel (struct partition *p, struct xbsd_disklabel *d, int pindex) {
1463 struct xbsd_partition *pp;
1466 bzero (d, sizeof (struct xbsd_disklabel));
1468 d -> d_magic = BSD_DISKMAGIC;
1470 if (strncmp (disk_device, "/dev/sd", 7) == 0)
1471 d -> d_type = BSD_DTYPE_SCSI;
1473 d -> d_type = BSD_DTYPE_ST506;
1475 #if 0 /* not used (at least not written to disk) by NetBSD/i386 1.0 */
1476 d -> d_subtype = BSD_DSTYPE_INDOSPART & pindex;
1479 #if !defined (__alpha__)
1480 d -> d_flags = BSD_D_DOSPART;
1484 d -> d_secsize = SECTOR_SIZE; /* bytes/sector */
1485 d -> d_nsectors = sectors; /* sectors/track */
1486 d -> d_ntracks = heads; /* tracks/cylinder (heads) */
1487 d -> d_ncylinders = cylinders;
1488 d -> d_secpercyl = sectors * heads;/* sectors/cylinder */
1489 if (d -> d_secpercyl == 0)
1490 d -> d_secpercyl = 1; /* avoid segfaults */
1491 d -> d_secperunit = d -> d_secpercyl * d -> d_ncylinders;
1494 d -> d_interleave = 1;
1495 d -> d_trackskew = 0;
1497 d -> d_headswitch = 0;
1500 d -> d_magic2 = BSD_DISKMAGIC;
1501 d -> d_bbsize = BSD_BBSIZE;
1502 d -> d_sbsize = BSD_SBSIZE;
1504 #if !defined (__alpha__)
1505 d -> d_npartitions = 4;
1506 pp = &d -> d_partitions[2]; /* Partition C should be
1507 the NetBSD partition */
1508 pp -> p_offset = get_start_sect(p);
1509 pp -> p_size = get_nr_sects(p);
1510 pp -> p_fstype = BSD_FS_UNUSED;
1511 pp = &d -> d_partitions[3]; /* Partition D should be
1514 pp -> p_size = d -> d_secperunit;
1515 pp -> p_fstype = BSD_FS_UNUSED;
1516 #elif defined (__alpha__)
1517 d -> d_npartitions = 3;
1518 pp = &d -> d_partitions[2]; /* Partition C should be
1521 pp -> p_size = d -> d_secperunit;
1522 pp -> p_fstype = BSD_FS_UNUSED;
1529 * Read a xbsd_disklabel from sector 0 or from the starting sector of p.
1530 * If it has the right magic, return 1.
1533 xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d)
1537 /* p is used only to get the starting sector */
1538 #if !defined (__alpha__)
1539 sector = (p ? get_start_sect(p) : 0);
1540 #elif defined (__alpha__)
1544 if (lseek (fd, sector * SECTOR_SIZE, SEEK_SET) == -1)
1545 fdisk_fatal (unable_to_seek);
1546 if (BSD_BBSIZE != read (fd, disklabelbuffer, BSD_BBSIZE))
1547 fdisk_fatal (unable_to_read);
1549 bcopy (&disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
1550 d, sizeof (struct xbsd_disklabel));
1552 if (d -> d_magic != BSD_DISKMAGIC || d -> d_magic2 != BSD_DISKMAGIC)
1555 for (t = d -> d_npartitions; t < BSD_MAXPARTITIONS; t++) {
1556 d -> d_partitions[t].p_size = 0;
1557 d -> d_partitions[t].p_offset = 0;
1558 d -> d_partitions[t].p_fstype = BSD_FS_UNUSED;
1561 if (d -> d_npartitions > BSD_MAXPARTITIONS)
1562 fprintf (stderr, _("Warning: too many partitions "
1563 "(%d, maximum is %d).\n"),
1564 d -> d_npartitions, BSD_MAXPARTITIONS);
1569 xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d)
1571 unsigned int sector;
1573 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
1574 sector = get_start_sect(p) + BSD_LABELSECTOR;
1576 sector = BSD_LABELSECTOR;
1579 d -> d_checksum = 0;
1580 d -> d_checksum = xbsd_dkcksum (d);
1582 /* This is necessary if we want to write the bootstrap later,
1583 otherwise we'd write the old disklabel with the bootstrap.
1585 bcopy (d, &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
1586 sizeof (struct xbsd_disklabel));
1588 #if defined (__alpha__) && BSD_LABELSECTOR == 0
1589 alpha_bootblock_checksum (disklabelbuffer);
1590 if (lseek (fd, 0, SEEK_SET) == -1)
1591 fdisk_fatal (unable_to_seek);
1592 if (BSD_BBSIZE != write (fd, disklabelbuffer, BSD_BBSIZE))
1593 fdisk_fatal (unable_to_write);
1595 if (lseek (fd, sector * SECTOR_SIZE + BSD_LABELOFFSET,
1597 fdisk_fatal (unable_to_seek);
1598 if (sizeof (struct xbsd_disklabel) != write (fd, d, sizeof (struct xbsd_disklabel)))
1599 fdisk_fatal (unable_to_write);
1608 #if !defined (__alpha__)
1610 xbsd_translate_fstype (int linux_type)
1614 case 0x01: /* DOS 12-bit FAT */
1615 case 0x04: /* DOS 16-bit <32M */
1616 case 0x06: /* DOS 16-bit >=32M */
1617 case 0xe1: /* DOS access */
1618 case 0xe3: /* DOS R/O */
1619 case 0xf2: /* DOS secondary */
1620 return BSD_FS_MSDOS;
1621 case 0x07: /* OS/2 HPFS */
1624 return BSD_FS_OTHER;
1629 xbsd_link_part (void)
1632 struct partition *p;
1634 k = get_partition (1, partitions);
1636 if (!xbsd_check_new_partition (&i))
1639 p = get_part_table(k);
1641 xbsd_dlabel.d_partitions[i].p_size = get_nr_sects(p);
1642 xbsd_dlabel.d_partitions[i].p_offset = get_start_sect(p);
1643 xbsd_dlabel.d_partitions[i].p_fstype = xbsd_translate_fstype(p->sys_ind);
1647 #if defined (__alpha__)
1649 #if !defined(__GLIBC__)
1650 typedef unsigned long long uint64_t;
1654 alpha_bootblock_checksum (char *boot)
1659 dp = (uint64_t *)boot;
1661 for (i = 0; i < 63; i++)
1665 #endif /* __alpha__ */
1667 #endif /* OSF_LABEL */
1669 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
1670 static inline unsigned short
1671 __swap16(unsigned short x) {
1672 return (((uint16_t)(x) & 0xFF) << 8) | (((uint16_t)(x) & 0xFF00) >> 8);
1675 static inline uint32_t
1676 __swap32(uint32_t x) {
1677 return (((x & 0xFF) << 24) |
1678 ((x & 0xFF00) << 8) |
1679 ((x & 0xFF0000) >> 8) |
1680 ((x & 0xFF000000) >> 24));
1684 #ifdef CONFIG_FEATURE_SGI_LABEL
1689 * Copyright (C) Andreas Neuper, Sep 1998.
1690 * This file may be modified and redistributed under
1691 * the terms of the GNU Public License.
1693 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
1694 * Internationalization
1698 static int sgi_other_endian;
1700 static short sgi_volumes=1;
1703 * only dealing with free blocks here
1706 typedef struct { unsigned int first; unsigned int last; } freeblocks;
1707 static freeblocks freelist[17]; /* 16 partitions can produce 17 vacant slots */
1710 setfreelist(int i, unsigned int f, unsigned int l) {
1711 freelist[i].first = f;
1712 freelist[i].last = l;
1716 add2freelist(unsigned int f, unsigned int l) {
1718 for ( ; i < 17 ; i++)
1719 if (freelist[i].last == 0)
1721 setfreelist(i, f, l);
1725 clearfreelist(void) {
1728 for (i = 0; i < 17 ; i++)
1729 setfreelist(i, 0, 0);
1733 isinfreelist(unsigned int b) {
1736 for (i = 0; i < 17 ; i++)
1737 if (freelist[i].first <= b && freelist[i].last >= b)
1738 return freelist[i].last;
1741 /* return last vacant block of this stride (never 0). */
1742 /* the '>=' is not quite correct, but simplifies the code */
1744 * end of free blocks section
1747 static const struct systypes sgi_sys_types[] = {
1748 /* SGI_VOLHDR */ {"\x00" "SGI volhdr" },
1749 /* 0x01 */ {"\x01" "SGI trkrepl" },
1750 /* 0x02 */ {"\x02" "SGI secrepl" },
1751 /* SGI_SWAP */ {"\x03" "SGI raw" },
1752 /* 0x04 */ {"\x04" "SGI bsd" },
1753 /* 0x05 */ {"\x05" "SGI sysv" },
1754 /* ENTIRE_DISK */ {"\x06" "SGI volume" },
1755 /* SGI_EFS */ {"\x07" "SGI efs" },
1756 /* 0x08 */ {"\x08" "SGI lvol" },
1757 /* 0x09 */ {"\x09" "SGI rlvol" },
1758 /* SGI_XFS */ {"\x0a" "SGI xfs" },
1759 /* SGI_XFSLOG */ {"\x0b" "SGI xfslog" },
1760 /* SGI_XLV */ {"\x0c" "SGI xlv" },
1761 /* SGI_XVM */ {"\x0d" "SGI xvm" },
1762 /* LINUX_SWAP */ {"\x82" "Linux swap" },
1763 /* LINUX_NATIVE */ {"\x83" "Linux native" },
1764 /* LINUX_LVM */ {"\x8d" "Linux LVM" },
1765 /* LINUX_RAID */ {"\xfd" "Linux RAID" },
1771 sgi_get_nsect(void) {
1772 return SGI_SSWAP16(sgilabel->devparam.nsect);
1776 sgi_get_ntrks(void) {
1777 return SGI_SSWAP16(sgilabel->devparam.ntrks);
1782 sgilabel->magic = 0;
1788 two_s_complement_32bit_sum(unsigned int* base, int size /* in bytes */) {
1792 size /= sizeof(unsigned int);
1793 for (i = 0; i < size; i++)
1794 sum -= SGI_SSWAP32(base[i]);
1799 check_sgi_label(void) {
1800 if (sizeof(sgilabel) > 512) {
1802 _("According to MIPS Computer Systems, Inc the "
1803 "Label must not contain more than 512 bytes\n"));
1807 if (sgilabel->magic != SGI_LABEL_MAGIC &&
1808 sgilabel->magic != SGI_LABEL_MAGIC_SWAPPED) {
1810 sgi_other_endian = 0;
1814 sgi_other_endian = (sgilabel->magic == SGI_LABEL_MAGIC_SWAPPED);
1816 * test for correct checksum
1818 if (two_s_complement_32bit_sum((unsigned int*)sgilabel,
1819 sizeof(*sgilabel))) {
1821 _("Detected sgi disklabel with wrong checksum.\n"));
1831 sgi_get_start_sector(int i) {
1832 return SGI_SSWAP32(sgilabel->partitions[i].start_sector);
1836 sgi_get_num_sectors(int i) {
1837 return SGI_SSWAP32(sgilabel->partitions[i].num_sectors);
1841 sgi_get_sysid(int i)
1843 return SGI_SSWAP32(sgilabel->partitions[i].id);
1847 sgi_get_bootpartition(void)
1849 return SGI_SSWAP16(sgilabel->boot_part);
1853 sgi_get_swappartition(void)
1855 return SGI_SSWAP16(sgilabel->swap_part);
1859 sgi_list_table(int xtra) {
1861 int kpi = 0; /* kernel partition ID */
1864 printf(_("\nDisk %s (SGI disk label): %d heads, %d sectors\n"
1865 "%d cylinders, %d physical cylinders\n"
1866 "%d extra sects/cyl, interleave %d:1\n"
1868 "Units = %s of %d * 512 bytes\n\n"),
1869 disk_device, heads, sectors, cylinders,
1870 SGI_SSWAP16(sgiparam.pcylcount),
1871 SGI_SSWAP16(sgiparam.sparecyl),
1872 SGI_SSWAP16(sgiparam.ilfact),
1874 str_units(PLURAL), units_per_sector);
1876 printf( _("\nDisk %s (SGI disk label): "
1877 "%d heads, %d sectors, %d cylinders\n"
1878 "Units = %s of %d * 512 bytes\n\n"),
1879 disk_device, heads, sectors, cylinders,
1880 str_units(PLURAL), units_per_sector );
1883 w = strlen(disk_device);
1884 wd = strlen(_("Device"));
1888 printf(_("----- partitions -----\n"
1889 "Pt# %*s Info Start End Sectors Id System\n"),
1890 w + 2, _("Device"));
1891 for (i = 0 ; i < partitions; i++) {
1892 if( sgi_get_num_sectors(i) || debug ) {
1893 uint32_t start = sgi_get_start_sector(i);
1894 uint32_t len = sgi_get_num_sectors(i);
1895 kpi++; /* only count nonempty partitions */
1897 "%2d: %s %4s %9ld %9ld %9ld %2x %s\n",
1898 /* fdisk part number */ i+1,
1899 /* device */ partname(disk_device, kpi, w+3),
1900 /* flags */ (sgi_get_swappartition() == i) ? "swap" :
1901 /* flags */ (sgi_get_bootpartition() == i) ? "boot" : " ",
1902 /* start */ (long) scround(start),
1903 /* end */ (long) scround(start+len)-1,
1904 /* no odd flag on end */ (long) len,
1905 /* type id */ sgi_get_sysid(i),
1906 /* type name */ partition_type(sgi_get_sysid(i)));
1909 printf(_("----- Bootinfo -----\nBootfile: %s\n"
1910 "----- Directory Entries -----\n"),
1911 sgilabel->boot_file);
1912 for (i = 0 ; i < sgi_volumes; i++) {
1913 if (sgilabel->directory[i].vol_file_size) {
1914 uint32_t start = SGI_SSWAP32(sgilabel->directory[i].vol_file_start);
1915 uint32_t len = SGI_SSWAP32(sgilabel->directory[i].vol_file_size);
1916 char*name = sgilabel->directory[i].vol_file_name;
1918 printf(_("%2d: %-10s sector%5u size%8u\n"),
1919 i, name, (unsigned int) start, (unsigned int) len);
1925 sgi_set_bootpartition( int i )
1927 sgilabel->boot_part = SGI_SSWAP16(((short)i));
1931 sgi_get_lastblock(void) {
1932 return heads * sectors * cylinders;
1936 sgi_set_swappartition( int i ) {
1937 sgilabel->swap_part = SGI_SSWAP16(((short)i));
1941 sgi_check_bootfile(const char* aFile) {
1943 if (strlen(aFile) < 3) /* "/a\n" is minimum */ {
1944 printf(_("\nInvalid Bootfile!\n"
1945 "\tThe bootfile must be an absolute non-zero pathname,\n"
1946 "\te.g. \"/unix\" or \"/unix.save\".\n"));
1949 if (strlen(aFile) > 16) {
1950 printf(_("\n\tName of Bootfile too long: "
1951 "16 bytes maximum.\n"));
1954 if (aFile[0] != '/') {
1955 printf(_("\n\tBootfile must have a "
1956 "fully qualified pathname.\n"));
1961 if (strncmp(aFile, sgilabel->boot_file, 16)) {
1962 printf(_("\n\tBe aware, that the bootfile is not checked for existence.\n\t"
1963 "SGI's default is \"/unix\" and for backup \"/unix.save\".\n"));
1964 /* filename is correct and did change */
1967 return 0; /* filename did not change */
1971 sgi_get_bootfile(void) {
1972 return sgilabel->boot_file;
1976 sgi_set_bootfile(const char* aFile) {
1979 if (sgi_check_bootfile(aFile)) {
1981 if ((aFile[i] != '\n') /* in principle caught again by next line */
1982 && (strlen(aFile) > i))
1983 sgilabel->boot_file[i] = aFile[i];
1985 sgilabel->boot_file[i] = 0;
1988 printf(_("\n\tBootfile is changed to \"%s\".\n"), sgilabel->boot_file);
1993 create_sgiinfo(void)
1995 /* I keep SGI's habit to write the sgilabel to the second block */
1996 sgilabel->directory[0].vol_file_start = SGI_SSWAP32(2);
1997 sgilabel->directory[0].vol_file_size = SGI_SSWAP32(sizeof(sgiinfo));
1998 strncpy(sgilabel->directory[0].vol_file_name, "sgilabel", 8);
2001 static sgiinfo *fill_sgiinfo(void);
2004 sgi_write_table(void) {
2006 sgilabel->csum = SGI_SSWAP32(two_s_complement_32bit_sum(
2007 (unsigned int*)sgilabel,
2008 sizeof(*sgilabel)));
2009 assert(two_s_complement_32bit_sum(
2010 (unsigned int*)sgilabel, sizeof(*sgilabel)) == 0);
2011 if (lseek(fd, 0, SEEK_SET) < 0)
2012 fdisk_fatal(unable_to_seek);
2013 if (write(fd, sgilabel, SECTOR_SIZE) != SECTOR_SIZE)
2014 fdisk_fatal(unable_to_write);
2015 if (! strncmp(sgilabel->directory[0].vol_file_name, "sgilabel", 8)) {
2017 * keep this habit of first writing the "sgilabel".
2018 * I never tested whether it works without (AN 981002).
2020 sgiinfo *info = fill_sgiinfo();
2021 int infostartblock = SGI_SSWAP32(sgilabel->directory[0].vol_file_start);
2022 if (lseek(fd, infostartblock*SECTOR_SIZE, SEEK_SET) < 0)
2023 fdisk_fatal(unable_to_seek);
2024 if (write(fd, info, SECTOR_SIZE) != SECTOR_SIZE)
2025 fdisk_fatal(unable_to_write);
2031 compare_start(int *x, int *y) {
2033 * sort according to start sectors
2034 * and prefers largest partition:
2035 * entry zero is entire disk entry
2037 unsigned int i = *x;
2038 unsigned int j = *y;
2039 unsigned int a = sgi_get_start_sector(i);
2040 unsigned int b = sgi_get_start_sector(j);
2041 unsigned int c = sgi_get_num_sectors(i);
2042 unsigned int d = sgi_get_num_sectors(j);
2045 return (d > c) ? 1 : (d == c) ? 0 : -1;
2046 return (a > b) ? 1 : -1;
2051 verify_sgi(int verbose)
2053 int Index[16]; /* list of valid partitions */
2054 int sortcount = 0; /* number of used partitions, i.e. non-zero lengths */
2055 int entire = 0, i = 0;
2056 unsigned int start = 0;
2057 long long gap = 0; /* count unused blocks */
2058 unsigned int lastblock = sgi_get_lastblock();
2061 for (i=0; i<16; i++) {
2062 if (sgi_get_num_sectors(i) != 0) {
2063 Index[sortcount++]=i;
2064 if (sgi_get_sysid(i) == ENTIRE_DISK) {
2065 if (entire++ == 1) {
2067 printf(_("More than one entire disk entry present.\n"));
2072 if (sortcount == 0) {
2074 printf(_("No partitions defined\n"));
2075 return (lastblock > 0) ? 1 : (lastblock == 0) ? 0 : -1;
2077 qsort(Index, sortcount, sizeof(Index[0]), (void*)compare_start);
2078 if (sgi_get_sysid(Index[0]) == ENTIRE_DISK) {
2079 if ((Index[0] != 10) && verbose)
2080 printf(_("IRIX likes when Partition 11 covers the entire disk.\n"));
2081 if ((sgi_get_start_sector(Index[0]) != 0) && verbose)
2082 printf(_("The entire disk partition should start "
2084 "not at diskblock %d.\n"),
2085 sgi_get_start_sector(Index[0]));
2086 if (debug) /* I do not understand how some disks fulfil it */
2087 if ((sgi_get_num_sectors(Index[0]) != lastblock) && verbose)
2088 printf(_("The entire disk partition is only %d diskblock large,\n"
2089 "but the disk is %d diskblocks long.\n"),
2090 sgi_get_num_sectors(Index[0]), lastblock);
2091 lastblock = sgi_get_num_sectors(Index[0]);
2094 printf(_("One Partition (#11) should cover the entire disk.\n"));
2096 printf("sysid=%d\tpartition=%d\n",
2097 sgi_get_sysid(Index[0]), Index[0]+1);
2099 for (i=1, start=0; i<sortcount; i++) {
2100 int cylsize = sgi_get_nsect() * sgi_get_ntrks();
2102 if ((sgi_get_start_sector(Index[i]) % cylsize) != 0) {
2103 if (debug) /* I do not understand how some disks fulfil it */
2105 printf(_("Partition %d does not start on cylinder boundary.\n"),
2108 if (sgi_get_num_sectors(Index[i]) % cylsize != 0) {
2109 if (debug) /* I do not understand how some disks fulfil it */
2111 printf(_("Partition %d does not end on cylinder boundary.\n"),
2114 /* We cannot handle several "entire disk" entries. */
2115 if (sgi_get_sysid(Index[i]) == ENTIRE_DISK) continue;
2116 if (start > sgi_get_start_sector(Index[i])) {
2118 printf(_("The Partition %d and %d overlap by %d sectors.\n"),
2119 Index[i-1]+1, Index[i]+1,
2120 start - sgi_get_start_sector(Index[i]));
2121 if (gap > 0) gap = -gap;
2122 if (gap == 0) gap = -1;
2124 if (start < sgi_get_start_sector(Index[i])) {
2126 printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"),
2127 sgi_get_start_sector(Index[i]) - start,
2128 start, sgi_get_start_sector(Index[i])-1);
2129 gap += sgi_get_start_sector(Index[i]) - start;
2130 add2freelist(start, sgi_get_start_sector(Index[i]));
2132 start = sgi_get_start_sector(Index[i])
2133 + sgi_get_num_sectors(Index[i]);
2136 printf("%2d:%12d\t%12d\t%12d\n", Index[i],
2137 sgi_get_start_sector(Index[i]),
2138 sgi_get_num_sectors(Index[i]),
2139 sgi_get_sysid(Index[i]));
2142 if (start < lastblock) {
2144 printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"),
2145 lastblock - start, start, lastblock-1);
2146 gap += lastblock - start;
2147 add2freelist(start, lastblock);
2150 * Done with arithmetics
2151 * Go for details now
2154 if (!sgi_get_num_sectors(sgi_get_bootpartition())) {
2155 printf(_("\nThe boot partition does not exist.\n"));
2157 if (!sgi_get_num_sectors(sgi_get_swappartition())) {
2158 printf(_("\nThe swap partition does not exist.\n"));
2160 if ((sgi_get_sysid(sgi_get_swappartition()) != SGI_SWAP)
2161 && (sgi_get_sysid(sgi_get_swappartition()) != LINUX_SWAP))
2162 printf(_("\nThe swap partition has no swap type.\n"));
2164 if (sgi_check_bootfile("/unix"))
2165 printf(_("\tYou have chosen an unusual boot file name.\n"));
2167 return (gap > 0) ? 1 : (gap == 0) ? 0 : -1;
2173 * returned value is:
2174 * = 0 : disk is properly filled to the rim
2175 * < 0 : there is an overlap
2176 * > 0 : there is still some vacant space
2178 return verify_sgi(0);
2182 sgi_change_sysid( int i, int sys )
2184 if( sgi_get_num_sectors(i) == 0 ) /* caught already before, ... */
2186 printf(_("Sorry You may change the Tag of non-empty partitions.\n"));
2189 if( ((sys != ENTIRE_DISK ) && (sys != SGI_VOLHDR))
2190 && (sgi_get_start_sector(i)<1) )
2193 _("It is highly recommended that the partition at offset 0\n"
2194 "is of type \"SGI volhdr\", the IRIX system will rely on it to\n"
2195 "retrieve from its directory standalone tools like sash and fx.\n"
2196 "Only the \"SGI volume\" entire disk section may violate this.\n"
2197 "Type YES if you are sure about tagging this partition differently.\n"));
2198 if (strcmp (line_ptr, _("YES\n")))
2201 sgilabel->partitions[i].id = SGI_SSWAP32(sys);
2204 /* returns partition index of first entry marked as entire disk */
2210 if(sgi_get_sysid(i) == SGI_VOLUME)
2216 sgi_set_partition(int i, unsigned int start, unsigned int length, int sys) {
2218 sgilabel->partitions[i].id = SGI_SSWAP32(sys);
2219 sgilabel->partitions[i].num_sectors = SGI_SSWAP32(length);
2220 sgilabel->partitions[i].start_sector = SGI_SSWAP32(start);
2222 if (sgi_gaps() < 0) /* rebuild freelist */
2223 printf(_("Do You know, You got a partition overlap on the disk?\n"));
2227 sgi_set_entire(void) {
2230 for(n=10; n < partitions; n++) {
2231 if(!sgi_get_num_sectors(n) ) {
2232 sgi_set_partition(n, 0, sgi_get_lastblock(), SGI_VOLUME);
2239 sgi_set_volhdr(void)
2242 for( n=8; n<partitions; n++ )
2244 if(!sgi_get_num_sectors( n ) )
2247 * 5 cylinders is an arbitrary value I like
2248 * IRIX 5.3 stored files in the volume header
2249 * (like sash, symmon, fx, ide) with ca. 3200
2252 if( heads * sectors * 5 < sgi_get_lastblock() )
2253 sgi_set_partition( n, 0, heads * sectors * 5, SGI_VOLHDR );
2260 sgi_delete_partition( int i )
2262 sgi_set_partition( i, 0, 0, 0 );
2266 sgi_add_partition( int n, int sys )
2269 unsigned int first=0, last=0;
2273 } else if ( n == 8 ) {
2276 if(sgi_get_num_sectors(n)) {
2277 printf(_("Partition %d is already defined. Delete "
2278 "it before re-adding it.\n"), n + 1);
2281 if( (sgi_entire() == -1) && (sys != SGI_VOLUME) ) {
2282 printf(_("Attempting to generate entire disk entry automatically.\n"));
2286 if( (sgi_gaps() == 0) && (sys != SGI_VOLUME) ) {
2287 printf(_("The entire disk is already covered with partitions.\n"));
2290 if(sgi_gaps() < 0) {
2291 printf(_("You got a partition overlap on the disk. Fix it first!\n"));
2294 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
2296 if(sys == SGI_VOLUME) {
2297 last = sgi_get_lastblock();
2298 first = read_int(0, 0, last-1, 0, mesg);
2300 printf(_("It is highly recommended that eleventh partition\n"
2301 "covers the entire disk and is of type `SGI volume'\n"));
2304 first = freelist[0].first;
2305 last = freelist[0].last;
2306 first = read_int(scround(first), scround(first), scround(last)-1,
2309 if (display_in_cyl_units)
2310 first *= units_per_sector;
2312 first = first; /* align to cylinder if you know how ... */
2314 last = isinfreelist(first);
2316 printf(_("You will get a partition overlap on the disk. "
2317 "Fix it first!\n"));
2321 snprintf(mesg, sizeof(mesg), _(" Last %s"), str_units(SINGULAR));
2322 last = read_int(scround(first), scround(last)-1, scround(last)-1,
2323 scround(first), mesg)+1;
2324 if (display_in_cyl_units)
2325 last *= units_per_sector;
2327 last = last; /* align to cylinder if You know how ... */
2328 if( (sys == SGI_VOLUME) && ( first != 0 || last != sgi_get_lastblock() ) )
2329 printf(_("It is highly recommended that eleventh partition\n"
2330 "covers the entire disk and is of type `SGI volume'\n"));
2331 sgi_set_partition( n, first, last-first, sys );
2334 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
2336 create_sgilabel(void)
2338 struct hd_geometry geometry;
2345 long longsectors; /* the number of sectors on the device */
2346 int res; /* the result from the ioctl */
2347 int sec_fac; /* the sector factor */
2349 sec_fac = sector_size / 512; /* determine the sector factor */
2352 _("Building a new SGI disklabel. Changes will remain in memory only,\n"
2353 "until you decide to write them. After that, of course, the previous\n"
2354 "content will be unrecoverably lost.\n\n"));
2356 sgi_other_endian = (BYTE_ORDER == LITTLE_ENDIAN);
2357 res = ioctl(fd, BLKGETSIZE, &longsectors);
2358 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
2359 heads = geometry.heads;
2360 sectors = geometry.sectors;
2362 /* the get device size ioctl was successful */
2363 cylinders = longsectors / (heads * sectors);
2364 cylinders /= sec_fac;
2366 /* otherwise print error and use truncated version */
2367 cylinders = geometry.cylinders;
2369 _("Warning: BLKGETSIZE ioctl failed on %s. "
2370 "Using geometry cylinder value of %d.\n"
2371 "This value may be truncated for devices"
2372 " > 33.8 GB.\n"), disk_device, cylinders);
2375 for (i = 0; i < 4; i++) {
2377 if(valid_part_table_flag(MBRbuffer)) {
2378 if(get_part_table(i)->sys_ind) {
2379 old[i].sysid = get_part_table(i)->sys_ind;
2380 old[i].start = get_start_sect(get_part_table(i));
2381 old[i].nsect = get_nr_sects(get_part_table(i));
2382 printf(_("Trying to keep parameters of partition %d.\n"), i);
2384 printf(_("ID=%02x\tSTART=%d\tLENGTH=%d\n"),
2385 old[i].sysid, old[i].start, old[i].nsect);
2390 memset(MBRbuffer, 0, sizeof(MBRbuffer));
2391 sgilabel->magic = SGI_SSWAP32(SGI_LABEL_MAGIC);
2392 sgilabel->boot_part = SGI_SSWAP16(0);
2393 sgilabel->swap_part = SGI_SSWAP16(1);
2395 /* sizeof(sgilabel->boot_file) = 16 > 6 */
2396 memset(sgilabel->boot_file, 0, 16);
2397 strcpy(sgilabel->boot_file, "/unix");
2399 sgilabel->devparam.skew = (0);
2400 sgilabel->devparam.gap1 = (0);
2401 sgilabel->devparam.gap2 = (0);
2402 sgilabel->devparam.sparecyl = (0);
2403 sgilabel->devparam.pcylcount = SGI_SSWAP16(geometry.cylinders);
2404 sgilabel->devparam.head_vol0 = SGI_SSWAP16(0);
2405 sgilabel->devparam.ntrks = SGI_SSWAP16(geometry.heads);
2406 /* tracks/cylinder (heads) */
2407 sgilabel->devparam.cmd_tag_queue_depth = (0);
2408 sgilabel->devparam.unused0 = (0);
2409 sgilabel->devparam.unused1 = SGI_SSWAP16(0);
2410 sgilabel->devparam.nsect = SGI_SSWAP16(geometry.sectors);
2412 sgilabel->devparam.bytes = SGI_SSWAP16(512);
2413 sgilabel->devparam.ilfact = SGI_SSWAP16(1);
2414 sgilabel->devparam.flags = SGI_SSWAP32(TRACK_FWD|
2415 IGNORE_ERRORS|RESEEK);
2416 sgilabel->devparam.datarate = SGI_SSWAP32(0);
2417 sgilabel->devparam.retries_on_error = SGI_SSWAP32(1);
2418 sgilabel->devparam.ms_per_word = SGI_SSWAP32(0);
2419 sgilabel->devparam.xylogics_gap1 = SGI_SSWAP16(0);
2420 sgilabel->devparam.xylogics_syncdelay = SGI_SSWAP16(0);
2421 sgilabel->devparam.xylogics_readdelay = SGI_SSWAP16(0);
2422 sgilabel->devparam.xylogics_gap2 = SGI_SSWAP16(0);
2423 sgilabel->devparam.xylogics_readgate = SGI_SSWAP16(0);
2424 sgilabel->devparam.xylogics_writecont = SGI_SSWAP16(0);
2425 memset( &(sgilabel->directory), 0, sizeof(struct volume_directory)*15 );
2426 memset( &(sgilabel->partitions), 0, sizeof(struct sgi_partition)*16 );
2432 for (i = 0; i < 4; i++) {
2434 sgi_set_partition(i, old[i].start, old[i].nsect, old[i].sysid);
2442 /* do nothing in the beginning */
2444 #endif /* CONFIG_FEATURE_FDISK_ADVANCED */
2446 /* _____________________________________________________________
2452 sgiinfo *info = calloc(1, sizeof(sgiinfo));
2454 info->magic=SGI_SSWAP32(SGI_INFO_MAGIC);
2455 info->b1=SGI_SSWAP32(-1);
2456 info->b2=SGI_SSWAP16(-1);
2457 info->b3=SGI_SSWAP16(1);
2458 /* You may want to replace this string !!!!!!! */
2459 strcpy( info->scsi_string, "IBM OEM 0662S12 3 30" );
2460 strcpy( info->serial, "0000" );
2461 info->check1816 = SGI_SSWAP16(18*256 +16 );
2462 strcpy( info->installer, "Sfx version 5.3, Oct 18, 1994" );
2465 #endif /* SGI_LABEL */
2468 #ifdef CONFIG_FEATURE_SUN_LABEL
2472 * I think this is mostly, or entirely, due to
2473 * Jakub Jelinek (jj@sunsite.mff.cuni.cz), July 1996
2475 * Merged with fdisk for other architectures, aeb, June 1998.
2477 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
2478 * Internationalization
2482 static int sun_other_endian;
2483 static int scsi_disk;
2487 #define IDE0_MAJOR 3
2490 #define IDE1_MAJOR 22
2493 static void guess_device_type(void) {
2494 struct stat bootstat;
2496 if (fstat (fd, &bootstat) < 0) {
2499 } else if (S_ISBLK(bootstat.st_mode)
2500 && (major(bootstat.st_rdev) == IDE0_MAJOR ||
2501 major(bootstat.st_rdev) == IDE1_MAJOR)) {
2504 } else if (S_ISBLK(bootstat.st_mode)
2505 && major(bootstat.st_rdev) == FLOPPY_MAJOR) {
2514 static const struct systypes sun_sys_types[] = {
2515 /* 0 */ {"\x00" "Empty" },
2516 /* 1 */ {"\x01" "Boot" },
2517 /* 2 */ {"\x02" "SunOS root" },
2518 /* SUNOS_SWAP */ {"\x03" "SunOS swap" },
2519 /* 4 */ {"\x04" "SunOS usr" },
2520 /* WHOLE_DISK */ {"\x05" "Whole disk" },
2521 /* 6 */ {"\x06" "SunOS stand" },
2522 /* 7 */ {"\x07" "SunOS var" },
2523 /* 8 */ {"\x08" "SunOS home" },
2524 /* LINUX_SWAP */ {"\x82" "Linux swap" },
2525 /* LINUX_NATIVE */ {"\x83" "Linux native" },
2526 /* 0x8e */ {"\x8e" "Linux LVM" },
2527 /* New (2.2.x) raid partition with autodetect using persistent superblock */
2528 /* 0xfd */ {"\xfd" "Linux raid autodetect" },
2534 set_sun_partition(int i, uint start, uint stop, int sysid) {
2535 sunlabel->infos[i].id = sysid;
2536 sunlabel->partitions[i].start_cylinder =
2537 SUN_SSWAP32(start / (heads * sectors));
2538 sunlabel->partitions[i].num_sectors =
2539 SUN_SSWAP32(stop - start);
2546 sunlabel->magic = 0;
2551 check_sun_label(void) {
2552 unsigned short *ush;
2555 if (sunlabel->magic != SUN_LABEL_MAGIC &&
2556 sunlabel->magic != SUN_LABEL_MAGIC_SWAPPED) {
2558 sun_other_endian = 0;
2561 sun_other_endian = (sunlabel->magic == SUN_LABEL_MAGIC_SWAPPED);
2562 ush = ((unsigned short *) (sunlabel + 1)) - 1;
2563 for (csum = 0; ush >= (unsigned short *)sunlabel;) csum ^= *ush--;
2565 fprintf(stderr,_("Detected sun disklabel with wrong checksum.\n"
2566 "Probably you'll have to set all the values,\n"
2567 "e.g. heads, sectors, cylinders and partitions\n"
2568 "or force a fresh label (s command in main menu)\n"));
2570 heads = SUN_SSWAP16(sunlabel->ntrks);
2571 cylinders = SUN_SSWAP16(sunlabel->ncyl);
2572 sectors = SUN_SSWAP16(sunlabel->nsect);
2580 static const struct sun_predefined_drives {
2583 unsigned short sparecyl;
2584 unsigned short ncyl;
2585 unsigned short nacyl;
2586 unsigned short pcylcount;
2587 unsigned short ntrks;
2588 unsigned short nsect;
2589 unsigned short rspeed;
2591 {"Quantum","ProDrive 80S",1,832,2,834,6,34,3662},
2592 {"Quantum","ProDrive 105S",1,974,2,1019,6,35,3662},
2593 {"CDC","Wren IV 94171-344",3,1545,2,1549,9,46,3600},
2594 {"IBM","DPES-31080",0,4901,2,4903,4,108,5400},
2595 {"IBM","DORS-32160",0,1015,2,1017,67,62,5400},
2596 {"IBM","DNES-318350",0,11199,2,11474,10,320,7200},
2597 {"SEAGATE","ST34371",0,3880,2,3882,16,135,7228},
2598 {"","SUN0104",1,974,2,1019,6,35,3662},
2599 {"","SUN0207",4,1254,2,1272,9,36,3600},
2600 {"","SUN0327",3,1545,2,1549,9,46,3600},
2601 {"","SUN0340",0,1538,2,1544,6,72,4200},
2602 {"","SUN0424",2,1151,2,2500,9,80,4400},
2603 {"","SUN0535",0,1866,2,2500,7,80,5400},
2604 {"","SUN0669",5,1614,2,1632,15,54,3600},
2605 {"","SUN1.0G",5,1703,2,1931,15,80,3597},
2606 {"","SUN1.05",0,2036,2,2038,14,72,5400},
2607 {"","SUN1.3G",6,1965,2,3500,17,80,5400},
2608 {"","SUN2.1G",0,2733,2,3500,19,80,5400},
2609 {"IOMEGA","Jaz",0,1019,2,1021,64,32,5394},
2612 static const struct sun_predefined_drives *
2613 sun_autoconfigure_scsi(void) {
2614 const struct sun_predefined_drives *p = NULL;
2616 #ifdef SCSI_IOCTL_GET_IDLUN
2626 if (!ioctl(fd, SCSI_IOCTL_GET_IDLUN, &id)) {
2628 "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n",
2630 ((id[0]>>24)&0xff)-/*PROC_SCSI_SCSI+PROC_SCSI_FILE*/33,
2632 /* This is very wrong (works only if you have one HBA),
2633 but I haven't found a way how to get hostno
2634 from the current kernel */
2640 pfd = fopen("/proc/scsi/scsi","r");
2642 while (fgets(buffer2,2048,pfd)) {
2643 if (!strcmp(buffer, buffer2)) {
2644 if (fgets(buffer2,2048,pfd)) {
2645 q = strstr(buffer2,"Vendor: ");
2650 *q++ = 0; /* truncate vendor name */
2651 q = strstr(q,"Model: ");
2656 q = strstr(q," Rev: ");
2659 for (i = 0; i < SIZE(sun_drives); i++) {
2660 if (*sun_drives[i].vendor && strcasecmp(sun_drives[i].vendor, vendor))
2662 if (!strstr(model, sun_drives[i].model))
2664 printf(_("Autoconfigure found a %s%s%s\n"),sun_drives[i].vendor,(*sun_drives[i].vendor) ? " " : "",sun_drives[i].model);
2682 static void create_sunlabel(void)
2684 struct hd_geometry geometry;
2688 const struct sun_predefined_drives *p = NULL;
2691 _("Building a new sun disklabel. Changes will remain in memory only,\n"
2692 "until you decide to write them. After that, of course, the previous\n"
2693 "content won't be recoverable.\n\n"));
2694 #if BYTE_ORDER == LITTLE_ENDIAN
2695 sun_other_endian = 1;
2697 sun_other_endian = 0;
2699 memset(MBRbuffer, 0, sizeof(MBRbuffer));
2700 sunlabel->magic = SUN_SSWAP16(SUN_LABEL_MAGIC);
2702 puts(_("Drive type\n"
2703 " ? auto configure\n"
2704 " 0 custom (with hardware detected defaults)"));
2705 for (i = 0; i < SIZE(sun_drives); i++) {
2706 printf(" %c %s%s%s\n",
2707 i + 'a', sun_drives[i].vendor,
2708 (*sun_drives[i].vendor) ? " " : "",
2709 sun_drives[i].model);
2712 c = read_char(_("Select type (? for auto, 0 for custom): "));
2713 if (c >= 'a' && c < 'a' + SIZE(sun_drives)) {
2714 p = sun_drives + c - 'a';
2716 } else if (c >= 'A' && c < 'A' + SIZE(sun_drives)) {
2717 p = sun_drives + c - 'A';
2719 } else if (c == '0') {
2721 } else if (c == '?' && scsi_disk) {
2722 p = sun_autoconfigure_scsi();
2724 printf(_("Autoconfigure failed.\n"));
2731 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
2732 heads = geometry.heads;
2733 sectors = geometry.sectors;
2734 cylinders = geometry.cylinders;
2741 sunlabel->nacyl = 0;
2742 sunlabel->pcylcount = SUN_SSWAP16(cylinders);
2743 sunlabel->rspeed = SUN_SSWAP16(300);
2744 sunlabel->ilfact = SUN_SSWAP16(1);
2745 sunlabel->sparecyl = 0;
2747 heads = read_int(1,heads,1024,0,_("Heads"));
2748 sectors = read_int(1,sectors,1024,0,_("Sectors/track"));
2750 cylinders = read_int(1,cylinders-2,65535,0,_("Cylinders"));
2752 cylinders = read_int(1,0,65535,0,_("Cylinders"));
2754 SUN_SSWAP16(read_int(0,2,65535,0,
2755 _("Alternate cylinders")));
2756 sunlabel->pcylcount =
2757 SUN_SSWAP16(read_int(0,cylinders+SUN_SSWAP16(sunlabel->nacyl),
2758 65535,0,_("Physical cylinders")));
2760 SUN_SSWAP16(read_int(1,5400,100000,0,
2761 _("Rotation speed (rpm)")));
2763 SUN_SSWAP16(read_int(1,1,32,0,_("Interleave factor")));
2764 sunlabel->sparecyl =
2765 SUN_SSWAP16(read_int(0,0,sectors,0,
2766 _("Extra sectors per cylinder")));
2769 sunlabel->sparecyl = SUN_SSWAP16(p->sparecyl);
2770 sunlabel->ncyl = SUN_SSWAP16(p->ncyl);
2771 sunlabel->nacyl = SUN_SSWAP16(p->nacyl);
2772 sunlabel->pcylcount = SUN_SSWAP16(p->pcylcount);
2773 sunlabel->ntrks = SUN_SSWAP16(p->ntrks);
2774 sunlabel->nsect = SUN_SSWAP16(p->nsect);
2775 sunlabel->rspeed = SUN_SSWAP16(p->rspeed);
2776 sunlabel->ilfact = SUN_SSWAP16(1);
2777 cylinders = p->ncyl;
2780 puts(_("You may change all the disk params from the x menu"));
2783 snprintf(sunlabel->info, sizeof(sunlabel->info),
2784 "%s%s%s cyl %d alt %d hd %d sec %d",
2785 p ? p->vendor : "", (p && *p->vendor) ? " " : "",
2787 : (floppy ? _("3,5\" floppy") : _("Linux custom")),
2788 cylinders, SUN_SSWAP16(sunlabel->nacyl), heads, sectors);
2790 sunlabel->ntrks = SUN_SSWAP16(heads);
2791 sunlabel->nsect = SUN_SSWAP16(sectors);
2792 sunlabel->ncyl = SUN_SSWAP16(cylinders);
2794 set_sun_partition(0, 0, cylinders * heads * sectors, LINUX_NATIVE);
2796 if (cylinders * heads * sectors >= 150 * 2048) {
2797 ndiv = cylinders - (50 * 2048 / (heads * sectors)); /* 50M swap */
2799 ndiv = cylinders * 2 / 3;
2800 set_sun_partition(0, 0, ndiv * heads * sectors, LINUX_NATIVE);
2801 set_sun_partition(1, ndiv * heads * sectors, cylinders * heads * sectors, LINUX_SWAP);
2802 sunlabel->infos[1].flags |= 0x01; /* Not mountable */
2804 set_sun_partition(2, 0, cylinders * heads * sectors, WHOLE_DISK);
2806 unsigned short *ush = (unsigned short *)sunlabel;
2807 unsigned short csum = 0;
2808 while(ush < (unsigned short *)(&sunlabel->csum))
2810 sunlabel->csum = csum;
2813 set_all_unchanged();
2815 get_boot(create_empty_sun);
2819 toggle_sunflags(int i, unsigned char mask) {
2820 if (sunlabel->infos[i].flags & mask)
2821 sunlabel->infos[i].flags &= ~mask;
2822 else sunlabel->infos[i].flags |= mask;
2827 fetch_sun(uint *starts, uint *lens, uint *start, uint *stop) {
2828 int i, continuous = 1;
2829 *start = 0; *stop = cylinders * heads * sectors;
2830 for (i = 0; i < partitions; i++) {
2831 if (sunlabel->partitions[i].num_sectors
2832 && sunlabel->infos[i].id
2833 && sunlabel->infos[i].id != WHOLE_DISK) {
2834 starts[i] = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
2835 lens[i] = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
2837 if (starts[i] == *start)
2839 else if (starts[i] + lens[i] >= *stop)
2843 /* There will be probably more gaps
2844 than one, so lets check afterwards */
2853 static uint *verify_sun_starts;
2856 verify_sun_cmp(int *a, int *b) {
2857 if (*a == -1) return 1;
2858 if (*b == -1) return -1;
2859 if (verify_sun_starts[*a] > verify_sun_starts[*b]) return 1;
2865 uint starts[8], lens[8], start, stop;
2866 int i,j,k,starto,endo;
2869 verify_sun_starts = starts;
2870 fetch_sun(starts,lens,&start,&stop);
2871 for (k = 0; k < 7; k++) {
2872 for (i = 0; i < 8; i++) {
2873 if (k && (lens[i] % (heads * sectors))) {
2874 printf(_("Partition %d doesn't end on cylinder boundary\n"), i+1);
2877 for (j = 0; j < i; j++)
2879 if (starts[j] == starts[i]+lens[i]) {
2880 starts[j] = starts[i]; lens[j] += lens[i];
2882 } else if (starts[i] == starts[j]+lens[j]){
2886 if (starts[i] < starts[j]+lens[j] &&
2887 starts[j] < starts[i]+lens[i]) {
2889 if (starts[j] > starto)
2891 endo = starts[i]+lens[i];
2892 if (starts[j]+lens[j] < endo)
2893 endo = starts[j]+lens[j];
2894 printf(_("Partition %d overlaps with others in "
2895 "sectors %d-%d\n"), i+1, starto, endo);
2902 for (i = 0; i < 8; i++) {
2908 qsort(array,SIZE(array),sizeof(array[0]),
2909 (int (*)(const void *,const void *)) verify_sun_cmp);
2910 if (array[0] == -1) {
2911 printf(_("No partitions defined\n"));
2914 stop = cylinders * heads * sectors;
2915 if (starts[array[0]])
2916 printf(_("Unused gap - sectors 0-%d\n"),starts[array[0]]);
2917 for (i = 0; i < 7 && array[i+1] != -1; i++) {
2918 printf(_("Unused gap - sectors %d-%d\n"),starts[array[i]]+lens[array[i]],starts[array[i+1]]);
2920 start = starts[array[i]]+lens[array[i]];
2922 printf(_("Unused gap - sectors %d-%d\n"),start,stop);
2926 add_sun_partition(int n, int sys) {
2927 uint start, stop, stop2;
2928 uint starts[8], lens[8];
2934 if (sunlabel->partitions[n].num_sectors && sunlabel->infos[n].id) {
2935 printf(_("Partition %d is already defined. Delete "
2936 "it before re-adding it.\n"), n + 1);
2940 fetch_sun(starts,lens,&start,&stop);
2941 if (stop <= start) {
2945 printf(_("Other partitions already cover the whole disk.\nDelete "
2946 "some/shrink them before retry.\n"));
2950 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
2953 first = read_int(0, 0, 0, 0, mesg);
2955 first = read_int(scround(start), scround(stop)+1,
2956 scround(stop), 0, mesg);
2957 if (display_in_cyl_units)
2958 first *= units_per_sector;
2960 /* Starting sector has to be properly aligned */
2961 first = (first + heads * sectors - 1) / (heads * sectors);
2962 if (n == 2 && first != 0)
2964 It is highly recommended that the third partition covers the whole disk\n\
2965 and is of type `Whole disk'\n");
2966 /* ewt asks to add: "don't start a partition at cyl 0"
2967 However, edmundo@rano.demon.co.uk writes:
2968 "In addition to having a Sun partition table, to be able to
2969 boot from the disc, the first partition, /dev/sdX1, must
2970 start at cylinder 0. This means that /dev/sdX1 contains
2971 the partition table and the boot block, as these are the
2972 first two sectors of the disc. Therefore you must be
2973 careful what you use /dev/sdX1 for. In particular, you must
2974 not use a partition starting at cylinder 0 for Linux swap,
2975 as that would overwrite the partition table and the boot
2976 block. You may, however, use such a partition for a UFS
2977 or EXT2 file system, as these file systems leave the first
2978 1024 bytes undisturbed. */
2979 /* On the other hand, one should not use partitions
2980 starting at block 0 in an md, or the label will
2982 for (i = 0; i < partitions; i++)
2983 if (lens[i] && starts[i] <= first
2984 && starts[i] + lens[i] > first)
2986 if (i < partitions && !whole_disk) {
2987 if (n == 2 && !first) {
2991 printf(_("Sector %d is already allocated\n"), first);
2995 stop = cylinders * heads * sectors;
2997 for (i = 0; i < partitions; i++) {
2998 if (starts[i] > first && starts[i] < stop)
3001 snprintf(mesg, sizeof(mesg),
3002 _("Last %s or +size or +sizeM or +sizeK"),
3003 str_units(SINGULAR));
3005 last = read_int(scround(stop2), scround(stop2), scround(stop2),
3007 else if (n == 2 && !first)
3008 last = read_int(scround(first), scround(stop2), scround(stop2),
3009 scround(first), mesg);
3011 last = read_int(scround(first), scround(stop), scround(stop),
3012 scround(first), mesg);
3013 if (display_in_cyl_units)
3014 last *= units_per_sector;
3015 if (n == 2 && !first) {
3016 if (last >= stop2) {
3019 } else if (last > stop) {
3021 _("You haven't covered the whole disk with the 3rd partition, but your value\n"
3022 "%d %s covers some other partition. Your entry has been changed\n"
3024 scround(last), str_units(SINGULAR),
3025 scround(stop), str_units(SINGULAR));
3028 } else if (!whole_disk && last > stop)
3031 if (whole_disk) sys = WHOLE_DISK;
3032 set_sun_partition(n, first, last, sys);
3036 sun_delete_partition(int i) {
3039 if (i == 2 && sunlabel->infos[i].id == WHOLE_DISK &&
3040 !sunlabel->partitions[i].start_cylinder &&
3041 (nsec = SUN_SSWAP32(sunlabel->partitions[i].num_sectors))
3042 == heads * sectors * cylinders)
3043 printf(_("If you want to maintain SunOS/Solaris compatibility, "
3044 "consider leaving this\n"
3045 "partition as Whole disk (5), starting at 0, with %u "
3046 "sectors\n"), nsec);
3047 sunlabel->infos[i].id = 0;
3048 sunlabel->partitions[i].num_sectors = 0;
3052 sun_change_sysid(int i, int sys) {
3053 if (sys == LINUX_SWAP && !sunlabel->partitions[i].start_cylinder) {
3055 _("It is highly recommended that the partition at offset 0\n"
3056 "is UFS, EXT2FS filesystem or SunOS swap. Putting Linux swap\n"
3057 "there may destroy your partition table and bootblock.\n"
3058 "Type YES if you're very sure you would like that partition\n"
3059 "tagged with 82 (Linux swap): "));
3060 if (strcmp (line_ptr, _("YES\n")))
3066 /* swaps are not mountable by default */
3067 sunlabel->infos[i].flags |= 0x01;
3070 /* assume other types are mountable;
3071 user can change it anyway */
3072 sunlabel->infos[i].flags &= ~0x01;
3075 sunlabel->infos[i].id = sys;
3079 sun_list_table(int xtra) {
3082 w = strlen(disk_device);
3085 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d rpm\n"
3086 "%d cylinders, %d alternate cylinders, %d physical cylinders\n"
3087 "%d extra sects/cyl, interleave %d:1\n"
3089 "Units = %s of %d * 512 bytes\n\n"),
3090 disk_device, heads, sectors, SUN_SSWAP16(sunlabel->rspeed),
3091 cylinders, SUN_SSWAP16(sunlabel->nacyl),
3092 SUN_SSWAP16(sunlabel->pcylcount),
3093 SUN_SSWAP16(sunlabel->sparecyl),
3094 SUN_SSWAP16(sunlabel->ilfact),
3096 str_units(PLURAL), units_per_sector);
3099 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d cylinders\n"
3100 "Units = %s of %d * 512 bytes\n\n"),
3101 disk_device, heads, sectors, cylinders,
3102 str_units(PLURAL), units_per_sector);
3104 printf(_("%*s Flag Start End Blocks Id System\n"),
3105 w + 1, _("Device"));
3106 for (i = 0 ; i < partitions; i++) {
3107 if (sunlabel->partitions[i].num_sectors) {
3108 uint32_t start = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
3109 uint32_t len = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
3111 "%s %c%c %9ld %9ld %9ld%c %2x %s\n",
3112 /* device */ partname(disk_device, i+1, w),
3113 /* flags */ (sunlabel->infos[i].flags & 0x01) ? 'u' : ' ',
3114 (sunlabel->infos[i].flags & 0x10) ? 'r' : ' ',
3115 /* start */ (long) scround(start),
3116 /* end */ (long) scround(start+len),
3117 /* odd flag on end */ (long) len / 2, len & 1 ? '+' : ' ',
3118 /* type id */ sunlabel->infos[i].id,
3119 /* type name */ partition_type(sunlabel->infos[i].id));
3124 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3127 sun_set_alt_cyl(void) {
3129 SUN_SSWAP16(read_int(0,SUN_SSWAP16(sunlabel->nacyl), 65535, 0,
3130 _("Number of alternate cylinders")));
3134 sun_set_ncyl(int cyl) {
3135 sunlabel->ncyl = SUN_SSWAP16(cyl);
3139 sun_set_xcyl(void) {
3140 sunlabel->sparecyl =
3141 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->sparecyl), sectors, 0,
3142 _("Extra sectors per cylinder")));
3146 sun_set_ilfact(void) {
3148 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->ilfact), 32, 0,
3149 _("Interleave factor")));
3153 sun_set_rspeed(void) {
3155 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->rspeed), 100000, 0,
3156 _("Rotation speed (rpm)")));
3160 sun_set_pcylcount(void) {
3161 sunlabel->pcylcount =
3162 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->pcylcount), 65535, 0,
3163 _("Number of physical cylinders")));
3165 #endif /* CONFIG_FEATURE_FDISK_ADVANCED */
3168 sun_write_table(void) {
3169 unsigned short *ush = (unsigned short *)sunlabel;
3170 unsigned short csum = 0;
3172 while(ush < (unsigned short *)(&sunlabel->csum))
3174 sunlabel->csum = csum;
3175 if (lseek(fd, 0, SEEK_SET) < 0)
3176 fdisk_fatal(unable_to_seek);
3177 if (write(fd, sunlabel, SECTOR_SIZE) != SECTOR_SIZE)
3178 fdisk_fatal(unable_to_write);
3180 #endif /* SUN_LABEL */
3182 /* DOS partition types */
3184 static const struct systypes i386_sys_types[] = {
3187 {"\x04" "FAT16 <32M"},
3188 {"\x05" "Extended"}, /* DOS 3.3+ extended partition */
3189 {"\x06" "FAT16"}, /* DOS 16-bit >=32M */
3190 {"\x07" "HPFS/NTFS"}, /* OS/2 IFS, eg, HPFS or NTFS or QNX */
3191 {"\x0a" "OS/2 Boot Manager"},/* OS/2 Boot Manager */
3192 {"\x0b" "Win95 FAT32"},
3193 {"\x0c" "Win95 FAT32 (LBA)"},/* LBA really is `Extended Int 13h' */
3194 {"\x0e" "Win95 FAT16 (LBA)"},
3195 {"\x0f" "Win95 Ext'd (LBA)"},
3196 {"\x11" "Hidden FAT12"},
3197 {"\x12" "Compaq diagnostics"},
3198 {"\x14" "Hidden FAT16 <32M"},
3199 {"\x16" "Hidden FAT16"},
3200 {"\x17" "Hidden HPFS/NTFS"},
3201 {"\x1b" "Hidden Win95 FAT32"},
3202 {"\x1c" "Hidden Win95 FAT32 (LBA)"},
3203 {"\x1e" "Hidden Win95 FAT16 (LBA)"},
3204 {"\x3c" "PartitionMagic recovery"},
3205 {"\x41" "PPC PReP Boot"},
3207 {"\x63" "GNU HURD or SysV"}, /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */
3208 {"\x80" "Old Minix"}, /* Minix 1.4a and earlier */
3209 {"\x81" "Minix / old Linux"},/* Minix 1.4b and later */
3210 {"\x82" "Linux swap"}, /* also Solaris */
3212 {"\x84" "OS/2 hidden C: drive"},
3213 {"\x85" "Linux extended"},
3214 {"\x86" "NTFS volume set"},
3215 {"\x87" "NTFS volume set"},
3216 {"\x8e" "Linux LVM"},
3217 {"\x9f" "BSD/OS"}, /* BSDI */
3218 {"\xa0" "IBM Thinkpad hibernation"},
3219 {"\xa5" "FreeBSD"}, /* various BSD flavours */
3221 {"\xa8" "Darwin UFS"},
3223 {"\xab" "Darwin boot"},
3225 {"\xb8" "BSDI swap"},
3226 {"\xbe" "Solaris boot"},
3228 {"\xee" "EFI GPT"}, /* Intel EFI GUID Partition Table */
3229 {"\xef" "EFI (FAT-12/16/32)"},/* Intel EFI System Partition */
3230 {"\xf0" "Linux/PA-RISC boot"},/* Linux/PA-RISC boot loader */
3231 {"\xf2" "DOS secondary"}, /* DOS 3.3+ secondary */
3232 {"\xfd" "Linux raid autodetect"},/* New (2.2.x) raid partition with
3233 autodetect using persistent
3235 #ifdef CONFIG_WEIRD_PARTITION_TYPES
3236 {"\x02" "XENIX root"},
3237 {"\x03" "XENIX usr"},
3238 {"\x08" "AIX"}, /* AIX boot (AIX -- PS/2 port) or SplitDrive */
3239 {"\x09" "AIX bootable"}, /* AIX data or Coherent */
3241 {"\x18" "AST SmartSleep"},
3244 {"\x40" "Venix 80286"},
3246 {"\x4e" "QNX4.x 2nd part"},
3247 {"\x4f" "QNX4.x 3rd part"},
3248 {"\x50" "OnTrack DM"},
3249 {"\x51" "OnTrack DM6 Aux1"}, /* (or Novell) */
3250 {"\x52" "CP/M"}, /* CP/M or Microport SysV/AT */
3251 {"\x53" "OnTrack DM6 Aux3"},
3252 {"\x54" "OnTrackDM6"},
3253 {"\x55" "EZ-Drive"},
3254 {"\x56" "Golden Bow"},
3255 {"\x5c" "Priam Edisk"},
3256 {"\x61" "SpeedStor"},
3257 {"\x64" "Novell Netware 286"},
3258 {"\x65" "Novell Netware 386"},
3259 {"\x70" "DiskSecure Multi-Boot"},
3262 {"\x94" "Amoeba BBT"}, /* (bad block table) */
3263 {"\xa7" "NeXTSTEP"},
3264 {"\xbb" "Boot Wizard hidden"},
3265 {"\xc1" "DRDOS/sec (FAT-12)"},
3266 {"\xc4" "DRDOS/sec (FAT-16 < 32M)"},
3267 {"\xc6" "DRDOS/sec (FAT-16)"},
3269 {"\xda" "Non-FS data"},
3270 {"\xdb" "CP/M / CTOS / ..."},/* CP/M or Concurrent CP/M or
3271 Concurrent DOS or CTOS */
3272 {"\xde" "Dell Utility"}, /* Dell PowerEdge Server utilities */
3273 {"\xdf" "BootIt"}, /* BootIt EMBRM */
3274 {"\xe1" "DOS access"}, /* DOS access or SpeedStor 12-bit FAT
3275 extended partition */
3276 {"\xe3" "DOS R/O"}, /* DOS R/O or SpeedStor */
3277 {"\xe4" "SpeedStor"}, /* SpeedStor 16-bit FAT extended
3278 partition < 1024 cyl. */
3279 {"\xf1" "SpeedStor"},
3280 {"\xf4" "SpeedStor"}, /* SpeedStor large partition */
3281 {"\xfe" "LANstep"}, /* SpeedStor >1024 cyl. or LANstep */
3282 {"\xff" "BBT"}, /* Xenix Bad Block Table */
3289 /* A valid partition table sector ends in 0x55 0xaa */
3291 part_table_flag(const char *b) {
3292 return ((uint) b[510]) + (((uint) b[511]) << 8);
3296 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3298 write_part_table_flag(char *b) {
3303 /* start_sect and nr_sects are stored little endian on all machines */
3304 /* moreover, they are not aligned correctly */
3306 store4_little_endian(unsigned char *cp, unsigned int val) {
3307 cp[0] = (val & 0xff);
3308 cp[1] = ((val >> 8) & 0xff);
3309 cp[2] = ((val >> 16) & 0xff);
3310 cp[3] = ((val >> 24) & 0xff);
3312 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3315 read4_little_endian(const unsigned char *cp) {
3316 return (uint)(cp[0]) + ((uint)(cp[1]) << 8)
3317 + ((uint)(cp[2]) << 16) + ((uint)(cp[3]) << 24);
3320 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3322 set_start_sect(struct partition *p, unsigned int start_sect) {
3323 store4_little_endian(p->start4, start_sect);
3328 get_start_sect(const struct partition *p) {
3329 return read4_little_endian(p->start4);
3332 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3334 set_nr_sects(struct partition *p, unsigned int nr_sects) {
3335 store4_little_endian(p->size4, nr_sects);
3340 get_nr_sects(const struct partition *p) {
3341 return read4_little_endian(p->size4);
3344 /* normally O_RDWR, -l option gives O_RDONLY */
3345 static int type_open = O_RDWR;
3348 static int ext_index, /* the prime extended partition */
3349 listing, /* no aborts for fdisk -l */
3350 dos_compatible_flag = ~0;
3351 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3352 static int dos_changed;
3353 static int nowarn; /* no warnings for fdisk -l/-s */
3358 static uint user_cylinders, user_heads, user_sectors;
3359 static uint pt_heads, pt_sectors;
3360 static uint kern_heads, kern_sectors;
3362 static uint extended_offset; /* offset of link pointers */
3364 static unsigned long long total_number_of_sectors;
3367 static jmp_buf listingbuf;
3369 static void fdisk_fatal(enum failure why) {
3370 const char *message;
3374 longjmp(listingbuf, 1);
3378 case unable_to_open:
3379 message = "Unable to open %s\n";
3381 case unable_to_read:
3382 message = "Unable to read %s\n";
3384 case unable_to_seek:
3385 message = "Unable to seek on %s\n";
3387 case unable_to_write:
3388 message = "Unable to write %s\n";
3391 message = "BLKGETSIZE ioctl failed on %s\n";
3394 message = "Fatal error\n";
3397 fputc('\n', stderr);
3398 fprintf(stderr, message, disk_device);
3403 seek_sector(uint secno) {
3404 off_t offset = secno * sector_size;
3405 if (lseek(fd, offset, SEEK_SET) == (off_t) -1)
3406 fdisk_fatal(unable_to_seek);
3409 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3411 write_sector(uint secno, char *buf) {
3413 if (write(fd, buf, sector_size) != sector_size)
3414 fdisk_fatal(unable_to_write);
3418 /* Allocate a buffer and read a partition table sector */
3420 read_pte(struct pte *pe, uint offset) {
3422 pe->offset = offset;
3423 pe->sectorbuffer = (char *) xmalloc(sector_size);
3424 seek_sector(offset);
3425 if (read(fd, pe->sectorbuffer, sector_size) != sector_size)
3426 fdisk_fatal(unable_to_read);
3427 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3430 pe->part_table = pe->ext_pointer = NULL;
3434 get_partition_start(const struct pte *pe) {
3435 return pe->offset + get_start_sect(pe->part_table);
3438 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3440 * Avoid warning about DOS partitions when no DOS partition was changed.
3441 * Here a heuristic "is probably dos partition".
3442 * We might also do the opposite and warn in all cases except
3443 * for "is probably nondos partition".
3446 is_dos_partition(int t) {
3447 return (t == 1 || t == 4 || t == 6 ||
3448 t == 0x0b || t == 0x0c || t == 0x0e ||
3449 t == 0x11 || t == 0x12 || t == 0x14 || t == 0x16 ||
3450 t == 0x1b || t == 0x1c || t == 0x1e || t == 0x24 ||
3451 t == 0xc1 || t == 0xc4 || t == 0xc6);
3456 #ifdef CONFIG_FEATURE_SUN_LABEL
3458 puts(_("Command action"));
3459 puts(_("\ta\ttoggle a read only flag")); /* sun */
3460 puts(_("\tb\tedit bsd disklabel"));
3461 puts(_("\tc\ttoggle the mountable flag")); /* sun */
3462 puts(_("\td\tdelete a partition"));
3463 puts(_("\tl\tlist known partition types"));
3464 puts(_("\tm\tprint this menu"));
3465 puts(_("\tn\tadd a new partition"));
3466 puts(_("\to\tcreate a new empty DOS partition table"));
3467 puts(_("\tp\tprint the partition table"));
3468 puts(_("\tq\tquit without saving changes"));
3469 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3470 puts(_("\tt\tchange a partition's system id"));
3471 puts(_("\tu\tchange display/entry units"));
3472 puts(_("\tv\tverify the partition table"));
3473 puts(_("\tw\twrite table to disk and exit"));
3474 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3475 puts(_("\tx\textra functionality (experts only)"));
3479 #ifdef CONFIG_FEATURE_SGI_LABEL
3481 puts(_("Command action"));
3482 puts(_("\ta\tselect bootable partition")); /* sgi flavour */
3483 puts(_("\tb\tedit bootfile entry")); /* sgi */
3484 puts(_("\tc\tselect sgi swap partition")); /* sgi flavour */
3485 puts(_("\td\tdelete a partition"));
3486 puts(_("\tl\tlist known partition types"));
3487 puts(_("\tm\tprint this menu"));
3488 puts(_("\tn\tadd a new partition"));
3489 puts(_("\to\tcreate a new empty DOS partition table"));
3490 puts(_("\tp\tprint the partition table"));
3491 puts(_("\tq\tquit without saving changes"));
3492 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3493 puts(_("\tt\tchange a partition's system id"));
3494 puts(_("\tu\tchange display/entry units"));
3495 puts(_("\tv\tverify the partition table"));
3496 puts(_("\tw\twrite table to disk and exit"));
3499 #ifdef CONFIG_FEATURE_AIX_LABEL
3501 puts(_("Command action"));
3502 puts(_("\tm\tprint this menu"));
3503 puts(_("\to\tcreate a new empty DOS partition table"));
3504 puts(_("\tq\tquit without saving changes"));
3505 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3509 puts(_("Command action"));
3510 puts(_("\ta\ttoggle a bootable flag"));
3511 puts(_("\tb\tedit bsd disklabel"));
3512 puts(_("\tc\ttoggle the dos compatibility flag"));
3513 puts(_("\td\tdelete a partition"));
3514 puts(_("\tl\tlist known partition types"));
3515 puts(_("\tm\tprint this menu"));
3516 puts(_("\tn\tadd a new partition"));
3517 puts(_("\to\tcreate a new empty DOS partition table"));
3518 puts(_("\tp\tprint the partition table"));
3519 puts(_("\tq\tquit without saving changes"));
3520 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3521 puts(_("\tt\tchange a partition's system id"));
3522 puts(_("\tu\tchange display/entry units"));
3523 puts(_("\tv\tverify the partition table"));
3524 puts(_("\tw\twrite table to disk and exit"));
3525 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3526 puts(_("\tx\textra functionality (experts only)"));
3530 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3533 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3536 #ifdef CONFIG_FEATURE_SUN_LABEL
3538 puts(_("Command action"));
3539 puts(_("\ta\tchange number of alternate cylinders")); /*sun*/
3540 puts(_("\tc\tchange number of cylinders"));
3541 puts(_("\td\tprint the raw data in the partition table"));
3542 puts(_("\te\tchange number of extra sectors per cylinder"));/*sun*/
3543 puts(_("\th\tchange number of heads"));
3544 puts(_("\ti\tchange interleave factor")); /*sun*/
3545 puts(_("\to\tchange rotation speed (rpm)")); /*sun*/
3546 puts(_("\tm\tprint this menu"));
3547 puts(_("\tp\tprint the partition table"));
3548 puts(_("\tq\tquit without saving changes"));
3549 puts(_("\tr\treturn to main menu"));
3550 puts(_("\ts\tchange number of sectors/track"));
3551 puts(_("\tv\tverify the partition table"));
3552 puts(_("\tw\twrite table to disk and exit"));
3553 puts(_("\ty\tchange number of physical cylinders")); /*sun*/
3556 #ifdef CONFIG_FEATURE_SGI_LABEL
3558 puts(_("Command action"));
3559 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3560 puts(_("\tc\tchange number of cylinders"));
3561 puts(_("\td\tprint the raw data in the partition table"));
3562 puts(_("\te\tlist extended partitions")); /* !sun */
3563 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3564 puts(_("\th\tchange number of heads"));
3565 puts(_("\tm\tprint this menu"));
3566 puts(_("\tp\tprint the partition table"));
3567 puts(_("\tq\tquit without saving changes"));
3568 puts(_("\tr\treturn to main menu"));
3569 puts(_("\ts\tchange number of sectors/track"));
3570 puts(_("\tv\tverify the partition table"));
3571 puts(_("\tw\twrite table to disk and exit"));
3574 #ifdef CONFIG_FEATURE_AIX_LABEL
3576 puts(_("Command action"));
3577 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3578 puts(_("\tc\tchange number of cylinders"));
3579 puts(_("\td\tprint the raw data in the partition table"));
3580 puts(_("\te\tlist extended partitions")); /* !sun */
3581 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3582 puts(_("\th\tchange number of heads"));
3583 puts(_("\tm\tprint this menu"));
3584 puts(_("\tp\tprint the partition table"));
3585 puts(_("\tq\tquit without saving changes"));
3586 puts(_("\tr\treturn to main menu"));
3587 puts(_("\ts\tchange number of sectors/track"));
3588 puts(_("\tv\tverify the partition table"));
3589 puts(_("\tw\twrite table to disk and exit"));
3593 puts(_("Command action"));
3594 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3595 puts(_("\tc\tchange number of cylinders"));
3596 puts(_("\td\tprint the raw data in the partition table"));
3597 puts(_("\te\tlist extended partitions")); /* !sun */
3598 puts(_("\tf\tfix partition order")); /* !sun, !aix, !sgi */
3599 #ifdef CONFIG_FEATURE_SGI_LABEL
3600 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3602 puts(_("\th\tchange number of heads"));
3603 puts(_("\tm\tprint this menu"));
3604 puts(_("\tp\tprint the partition table"));
3605 puts(_("\tq\tquit without saving changes"));
3606 puts(_("\tr\treturn to main menu"));
3607 puts(_("\ts\tchange number of sectors/track"));
3608 puts(_("\tv\tverify the partition table"));
3609 puts(_("\tw\twrite table to disk and exit"));
3612 #endif /* ADVANCED mode */
3614 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3615 static const struct systypes *
3616 get_sys_types(void) {
3618 #ifdef CONFIG_FEATURE_SUN_LABEL
3619 sun_label ? sun_sys_types :
3621 #ifdef CONFIG_FEATURE_SGI_LABEL
3622 sgi_label ? sgi_sys_types :
3627 #define get_sys_types() i386_sys_types
3628 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3630 static const char *partition_type(unsigned char type)
3633 const struct systypes *types = get_sys_types();
3635 for (i=0; types[i].name; i++)
3636 if (types[i].name[0] == type)
3637 return types[i].name + 1;
3639 return _("Unknown");
3643 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3647 #ifdef CONFIG_FEATURE_SUN_LABEL
3648 sun_label ? sunlabel->infos[i].id :
3650 #ifdef CONFIG_FEATURE_SGI_LABEL
3651 sgi_label ? sgi_get_sysid(i) :
3653 ptes[i].part_table->sys_ind);
3656 void list_types(const struct systypes *sys)
3658 uint last[4], done = 0, next = 0, size;
3661 for (i = 0; sys[i].name; i++);
3664 for (i = 3; i >= 0; i--)
3665 last[3 - i] = done += (size + i - done) / (i + 1);
3669 printf("%c%2x %-15.15s", i ? ' ' : '\n',
3670 sys[next].name[0], partition_type(sys[next].name[0]));
3671 next = last[i++] + done;
3672 if (i > 3 || next >= last[i]) {
3676 } while (done < last[0]);
3679 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3682 is_cleared_partition(const struct partition *p) {
3683 return !(!p || p->boot_ind || p->head || p->sector || p->cyl ||
3684 p->sys_ind || p->end_head || p->end_sector || p->end_cyl ||
3685 get_start_sect(p) || get_nr_sects(p));
3689 clear_partition(struct partition *p) {
3692 memset(p, 0, sizeof(struct partition));
3695 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3697 set_partition(int i, int doext, uint start, uint stop, int sysid) {
3698 struct partition *p;
3702 p = ptes[i].ext_pointer;
3703 offset = extended_offset;
3705 p = ptes[i].part_table;
3706 offset = ptes[i].offset;
3710 set_start_sect(p, start - offset);
3711 set_nr_sects(p, stop - start + 1);
3712 if (dos_compatible_flag && (start/(sectors*heads) > 1023))
3713 start = heads*sectors*1024 - 1;
3714 set_hsc(p->head, p->sector, p->cyl, start);
3715 if (dos_compatible_flag && (stop/(sectors*heads) > 1023))
3716 stop = heads*sectors*1024 - 1;
3717 set_hsc(p->end_head, p->end_sector, p->end_cyl, stop);
3718 ptes[i].changed = 1;
3723 test_c(const char **m, const char *mesg) {
3726 fprintf(stderr, _("You must set"));
3728 fprintf(stderr, " %s", *m);
3736 warn_geometry(void) {
3737 const char *m = NULL;
3741 prev = test_c(&m, _("heads"));
3743 prev = test_c(&m, _("sectors"));
3745 prev = test_c(&m, _("cylinders"));
3749 fprintf(stderr, "%s%s.\n"
3750 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3751 "You can do this from the extra functions menu.\n"
3753 , prev ? _(" and ") : " ", m);
3758 static void update_units(void)
3760 int cyl_units = heads * sectors;
3762 if (display_in_cyl_units && cyl_units)
3763 units_per_sector = cyl_units;
3765 units_per_sector = 1; /* in sectors */
3768 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3770 warn_cylinders(void) {
3771 if (dos_label && cylinders > 1024 && !nowarn)
3772 fprintf(stderr, _("\n"
3773 "The number of cylinders for this disk is set to %d.\n"
3774 "There is nothing wrong with that, but this is larger than 1024,\n"
3775 "and could in certain setups cause problems with:\n"
3776 "1) software that runs at boot time (e.g., old versions of LILO)\n"
3777 "2) booting and partitioning software from other OSs\n"
3778 " (e.g., DOS FDISK, OS/2 FDISK)\n"),
3784 read_extended(int ext) {
3787 struct partition *p, *q;
3791 pex->ext_pointer = pex->part_table;
3793 p = pex->part_table;
3794 if (!get_start_sect(p)) {
3796 _("Bad offset in primary extended partition\n"));
3800 while (IS_EXTENDED (p->sys_ind)) {
3801 struct pte *pe = &ptes[partitions];
3803 if (partitions >= MAXIMUM_PARTS) {
3804 /* This is not a Linux restriction, but
3805 this program uses arrays of size MAXIMUM_PARTS.
3806 Do not try to `improve' this test. */
3807 struct pte *pre = &ptes[partitions-1];
3808 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3810 _("Warning: deleting partitions after %d\n"),
3814 clear_partition(pre->ext_pointer);
3818 read_pte(pe, extended_offset + get_start_sect(p));
3820 if (!extended_offset)
3821 extended_offset = get_start_sect(p);
3823 q = p = pt_offset(pe->sectorbuffer, 0);
3824 for (i = 0; i < 4; i++, p++) if (get_nr_sects(p)) {
3825 if (IS_EXTENDED (p->sys_ind)) {
3826 if (pe->ext_pointer)
3828 _("Warning: extra link "
3829 "pointer in partition table"
3830 " %d\n"), partitions + 1);
3832 pe->ext_pointer = p;
3833 } else if (p->sys_ind) {
3836 _("Warning: ignoring extra "
3837 "data in partition table"
3838 " %d\n"), partitions + 1);
3844 /* very strange code here... */
3845 if (!pe->part_table) {
3846 if (q != pe->ext_pointer)
3849 pe->part_table = q + 1;
3851 if (!pe->ext_pointer) {
3852 if (q != pe->part_table)
3853 pe->ext_pointer = q;
3855 pe->ext_pointer = q + 1;
3858 p = pe->ext_pointer;
3862 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3863 /* remove empty links */
3865 for (i = 4; i < partitions; i++) {
3866 struct pte *pe = &ptes[i];
3868 if (!get_nr_sects(pe->part_table) &&
3869 (partitions > 5 || ptes[4].part_table->sys_ind)) {
3870 printf("omitting empty partition (%d)\n", i+1);
3871 delete_partition(i);
3872 goto remove; /* numbering changed */
3878 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3880 create_doslabel(void) {
3884 _("Building a new DOS disklabel. Changes will remain in memory only,\n"
3885 "until you decide to write them. After that, of course, the previous\n"
3886 "content won't be recoverable.\n\n"));
3887 #ifdef CONFIG_FEATURE_SUN_LABEL
3888 sun_nolabel(); /* otherwise always recognised as sun */
3890 #ifdef CONFIG_FEATURE_SGI_LABEL
3891 sgi_nolabel(); /* otherwise always recognised as sgi */
3893 #ifdef CONFIG_FEATURE_AIX_LABEL
3896 #ifdef CONFIG_FEATURE_OSF_LABEL
3898 possibly_osf_label = 0;
3902 for (i = 510-64; i < 510; i++)
3904 write_part_table_flag(MBRbuffer);
3905 extended_offset = 0;
3906 set_all_unchanged();
3908 get_boot(create_empty_dos);
3910 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3913 get_sectorsize(void) {
3914 if (!user_set_sector_size &&
3915 get_kernel_revision() >= MAKE_VERSION(2,3,3)) {
3917 if (ioctl(fd, BLKSSZGET, &arg) == 0)
3919 if (sector_size != DEFAULT_SECTOR_SIZE)
3920 printf(_("Note: sector size is %d (not %d)\n"),
3921 sector_size, DEFAULT_SECTOR_SIZE);
3926 get_kernel_geometry(void) {
3927 struct hd_geometry geometry;
3929 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
3930 kern_heads = geometry.heads;
3931 kern_sectors = geometry.sectors;
3932 /* never use geometry.cylinders - it is truncated */
3937 get_partition_table_geometry(void) {
3938 const unsigned char *bufp = MBRbuffer;
3939 struct partition *p;
3940 int i, h, s, hh, ss;
3944 if (!(valid_part_table_flag(bufp)))
3948 for (i=0; i<4; i++) {
3949 p = pt_offset(bufp, i);
3950 if (p->sys_ind != 0) {
3951 h = p->end_head + 1;
3952 s = (p->end_sector & 077);
3957 } else if (hh != h || ss != s)
3962 if (!first && !bad) {
3969 get_geometry(void) {
3971 unsigned long long bytes; /* really u64 */
3974 sec_fac = sector_size / 512;
3975 #ifdef CONFIG_FEATURE_SUN_LABEL
3976 guess_device_type();
3978 heads = cylinders = sectors = 0;
3979 kern_heads = kern_sectors = 0;
3980 pt_heads = pt_sectors = 0;
3982 get_kernel_geometry();
3983 get_partition_table_geometry();
3985 heads = user_heads ? user_heads :
3986 pt_heads ? pt_heads :
3987 kern_heads ? kern_heads : 255;
3988 sectors = user_sectors ? user_sectors :
3989 pt_sectors ? pt_sectors :
3990 kern_sectors ? kern_sectors : 63;
3991 if (ioctl(fd, BLKGETSIZE64, &bytes) == 0) {
3994 unsigned long longsectors;
3996 if (ioctl(fd, BLKGETSIZE, &longsectors))
3998 bytes = ((unsigned long long) longsectors) << 9;
4001 total_number_of_sectors = (bytes >> 9);
4004 if (dos_compatible_flag)
4005 sector_offset = sectors;
4007 cylinders = total_number_of_sectors / (heads * sectors * sec_fac);
4009 cylinders = user_cylinders;
4013 * Read MBR. Returns:
4014 * -1: no 0xaa55 flag present (possibly entire disk BSD)
4015 * 0: found or created label
4019 get_boot(enum action what) {
4024 for (i = 0; i < 4; i++) {
4025 struct pte *pe = &ptes[i];
4027 pe->part_table = pt_offset(MBRbuffer, i);
4028 pe->ext_pointer = NULL;
4030 pe->sectorbuffer = MBRbuffer;
4031 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4032 pe->changed = (what == create_empty_dos);
4036 #ifdef CONFIG_FEATURE_SUN_LABEL
4037 if (what == create_empty_sun && check_sun_label())
4041 memset(MBRbuffer, 0, 512);
4043 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4044 if (what == create_empty_dos)
4045 goto got_dos_table; /* skip reading disk */
4047 if ((fd = open(disk_device, type_open)) < 0) {
4048 if ((fd = open(disk_device, O_RDONLY)) < 0) {
4049 if (what == try_only)
4051 fdisk_fatal(unable_to_open);
4053 printf(_("You will not be able to write "
4054 "the partition table.\n"));
4057 if (512 != read(fd, MBRbuffer, 512)) {
4058 if (what == try_only)
4060 fdisk_fatal(unable_to_read);
4063 if ((fd = open(disk_device, O_RDONLY)) < 0)
4065 if (512 != read(fd, MBRbuffer, 512))
4073 #ifdef CONFIG_FEATURE_SUN_LABEL
4074 if (check_sun_label())
4078 #ifdef CONFIG_FEATURE_SGI_LABEL
4079 if (check_sgi_label())
4083 #ifdef CONFIG_FEATURE_AIX_LABEL
4084 if (check_aix_label())
4088 #ifdef CONFIG_FEATURE_OSF_LABEL
4089 if (check_osf_label()) {
4090 possibly_osf_label = 1;
4091 if (!valid_part_table_flag(MBRbuffer)) {
4095 printf(_("This disk has both DOS and BSD magic.\n"
4096 "Give the 'b' command to go to BSD mode.\n"));
4100 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4104 if (!valid_part_table_flag(MBRbuffer)) {
4105 #ifndef CONFIG_FEATURE_FDISK_WRITABLE
4111 _("Device contains neither a valid DOS "
4112 "partition table, nor Sun, SGI or OSF "
4115 #ifdef CONFIG_FEATURE_SUN_LABEL
4124 case create_empty_dos:
4125 #ifdef CONFIG_FEATURE_SUN_LABEL
4126 case create_empty_sun:
4130 fprintf(stderr, _("Internal error\n"));
4133 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
4136 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4141 for (i = 0; i < 4; i++) {
4142 struct pte *pe = &ptes[i];
4144 if (IS_EXTENDED (pe->part_table->sys_ind)) {
4145 if (partitions != 4)
4146 fprintf(stderr, _("Ignoring extra extended "
4147 "partition %d\n"), i + 1);
4153 for (i = 3; i < partitions; i++) {
4154 struct pte *pe = &ptes[i];
4156 if (!valid_part_table_flag(pe->sectorbuffer)) {
4158 _("Warning: invalid flag 0x%04x of partition "
4159 "table %d will be corrected by w(rite)\n"),
4160 part_table_flag(pe->sectorbuffer), i + 1);
4161 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4170 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4172 * Print the message MESG, then read an integer between LOW and HIGH (inclusive).
4173 * If the user hits Enter, DFLT is returned.
4174 * Answers like +10 are interpreted as offsets from BASE.
4176 * There is no default if DFLT is not between LOW and HIGH.
4179 read_int(uint low, uint dflt, uint high, uint base, char *mesg)
4183 static char *ms = NULL;
4184 static int mslen = 0;
4186 if (!ms || strlen(mesg)+100 > mslen) {
4187 mslen = strlen(mesg)+200;
4188 ms = xrealloc(ms,mslen);
4191 if (dflt < low || dflt > high)
4195 snprintf(ms, mslen, _("%s (%u-%u, default %u): "),
4196 mesg, low, high, dflt);
4198 snprintf(ms, mslen, "%s (%u-%u): ",
4202 int use_default = default_ok;
4204 /* ask question and read answer */
4205 while (read_chars(ms) != '\n' && !isdigit(*line_ptr)
4206 && *line_ptr != '-' && *line_ptr != '+')
4209 if (*line_ptr == '+' || *line_ptr == '-') {
4210 int minus = (*line_ptr == '-');
4213 i = atoi(line_ptr+1);
4215 while (isdigit(*++line_ptr))
4218 switch (*line_ptr) {
4221 if (!display_in_cyl_units)
4222 i *= heads * sectors;
4236 absolute = 1000000000;
4242 unsigned long long bytes;
4245 bytes = (unsigned long long) i * absolute;
4246 unit = sector_size * units_per_sector;
4247 bytes += unit/2; /* round */
4256 while (isdigit(*line_ptr)) {
4262 printf(_("Using default value %u\n"), i = dflt);
4263 if (i >= low && i <= high)
4266 printf(_("Value out of range.\n"));
4272 get_partition(int warn, int max) {
4276 i = read_int(1, 0, max, 0, _("Partition number")) - 1;
4280 if ((!sun_label && !sgi_label && !pe->part_table->sys_ind)
4281 #ifdef CONFIG_FEATURE_SUN_LABEL
4283 (!sunlabel->partitions[i].num_sectors ||
4284 !sunlabel->infos[i].id))
4286 #ifdef CONFIG_FEATURE_SGI_LABEL
4287 || (sgi_label && (!sgi_get_num_sectors(i)))
4291 _("Warning: partition %d has empty type\n"),
4298 get_existing_partition(int warn, int max) {
4302 for (i = 0; i < max; i++) {
4303 struct pte *pe = &ptes[i];
4304 struct partition *p = pe->part_table;
4306 if (p && !is_cleared_partition(p)) {
4313 printf(_("Selected partition %d\n"), pno+1);
4316 printf(_("No partition is defined yet!\n"));
4320 return get_partition(warn, max);
4324 get_nonexisting_partition(int warn, int max) {
4328 for (i = 0; i < max; i++) {
4329 struct pte *pe = &ptes[i];
4330 struct partition *p = pe->part_table;
4332 if (p && is_cleared_partition(p)) {
4339 printf(_("Selected partition %d\n"), pno+1);
4342 printf(_("All primary partitions have been defined already!\n"));
4346 return get_partition(warn, max);
4350 void change_units(void)
4352 display_in_cyl_units = !display_in_cyl_units;
4354 printf(_("Changing display/entry units to %s\n"),
4359 toggle_active(int i) {
4360 struct pte *pe = &ptes[i];
4361 struct partition *p = pe->part_table;
4363 if (IS_EXTENDED (p->sys_ind) && !p->boot_ind)
4365 _("WARNING: Partition %d is an extended partition\n"),
4367 p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG);
4372 toggle_dos_compatibility_flag(void) {
4373 dos_compatible_flag = ~dos_compatible_flag;
4374 if (dos_compatible_flag) {
4375 sector_offset = sectors;
4376 printf(_("DOS Compatibility flag is set\n"));
4380 printf(_("DOS Compatibility flag is not set\n"));
4385 delete_partition(int i) {
4386 struct pte *pe = &ptes[i];
4387 struct partition *p = pe->part_table;
4388 struct partition *q = pe->ext_pointer;
4390 /* Note that for the fifth partition (i == 4) we don't actually
4391 * decrement partitions.
4394 if (warn_geometry())
4395 return; /* C/H/S not set */
4398 #ifdef CONFIG_FEATURE_SUN_LABEL
4400 sun_delete_partition(i);
4404 #ifdef CONFIG_FEATURE_SGI_LABEL
4406 sgi_delete_partition(i);
4412 if (IS_EXTENDED (p->sys_ind) && i == ext_index) {
4414 ptes[ext_index].ext_pointer = NULL;
4415 extended_offset = 0;
4421 if (!q->sys_ind && i > 4) {
4422 /* the last one in the chain - just delete */
4425 clear_partition(ptes[i].ext_pointer);
4426 ptes[i].changed = 1;
4428 /* not the last one - further ones will be moved down */
4430 /* delete this link in the chain */
4431 p = ptes[i-1].ext_pointer;
4433 set_start_sect(p, get_start_sect(q));
4434 set_nr_sects(p, get_nr_sects(q));
4435 ptes[i-1].changed = 1;
4436 } else if (partitions > 5) { /* 5 will be moved to 4 */
4437 /* the first logical in a longer chain */
4440 if (pe->part_table) /* prevent SEGFAULT */
4441 set_start_sect(pe->part_table,
4442 get_partition_start(pe) -
4444 pe->offset = extended_offset;
4448 if (partitions > 5) {
4450 while (i < partitions) {
4451 ptes[i] = ptes[i+1];
4455 /* the only logical: clear only */
4456 clear_partition(ptes[i].part_table);
4461 change_sysid(void) {
4462 int i, sys, origsys;
4463 struct partition *p;
4465 #ifdef CONFIG_FEATURE_SGI_LABEL
4466 /* If sgi_label then don't use get_existing_partition,
4467 let the user select a partition, since get_existing_partition()
4468 only works for Linux like partition tables. */
4470 i = get_existing_partition(0, partitions);
4472 i = get_partition(0, partitions);
4475 i = get_existing_partition(0, partitions);
4479 p = ptes[i].part_table;
4480 origsys = sys = get_sysid(i);
4482 /* if changing types T to 0 is allowed, then
4483 the reverse change must be allowed, too */
4484 if (!sys && !sgi_label && !sun_label && !get_nr_sects(p))
4485 printf(_("Partition %d does not exist yet!\n"), i + 1);
4487 sys = read_hex (get_sys_types());
4489 if (!sys && !sgi_label && !sun_label) {
4490 printf(_("Type 0 means free space to many systems\n"
4491 "(but not to Linux). Having partitions of\n"
4492 "type 0 is probably unwise. You can delete\n"
4493 "a partition using the `d' command.\n"));
4497 if (!sun_label && !sgi_label) {
4498 if (IS_EXTENDED (sys) != IS_EXTENDED (p->sys_ind)) {
4499 printf(_("You cannot change a partition into"
4500 " an extended one or vice versa\n"
4501 "Delete it first.\n"));
4507 #ifdef CONFIG_FEATURE_SUN_LABEL
4508 if (sun_label && i == 2 && sys != WHOLE_DISK)
4509 printf(_("Consider leaving partition 3 "
4510 "as Whole disk (5),\n"
4511 "as SunOS/Solaris expects it and "
4512 "even Linux likes it.\n\n"));
4514 #ifdef CONFIG_FEATURE_SGI_LABEL
4515 if (sgi_label && ((i == 10 && sys != ENTIRE_DISK)
4516 || (i == 8 && sys != 0)))
4517 printf(_("Consider leaving partition 9 "
4518 "as volume header (0),\nand "
4519 "partition 11 as entire volume (6)"
4520 "as IRIX expects it.\n\n"));
4524 #ifdef CONFIG_FEATURE_SUN_LABEL
4526 sun_change_sysid(i, sys);
4529 #ifdef CONFIG_FEATURE_SGI_LABEL
4531 sgi_change_sysid(i, sys);
4535 printf (_("Changed system type of partition %d "
4536 "to %x (%s)\n"), i + 1, sys,
4537 partition_type(sys));
4538 ptes[i].changed = 1;
4539 if (is_dos_partition(origsys) ||
4540 is_dos_partition(sys))
4546 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
4549 /* check_consistency() and long2chs() added Sat Mar 6 12:28:16 1993,
4550 * faith@cs.unc.edu, based on code fragments from pfdisk by Gordon W. Ross,
4551 * Jan. 1990 (version 1.2.1 by Gordon W. Ross Aug. 1990; Modified by S.
4552 * Lubkin Oct. 1991). */
4554 static void long2chs(ulong ls, uint *c, uint *h, uint *s) {
4555 int spc = heads * sectors;
4560 *s = ls % sectors + 1; /* sectors count from 1 */
4563 static void check_consistency(const struct partition *p, int partition) {
4564 uint pbc, pbh, pbs; /* physical beginning c, h, s */
4565 uint pec, peh, pes; /* physical ending c, h, s */
4566 uint lbc, lbh, lbs; /* logical beginning c, h, s */
4567 uint lec, leh, les; /* logical ending c, h, s */
4569 if (!heads || !sectors || (partition >= 4))
4570 return; /* do not check extended partitions */
4572 /* physical beginning c, h, s */
4573 pbc = (p->cyl & 0xff) | ((p->sector << 2) & 0x300);
4575 pbs = p->sector & 0x3f;
4577 /* physical ending c, h, s */
4578 pec = (p->end_cyl & 0xff) | ((p->end_sector << 2) & 0x300);
4580 pes = p->end_sector & 0x3f;
4582 /* compute logical beginning (c, h, s) */
4583 long2chs(get_start_sect(p), &lbc, &lbh, &lbs);
4585 /* compute logical ending (c, h, s) */
4586 long2chs(get_start_sect(p) + get_nr_sects(p) - 1, &lec, &leh, &les);
4588 /* Same physical / logical beginning? */
4589 if (cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) {
4590 printf(_("Partition %d has different physical/logical "
4591 "beginnings (non-Linux?):\n"), partition + 1);
4592 printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs);
4593 printf(_("logical=(%d, %d, %d)\n"),lbc, lbh, lbs);
4596 /* Same physical / logical ending? */
4597 if (cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) {
4598 printf(_("Partition %d has different physical/logical "
4599 "endings:\n"), partition + 1);
4600 printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
4601 printf(_("logical=(%d, %d, %d)\n"),lec, leh, les);
4605 /* Beginning on cylinder boundary? */
4606 if (pbh != !pbc || pbs != 1) {
4607 printf(_("Partition %i does not start on cylinder "
4608 "boundary:\n"), partition + 1);
4609 printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs);
4610 printf(_("should be (%d, %d, 1)\n"), pbc, !pbc);
4614 /* Ending on cylinder boundary? */
4615 if (peh != (heads - 1) || pes != sectors) {
4616 printf(_("Partition %i does not end on cylinder boundary.\n"),
4619 printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
4620 printf(_("should be (%d, %d, %d)\n"),
4621 pec, heads - 1, sectors);
4627 list_disk_geometry(void) {
4628 long long bytes = (total_number_of_sectors << 9);
4629 long megabytes = bytes/1000000;
4631 if (megabytes < 10000)
4632 printf(_("\nDisk %s: %ld MB, %lld bytes\n"),
4633 disk_device, megabytes, bytes);
4635 printf(_("\nDisk %s: %ld.%ld GB, %lld bytes\n"),
4636 disk_device, megabytes/1000, (megabytes/100)%10, bytes);
4637 printf(_("%d heads, %d sectors/track, %d cylinders"),
4638 heads, sectors, cylinders);
4639 if (units_per_sector == 1)
4640 printf(_(", total %llu sectors"),
4641 total_number_of_sectors / (sector_size/512));
4642 printf(_("\nUnits = %s of %d * %d = %d bytes\n\n"),
4644 units_per_sector, sector_size, units_per_sector * sector_size);
4648 * Check whether partition entries are ordered by their starting positions.
4649 * Return 0 if OK. Return i if partition i should have been earlier.
4650 * Two separate checks: primary and logical partitions.
4653 wrong_p_order(int *prev) {
4654 const struct pte *pe;
4655 const struct partition *p;
4656 uint last_p_start_pos = 0, p_start_pos;
4659 for (i = 0 ; i < partitions; i++) {
4662 last_p_start_pos = 0;
4665 if ((p = pe->part_table)->sys_ind) {
4666 p_start_pos = get_partition_start(pe);
4668 if (last_p_start_pos > p_start_pos) {
4674 last_p_start_pos = p_start_pos;
4681 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
4683 * Fix the chain of logicals.
4684 * extended_offset is unchanged, the set of sectors used is unchanged
4685 * The chain is sorted so that sectors increase, and so that
4686 * starting sectors increase.
4688 * After this it may still be that cfdisk doesnt like the table.
4689 * (This is because cfdisk considers expanded parts, from link to
4690 * end of partition, and these may still overlap.)
4692 * sfdisk /dev/hda > ohda; sfdisk /dev/hda < ohda
4696 fix_chain_of_logicals(void) {
4697 int j, oj, ojj, sj, sjj;
4698 struct partition *pj,*pjj,tmp;
4700 /* Stage 1: sort sectors but leave sector of part 4 */
4701 /* (Its sector is the global extended_offset.) */
4703 for (j = 5; j < partitions-1; j++) {
4704 oj = ptes[j].offset;
4705 ojj = ptes[j+1].offset;
4707 ptes[j].offset = ojj;
4708 ptes[j+1].offset = oj;
4709 pj = ptes[j].part_table;
4710 set_start_sect(pj, get_start_sect(pj)+oj-ojj);
4711 pjj = ptes[j+1].part_table;
4712 set_start_sect(pjj, get_start_sect(pjj)+ojj-oj);
4713 set_start_sect(ptes[j-1].ext_pointer,
4714 ojj-extended_offset);
4715 set_start_sect(ptes[j].ext_pointer,
4716 oj-extended_offset);
4721 /* Stage 2: sort starting sectors */
4723 for (j = 4; j < partitions-1; j++) {
4724 pj = ptes[j].part_table;
4725 pjj = ptes[j+1].part_table;
4726 sj = get_start_sect(pj);
4727 sjj = get_start_sect(pjj);
4728 oj = ptes[j].offset;
4729 ojj = ptes[j+1].offset;
4730 if (oj+sj > ojj+sjj) {
4734 set_start_sect(pj, ojj+sjj-oj);
4735 set_start_sect(pjj, oj+sj-ojj);
4740 /* Probably something was changed */
4741 for (j = 4; j < partitions; j++)
4742 ptes[j].changed = 1;
4747 fix_partition_table_order(void) {
4748 struct pte *pei, *pek;
4751 if (!wrong_p_order(NULL)) {
4752 printf(_("Nothing to do. Ordering is correct already.\n\n"));
4756 while ((i = wrong_p_order(&k)) != 0 && i < 4) {
4757 /* partition i should have come earlier, move it */
4758 /* We have to move data in the MBR */
4759 struct partition *pi, *pk, *pe, pbuf;
4763 pe = pei->ext_pointer;
4764 pei->ext_pointer = pek->ext_pointer;
4765 pek->ext_pointer = pe;
4767 pi = pei->part_table;
4768 pk = pek->part_table;
4770 memmove(&pbuf, pi, sizeof(struct partition));
4771 memmove(pi, pk, sizeof(struct partition));
4772 memmove(pk, &pbuf, sizeof(struct partition));
4774 pei->changed = pek->changed = 1;
4778 fix_chain_of_logicals();
4786 list_table(int xtra) {
4787 const struct partition *p;
4790 #ifdef CONFIG_FEATURE_SUN_LABEL
4792 sun_list_table(xtra);
4797 #ifdef CONFIG_FEATURE_SGI_LABEL
4799 sgi_list_table(xtra);
4804 list_disk_geometry();
4806 #ifdef CONFIG_FEATURE_OSF_LABEL
4808 xbsd_print_disklabel(xtra);
4813 /* Heuristic: we list partition 3 of /dev/foo as /dev/foo3,
4814 but if the device name ends in a digit, say /dev/foo1,
4815 then the partition is called /dev/foo1p3. */
4816 w = strlen(disk_device);
4817 if (w && isdigit(disk_device[w-1]))
4822 printf(_("%*s Boot Start End Blocks Id System\n"),
4825 for (i = 0; i < partitions; i++) {
4826 const struct pte *pe = &ptes[i];
4829 if (p && !is_cleared_partition(p)) {
4830 unsigned int psects = get_nr_sects(p);
4831 unsigned int pblocks = psects;
4832 unsigned int podd = 0;
4834 if (sector_size < 1024) {
4835 pblocks /= (1024 / sector_size);
4836 podd = psects % (1024 / sector_size);
4838 if (sector_size > 1024)
4839 pblocks *= (sector_size / 1024);
4841 "%s %c %11lu %11lu %11lu%c %2x %s\n",
4842 partname(disk_device, i+1, w+2),
4843 /* boot flag */ !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG
4845 /* start */ (unsigned long) cround(get_partition_start(pe)),
4846 /* end */ (unsigned long) cround(get_partition_start(pe) + psects
4847 - (psects ? 1 : 0)),
4848 /* odd flag on end */ (unsigned long) pblocks, podd ? '+' : ' ',
4849 /* type id */ p->sys_ind,
4850 /* type name */ partition_type(p->sys_ind));
4851 check_consistency(p, i);
4855 /* Is partition table in disk order? It need not be, but... */
4856 /* partition table entries are not checked for correct order if this
4857 is a sgi, sun or aix labeled disk... */
4858 if (dos_label && wrong_p_order(NULL)) {
4859 printf(_("\nPartition table entries are not in disk order\n"));
4863 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
4865 x_list_table(int extend) {
4866 const struct pte *pe;
4867 const struct partition *p;
4870 printf(_("\nDisk %s: %d heads, %d sectors, %d cylinders\n\n"),
4871 disk_device, heads, sectors, cylinders);
4872 printf(_("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n"));
4873 for (i = 0 ; i < partitions; i++) {
4875 p = (extend ? pe->ext_pointer : pe->part_table);
4877 printf("%2d %02x%4d%4d%5d%4d%4d%5d%11u%11u %02x\n",
4878 i + 1, p->boot_ind, p->head,
4880 cylinder(p->sector, p->cyl), p->end_head,
4881 sector(p->end_sector),
4882 cylinder(p->end_sector, p->end_cyl),
4883 get_start_sect(p), get_nr_sects(p), p->sys_ind);
4885 check_consistency(p, i);
4891 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4893 fill_bounds(uint *first, uint *last) {
4895 const struct pte *pe = &ptes[0];
4896 const struct partition *p;
4898 for (i = 0; i < partitions; pe++,i++) {
4900 if (!p->sys_ind || IS_EXTENDED (p->sys_ind)) {
4901 first[i] = 0xffffffff;
4904 first[i] = get_partition_start(pe);
4905 last[i] = first[i] + get_nr_sects(p) - 1;
4911 check(int n, uint h, uint s, uint c, uint start) {
4912 uint total, real_s, real_c;
4914 real_s = sector(s) - 1;
4915 real_c = cylinder(s, c);
4916 total = (real_c * sectors + real_s) * heads + h;
4918 fprintf(stderr, _("Warning: partition %d contains sector 0\n"), n);
4921 _("Partition %d: head %d greater than maximum %d\n"),
4923 if (real_s >= sectors)
4924 fprintf(stderr, _("Partition %d: sector %d greater than "
4925 "maximum %d\n"), n, s, sectors);
4926 if (real_c >= cylinders)
4927 fprintf(stderr, _("Partitions %d: cylinder %d greater than "
4928 "maximum %d\n"), n, real_c + 1, cylinders);
4929 if (cylinders <= 1024 && start != total)
4931 _("Partition %d: previous sectors %d disagrees with "
4932 "total %d\n"), n, start, total);
4939 uint first[partitions], last[partitions];
4940 struct partition *p;
4942 if (warn_geometry())
4945 #ifdef CONFIG_FEATURE_SUN_LABEL
4951 #ifdef CONFIG_FEATURE_SGI_LABEL
4958 fill_bounds(first, last);
4959 for (i = 0; i < partitions; i++) {
4960 struct pte *pe = &ptes[i];
4963 if (p->sys_ind && !IS_EXTENDED (p->sys_ind)) {
4964 check_consistency(p, i);
4965 if (get_partition_start(pe) < first[i])
4966 printf(_("Warning: bad start-of-data in "
4967 "partition %d\n"), i + 1);
4968 check(i + 1, p->end_head, p->end_sector, p->end_cyl,
4970 total += last[i] + 1 - first[i];
4971 for (j = 0; j < i; j++)
4972 if ((first[i] >= first[j] && first[i] <= last[j])
4973 || ((last[i] <= last[j] && last[i] >= first[j]))) {
4974 printf(_("Warning: partition %d overlaps "
4975 "partition %d.\n"), j + 1, i + 1);
4976 total += first[i] >= first[j] ?
4977 first[i] : first[j];
4978 total -= last[i] <= last[j] ?
4984 if (extended_offset) {
4985 struct pte *pex = &ptes[ext_index];
4986 uint e_last = get_start_sect(pex->part_table) +
4987 get_nr_sects(pex->part_table) - 1;
4989 for (i = 4; i < partitions; i++) {
4991 p = ptes[i].part_table;
4993 if (i != 4 || i + 1 < partitions)
4994 printf(_("Warning: partition %d "
4995 "is empty\n"), i + 1);
4997 else if (first[i] < extended_offset ||
4999 printf(_("Logical partition %d not entirely in "
5000 "partition %d\n"), i + 1, ext_index + 1);
5004 if (total > heads * sectors * cylinders)
5005 printf(_("Total allocated sectors %d greater than the maximum "
5006 "%d\n"), total, heads * sectors * cylinders);
5007 else if ((total = heads * sectors * cylinders - total) != 0)
5008 printf(_("%d unallocated sectors\n"), total);
5012 add_partition(int n, int sys) {
5013 char mesg[256]; /* 48 does not suffice in Japanese */
5015 struct partition *p = ptes[n].part_table;
5016 struct partition *q = ptes[ext_index].part_table;
5018 uint start, stop = 0, limit, temp,
5019 first[partitions], last[partitions];
5021 if (p && p->sys_ind) {
5022 printf(_("Partition %d is already defined. Delete "
5023 "it before re-adding it.\n"), n + 1);
5026 fill_bounds(first, last);
5028 start = sector_offset;
5029 if (display_in_cyl_units || !total_number_of_sectors)
5030 llimit = heads * sectors * cylinders - 1;
5032 llimit = total_number_of_sectors - 1;
5034 if (limit != llimit)
5036 if (extended_offset) {
5037 first[ext_index] = extended_offset;
5038 last[ext_index] = get_start_sect(q) +
5039 get_nr_sects(q) - 1;
5042 start = extended_offset + sector_offset;
5043 limit = get_start_sect(q) + get_nr_sects(q) - 1;
5045 if (display_in_cyl_units)
5046 for (i = 0; i < partitions; i++)
5047 first[i] = (cround(first[i]) - 1) * units_per_sector;
5049 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
5052 for (i = 0; i < partitions; i++) {
5055 if (start == ptes[i].offset)
5056 start += sector_offset;
5057 lastplusoff = last[i] + ((n<4) ? 0 : sector_offset);
5058 if (start >= first[i] && start <= lastplusoff)
5059 start = lastplusoff + 1;
5063 if (start >= temp+units_per_sector && readed) {
5064 printf(_("Sector %d is already allocated\n"), temp);
5068 if (!readed && start == temp) {
5071 saved_start = start;
5072 start = read_int(cround(saved_start), cround(saved_start), cround(limit),
5074 if (display_in_cyl_units) {
5075 start = (start - 1) * units_per_sector;
5076 if (start < saved_start) start = saved_start;
5080 } while (start != temp || !readed);
5081 if (n > 4) { /* NOT for fifth partition */
5082 struct pte *pe = &ptes[n];
5084 pe->offset = start - sector_offset;
5085 if (pe->offset == extended_offset) { /* must be corrected */
5087 if (sector_offset == 1)
5092 for (i = 0; i < partitions; i++) {
5093 struct pte *pe = &ptes[i];
5095 if (start < pe->offset && limit >= pe->offset)
5096 limit = pe->offset - 1;
5097 if (start < first[i] && limit >= first[i])
5098 limit = first[i] - 1;
5100 if (start > limit) {
5101 printf(_("No free sectors available\n"));
5106 if (cround(start) == cround(limit)) {
5109 snprintf(mesg, sizeof(mesg),
5110 _("Last %s or +size or +sizeM or +sizeK"),
5111 str_units(SINGULAR));
5112 stop = read_int(cround(start), cround(limit), cround(limit),
5113 cround(start), mesg);
5114 if (display_in_cyl_units) {
5115 stop = stop * units_per_sector - 1;
5121 set_partition(n, 0, start, stop, sys);
5123 set_partition(n - 1, 1, ptes[n].offset, stop, EXTENDED);
5125 if (IS_EXTENDED (sys)) {
5126 struct pte *pe4 = &ptes[4];
5127 struct pte *pen = &ptes[n];
5130 pen->ext_pointer = p;
5131 pe4->offset = extended_offset = start;
5132 pe4->sectorbuffer = xcalloc(1, sector_size);
5133 pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
5134 pe4->ext_pointer = pe4->part_table + 1;
5142 if (partitions > 5 || ptes[4].part_table->sys_ind) {
5143 struct pte *pe = &ptes[partitions];
5145 pe->sectorbuffer = xcalloc(1, sector_size);
5146 pe->part_table = pt_offset(pe->sectorbuffer, 0);
5147 pe->ext_pointer = pe->part_table + 1;
5152 add_partition(partitions - 1, LINUX_NATIVE);
5156 new_partition(void) {
5157 int i, free_primary = 0;
5159 if (warn_geometry())
5162 #ifdef CONFIG_FEATURE_SUN_LABEL
5164 add_sun_partition(get_partition(0, partitions), LINUX_NATIVE);
5168 #ifdef CONFIG_FEATURE_SGI_LABEL
5170 sgi_add_partition(get_partition(0, partitions), LINUX_NATIVE);
5174 #ifdef CONFIG_FEATURE_AIX_LABEL
5176 printf(_("\tSorry - this fdisk cannot handle AIX disk labels."
5177 "\n\tIf you want to add DOS-type partitions, create"
5178 "\n\ta new empty DOS partition table first. (Use o.)"
5180 "This will destroy the present disk contents.\n"));
5185 for (i = 0; i < 4; i++)
5186 free_primary += !ptes[i].part_table->sys_ind;
5188 if (!free_primary && partitions >= MAXIMUM_PARTS) {
5189 printf(_("The maximum number of partitions has been created\n"));
5193 if (!free_primary) {
5194 if (extended_offset)
5197 printf(_("You must delete some partition and add "
5198 "an extended partition first\n"));
5200 char c, line[LINE_LENGTH];
5201 snprintf(line, sizeof(line), "%s\n %s\n p primary "
5202 "partition (1-4)\n",
5203 "Command action", (extended_offset ?
5204 "l logical (5 or over)" : "e extended"));
5206 if ((c = read_char(line)) == 'p' || c == 'P') {
5207 i = get_nonexisting_partition(0, 4);
5209 add_partition(i, LINUX_NATIVE);
5212 else if (c == 'l' && extended_offset) {
5216 else if (c == 'e' && !extended_offset) {
5217 i = get_nonexisting_partition(0, 4);
5219 add_partition(i, EXTENDED);
5223 printf(_("Invalid partition number "
5224 "for type `%c'\n"), c);
5235 if (ptes[i].changed)
5236 ptes[3].changed = 1;
5237 for (i = 3; i < partitions; i++) {
5238 struct pte *pe = &ptes[i];
5241 write_part_table_flag(pe->sectorbuffer);
5242 write_sector(pe->offset, pe->sectorbuffer);
5246 #ifdef CONFIG_FEATURE_SGI_LABEL
5247 else if (sgi_label) {
5248 /* no test on change? the printf below might be mistaken */
5252 #ifdef CONFIG_FEATURE_SUN_LABEL
5253 else if (sun_label) {
5257 if (ptes[i].changed)
5264 printf(_("The partition table has been altered!\n\n"));
5265 reread_partition_table(1);
5269 reread_partition_table(int leave) {
5273 printf(_("Calling ioctl() to re-read partition table.\n"));
5276 if ((i = ioctl(fd, BLKRRPART)) != 0) {
5279 /* some kernel versions (1.2.x) seem to have trouble
5280 rereading the partition table, but if asked to do it
5281 twice, the second time works. - biro@yggdrasil.com */
5284 if ((i = ioctl(fd, BLKRRPART)) != 0)
5289 printf(_("\nWARNING: Re-reading the partition table "
5290 "failed with error %d: %s.\n"
5291 "The kernel still uses the old table.\n"
5292 "The new table will be used "
5293 "at the next reboot.\n"),
5294 error, strerror(error));
5299 _("\nWARNING: If you have created or modified any DOS 6.x\n"
5300 "partitions, please see the fdisk manual page for additional\n"
5306 printf(_("Syncing disks.\n"));
5308 sleep(4); /* for sync() */
5312 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
5314 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
5315 #define MAX_PER_LINE 16
5317 print_buffer(char pbuffer[]) {
5321 for (i = 0, l = 0; i < sector_size; i++, l++) {
5323 printf("0x%03X:", i);
5324 printf(" %02X", (unsigned char) pbuffer[i]);
5325 if (l == MAX_PER_LINE - 1) {
5340 printf(_("Device: %s\n"), disk_device);
5341 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
5342 if (sun_label || sgi_label)
5343 print_buffer(MBRbuffer);
5346 for (i = 3; i < partitions; i++)
5347 print_buffer(ptes[i].sectorbuffer);
5352 struct pte *pe = &ptes[i];
5353 struct partition *p = pe->part_table;
5356 if (warn_geometry())
5358 if (!p->sys_ind || !get_nr_sects(p) || IS_EXTENDED (p->sys_ind)) {
5359 printf(_("Partition %d has no data area\n"), i + 1);
5362 first = get_partition_start(pe);
5363 new = read_int(first, first, first + get_nr_sects(p) - 1, first,
5364 _("New beginning of data")) - pe->offset;
5366 if (new != get_nr_sects(p)) {
5367 first = get_nr_sects(p) + get_start_sect(p) - new;
5368 set_nr_sects(p, first);
5369 set_start_sect(p, new);
5380 c = tolower(read_char(_("Expert command (m for help): ")));
5383 #ifdef CONFIG_FEATURE_SUN_LABEL
5390 move_begin(get_partition(0, partitions));
5393 user_cylinders = cylinders =
5394 read_int(1, cylinders, 1048576, 0,
5395 _("Number of cylinders"));
5396 #ifdef CONFIG_FEATURE_SUN_LABEL
5398 sun_set_ncyl(cylinders);
5407 #ifdef CONFIG_FEATURE_SGI_LABEL
5412 #ifdef CONFIG_FEATURE_SUN_LABEL
5422 fix_partition_table_order();
5425 #ifdef CONFIG_FEATURE_SGI_LABEL
5430 user_heads = heads = read_int(1, heads, 256, 0,
5431 _("Number of heads"));
5435 #ifdef CONFIG_FEATURE_SUN_LABEL
5441 #ifdef CONFIG_FEATURE_SUN_LABEL
5447 #ifdef CONFIG_FEATURE_SUN_LABEL
5461 user_sectors = sectors = read_int(1, sectors, 63, 0,
5462 _("Number of sectors"));
5463 if (dos_compatible_flag) {
5464 sector_offset = sectors;
5465 fprintf(stderr, _("Warning: setting "
5466 "sector offset for DOS "
5475 write_table(); /* does not return */
5478 #ifdef CONFIG_FEATURE_SUN_LABEL
5480 sun_set_pcylcount();
5488 #endif /* ADVANCED mode */
5491 is_ide_cdrom_or_tape(const char *device) {
5494 struct stat statbuf;
5497 /* No device was given explicitly, and we are trying some
5498 likely things. But opening /dev/hdc may produce errors like
5499 "hdc: tray open or drive not ready"
5500 if it happens to be a CD-ROM drive. It even happens that
5501 the process hangs on the attempt to read a music CD.
5502 So try to be careful. This only works since 2.1.73. */
5504 if (strncmp("/dev/hd", device, 7))
5507 snprintf(buf, sizeof(buf), "/proc/ide/%s/media", device+5);
5508 procf = fopen(buf, "r");
5509 if (procf != NULL && fgets(buf, sizeof(buf), procf))
5510 is_ide = (!strncmp(buf, "cdrom", 5) ||
5511 !strncmp(buf, "tape", 4));
5513 /* Now when this proc file does not exist, skip the
5514 device when it is read-only. */
5515 if (stat(device, &statbuf) == 0)
5516 is_ide = ((statbuf.st_mode & 0222) == 0);
5524 try(const char *device, int user_specified) {
5527 disk_device = device;
5528 if (setjmp(listingbuf))
5530 if (!user_specified)
5531 if (is_ide_cdrom_or_tape(device))
5533 if ((fd = open(disk_device, type_open)) >= 0) {
5534 gb = get_boot(try_only);
5535 if (gb > 0) { /* I/O error */
5537 } else if (gb < 0) { /* no DOS signature */
5538 list_disk_geometry();
5541 #ifdef CONFIG_FEATURE_OSF_LABEL
5542 if (btrydev(device) < 0)
5545 _("Disk %s doesn't contain a valid "
5546 "partition table\n"), device);
5551 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5552 if (!sun_label && partitions > 4)
5553 delete_partition(ext_index);
5557 /* Ignore other errors, since we try IDE
5558 and SCSI hard disks which may not be
5559 installed on the system. */
5560 if (errno == EACCES) {
5561 fprintf(stderr, _("Cannot open %s\n"), device);
5567 /* for fdisk -l: try all things in /proc/partitions
5568 that look like a partition name (do not end in a digit) */
5572 char line[100], ptname[100], devname[120], *s;
5575 procpt = bb_wfopen(PROC_PARTITIONS, "r");
5577 while (fgets(line, sizeof(line), procpt)) {
5578 if (sscanf (line, " %d %d %d %[^\n ]",
5579 &ma, &mi, &sz, ptname) != 4)
5581 for (s = ptname; *s; s++);
5584 sprintf(devname, "/dev/%s", ptname);
5587 #ifdef CONFIG_FEATURE_CLEAN_UP
5592 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5594 unknown_command(int c) {
5595 printf(_("%c: unknown command\n"), c);
5599 int fdisk_main(int argc, char **argv) {
5601 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5604 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5610 * fdisk -l [-b sectorsize] [-u] device ...
5611 * fdisk -s [partition] ...
5612 * fdisk [-b sectorsize] [-u] device
5614 * Options -C, -H, -S set the geometry.
5617 while ((c = getopt(argc, argv, "b:C:H:lS:uvV"
5618 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5624 /* Ugly: this sector size is really per device,
5625 so cannot be combined with multiple disks,
5626 and te same goes for the C/H/S options.
5628 sector_size = atoi(optarg);
5629 if (sector_size != 512 && sector_size != 1024 &&
5630 sector_size != 2048)
5633 user_set_sector_size = 1;
5636 user_cylinders = atoi(optarg);
5639 user_heads = atoi(optarg);
5640 if (user_heads <= 0 || user_heads >= 256)
5644 user_sectors = atoi(optarg);
5645 if (user_sectors <= 0 || user_sectors >= 64)
5649 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5653 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5659 display_in_cyl_units = 0;
5663 printf("fdisk v" UTIL_LINUX_VERSION "\n");
5671 printf(_("This kernel finds the sector size itself - "
5672 "-b option ignored\n"));
5674 if (user_set_sector_size && argc-optind != 1)
5675 printf(_("Warning: the -b (set sector size) option should"
5676 " be used with one specified device\n"));
5679 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5683 type_open = O_RDONLY;
5684 if (argc > optind) {
5687 /* avoid gcc warning:
5688 variable `k' might be clobbered by `longjmp' */
5692 for (k=optind; k<argc; k++)
5695 /* we no longer have default device names */
5696 /* but, we can use /proc/partitions instead */
5700 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5704 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5710 type_open = O_RDONLY;
5712 opts = argc - optind;
5716 for (j = optind; j < argc; j++) {
5717 disk_device = argv[j];
5718 if ((fd = open(disk_device, type_open)) < 0)
5719 fdisk_fatal(unable_to_open);
5720 if (ioctl(fd, BLKGETSIZE, &size))
5721 fdisk_fatal(ioctl_error);
5724 printf("%ld\n", size/2);
5726 printf("%s: %ld\n", argv[j], size/2);
5732 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5733 if (argc-optind == 1)
5734 disk_device = argv[optind];
5740 #ifdef CONFIG_FEATURE_OSF_LABEL
5742 /* OSF label, and no DOS label */
5743 printf(_("Detected an OSF/1 disklabel on %s, entering "
5744 "disklabel mode.\n"),
5748 /* If we return we may want to make an empty DOS label? */
5754 c = tolower(read_char(_("Command (m for help): ")));
5758 toggle_active(get_partition(1, partitions));
5759 #ifdef CONFIG_FEATURE_SUN_LABEL
5761 toggle_sunflags(get_partition(1, partitions),
5764 #ifdef CONFIG_FEATURE_SGI_LABEL
5766 sgi_set_bootpartition(
5767 get_partition(1, partitions));
5773 #ifdef CONFIG_FEATURE_SGI_LABEL
5775 printf(_("\nThe current boot file is: %s\n"),
5776 sgi_get_bootfile());
5777 if (read_chars(_("Please enter the name of the "
5778 "new boot file: ")) == '\n')
5779 printf(_("Boot file unchanged\n"));
5781 sgi_set_bootfile(line_ptr);
5784 #ifdef CONFIG_FEATURE_OSF_LABEL
5790 toggle_dos_compatibility_flag();
5791 #ifdef CONFIG_FEATURE_SUN_LABEL
5793 toggle_sunflags(get_partition(1, partitions),
5796 #ifdef CONFIG_FEATURE_SGI_LABEL
5798 sgi_set_swappartition(
5799 get_partition(1, partitions));
5807 #ifdef CONFIG_FEATURE_SGI_LABEL
5808 /* If sgi_label then don't use get_existing_partition,
5809 let the user select a partition, since
5810 get_existing_partition() only works for Linux-like
5813 j = get_existing_partition(1, partitions);
5815 j = get_partition(1, partitions);
5818 j = get_existing_partition(1, partitions);
5821 delete_partition(j);
5825 #ifdef CONFIG_FEATURE_SGI_LABEL
5832 list_types(get_sys_types());
5851 #ifdef CONFIG_FEATURE_SUN_LABEL
5865 write_table(); /* does not return */
5867 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
5869 #ifdef CONFIG_FEATURE_SGI_LABEL
5872 _("\n\tSorry, no experts menu for SGI "
5873 "partition tables available.\n\n"));
5886 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */