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 #include <sys/types.h>
19 #include <sys/stat.h> /* stat */
28 #include <assert.h> /* assert */
31 #include <sys/ioctl.h>
32 #include <sys/param.h>
33 #include <sys/sysmacros.h> /* major */
35 #include <stdint.h> /* for uint32_t, uint16_t, uint8_t, int16_t, etc */
37 /* Copied from linux/major.h */
38 #define FLOPPY_MAJOR 2
40 #include <sys/utsname.h>
44 #define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r))
50 #define BLKRRPART _IO(0x12,95) /* re-read partition table */
51 #define BLKGETSIZE _IO(0x12,96) /* return device size */
52 #define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */
53 #define BLKSSZGET _IO(0x12,104) /* get block device sector size */
55 /* Avoid conflicts with the 2.6 kernel headers, which define
56 * _IOR rather differently */
58 #define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size))
59 #define BLKGETSIZE64 _IOR(0x12,114,uint64_t)
65 #define DEFAULT_SECTOR_SIZE 512
66 #define MAX_SECTOR_SIZE 2048
67 #define SECTOR_SIZE 512 /* still used in BSD code */
68 #define MAXIMUM_PARTS 60
70 #define ACTIVE_FLAG 0x80
73 #define WIN98_EXTENDED 0x0f
74 #define LINUX_PARTITION 0x81
75 #define LINUX_SWAP 0x82
76 #define LINUX_NATIVE 0x83
77 #define LINUX_EXTENDED 0x85
78 #define LINUX_LVM 0x8e
79 #define LINUX_RAID 0xfd
84 #define IS_EXTENDED(i) \
85 ((i) == EXTENDED || (i) == WIN98_EXTENDED || (i) == LINUX_EXTENDED)
87 #define SIZE(a) (sizeof(a)/sizeof((a)[0]))
89 #define cround(n) (display_in_cyl_units ? ((n)/units_per_sector)+1 : (n))
90 #define scround(x) (((x)+units_per_sector-1)/units_per_sector)
92 #ifdef CONFIG_FEATURE_SUN_LABEL
93 #define SCSI_IOCTL_GET_IDLUN 0x5382
97 /* including <linux/hdreg.h> also fails */
100 unsigned char sectors;
101 unsigned short cylinders;
105 #define HDIO_GETGEO 0x0301 /* get device geometry */
109 const unsigned char *name;
112 static uint sector_size = DEFAULT_SECTOR_SIZE,
113 user_set_sector_size,
117 * Raw disk label. For DOS-type partition tables the MBR,
118 * with descriptions of the primary partitions.
120 static char MBRbuffer[MAX_SECTOR_SIZE];
122 #ifdef CONFIG_FEATURE_SUN_LABEL
123 static int sun_label; /* looking at sun disklabel */
127 #ifdef CONFIG_FEATURE_SGI_LABEL
128 static int sgi_label; /* looking at sgi disklabel */
132 #ifdef CONFIG_FEATURE_AIX_LABEL
133 static int aix_label; /* looking at aix disklabel */
137 #ifdef CONFIG_FEATURE_OSF_LABEL
138 static int osf_label; /* looking at OSF/1 disklabel */
139 static int possibly_osf_label;
144 #define dos_label (!sun_label && !sgi_label && !aix_label && !osf_label)
146 static uint heads, sectors, cylinders;
147 static void update_units(void);
151 * return partition name - uses static storage unless buf is supplied
154 partname(const char *dev, int pno, int lth) {
155 static char buffer[80];
162 bufsiz = sizeof(buffer);
167 if (isdigit(dev[w-1]))
170 /* devfs kludge - note: fdisk partition names are not supposed
171 to equal kernel names, so there is no reason to do this */
172 if (strcmp (dev + w - 4, "disc") == 0) {
180 snprintf(bufp, bufsiz, "%*.*s%s%-2u",
181 lth-wp-2, w, dev, p, pno);
183 snprintf(bufp, bufsiz, "%.*s%s%-2u", w, dev, p, pno);
189 unsigned char boot_ind; /* 0x80 - active */
190 unsigned char head; /* starting head */
191 unsigned char sector; /* starting sector */
192 unsigned char cyl; /* starting cylinder */
193 unsigned char sys_ind; /* What partition type */
194 unsigned char end_head; /* end head */
195 unsigned char end_sector; /* end sector */
196 unsigned char end_cyl; /* end cylinder */
197 unsigned char start4[4]; /* starting sector counting from 0 */
198 unsigned char size4[4]; /* nr of sectors in partition */
199 } __attribute__((__packed__));
202 ioctl_error, unable_to_open, unable_to_read, unable_to_seek,
206 enum action {fdisk, require, try_only, create_empty_dos, create_empty_sun};
208 static const char *disk_device;
209 static int fd; /* the disk */
210 static int partitions = 4; /* maximum partition + 1 */
211 static uint display_in_cyl_units = 1;
212 static uint units_per_sector = 1;
213 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
214 static char *line_ptr;
215 static void change_units(void);
216 static void reread_partition_table(int leave);
217 static void delete_partition(int i);
218 static int get_partition(int warn, int max);
219 static void list_types(const struct systypes *sys);
220 static uint read_int(uint low, uint dflt, uint high, uint base, char *mesg);
222 static const char *partition_type(unsigned char type);
223 static void fdisk_fatal(enum failure why) __attribute__ ((noreturn));
224 static void get_geometry(void);
225 static int get_boot(enum action what);
230 #define hex_val(c) ({ \
232 isdigit(_c) ? _c - '0' : \
233 tolower(_c) + 10 - 'a'; \
237 #define LINE_LENGTH 800
238 #define pt_offset(b, n) ((struct partition *)((b) + 0x1be + \
239 (n) * sizeof(struct partition)))
240 #define sector(s) ((s) & 0x3f)
241 #define cylinder(s, c) ((c) | (((s) & 0xc0) << 2))
243 #define hsc2sector(h,s,c) (sector(s) - 1 + sectors * \
244 ((h) + heads * cylinder(s,c)))
245 #define set_hsc(h,s,c,sector) { \
246 s = sector % sectors + 1; \
248 h = sector % heads; \
251 s |= (sector >> 2) & 0xc0; \
255 static int32_t get_start_sect(const struct partition *p);
256 static int32_t get_nr_sects(const struct partition *p);
259 * per partition table entry data
261 * The four primary partitions have the same sectorbuffer (MBRbuffer)
262 * and have NULL ext_pointer.
263 * Each logical partition table entry has two pointers, one for the
264 * partition and one link to the next one.
267 struct partition *part_table; /* points into sectorbuffer */
268 struct partition *ext_pointer; /* points into sectorbuffer */
269 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
270 char changed; /* boolean */
272 off_t offset; /* disk sector number */
273 char *sectorbuffer; /* disk sector contents */
274 } ptes[MAXIMUM_PARTS];
277 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
279 set_all_unchanged(void) {
282 for (i = 0; i < MAXIMUM_PARTS; i++)
290 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
292 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_OSF_LABEL)
293 static struct partition *
294 get_part_table(int i) {
295 return ptes[i].part_table;
300 str_units(int n) { /* n==1: use singular */
302 return display_in_cyl_units ? _("cylinder") : _("sector");
304 return display_in_cyl_units ? _("cylinders") : _("sectors");
308 valid_part_table_flag(const unsigned char *b) {
309 return (b[510] == 0x55 && b[511] == 0xaa);
312 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
313 static char line_buffer[LINE_LENGTH];
315 /* read line; return 0 or first char */
319 static int got_eof = 0;
321 fflush (stdout); /* requested by niles@scyld.com */
322 line_ptr = line_buffer;
323 if (!fgets(line_buffer, LINE_LENGTH, stdin)) {
325 got_eof++; /* user typed ^D ? */
327 fprintf(stderr, _("\ngot EOF thrice - exiting..\n"));
332 while (*line_ptr && !isgraph(*line_ptr))
338 read_char(const char *mesg)
342 } while (!read_line());
347 read_chars(const char *mesg)
358 read_hex(const struct systypes *sys)
364 read_char(_("Hex code (type L to list codes): "));
365 if (*line_ptr == 'l' || *line_ptr == 'L')
367 else if (isxdigit (*line_ptr))
371 hex = hex << 4 | hex_val(*line_ptr++);
372 while (isxdigit(*line_ptr));
377 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
379 #ifdef CONFIG_FEATURE_AIX_LABEL
381 * Copyright (C) Andreas Neuper, Sep 1998.
382 * This file may be redistributed under
383 * the terms of the GNU Public License.
387 unsigned int magic; /* expect AIX_LABEL_MAGIC */
388 unsigned int fillbytes1[124];
389 unsigned int physical_volume_id;
390 unsigned int fillbytes2[124];
393 #define AIX_LABEL_MAGIC 0xc9c2d4c1
394 #define AIX_LABEL_MAGIC_SWAPPED 0xc1d4c2c9
395 #define AIX_INFO_MAGIC 0x00072959
396 #define AIX_INFO_MAGIC_SWAPPED 0x59290700
398 #define aixlabel ((aix_partition *)MBRbuffer)
403 * 1999-03-20 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
404 * Internationalization
406 * 2003-03-20 Phillip Kesling <pkesling@sgi.com>
410 static int aix_other_endian;
411 static short aix_volumes=1;
414 * only dealing with free blocks here
420 _("\n\tThere is a valid AIX label on this disk.\n"
421 "\tUnfortunately Linux cannot handle these\n"
422 "\tdisks at the moment. Nevertheless some\n"
424 "\t1. fdisk will destroy its contents on write.\n"
425 "\t2. Be sure that this disk is NOT a still vital\n"
426 "\t part of a volume group. (Otherwise you may\n"
427 "\t erase the other disks as well, if unmirrored.)\n"
428 "\t3. Before deleting this physical volume be sure\n"
429 "\t to remove the disk logically from your AIX\n"
430 "\t machine. (Otherwise you become an AIXpert).")
440 memset( MBRbuffer, 0, sizeof(MBRbuffer) ); /* avoid fdisk cores */
445 check_aix_label( void )
447 if (aixlabel->magic != AIX_LABEL_MAGIC &&
448 aixlabel->magic != AIX_LABEL_MAGIC_SWAPPED) {
450 aix_other_endian = 0;
453 aix_other_endian = (aixlabel->magic == AIX_LABEL_MAGIC_SWAPPED);
459 aix_nolabel(); /* %% */
460 aix_label = 1; /* %% */
463 #endif /* AIX_LABEL */
465 #ifdef CONFIG_FEATURE_OSF_LABEL
467 * Copyright (c) 1987, 1988 Regents of the University of California.
468 * All rights reserved.
470 * Redistribution and use in source and binary forms, with or without
471 * modification, are permitted provided that the following conditions
473 * 1. Redistributions of source code must retain the above copyright
474 * notice, this list of conditions and the following disclaimer.
475 * 2. Redistributions in binary form must reproduce the above copyright
476 * notice, this list of conditions and the following disclaimer in the
477 * documentation and/or other materials provided with the distribution.
478 * 3. All advertising materials mentioning features or use of this software
479 * must display the following acknowledgment:
480 * This product includes software developed by the University of
481 * California, Berkeley and its contributors.
482 * 4. Neither the name of the University nor the names of its contributors
483 * may be used to endorse or promote products derived from this software
484 * without specific prior written permission.
486 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
487 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
488 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
489 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
490 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
491 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
492 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
493 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
494 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
495 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
500 #ifndef BSD_DISKMAGIC
501 #define BSD_DISKMAGIC ((uint32_t) 0x82564557)
504 #ifndef BSD_MAXPARTITIONS
505 #define BSD_MAXPARTITIONS 16
508 #define BSD_LINUX_BOOTDIR "/usr/ucb/mdec"
510 #if defined (i386) || defined (__sparc__) || defined (__arm__) || defined (__mips__) || defined (__s390__) || defined (__sh__) || defined(__x86_64__)
511 #define BSD_LABELSECTOR 1
512 #define BSD_LABELOFFSET 0
513 #elif defined (__alpha__) || defined (__powerpc__) || defined (__ia64__) || defined (__hppa__)
514 #define BSD_LABELSECTOR 0
515 #define BSD_LABELOFFSET 64
516 #elif defined (__s390__) || defined (__s390x__)
517 #define BSD_LABELSECTOR 1
518 #define BSD_LABELOFFSET 0
520 #error unknown architecture
523 #define BSD_BBSIZE 8192 /* size of boot area, with label */
524 #define BSD_SBSIZE 8192 /* max size of fs superblock */
526 struct xbsd_disklabel {
527 uint32_t d_magic; /* the magic number */
528 int16_t d_type; /* drive type */
529 int16_t d_subtype; /* controller/d_type specific */
530 char d_typename[16]; /* type name, e.g. "eagle" */
531 char d_packname[16]; /* pack identifier */
533 uint32_t d_secsize; /* # of bytes per sector */
534 uint32_t d_nsectors; /* # of data sectors per track */
535 uint32_t d_ntracks; /* # of tracks per cylinder */
536 uint32_t d_ncylinders; /* # of data cylinders per unit */
537 uint32_t d_secpercyl; /* # of data sectors per cylinder */
538 uint32_t d_secperunit; /* # of data sectors per unit */
540 * Spares (bad sector replacements) below
541 * are not counted in d_nsectors or d_secpercyl.
542 * Spare sectors are assumed to be physical sectors
543 * which occupy space at the end of each track and/or cylinder.
545 uint16_t d_sparespertrack; /* # of spare sectors per track */
546 uint16_t d_sparespercyl; /* # of spare sectors per cylinder */
548 * Alternate cylinders include maintenance, replacement,
549 * configuration description areas, etc.
551 uint32_t d_acylinders; /* # of alt. cylinders per unit */
553 /* hardware characteristics: */
555 * d_interleave, d_trackskew and d_cylskew describe perturbations
556 * in the media format used to compensate for a slow controller.
557 * Interleave is physical sector interleave, set up by the formatter
558 * or controller when formatting. When interleaving is in use,
559 * logically adjacent sectors are not physically contiguous,
560 * but instead are separated by some number of sectors.
561 * It is specified as the ratio of physical sectors traversed
562 * per logical sector. Thus an interleave of 1:1 implies contiguous
563 * layout, while 2:1 implies that logical sector 0 is separated
564 * by one sector from logical sector 1.
565 * d_trackskew is the offset of sector 0 on track N
566 * relative to sector 0 on track N-1 on the same cylinder.
567 * Finally, d_cylskew is the offset of sector 0 on cylinder N
568 * relative to sector 0 on cylinder N-1.
570 uint16_t d_rpm; /* rotational speed */
571 uint16_t d_interleave; /* hardware sector interleave */
572 uint16_t d_trackskew; /* sector 0 skew, per track */
573 uint16_t d_cylskew; /* sector 0 skew, per cylinder */
574 uint32_t d_headswitch; /* head switch time, usec */
575 uint32_t d_trkseek; /* track-to-track seek, usec */
576 uint32_t d_flags; /* generic flags */
578 uint32_t d_drivedata[NDDATA]; /* drive-type specific information */
580 uint32_t d_spare[NSPARE]; /* reserved for future use */
581 uint32_t d_magic2; /* the magic number (again) */
582 uint16_t d_checksum; /* xor of data incl. partitions */
583 /* filesystem and partition information: */
584 uint16_t d_npartitions; /* number of partitions in following */
585 uint32_t d_bbsize; /* size of boot area at sn0, bytes */
586 uint32_t d_sbsize; /* max size of fs superblock, bytes */
587 struct xbsd_partition { /* the partition table */
588 uint32_t p_size; /* number of sectors in partition */
589 uint32_t p_offset; /* starting sector */
590 uint32_t p_fsize; /* filesystem basic fragment size */
591 uint8_t p_fstype; /* filesystem type, see below */
592 uint8_t p_frag; /* filesystem fragments per block */
593 uint16_t p_cpg; /* filesystem cylinders per group */
594 } d_partitions[BSD_MAXPARTITIONS]; /* actually may be more */
598 #define BSD_DTYPE_SMD 1 /* SMD, XSMD; VAX hp/up */
599 #define BSD_DTYPE_MSCP 2 /* MSCP */
600 #define BSD_DTYPE_DEC 3 /* other DEC (rk, rl) */
601 #define BSD_DTYPE_SCSI 4 /* SCSI */
602 #define BSD_DTYPE_ESDI 5 /* ESDI interface */
603 #define BSD_DTYPE_ST506 6 /* ST506 etc. */
604 #define BSD_DTYPE_HPIB 7 /* CS/80 on HP-IB */
605 #define BSD_DTYPE_HPFL 8 /* HP Fiber-link */
606 #define BSD_DTYPE_FLOPPY 10 /* floppy */
608 /* d_subtype values: */
609 #define BSD_DSTYPE_INDOSPART 0x8 /* is inside dos partition */
610 #define BSD_DSTYPE_DOSPART(s) ((s) & 3) /* dos partition number */
611 #define BSD_DSTYPE_GEOMETRY 0x10 /* drive params in label */
614 static const char * const xbsd_dktypenames[] = {
628 #define BSD_DKMAXTYPES (sizeof(xbsd_dktypenames) / sizeof(xbsd_dktypenames[0]) - 1)
632 * Filesystem type and version.
633 * Used to interpret other filesystem-specific
634 * per-partition information.
636 #define BSD_FS_UNUSED 0 /* unused */
637 #define BSD_FS_SWAP 1 /* swap */
638 #define BSD_FS_V6 2 /* Sixth Edition */
639 #define BSD_FS_V7 3 /* Seventh Edition */
640 #define BSD_FS_SYSV 4 /* System V */
641 #define BSD_FS_V71K 5 /* V7 with 1K blocks (4.1, 2.9) */
642 #define BSD_FS_V8 6 /* Eighth Edition, 4K blocks */
643 #define BSD_FS_BSDFFS 7 /* 4.2BSD fast file system */
644 #define BSD_FS_BSDLFS 9 /* 4.4BSD log-structured file system */
645 #define BSD_FS_OTHER 10 /* in use, but unknown/unsupported */
646 #define BSD_FS_HPFS 11 /* OS/2 high-performance file system */
647 #define BSD_FS_ISO9660 12 /* ISO-9660 filesystem (cdrom) */
648 #define BSD_FS_ISOFS BSD_FS_ISO9660
649 #define BSD_FS_BOOT 13 /* partition contains bootstrap */
650 #define BSD_FS_ADOS 14 /* AmigaDOS fast file system */
651 #define BSD_FS_HFS 15 /* Macintosh HFS */
652 #define BSD_FS_ADVFS 16 /* Digital Unix AdvFS */
654 /* this is annoying, but it's also the way it is :-( */
656 #define BSD_FS_EXT2 8 /* ext2 file system */
658 #define BSD_FS_MSDOS 8 /* MS-DOS file system */
662 static const struct systypes xbsd_fstypes[] = {
663 /* BSD_FS_UNUSED */ {"\x00" "unused"},
664 /* BSD_FS_SWAP */ {"\x01" "swap"},
665 /* BSD_FS_V6 */ {"\x02" "Version 6"},
666 /* BSD_FS_V7 */ {"\x03" "Version 7"},
667 /* BSD_FS_SYSV */ {"\x04" "System V"},
668 /* BSD_FS_V71K */ {"\x05" "4.1BSD"},
669 /* BSD_FS_V8 */ {"\x06" "Eighth Edition"},
670 /* BSD_FS_BSDFFS */ {"\x07" "4.2BSD"},
672 /* BSD_FS_EXT2 */ {"\x08" "ext2"},
674 /* BSD_FS_MSDOS */ {"\x08" "MS-DOS"},
676 /* BSD_FS_BSDLFS */ {"\x09" "4.4LFS"},
677 /* BSD_FS_OTHER */ {"\x0a" "unknown"},
678 /* BSD_FS_HPFS */ {"\x0b" "HPFS"},
679 /* BSD_FS_ISO9660 */ {"\x0c" "ISO-9660"},
680 /* BSD_FS_BOOT */ {"\x0d" "boot"},
681 /* BSD_FS_ADOS */ {"\x0e" "ADOS"},
682 /* BSD_FS_HFS */ {"\x0f" "HFS"},
683 /* BSD_FS_ADVFS */ {"\x10" "AdvFS"},
686 #define BSD_FSMAXTYPES (SIZE(xbsd_fstypes)-1)
691 * flags shared by various drives:
693 #define BSD_D_REMOVABLE 0x01 /* removable media */
694 #define BSD_D_ECC 0x02 /* supports ECC */
695 #define BSD_D_BADSECT 0x04 /* supports bad sector forw. */
696 #define BSD_D_RAMDISK 0x08 /* disk emulator */
697 #define BSD_D_CHAIN 0x10 /* can do back-back transfers */
698 #define BSD_D_DOSPART 0x20 /* within MSDOS partition */
700 #endif /* OSF_LABEL */
703 * Copyright (C) Andreas Neuper, Sep 1998.
704 * This file may be modified and redistributed under
705 * the terms of the GNU Public License.
708 struct device_parameter { /* 48 bytes */
712 unsigned char sparecyl;
713 unsigned short pcylcount;
714 unsigned short head_vol0;
715 unsigned short ntrks; /* tracks in cyl 0 or vol 0 */
716 unsigned char cmd_tag_queue_depth;
717 unsigned char unused0;
718 unsigned short unused1;
719 unsigned short nsect; /* sectors/tracks in cyl 0 or vol 0 */
720 unsigned short bytes;
721 unsigned short ilfact;
722 unsigned int flags; /* controller flags */
723 unsigned int datarate;
724 unsigned int retries_on_error;
725 unsigned int ms_per_word;
726 unsigned short xylogics_gap1;
727 unsigned short xylogics_syncdelay;
728 unsigned short xylogics_readdelay;
729 unsigned short xylogics_gap2;
730 unsigned short xylogics_readgate;
731 unsigned short xylogics_writecont;
734 #define SGI_VOLHDR 0x00
735 /* 1 and 2 were used for drive types no longer supported by SGI */
736 #define SGI_SWAP 0x03
737 /* 4 and 5 were for filesystem types SGI haven't ever supported on MIPS CPUs */
738 #define SGI_VOLUME 0x06
740 #define SGI_LVOL 0x08
741 #define SGI_RLVOL 0x09
743 #define SGI_XFSLOG 0x0b
746 #define ENTIRE_DISK SGI_VOLUME
750 #define SECTOR_SLIP 0x01
751 #define SECTOR_FWD 0x02
752 #define TRACK_FWD 0x04
753 #define TRACK_MULTIVOL 0x08
754 #define IGNORE_ERRORS 0x10
756 #define ENABLE_CMDTAGQ 0x40
759 unsigned int magic; /* expect SGI_LABEL_MAGIC */
760 unsigned short boot_part; /* active boot partition */
761 unsigned short swap_part; /* active swap partition */
762 unsigned char boot_file[16]; /* name of the bootfile */
763 struct device_parameter devparam; /* 1 * 48 bytes */
764 struct volume_directory { /* 15 * 16 bytes */
765 unsigned char vol_file_name[8]; /* a character array */
766 unsigned int vol_file_start; /* number of logical block */
767 unsigned int vol_file_size; /* number of bytes */
769 struct sgi_partition { /* 16 * 12 bytes */
770 unsigned int num_sectors; /* number of blocks */
771 unsigned int start_sector; /* must be cylinder aligned */
775 unsigned int fillbytes;
779 unsigned int magic; /* looks like a magic number */
788 unsigned char scsi_string[50];
789 unsigned char serial[137];
790 unsigned short check1816;
791 unsigned char installer[225];
794 #define SGI_LABEL_MAGIC 0x0be5a941
795 #define SGI_LABEL_MAGIC_SWAPPED 0x41a9e50b
796 #define SGI_INFO_MAGIC 0x00072959
797 #define SGI_INFO_MAGIC_SWAPPED 0x59290700
798 #define SGI_SSWAP16(x) (sgi_other_endian ? __swap16(x) \
800 #define SGI_SSWAP32(x) (sgi_other_endian ? __swap32(x) \
803 #define sgilabel ((sgi_partition *)MBRbuffer)
804 #define sgiparam (sgilabel->devparam)
807 unsigned char info[128]; /* Informative text string */
808 unsigned char spare0[14];
810 unsigned char spare1;
812 unsigned char spare2;
815 unsigned char spare1[246]; /* Boot information etc. */
816 unsigned short rspeed; /* Disk rotational speed */
817 unsigned short pcylcount; /* Physical cylinder count */
818 unsigned short sparecyl; /* extra sects per cylinder */
819 unsigned char spare2[4]; /* More magic... */
820 unsigned short ilfact; /* Interleave factor */
821 unsigned short ncyl; /* Data cylinder count */
822 unsigned short nacyl; /* Alt. cylinder count */
823 unsigned short ntrks; /* Tracks per cylinder */
824 unsigned short nsect; /* Sectors per track */
825 unsigned char spare3[4]; /* Even more magic... */
826 struct sun_partition {
827 uint32_t start_cylinder;
828 uint32_t num_sectors;
830 unsigned short magic; /* Magic number */
831 unsigned short csum; /* Label xor'd checksum */
835 #define SUN_LABEL_MAGIC 0xDABE
836 #define SUN_LABEL_MAGIC_SWAPPED 0xBEDA
837 #define sunlabel ((sun_partition *)MBRbuffer)
838 #define SUN_SSWAP16(x) (sun_other_endian ? __swap16(x) \
840 #define SUN_SSWAP32(x) (sun_other_endian ? __swap32(x) \
844 #ifdef CONFIG_FEATURE_OSF_LABEL
847 19990319 - Arnaldo Carvalho de Melo <acme@conectiva.com.br> - i18n/nls
849 20000101 - David Huggins-Daines <dhuggins@linuxcare.com> - Better
850 support for OSF/1 disklabels on Alpha.
851 Also fixed unaligned accesses in alpha_bootblock_checksum()
854 #define FREEBSD_PARTITION 0xa5
855 #define NETBSD_PARTITION 0xa9
857 static void xbsd_delete_part (void);
858 static void xbsd_new_part (void);
859 static void xbsd_write_disklabel (void);
860 static int xbsd_create_disklabel (void);
861 static void xbsd_edit_disklabel (void);
862 static void xbsd_write_bootstrap (void);
863 static void xbsd_change_fstype (void);
864 static int xbsd_get_part_index (int max);
865 static int xbsd_check_new_partition (int *i);
866 static void xbsd_list_types (void);
867 static u_short xbsd_dkcksum (struct xbsd_disklabel *lp);
868 static int xbsd_initlabel (struct partition *p, struct xbsd_disklabel *d,
870 static int xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d);
871 static int xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d);
873 #if defined (__alpha__)
874 static void alpha_bootblock_checksum (char *boot);
877 #if !defined (__alpha__)
878 static int xbsd_translate_fstype (int linux_type);
879 static void xbsd_link_part (void);
880 static struct partition *xbsd_part;
881 static int xbsd_part_index;
884 #if defined (__alpha__)
885 /* We access this through a uint64_t * when checksumming */
886 static char disklabelbuffer[BSD_BBSIZE] __attribute__((aligned(8)));
888 static char disklabelbuffer[BSD_BBSIZE];
891 static struct xbsd_disklabel xbsd_dlabel;
893 #define bsd_cround(n) \
894 (display_in_cyl_units ? ((n)/xbsd_dlabel.d_secpercyl) + 1 : (n))
897 * Test whether the whole disk has BSD disk label magic.
899 * Note: often reformatting with DOS-type label leaves the BSD magic,
900 * so this does not mean that there is a BSD disk label.
903 check_osf_label(void) {
904 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
909 static void xbsd_print_disklabel(int);
912 btrydev (const char * dev) {
913 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
915 printf(_("\nBSD label for device: %s\n"), dev);
916 xbsd_print_disklabel (0);
922 puts (_("Command action"));
923 puts (_("\td\tdelete a BSD partition"));
924 puts (_("\te\tedit drive data"));
925 puts (_("\ti\tinstall bootstrap"));
926 puts (_("\tl\tlist known filesystem types"));
927 puts (_("\tm\tprint this menu"));
928 puts (_("\tn\tadd a new BSD partition"));
929 puts (_("\tp\tprint BSD partition table"));
930 puts (_("\tq\tquit without saving changes"));
931 puts (_("\tr\treturn to main menu"));
932 puts (_("\ts\tshow complete disklabel"));
933 puts (_("\tt\tchange a partition's filesystem id"));
934 puts (_("\tu\tchange units (cylinders/sectors)"));
935 puts (_("\tw\twrite disklabel to disk"));
936 #if !defined (__alpha__)
937 puts (_("\tx\tlink BSD partition to non-BSD partition"));
941 #if !defined (__alpha__)
948 is_bsd_partition_type(int type) {
949 return (type == FREEBSD_PARTITION ||
950 type == hidden(FREEBSD_PARTITION) ||
951 type == NETBSD_PARTITION ||
952 type == hidden(NETBSD_PARTITION));
958 #if !defined (__alpha__)
962 for (t=0; t<4; t++) {
963 p = get_part_table(t);
964 if (p && is_bsd_partition_type(p->sys_ind)) {
967 ss = get_start_sect(xbsd_part);
969 fprintf (stderr, _("Partition %s has invalid starting sector 0.\n"),
970 partname(disk_device, t+1, 0));
973 printf (_("Reading disklabel of %s at sector %d.\n"),
974 partname(disk_device, t+1, 0), ss + BSD_LABELSECTOR);
975 if (xbsd_readlabel (xbsd_part, &xbsd_dlabel) == 0)
976 if (xbsd_create_disklabel () == 0)
983 printf (_("There is no *BSD partition on %s.\n"), disk_device);
987 #elif defined (__alpha__)
989 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
990 if (xbsd_create_disklabel () == 0)
991 exit ( EXIT_SUCCESS );
997 switch (tolower (read_char (_("BSD disklabel command (m for help): ")))) {
1002 xbsd_edit_disklabel ();
1005 xbsd_write_bootstrap ();
1014 xbsd_print_disklabel (0);
1018 exit ( EXIT_SUCCESS );
1022 xbsd_print_disklabel (1);
1025 xbsd_change_fstype ();
1031 xbsd_write_disklabel ();
1033 #if !defined (__alpha__)
1046 xbsd_delete_part (void)
1050 i = xbsd_get_part_index (xbsd_dlabel.d_npartitions);
1051 xbsd_dlabel.d_partitions[i].p_size = 0;
1052 xbsd_dlabel.d_partitions[i].p_offset = 0;
1053 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
1054 if (xbsd_dlabel.d_npartitions == i + 1)
1055 while (xbsd_dlabel.d_partitions[xbsd_dlabel.d_npartitions-1].p_size == 0)
1056 xbsd_dlabel.d_npartitions--;
1060 xbsd_new_part (void)
1066 if (!xbsd_check_new_partition (&i))
1069 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
1070 begin = get_start_sect(xbsd_part);
1071 end = begin + get_nr_sects(xbsd_part) - 1;
1074 end = xbsd_dlabel.d_secperunit - 1;
1077 snprintf (mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
1078 begin = read_int (bsd_cround (begin), bsd_cround (begin), bsd_cround (end),
1081 if (display_in_cyl_units)
1082 begin = (begin - 1) * xbsd_dlabel.d_secpercyl;
1084 snprintf (mesg, sizeof(mesg), _("Last %s or +size or +sizeM or +sizeK"),
1085 str_units(SINGULAR));
1086 end = read_int (bsd_cround (begin), bsd_cround (end), bsd_cround (end),
1087 bsd_cround (begin), mesg);
1089 if (display_in_cyl_units)
1090 end = end * xbsd_dlabel.d_secpercyl - 1;
1092 xbsd_dlabel.d_partitions[i].p_size = end - begin + 1;
1093 xbsd_dlabel.d_partitions[i].p_offset = begin;
1094 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
1098 xbsd_print_disklabel (int show_all) {
1099 struct xbsd_disklabel *lp = &xbsd_dlabel;
1100 struct xbsd_partition *pp;
1104 #if defined (__alpha__)
1105 printf("# %s:\n", disk_device);
1107 printf("# %s:\n", partname(disk_device, xbsd_part_index+1, 0));
1109 if ((unsigned) lp->d_type < BSD_DKMAXTYPES)
1110 printf(_("type: %s\n"), xbsd_dktypenames[lp->d_type]);
1112 printf(_("type: %d\n"), lp->d_type);
1113 printf(_("disk: %.*s\n"), (int) sizeof(lp->d_typename), lp->d_typename);
1114 printf(_("label: %.*s\n"), (int) sizeof(lp->d_packname), lp->d_packname);
1115 printf(_("flags:"));
1116 if (lp->d_flags & BSD_D_REMOVABLE)
1117 printf(_(" removable"));
1118 if (lp->d_flags & BSD_D_ECC)
1120 if (lp->d_flags & BSD_D_BADSECT)
1121 printf(_(" badsect"));
1123 /* On various machines the fields of *lp are short/int/long */
1124 /* In order to avoid problems, we cast them all to long. */
1125 printf(_("bytes/sector: %ld\n"), (long) lp->d_secsize);
1126 printf(_("sectors/track: %ld\n"), (long) lp->d_nsectors);
1127 printf(_("tracks/cylinder: %ld\n"), (long) lp->d_ntracks);
1128 printf(_("sectors/cylinder: %ld\n"), (long) lp->d_secpercyl);
1129 printf(_("cylinders: %ld\n"), (long) lp->d_ncylinders);
1130 printf(_("rpm: %d\n"), lp->d_rpm);
1131 printf(_("interleave: %d\n"), lp->d_interleave);
1132 printf(_("trackskew: %d\n"), lp->d_trackskew);
1133 printf(_("cylinderskew: %d\n"), lp->d_cylskew);
1134 printf(_("headswitch: %ld\t\t# milliseconds\n"),
1135 (long) lp->d_headswitch);
1136 printf(_("track-to-track seek: %ld\t# milliseconds\n"),
1137 (long) lp->d_trkseek);
1138 printf(_("drivedata: "));
1139 for (i = NDDATA - 1; i >= 0; i--)
1140 if (lp->d_drivedata[i])
1144 for (j = 0; j <= i; j++)
1145 printf("%ld ", (long) lp->d_drivedata[j]);
1147 printf(_("\n%d partitions:\n"), lp->d_npartitions);
1148 printf(_("# start end size fstype [fsize bsize cpg]\n"));
1149 pp = lp->d_partitions;
1150 for (i = 0; i < lp->d_npartitions; i++, pp++) {
1152 if (display_in_cyl_units && lp->d_secpercyl) {
1153 printf(" %c: %8ld%c %8ld%c %8ld%c ",
1155 (long) pp->p_offset / lp->d_secpercyl + 1,
1156 (pp->p_offset % lp->d_secpercyl) ? '*' : ' ',
1157 (long) (pp->p_offset + pp->p_size + lp->d_secpercyl - 1)
1159 ((pp->p_offset + pp->p_size) % lp->d_secpercyl) ? '*' : ' ',
1160 (long) pp->p_size / lp->d_secpercyl,
1161 (pp->p_size % lp->d_secpercyl) ? '*' : ' ');
1163 printf(" %c: %8ld %8ld %8ld ",
1165 (long) pp->p_offset,
1166 (long) pp->p_offset + pp->p_size - 1,
1169 if ((unsigned) pp->p_fstype < BSD_FSMAXTYPES)
1170 printf("%8.8s", xbsd_fstypes[pp->p_fstype].name);
1172 printf("%8x", pp->p_fstype);
1173 switch (pp->p_fstype) {
1175 printf(" %5ld %5ld %5.5s ",
1176 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, "");
1180 printf(" %5ld %5ld %5d ",
1181 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag,
1186 printf("%22.22s", "");
1195 xbsd_write_disklabel (void) {
1196 #if defined (__alpha__)
1197 printf (_("Writing disklabel to %s.\n"), disk_device);
1198 xbsd_writelabel (NULL, &xbsd_dlabel);
1200 printf (_("Writing disklabel to %s.\n"),
1201 partname(disk_device, xbsd_part_index+1, 0));
1202 xbsd_writelabel (xbsd_part, &xbsd_dlabel);
1204 reread_partition_table(0); /* no exit yet */
1208 xbsd_create_disklabel (void) {
1211 #if defined (__alpha__)
1212 fprintf (stderr, _("%s contains no disklabel.\n"), disk_device);
1214 fprintf (stderr, _("%s contains no disklabel.\n"),
1215 partname(disk_device, xbsd_part_index+1, 0));
1219 c = read_char (_("Do you want to create a disklabel? (y/n) "));
1220 if (c == 'y' || c == 'Y') {
1221 if (xbsd_initlabel (
1222 #if defined (__alpha__) || defined (__powerpc__) || defined (__hppa__) || \
1223 defined (__s390__) || defined (__s390x__)
1224 NULL, &xbsd_dlabel, 0
1226 xbsd_part, &xbsd_dlabel, xbsd_part_index
1229 xbsd_print_disklabel (1);
1233 } else if (c == 'n')
1239 edit_int (int def, char *mesg)
1242 fputs (mesg, stdout);
1243 printf (" (%d): ", def);
1247 while (!isdigit (*line_ptr));
1248 return atoi (line_ptr);
1252 xbsd_edit_disklabel (void)
1254 struct xbsd_disklabel *d;
1258 #if defined (__alpha__) || defined (__ia64__)
1259 d -> d_secsize = (u_long) edit_int ((u_long) d -> d_secsize ,_("bytes/sector"));
1260 d -> d_nsectors = (u_long) edit_int ((u_long) d -> d_nsectors ,_("sectors/track"));
1261 d -> d_ntracks = (u_long) edit_int ((u_long) d -> d_ntracks ,_("tracks/cylinder"));
1262 d -> d_ncylinders = (u_long) edit_int ((u_long) d -> d_ncylinders ,_("cylinders"));
1265 /* d -> d_secpercyl can be != d -> d_nsectors * d -> d_ntracks */
1268 d -> d_secpercyl = (u_long) edit_int ((u_long) d -> d_nsectors * d -> d_ntracks,
1269 _("sectors/cylinder"));
1270 if (d -> d_secpercyl <= d -> d_nsectors * d -> d_ntracks)
1273 printf (_("Must be <= sectors/track * tracks/cylinder (default).\n"));
1275 d -> d_rpm = (u_short) edit_int ((u_short) d -> d_rpm ,_("rpm"));
1276 d -> d_interleave = (u_short) edit_int ((u_short) d -> d_interleave,_("interleave"));
1277 d -> d_trackskew = (u_short) edit_int ((u_short) d -> d_trackskew ,_("trackskew"));
1278 d -> d_cylskew = (u_short) edit_int ((u_short) d -> d_cylskew ,_("cylinderskew"));
1279 d -> d_headswitch = (u_long) edit_int ((u_long) d -> d_headswitch ,_("headswitch"));
1280 d -> d_trkseek = (u_long) edit_int ((u_long) d -> d_trkseek ,_("track-to-track seek"));
1282 d -> d_secperunit = d -> d_secpercyl * d -> d_ncylinders;
1286 xbsd_get_bootstrap (char *path, void *ptr, int size)
1290 if ((fdb = open (path, O_RDONLY)) < 0)
1295 if (read (fdb, ptr, size) < 0)
1301 printf (" ... %s\n", path);
1309 printf (_("\nSyncing disks.\n"));
1315 xbsd_write_bootstrap (void)
1317 char *bootdir = BSD_LINUX_BOOTDIR;
1318 char path[MAXPATHLEN];
1320 struct xbsd_disklabel dl;
1324 if (xbsd_dlabel.d_type == BSD_DTYPE_SCSI)
1329 printf (_("Bootstrap: %sboot -> boot%s (%s): "),
1330 dkbasename, dkbasename, dkbasename);
1332 line_ptr[strlen (line_ptr)-1] = '\0';
1333 dkbasename = line_ptr;
1335 snprintf (path, sizeof(path), "%s/%sboot", bootdir, dkbasename);
1336 if (!xbsd_get_bootstrap (path, disklabelbuffer, (int) xbsd_dlabel.d_secsize))
1339 /* We need a backup of the disklabel (xbsd_dlabel might have changed). */
1340 d = &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE];
1341 bcopy (d, &dl, sizeof (struct xbsd_disklabel));
1343 /* The disklabel will be overwritten by 0's from bootxx anyway */
1344 bzero (d, sizeof (struct xbsd_disklabel));
1346 snprintf (path, sizeof(path), "%s/boot%s", bootdir, dkbasename);
1347 if (!xbsd_get_bootstrap (path, &disklabelbuffer[xbsd_dlabel.d_secsize],
1348 (int) xbsd_dlabel.d_bbsize - xbsd_dlabel.d_secsize))
1351 e = d + sizeof (struct xbsd_disklabel);
1352 for (p=d; p < e; p++)
1354 fprintf (stderr, _("Bootstrap overlaps with disk label!\n"));
1355 exit ( EXIT_FAILURE );
1358 bcopy (&dl, d, sizeof (struct xbsd_disklabel));
1360 #if defined (__powerpc__) || defined (__hppa__)
1362 #elif defined (__alpha__)
1364 alpha_bootblock_checksum (disklabelbuffer);
1366 sector = get_start_sect(xbsd_part);
1369 if (lseek (fd, sector * SECTOR_SIZE, SEEK_SET) == -1)
1370 fdisk_fatal (unable_to_seek);
1371 if (BSD_BBSIZE != write (fd, disklabelbuffer, BSD_BBSIZE))
1372 fdisk_fatal (unable_to_write);
1374 #if defined (__alpha__)
1375 printf (_("Bootstrap installed on %s.\n"), disk_device);
1377 printf (_("Bootstrap installed on %s.\n"),
1378 partname (disk_device, xbsd_part_index+1, 0));
1385 xbsd_change_fstype (void)
1389 i = xbsd_get_part_index (xbsd_dlabel.d_npartitions);
1390 xbsd_dlabel.d_partitions[i].p_fstype = read_hex (xbsd_fstypes);
1394 xbsd_get_part_index (int max)
1399 snprintf (prompt, sizeof(prompt), _("Partition (a-%c): "), 'a' + max - 1);
1401 l = tolower (read_char (prompt));
1402 while (l < 'a' || l > 'a' + max - 1);
1407 xbsd_check_new_partition (int *i) {
1409 /* room for more? various BSD flavours have different maxima */
1410 if (xbsd_dlabel.d_npartitions == BSD_MAXPARTITIONS) {
1413 for (t = 0; t < BSD_MAXPARTITIONS; t++)
1414 if (xbsd_dlabel.d_partitions[t].p_size == 0)
1417 if (t == BSD_MAXPARTITIONS) {
1418 fprintf (stderr, _("The maximum number of partitions "
1419 "has been created\n"));
1424 *i = xbsd_get_part_index (BSD_MAXPARTITIONS);
1426 if (*i >= xbsd_dlabel.d_npartitions)
1427 xbsd_dlabel.d_npartitions = (*i) + 1;
1429 if (xbsd_dlabel.d_partitions[*i].p_size != 0) {
1430 fprintf (stderr, _("This partition already exists.\n"));
1438 xbsd_list_types (void) {
1439 list_types (xbsd_fstypes);
1443 xbsd_dkcksum (struct xbsd_disklabel *lp) {
1444 u_short *start, *end;
1447 start = (u_short *) lp;
1448 end = (u_short *) &lp->d_partitions[lp->d_npartitions];
1455 xbsd_initlabel (struct partition *p, struct xbsd_disklabel *d, int pindex) {
1456 struct xbsd_partition *pp;
1459 bzero (d, sizeof (struct xbsd_disklabel));
1461 d -> d_magic = BSD_DISKMAGIC;
1463 if (strncmp (disk_device, "/dev/sd", 7) == 0)
1464 d -> d_type = BSD_DTYPE_SCSI;
1466 d -> d_type = BSD_DTYPE_ST506;
1468 #if 0 /* not used (at least not written to disk) by NetBSD/i386 1.0 */
1469 d -> d_subtype = BSD_DSTYPE_INDOSPART & pindex;
1472 #if !defined (__alpha__)
1473 d -> d_flags = BSD_D_DOSPART;
1477 d -> d_secsize = SECTOR_SIZE; /* bytes/sector */
1478 d -> d_nsectors = sectors; /* sectors/track */
1479 d -> d_ntracks = heads; /* tracks/cylinder (heads) */
1480 d -> d_ncylinders = cylinders;
1481 d -> d_secpercyl = sectors * heads;/* sectors/cylinder */
1482 if (d -> d_secpercyl == 0)
1483 d -> d_secpercyl = 1; /* avoid segfaults */
1484 d -> d_secperunit = d -> d_secpercyl * d -> d_ncylinders;
1487 d -> d_interleave = 1;
1488 d -> d_trackskew = 0;
1490 d -> d_headswitch = 0;
1493 d -> d_magic2 = BSD_DISKMAGIC;
1494 d -> d_bbsize = BSD_BBSIZE;
1495 d -> d_sbsize = BSD_SBSIZE;
1497 #if !defined (__alpha__)
1498 d -> d_npartitions = 4;
1499 pp = &d -> d_partitions[2]; /* Partition C should be
1500 the NetBSD partition */
1501 pp -> p_offset = get_start_sect(p);
1502 pp -> p_size = get_nr_sects(p);
1503 pp -> p_fstype = BSD_FS_UNUSED;
1504 pp = &d -> d_partitions[3]; /* Partition D should be
1507 pp -> p_size = d -> d_secperunit;
1508 pp -> p_fstype = BSD_FS_UNUSED;
1509 #elif defined (__alpha__)
1510 d -> d_npartitions = 3;
1511 pp = &d -> d_partitions[2]; /* Partition C should be
1514 pp -> p_size = d -> d_secperunit;
1515 pp -> p_fstype = BSD_FS_UNUSED;
1522 * Read a xbsd_disklabel from sector 0 or from the starting sector of p.
1523 * If it has the right magic, return 1.
1526 xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d)
1530 /* p is used only to get the starting sector */
1531 #if !defined (__alpha__)
1532 sector = (p ? get_start_sect(p) : 0);
1533 #elif defined (__alpha__)
1537 if (lseek (fd, sector * SECTOR_SIZE, SEEK_SET) == -1)
1538 fdisk_fatal (unable_to_seek);
1539 if (BSD_BBSIZE != read (fd, disklabelbuffer, BSD_BBSIZE))
1540 fdisk_fatal (unable_to_read);
1542 bcopy (&disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
1543 d, sizeof (struct xbsd_disklabel));
1545 if (d -> d_magic != BSD_DISKMAGIC || d -> d_magic2 != BSD_DISKMAGIC)
1548 for (t = d -> d_npartitions; t < BSD_MAXPARTITIONS; t++) {
1549 d -> d_partitions[t].p_size = 0;
1550 d -> d_partitions[t].p_offset = 0;
1551 d -> d_partitions[t].p_fstype = BSD_FS_UNUSED;
1554 if (d -> d_npartitions > BSD_MAXPARTITIONS)
1555 fprintf (stderr, _("Warning: too many partitions "
1556 "(%d, maximum is %d).\n"),
1557 d -> d_npartitions, BSD_MAXPARTITIONS);
1562 xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d)
1564 unsigned int sector;
1566 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
1567 sector = get_start_sect(p) + BSD_LABELSECTOR;
1569 sector = BSD_LABELSECTOR;
1572 d -> d_checksum = 0;
1573 d -> d_checksum = xbsd_dkcksum (d);
1575 /* This is necessary if we want to write the bootstrap later,
1576 otherwise we'd write the old disklabel with the bootstrap.
1578 bcopy (d, &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
1579 sizeof (struct xbsd_disklabel));
1581 #if defined (__alpha__) && BSD_LABELSECTOR == 0
1582 alpha_bootblock_checksum (disklabelbuffer);
1583 if (lseek (fd, 0, SEEK_SET) == -1)
1584 fdisk_fatal (unable_to_seek);
1585 if (BSD_BBSIZE != write (fd, disklabelbuffer, BSD_BBSIZE))
1586 fdisk_fatal (unable_to_write);
1588 if (lseek (fd, sector * SECTOR_SIZE + BSD_LABELOFFSET,
1590 fdisk_fatal (unable_to_seek);
1591 if (sizeof (struct xbsd_disklabel) != write (fd, d, sizeof (struct xbsd_disklabel)))
1592 fdisk_fatal (unable_to_write);
1601 #if !defined (__alpha__)
1603 xbsd_translate_fstype (int linux_type)
1607 case 0x01: /* DOS 12-bit FAT */
1608 case 0x04: /* DOS 16-bit <32M */
1609 case 0x06: /* DOS 16-bit >=32M */
1610 case 0xe1: /* DOS access */
1611 case 0xe3: /* DOS R/O */
1612 case 0xf2: /* DOS secondary */
1613 return BSD_FS_MSDOS;
1614 case 0x07: /* OS/2 HPFS */
1617 return BSD_FS_OTHER;
1622 xbsd_link_part (void)
1625 struct partition *p;
1627 k = get_partition (1, partitions);
1629 if (!xbsd_check_new_partition (&i))
1632 p = get_part_table(k);
1634 xbsd_dlabel.d_partitions[i].p_size = get_nr_sects(p);
1635 xbsd_dlabel.d_partitions[i].p_offset = get_start_sect(p);
1636 xbsd_dlabel.d_partitions[i].p_fstype = xbsd_translate_fstype(p->sys_ind);
1640 #if defined (__alpha__)
1642 #if !defined(__GLIBC__)
1643 typedef unsigned long long uint64_t;
1647 alpha_bootblock_checksum (char *boot)
1652 dp = (uint64_t *)boot;
1654 for (i = 0; i < 63; i++)
1658 #endif /* __alpha__ */
1660 #endif /* OSF_LABEL */
1662 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
1663 static inline unsigned short
1664 __swap16(unsigned short x) {
1665 return (((uint16_t)(x) & 0xFF) << 8) | (((uint16_t)(x) & 0xFF00) >> 8);
1668 static inline uint32_t
1669 __swap32(uint32_t x) {
1670 return (((x & 0xFF) << 24) |
1671 ((x & 0xFF00) << 8) |
1672 ((x & 0xFF0000) >> 8) |
1673 ((x & 0xFF000000) >> 24));
1677 #ifdef CONFIG_FEATURE_SGI_LABEL
1682 * Copyright (C) Andreas Neuper, Sep 1998.
1683 * This file may be modified and redistributed under
1684 * the terms of the GNU Public License.
1686 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
1687 * Internationalization
1691 static int sgi_other_endian;
1693 static short sgi_volumes=1;
1696 * only dealing with free blocks here
1699 typedef struct { unsigned int first; unsigned int last; } freeblocks;
1700 static freeblocks freelist[17]; /* 16 partitions can produce 17 vacant slots */
1703 setfreelist(int i, unsigned int f, unsigned int l) {
1704 freelist[i].first = f;
1705 freelist[i].last = l;
1709 add2freelist(unsigned int f, unsigned int l) {
1711 for ( ; i < 17 ; i++)
1712 if (freelist[i].last == 0)
1714 setfreelist(i, f, l);
1718 clearfreelist(void) {
1721 for (i = 0; i < 17 ; i++)
1722 setfreelist(i, 0, 0);
1726 isinfreelist(unsigned int b) {
1729 for (i = 0; i < 17 ; i++)
1730 if (freelist[i].first <= b && freelist[i].last >= b)
1731 return freelist[i].last;
1734 /* return last vacant block of this stride (never 0). */
1735 /* the '>=' is not quite correct, but simplifies the code */
1737 * end of free blocks section
1740 static const struct systypes sgi_sys_types[] = {
1741 /* SGI_VOLHDR */ {"\x00" "SGI volhdr" },
1742 /* 0x01 */ {"\x01" "SGI trkrepl" },
1743 /* 0x02 */ {"\x02" "SGI secrepl" },
1744 /* SGI_SWAP */ {"\x03" "SGI raw" },
1745 /* 0x04 */ {"\x04" "SGI bsd" },
1746 /* 0x05 */ {"\x05" "SGI sysv" },
1747 /* ENTIRE_DISK */ {"\x06" "SGI volume" },
1748 /* SGI_EFS */ {"\x07" "SGI efs" },
1749 /* 0x08 */ {"\x08" "SGI lvol" },
1750 /* 0x09 */ {"\x09" "SGI rlvol" },
1751 /* SGI_XFS */ {"\x0a" "SGI xfs" },
1752 /* SGI_XFSLOG */ {"\x0b" "SGI xfslog" },
1753 /* SGI_XLV */ {"\x0c" "SGI xlv" },
1754 /* SGI_XVM */ {"\x0d" "SGI xvm" },
1755 /* LINUX_SWAP */ {"\x82" "Linux swap" },
1756 /* LINUX_NATIVE */ {"\x83" "Linux native" },
1757 /* LINUX_LVM */ {"\x8d" "Linux LVM" },
1758 /* LINUX_RAID */ {"\xfd" "Linux RAID" },
1764 sgi_get_nsect(void) {
1765 return SGI_SSWAP16(sgilabel->devparam.nsect);
1769 sgi_get_ntrks(void) {
1770 return SGI_SSWAP16(sgilabel->devparam.ntrks);
1775 sgilabel->magic = 0;
1781 two_s_complement_32bit_sum(unsigned int* base, int size /* in bytes */) {
1785 size /= sizeof(unsigned int);
1786 for (i = 0; i < size; i++)
1787 sum -= SGI_SSWAP32(base[i]);
1792 check_sgi_label(void) {
1793 if (sizeof(sgilabel) > 512) {
1795 _("According to MIPS Computer Systems, Inc the "
1796 "Label must not contain more than 512 bytes\n"));
1800 if (sgilabel->magic != SGI_LABEL_MAGIC &&
1801 sgilabel->magic != SGI_LABEL_MAGIC_SWAPPED) {
1803 sgi_other_endian = 0;
1807 sgi_other_endian = (sgilabel->magic == SGI_LABEL_MAGIC_SWAPPED);
1809 * test for correct checksum
1811 if (two_s_complement_32bit_sum((unsigned int*)sgilabel,
1812 sizeof(*sgilabel))) {
1814 _("Detected sgi disklabel with wrong checksum.\n"));
1824 sgi_get_start_sector(int i) {
1825 return SGI_SSWAP32(sgilabel->partitions[i].start_sector);
1829 sgi_get_num_sectors(int i) {
1830 return SGI_SSWAP32(sgilabel->partitions[i].num_sectors);
1834 sgi_get_sysid(int i)
1836 return SGI_SSWAP32(sgilabel->partitions[i].id);
1840 sgi_get_bootpartition(void)
1842 return SGI_SSWAP16(sgilabel->boot_part);
1846 sgi_get_swappartition(void)
1848 return SGI_SSWAP16(sgilabel->swap_part);
1852 sgi_list_table(int xtra) {
1854 int kpi = 0; /* kernel partition ID */
1857 printf(_("\nDisk %s (SGI disk label): %d heads, %d sectors\n"
1858 "%d cylinders, %d physical cylinders\n"
1859 "%d extra sects/cyl, interleave %d:1\n"
1861 "Units = %s of %d * 512 bytes\n\n"),
1862 disk_device, heads, sectors, cylinders,
1863 SGI_SSWAP16(sgiparam.pcylcount),
1864 SGI_SSWAP16(sgiparam.sparecyl),
1865 SGI_SSWAP16(sgiparam.ilfact),
1867 str_units(PLURAL), units_per_sector);
1869 printf( _("\nDisk %s (SGI disk label): "
1870 "%d heads, %d sectors, %d cylinders\n"
1871 "Units = %s of %d * 512 bytes\n\n"),
1872 disk_device, heads, sectors, cylinders,
1873 str_units(PLURAL), units_per_sector );
1876 w = strlen(disk_device);
1877 wd = strlen(_("Device"));
1881 printf(_("----- partitions -----\n"
1882 "Pt# %*s Info Start End Sectors Id System\n"),
1883 w + 2, _("Device"));
1884 for (i = 0 ; i < partitions; i++) {
1885 if( sgi_get_num_sectors(i) || debug ) {
1886 uint32_t start = sgi_get_start_sector(i);
1887 uint32_t len = sgi_get_num_sectors(i);
1888 kpi++; /* only count nonempty partitions */
1890 "%2d: %s %4s %9ld %9ld %9ld %2x %s\n",
1891 /* fdisk part number */ i+1,
1892 /* device */ partname(disk_device, kpi, w+3),
1893 /* flags */ (sgi_get_swappartition() == i) ? "swap" :
1894 /* flags */ (sgi_get_bootpartition() == i) ? "boot" : " ",
1895 /* start */ (long) scround(start),
1896 /* end */ (long) scround(start+len)-1,
1897 /* no odd flag on end */ (long) len,
1898 /* type id */ sgi_get_sysid(i),
1899 /* type name */ partition_type(sgi_get_sysid(i)));
1902 printf(_("----- Bootinfo -----\nBootfile: %s\n"
1903 "----- Directory Entries -----\n"),
1904 sgilabel->boot_file);
1905 for (i = 0 ; i < sgi_volumes; i++) {
1906 if (sgilabel->directory[i].vol_file_size) {
1907 uint32_t start = SGI_SSWAP32(sgilabel->directory[i].vol_file_start);
1908 uint32_t len = SGI_SSWAP32(sgilabel->directory[i].vol_file_size);
1909 char*name = sgilabel->directory[i].vol_file_name;
1911 printf(_("%2d: %-10s sector%5u size%8u\n"),
1912 i, name, (unsigned int) start, (unsigned int) len);
1918 sgi_set_bootpartition( int i )
1920 sgilabel->boot_part = SGI_SSWAP16(((short)i));
1924 sgi_get_lastblock(void) {
1925 return heads * sectors * cylinders;
1929 sgi_set_swappartition( int i ) {
1930 sgilabel->swap_part = SGI_SSWAP16(((short)i));
1934 sgi_check_bootfile(const char* aFile) {
1936 if (strlen(aFile) < 3) /* "/a\n" is minimum */ {
1937 printf(_("\nInvalid Bootfile!\n"
1938 "\tThe bootfile must be an absolute non-zero pathname,\n"
1939 "\te.g. \"/unix\" or \"/unix.save\".\n"));
1942 if (strlen(aFile) > 16) {
1943 printf(_("\n\tName of Bootfile too long: "
1944 "16 bytes maximum.\n"));
1947 if (aFile[0] != '/') {
1948 printf(_("\n\tBootfile must have a "
1949 "fully qualified pathname.\n"));
1954 if (strncmp(aFile, sgilabel->boot_file, 16)) {
1955 printf(_("\n\tBe aware, that the bootfile is not checked for existence.\n\t"
1956 "SGI's default is \"/unix\" and for backup \"/unix.save\".\n"));
1957 /* filename is correct and did change */
1960 return 0; /* filename did not change */
1964 sgi_get_bootfile(void) {
1965 return sgilabel->boot_file;
1969 sgi_set_bootfile(const char* aFile) {
1972 if (sgi_check_bootfile(aFile)) {
1974 if ((aFile[i] != '\n') /* in principle caught again by next line */
1975 && (strlen(aFile) > i))
1976 sgilabel->boot_file[i] = aFile[i];
1978 sgilabel->boot_file[i] = 0;
1981 printf(_("\n\tBootfile is changed to \"%s\".\n"), sgilabel->boot_file);
1986 create_sgiinfo(void)
1988 /* I keep SGI's habit to write the sgilabel to the second block */
1989 sgilabel->directory[0].vol_file_start = SGI_SSWAP32(2);
1990 sgilabel->directory[0].vol_file_size = SGI_SSWAP32(sizeof(sgiinfo));
1991 strncpy(sgilabel->directory[0].vol_file_name, "sgilabel", 8);
1994 static sgiinfo *fill_sgiinfo(void);
1997 sgi_write_table(void) {
1999 sgilabel->csum = SGI_SSWAP32(two_s_complement_32bit_sum(
2000 (unsigned int*)sgilabel,
2001 sizeof(*sgilabel)));
2002 assert(two_s_complement_32bit_sum(
2003 (unsigned int*)sgilabel, sizeof(*sgilabel)) == 0);
2004 if (lseek(fd, 0, SEEK_SET) < 0)
2005 fdisk_fatal(unable_to_seek);
2006 if (write(fd, sgilabel, SECTOR_SIZE) != SECTOR_SIZE)
2007 fdisk_fatal(unable_to_write);
2008 if (! strncmp(sgilabel->directory[0].vol_file_name, "sgilabel", 8)) {
2010 * keep this habit of first writing the "sgilabel".
2011 * I never tested whether it works without (AN 981002).
2013 sgiinfo *info = fill_sgiinfo();
2014 int infostartblock = SGI_SSWAP32(sgilabel->directory[0].vol_file_start);
2015 if (lseek(fd, infostartblock*SECTOR_SIZE, SEEK_SET) < 0)
2016 fdisk_fatal(unable_to_seek);
2017 if (write(fd, info, SECTOR_SIZE) != SECTOR_SIZE)
2018 fdisk_fatal(unable_to_write);
2024 compare_start(int *x, int *y) {
2026 * sort according to start sectors
2027 * and prefers largest partition:
2028 * entry zero is entire disk entry
2030 unsigned int i = *x;
2031 unsigned int j = *y;
2032 unsigned int a = sgi_get_start_sector(i);
2033 unsigned int b = sgi_get_start_sector(j);
2034 unsigned int c = sgi_get_num_sectors(i);
2035 unsigned int d = sgi_get_num_sectors(j);
2038 return (d > c) ? 1 : (d == c) ? 0 : -1;
2039 return (a > b) ? 1 : -1;
2044 verify_sgi(int verbose)
2046 int Index[16]; /* list of valid partitions */
2047 int sortcount = 0; /* number of used partitions, i.e. non-zero lengths */
2048 int entire = 0, i = 0;
2049 unsigned int start = 0;
2050 long long gap = 0; /* count unused blocks */
2051 unsigned int lastblock = sgi_get_lastblock();
2054 for (i=0; i<16; i++) {
2055 if (sgi_get_num_sectors(i) != 0) {
2056 Index[sortcount++]=i;
2057 if (sgi_get_sysid(i) == ENTIRE_DISK) {
2058 if (entire++ == 1) {
2060 printf(_("More than one entire disk entry present.\n"));
2065 if (sortcount == 0) {
2067 printf(_("No partitions defined\n"));
2068 return (lastblock > 0) ? 1 : (lastblock == 0) ? 0 : -1;
2070 qsort(Index, sortcount, sizeof(Index[0]), (void*)compare_start);
2071 if (sgi_get_sysid(Index[0]) == ENTIRE_DISK) {
2072 if ((Index[0] != 10) && verbose)
2073 printf(_("IRIX likes when Partition 11 covers the entire disk.\n"));
2074 if ((sgi_get_start_sector(Index[0]) != 0) && verbose)
2075 printf(_("The entire disk partition should start "
2077 "not at diskblock %d.\n"),
2078 sgi_get_start_sector(Index[0]));
2079 if (debug) /* I do not understand how some disks fulfil it */
2080 if ((sgi_get_num_sectors(Index[0]) != lastblock) && verbose)
2081 printf(_("The entire disk partition is only %d diskblock large,\n"
2082 "but the disk is %d diskblocks long.\n"),
2083 sgi_get_num_sectors(Index[0]), lastblock);
2084 lastblock = sgi_get_num_sectors(Index[0]);
2087 printf(_("One Partition (#11) should cover the entire disk.\n"));
2089 printf("sysid=%d\tpartition=%d\n",
2090 sgi_get_sysid(Index[0]), Index[0]+1);
2092 for (i=1, start=0; i<sortcount; i++) {
2093 int cylsize = sgi_get_nsect() * sgi_get_ntrks();
2095 if ((sgi_get_start_sector(Index[i]) % cylsize) != 0) {
2096 if (debug) /* I do not understand how some disks fulfil it */
2098 printf(_("Partition %d does not start on cylinder boundary.\n"),
2101 if (sgi_get_num_sectors(Index[i]) % cylsize != 0) {
2102 if (debug) /* I do not understand how some disks fulfil it */
2104 printf(_("Partition %d does not end on cylinder boundary.\n"),
2107 /* We cannot handle several "entire disk" entries. */
2108 if (sgi_get_sysid(Index[i]) == ENTIRE_DISK) continue;
2109 if (start > sgi_get_start_sector(Index[i])) {
2111 printf(_("The Partition %d and %d overlap by %d sectors.\n"),
2112 Index[i-1]+1, Index[i]+1,
2113 start - sgi_get_start_sector(Index[i]));
2114 if (gap > 0) gap = -gap;
2115 if (gap == 0) gap = -1;
2117 if (start < sgi_get_start_sector(Index[i])) {
2119 printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"),
2120 sgi_get_start_sector(Index[i]) - start,
2121 start, sgi_get_start_sector(Index[i])-1);
2122 gap += sgi_get_start_sector(Index[i]) - start;
2123 add2freelist(start, sgi_get_start_sector(Index[i]));
2125 start = sgi_get_start_sector(Index[i])
2126 + sgi_get_num_sectors(Index[i]);
2129 printf("%2d:%12d\t%12d\t%12d\n", Index[i],
2130 sgi_get_start_sector(Index[i]),
2131 sgi_get_num_sectors(Index[i]),
2132 sgi_get_sysid(Index[i]));
2135 if (start < lastblock) {
2137 printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"),
2138 lastblock - start, start, lastblock-1);
2139 gap += lastblock - start;
2140 add2freelist(start, lastblock);
2143 * Done with arithmetics
2144 * Go for details now
2147 if (!sgi_get_num_sectors(sgi_get_bootpartition())) {
2148 printf(_("\nThe boot partition does not exist.\n"));
2150 if (!sgi_get_num_sectors(sgi_get_swappartition())) {
2151 printf(_("\nThe swap partition does not exist.\n"));
2153 if ((sgi_get_sysid(sgi_get_swappartition()) != SGI_SWAP)
2154 && (sgi_get_sysid(sgi_get_swappartition()) != LINUX_SWAP))
2155 printf(_("\nThe swap partition has no swap type.\n"));
2157 if (sgi_check_bootfile("/unix"))
2158 printf(_("\tYou have chosen an unusual boot file name.\n"));
2160 return (gap > 0) ? 1 : (gap == 0) ? 0 : -1;
2166 * returned value is:
2167 * = 0 : disk is properly filled to the rim
2168 * < 0 : there is an overlap
2169 * > 0 : there is still some vacant space
2171 return verify_sgi(0);
2175 sgi_change_sysid( int i, int sys )
2177 if( sgi_get_num_sectors(i) == 0 ) /* caught already before, ... */
2179 printf(_("Sorry You may change the Tag of non-empty partitions.\n"));
2182 if( ((sys != ENTIRE_DISK ) && (sys != SGI_VOLHDR))
2183 && (sgi_get_start_sector(i)<1) )
2186 _("It is highly recommended that the partition at offset 0\n"
2187 "is of type \"SGI volhdr\", the IRIX system will rely on it to\n"
2188 "retrieve from its directory standalone tools like sash and fx.\n"
2189 "Only the \"SGI volume\" entire disk section may violate this.\n"
2190 "Type YES if you are sure about tagging this partition differently.\n"));
2191 if (strcmp (line_ptr, _("YES\n")))
2194 sgilabel->partitions[i].id = SGI_SSWAP32(sys);
2197 /* returns partition index of first entry marked as entire disk */
2203 if(sgi_get_sysid(i) == SGI_VOLUME)
2209 sgi_set_partition(int i, unsigned int start, unsigned int length, int sys) {
2211 sgilabel->partitions[i].id = SGI_SSWAP32(sys);
2212 sgilabel->partitions[i].num_sectors = SGI_SSWAP32(length);
2213 sgilabel->partitions[i].start_sector = SGI_SSWAP32(start);
2215 if (sgi_gaps() < 0) /* rebuild freelist */
2216 printf(_("Do You know, You got a partition overlap on the disk?\n"));
2220 sgi_set_entire(void) {
2223 for(n=10; n < partitions; n++) {
2224 if(!sgi_get_num_sectors(n) ) {
2225 sgi_set_partition(n, 0, sgi_get_lastblock(), SGI_VOLUME);
2232 sgi_set_volhdr(void)
2235 for( n=8; n<partitions; n++ )
2237 if(!sgi_get_num_sectors( n ) )
2240 * 5 cylinders is an arbitrary value I like
2241 * IRIX 5.3 stored files in the volume header
2242 * (like sash, symmon, fx, ide) with ca. 3200
2245 if( heads * sectors * 5 < sgi_get_lastblock() )
2246 sgi_set_partition( n, 0, heads * sectors * 5, SGI_VOLHDR );
2253 sgi_delete_partition( int i )
2255 sgi_set_partition( i, 0, 0, 0 );
2259 sgi_add_partition( int n, int sys )
2262 unsigned int first=0, last=0;
2266 } else if ( n == 8 ) {
2269 if(sgi_get_num_sectors(n)) {
2270 printf(_("Partition %d is already defined. Delete "
2271 "it before re-adding it.\n"), n + 1);
2274 if( (sgi_entire() == -1) && (sys != SGI_VOLUME) ) {
2275 printf(_("Attempting to generate entire disk entry automatically.\n"));
2279 if( (sgi_gaps() == 0) && (sys != SGI_VOLUME) ) {
2280 printf(_("The entire disk is already covered with partitions.\n"));
2283 if(sgi_gaps() < 0) {
2284 printf(_("You got a partition overlap on the disk. Fix it first!\n"));
2287 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
2289 if(sys == SGI_VOLUME) {
2290 last = sgi_get_lastblock();
2291 first = read_int(0, 0, last-1, 0, mesg);
2293 printf(_("It is highly recommended that eleventh partition\n"
2294 "covers the entire disk and is of type `SGI volume'\n"));
2297 first = freelist[0].first;
2298 last = freelist[0].last;
2299 first = read_int(scround(first), scround(first), scround(last)-1,
2302 if (display_in_cyl_units)
2303 first *= units_per_sector;
2305 first = first; /* align to cylinder if you know how ... */
2307 last = isinfreelist(first);
2309 printf(_("You will get a partition overlap on the disk. "
2310 "Fix it first!\n"));
2314 snprintf(mesg, sizeof(mesg), _(" Last %s"), str_units(SINGULAR));
2315 last = read_int(scround(first), scround(last)-1, scround(last)-1,
2316 scround(first), mesg)+1;
2317 if (display_in_cyl_units)
2318 last *= units_per_sector;
2320 last = last; /* align to cylinder if You know how ... */
2321 if( (sys == SGI_VOLUME) && ( first != 0 || last != sgi_get_lastblock() ) )
2322 printf(_("It is highly recommended that eleventh partition\n"
2323 "covers the entire disk and is of type `SGI volume'\n"));
2324 sgi_set_partition( n, first, last-first, sys );
2327 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
2329 create_sgilabel(void)
2331 struct hd_geometry geometry;
2338 long longsectors; /* the number of sectors on the device */
2339 int res; /* the result from the ioctl */
2340 int sec_fac; /* the sector factor */
2342 sec_fac = sector_size / 512; /* determine the sector factor */
2345 _("Building a new SGI disklabel. Changes will remain in memory only,\n"
2346 "until you decide to write them. After that, of course, the previous\n"
2347 "content will be unrecoverably lost.\n\n"));
2349 sgi_other_endian = (BYTE_ORDER == LITTLE_ENDIAN);
2350 res = ioctl(fd, BLKGETSIZE, &longsectors);
2351 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
2352 heads = geometry.heads;
2353 sectors = geometry.sectors;
2355 /* the get device size ioctl was successful */
2356 cylinders = longsectors / (heads * sectors);
2357 cylinders /= sec_fac;
2359 /* otherwise print error and use truncated version */
2360 cylinders = geometry.cylinders;
2362 _("Warning: BLKGETSIZE ioctl failed on %s. "
2363 "Using geometry cylinder value of %d.\n"
2364 "This value may be truncated for devices"
2365 " > 33.8 GB.\n"), disk_device, cylinders);
2368 for (i = 0; i < 4; i++) {
2370 if(valid_part_table_flag(MBRbuffer)) {
2371 if(get_part_table(i)->sys_ind) {
2372 old[i].sysid = get_part_table(i)->sys_ind;
2373 old[i].start = get_start_sect(get_part_table(i));
2374 old[i].nsect = get_nr_sects(get_part_table(i));
2375 printf(_("Trying to keep parameters of partition %d.\n"), i);
2377 printf(_("ID=%02x\tSTART=%d\tLENGTH=%d\n"),
2378 old[i].sysid, old[i].start, old[i].nsect);
2383 memset(MBRbuffer, 0, sizeof(MBRbuffer));
2384 sgilabel->magic = SGI_SSWAP32(SGI_LABEL_MAGIC);
2385 sgilabel->boot_part = SGI_SSWAP16(0);
2386 sgilabel->swap_part = SGI_SSWAP16(1);
2388 /* sizeof(sgilabel->boot_file) = 16 > 6 */
2389 memset(sgilabel->boot_file, 0, 16);
2390 strcpy(sgilabel->boot_file, "/unix");
2392 sgilabel->devparam.skew = (0);
2393 sgilabel->devparam.gap1 = (0);
2394 sgilabel->devparam.gap2 = (0);
2395 sgilabel->devparam.sparecyl = (0);
2396 sgilabel->devparam.pcylcount = SGI_SSWAP16(geometry.cylinders);
2397 sgilabel->devparam.head_vol0 = SGI_SSWAP16(0);
2398 sgilabel->devparam.ntrks = SGI_SSWAP16(geometry.heads);
2399 /* tracks/cylinder (heads) */
2400 sgilabel->devparam.cmd_tag_queue_depth = (0);
2401 sgilabel->devparam.unused0 = (0);
2402 sgilabel->devparam.unused1 = SGI_SSWAP16(0);
2403 sgilabel->devparam.nsect = SGI_SSWAP16(geometry.sectors);
2405 sgilabel->devparam.bytes = SGI_SSWAP16(512);
2406 sgilabel->devparam.ilfact = SGI_SSWAP16(1);
2407 sgilabel->devparam.flags = SGI_SSWAP32(TRACK_FWD|
2408 IGNORE_ERRORS|RESEEK);
2409 sgilabel->devparam.datarate = SGI_SSWAP32(0);
2410 sgilabel->devparam.retries_on_error = SGI_SSWAP32(1);
2411 sgilabel->devparam.ms_per_word = SGI_SSWAP32(0);
2412 sgilabel->devparam.xylogics_gap1 = SGI_SSWAP16(0);
2413 sgilabel->devparam.xylogics_syncdelay = SGI_SSWAP16(0);
2414 sgilabel->devparam.xylogics_readdelay = SGI_SSWAP16(0);
2415 sgilabel->devparam.xylogics_gap2 = SGI_SSWAP16(0);
2416 sgilabel->devparam.xylogics_readgate = SGI_SSWAP16(0);
2417 sgilabel->devparam.xylogics_writecont = SGI_SSWAP16(0);
2418 memset( &(sgilabel->directory), 0, sizeof(struct volume_directory)*15 );
2419 memset( &(sgilabel->partitions), 0, sizeof(struct sgi_partition)*16 );
2425 for (i = 0; i < 4; i++) {
2427 sgi_set_partition(i, old[i].start, old[i].nsect, old[i].sysid);
2435 /* do nothing in the beginning */
2437 #endif /* CONFIG_FEATURE_FDISK_ADVANCED */
2439 /* _____________________________________________________________
2445 sgiinfo *info = calloc(1, sizeof(sgiinfo));
2447 info->magic=SGI_SSWAP32(SGI_INFO_MAGIC);
2448 info->b1=SGI_SSWAP32(-1);
2449 info->b2=SGI_SSWAP16(-1);
2450 info->b3=SGI_SSWAP16(1);
2451 /* You may want to replace this string !!!!!!! */
2452 strcpy( info->scsi_string, "IBM OEM 0662S12 3 30" );
2453 strcpy( info->serial, "0000" );
2454 info->check1816 = SGI_SSWAP16(18*256 +16 );
2455 strcpy( info->installer, "Sfx version 5.3, Oct 18, 1994" );
2458 #endif /* SGI_LABEL */
2461 #ifdef CONFIG_FEATURE_SUN_LABEL
2465 * I think this is mostly, or entirely, due to
2466 * Jakub Jelinek (jj@sunsite.mff.cuni.cz), July 1996
2468 * Merged with fdisk for other architectures, aeb, June 1998.
2470 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
2471 * Internationalization
2475 static int sun_other_endian;
2476 static int scsi_disk;
2480 #define IDE0_MAJOR 3
2483 #define IDE1_MAJOR 22
2486 static void guess_device_type(void) {
2487 struct stat bootstat;
2489 if (fstat (fd, &bootstat) < 0) {
2492 } else if (S_ISBLK(bootstat.st_mode)
2493 && (major(bootstat.st_rdev) == IDE0_MAJOR ||
2494 major(bootstat.st_rdev) == IDE1_MAJOR)) {
2497 } else if (S_ISBLK(bootstat.st_mode)
2498 && major(bootstat.st_rdev) == FLOPPY_MAJOR) {
2507 static const struct systypes sun_sys_types[] = {
2508 /* 0 */ {"\x00" "Empty" },
2509 /* 1 */ {"\x01" "Boot" },
2510 /* 2 */ {"\x02" "SunOS root" },
2511 /* SUNOS_SWAP */ {"\x03" "SunOS swap" },
2512 /* 4 */ {"\x04" "SunOS usr" },
2513 /* WHOLE_DISK */ {"\x05" "Whole disk" },
2514 /* 6 */ {"\x06" "SunOS stand" },
2515 /* 7 */ {"\x07" "SunOS var" },
2516 /* 8 */ {"\x08" "SunOS home" },
2517 /* LINUX_SWAP */ {"\x82" "Linux swap" },
2518 /* LINUX_NATIVE */ {"\x83" "Linux native" },
2519 /* 0x8e */ {"\x8e" "Linux LVM" },
2520 /* New (2.2.x) raid partition with autodetect using persistent superblock */
2521 /* 0xfd */ {"\xfd" "Linux raid autodetect" },
2527 set_sun_partition(int i, uint start, uint stop, int sysid) {
2528 sunlabel->infos[i].id = sysid;
2529 sunlabel->partitions[i].start_cylinder =
2530 SUN_SSWAP32(start / (heads * sectors));
2531 sunlabel->partitions[i].num_sectors =
2532 SUN_SSWAP32(stop - start);
2539 sunlabel->magic = 0;
2544 check_sun_label(void) {
2545 unsigned short *ush;
2548 if (sunlabel->magic != SUN_LABEL_MAGIC &&
2549 sunlabel->magic != SUN_LABEL_MAGIC_SWAPPED) {
2551 sun_other_endian = 0;
2554 sun_other_endian = (sunlabel->magic == SUN_LABEL_MAGIC_SWAPPED);
2555 ush = ((unsigned short *) (sunlabel + 1)) - 1;
2556 for (csum = 0; ush >= (unsigned short *)sunlabel;) csum ^= *ush--;
2558 fprintf(stderr,_("Detected sun disklabel with wrong checksum.\n"
2559 "Probably you'll have to set all the values,\n"
2560 "e.g. heads, sectors, cylinders and partitions\n"
2561 "or force a fresh label (s command in main menu)\n"));
2563 heads = SUN_SSWAP16(sunlabel->ntrks);
2564 cylinders = SUN_SSWAP16(sunlabel->ncyl);
2565 sectors = SUN_SSWAP16(sunlabel->nsect);
2573 static const struct sun_predefined_drives {
2576 unsigned short sparecyl;
2577 unsigned short ncyl;
2578 unsigned short nacyl;
2579 unsigned short pcylcount;
2580 unsigned short ntrks;
2581 unsigned short nsect;
2582 unsigned short rspeed;
2584 {"Quantum","ProDrive 80S",1,832,2,834,6,34,3662},
2585 {"Quantum","ProDrive 105S",1,974,2,1019,6,35,3662},
2586 {"CDC","Wren IV 94171-344",3,1545,2,1549,9,46,3600},
2587 {"IBM","DPES-31080",0,4901,2,4903,4,108,5400},
2588 {"IBM","DORS-32160",0,1015,2,1017,67,62,5400},
2589 {"IBM","DNES-318350",0,11199,2,11474,10,320,7200},
2590 {"SEAGATE","ST34371",0,3880,2,3882,16,135,7228},
2591 {"","SUN0104",1,974,2,1019,6,35,3662},
2592 {"","SUN0207",4,1254,2,1272,9,36,3600},
2593 {"","SUN0327",3,1545,2,1549,9,46,3600},
2594 {"","SUN0340",0,1538,2,1544,6,72,4200},
2595 {"","SUN0424",2,1151,2,2500,9,80,4400},
2596 {"","SUN0535",0,1866,2,2500,7,80,5400},
2597 {"","SUN0669",5,1614,2,1632,15,54,3600},
2598 {"","SUN1.0G",5,1703,2,1931,15,80,3597},
2599 {"","SUN1.05",0,2036,2,2038,14,72,5400},
2600 {"","SUN1.3G",6,1965,2,3500,17,80,5400},
2601 {"","SUN2.1G",0,2733,2,3500,19,80,5400},
2602 {"IOMEGA","Jaz",0,1019,2,1021,64,32,5394},
2605 static const struct sun_predefined_drives *
2606 sun_autoconfigure_scsi(void) {
2607 const struct sun_predefined_drives *p = NULL;
2609 #ifdef SCSI_IOCTL_GET_IDLUN
2619 if (!ioctl(fd, SCSI_IOCTL_GET_IDLUN, &id)) {
2621 "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n",
2623 ((id[0]>>24)&0xff)-/*PROC_SCSI_SCSI+PROC_SCSI_FILE*/33,
2625 /* This is very wrong (works only if you have one HBA),
2626 but I haven't found a way how to get hostno
2627 from the current kernel */
2633 pfd = fopen("/proc/scsi/scsi","r");
2635 while (fgets(buffer2,2048,pfd)) {
2636 if (!strcmp(buffer, buffer2)) {
2637 if (fgets(buffer2,2048,pfd)) {
2638 q = strstr(buffer2,"Vendor: ");
2643 *q++ = 0; /* truncate vendor name */
2644 q = strstr(q,"Model: ");
2649 q = strstr(q," Rev: ");
2652 for (i = 0; i < SIZE(sun_drives); i++) {
2653 if (*sun_drives[i].vendor && strcasecmp(sun_drives[i].vendor, vendor))
2655 if (!strstr(model, sun_drives[i].model))
2657 printf(_("Autoconfigure found a %s%s%s\n"),sun_drives[i].vendor,(*sun_drives[i].vendor) ? " " : "",sun_drives[i].model);
2675 static void create_sunlabel(void)
2677 struct hd_geometry geometry;
2681 const struct sun_predefined_drives *p = NULL;
2684 _("Building a new sun disklabel. Changes will remain in memory only,\n"
2685 "until you decide to write them. After that, of course, the previous\n"
2686 "content won't be recoverable.\n\n"));
2687 #if BYTE_ORDER == LITTLE_ENDIAN
2688 sun_other_endian = 1;
2690 sun_other_endian = 0;
2692 memset(MBRbuffer, 0, sizeof(MBRbuffer));
2693 sunlabel->magic = SUN_SSWAP16(SUN_LABEL_MAGIC);
2695 puts(_("Drive type\n"
2696 " ? auto configure\n"
2697 " 0 custom (with hardware detected defaults)"));
2698 for (i = 0; i < SIZE(sun_drives); i++) {
2699 printf(" %c %s%s%s\n",
2700 i + 'a', sun_drives[i].vendor,
2701 (*sun_drives[i].vendor) ? " " : "",
2702 sun_drives[i].model);
2705 c = read_char(_("Select type (? for auto, 0 for custom): "));
2706 if (c >= 'a' && c < 'a' + SIZE(sun_drives)) {
2707 p = sun_drives + c - 'a';
2709 } else if (c >= 'A' && c < 'A' + SIZE(sun_drives)) {
2710 p = sun_drives + c - 'A';
2712 } else if (c == '0') {
2714 } else if (c == '?' && scsi_disk) {
2715 p = sun_autoconfigure_scsi();
2717 printf(_("Autoconfigure failed.\n"));
2724 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
2725 heads = geometry.heads;
2726 sectors = geometry.sectors;
2727 cylinders = geometry.cylinders;
2734 sunlabel->nacyl = 0;
2735 sunlabel->pcylcount = SUN_SSWAP16(cylinders);
2736 sunlabel->rspeed = SUN_SSWAP16(300);
2737 sunlabel->ilfact = SUN_SSWAP16(1);
2738 sunlabel->sparecyl = 0;
2740 heads = read_int(1,heads,1024,0,_("Heads"));
2741 sectors = read_int(1,sectors,1024,0,_("Sectors/track"));
2743 cylinders = read_int(1,cylinders-2,65535,0,_("Cylinders"));
2745 cylinders = read_int(1,0,65535,0,_("Cylinders"));
2747 SUN_SSWAP16(read_int(0,2,65535,0,
2748 _("Alternate cylinders")));
2749 sunlabel->pcylcount =
2750 SUN_SSWAP16(read_int(0,cylinders+SUN_SSWAP16(sunlabel->nacyl),
2751 65535,0,_("Physical cylinders")));
2753 SUN_SSWAP16(read_int(1,5400,100000,0,
2754 _("Rotation speed (rpm)")));
2756 SUN_SSWAP16(read_int(1,1,32,0,_("Interleave factor")));
2757 sunlabel->sparecyl =
2758 SUN_SSWAP16(read_int(0,0,sectors,0,
2759 _("Extra sectors per cylinder")));
2762 sunlabel->sparecyl = SUN_SSWAP16(p->sparecyl);
2763 sunlabel->ncyl = SUN_SSWAP16(p->ncyl);
2764 sunlabel->nacyl = SUN_SSWAP16(p->nacyl);
2765 sunlabel->pcylcount = SUN_SSWAP16(p->pcylcount);
2766 sunlabel->ntrks = SUN_SSWAP16(p->ntrks);
2767 sunlabel->nsect = SUN_SSWAP16(p->nsect);
2768 sunlabel->rspeed = SUN_SSWAP16(p->rspeed);
2769 sunlabel->ilfact = SUN_SSWAP16(1);
2770 cylinders = p->ncyl;
2773 puts(_("You may change all the disk params from the x menu"));
2776 snprintf(sunlabel->info, sizeof(sunlabel->info),
2777 "%s%s%s cyl %d alt %d hd %d sec %d",
2778 p ? p->vendor : "", (p && *p->vendor) ? " " : "",
2780 : (floppy ? _("3,5\" floppy") : _("Linux custom")),
2781 cylinders, SUN_SSWAP16(sunlabel->nacyl), heads, sectors);
2783 sunlabel->ntrks = SUN_SSWAP16(heads);
2784 sunlabel->nsect = SUN_SSWAP16(sectors);
2785 sunlabel->ncyl = SUN_SSWAP16(cylinders);
2787 set_sun_partition(0, 0, cylinders * heads * sectors, LINUX_NATIVE);
2789 if (cylinders * heads * sectors >= 150 * 2048) {
2790 ndiv = cylinders - (50 * 2048 / (heads * sectors)); /* 50M swap */
2792 ndiv = cylinders * 2 / 3;
2793 set_sun_partition(0, 0, ndiv * heads * sectors, LINUX_NATIVE);
2794 set_sun_partition(1, ndiv * heads * sectors, cylinders * heads * sectors, LINUX_SWAP);
2795 sunlabel->infos[1].flags |= 0x01; /* Not mountable */
2797 set_sun_partition(2, 0, cylinders * heads * sectors, WHOLE_DISK);
2799 unsigned short *ush = (unsigned short *)sunlabel;
2800 unsigned short csum = 0;
2801 while(ush < (unsigned short *)(&sunlabel->csum))
2803 sunlabel->csum = csum;
2806 set_all_unchanged();
2808 get_boot(create_empty_sun);
2812 toggle_sunflags(int i, unsigned char mask) {
2813 if (sunlabel->infos[i].flags & mask)
2814 sunlabel->infos[i].flags &= ~mask;
2815 else sunlabel->infos[i].flags |= mask;
2820 fetch_sun(uint *starts, uint *lens, uint *start, uint *stop) {
2821 int i, continuous = 1;
2822 *start = 0; *stop = cylinders * heads * sectors;
2823 for (i = 0; i < partitions; i++) {
2824 if (sunlabel->partitions[i].num_sectors
2825 && sunlabel->infos[i].id
2826 && sunlabel->infos[i].id != WHOLE_DISK) {
2827 starts[i] = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
2828 lens[i] = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
2830 if (starts[i] == *start)
2832 else if (starts[i] + lens[i] >= *stop)
2836 /* There will be probably more gaps
2837 than one, so lets check afterwards */
2846 static uint *verify_sun_starts;
2849 verify_sun_cmp(int *a, int *b) {
2850 if (*a == -1) return 1;
2851 if (*b == -1) return -1;
2852 if (verify_sun_starts[*a] > verify_sun_starts[*b]) return 1;
2858 uint starts[8], lens[8], start, stop;
2859 int i,j,k,starto,endo;
2862 verify_sun_starts = starts;
2863 fetch_sun(starts,lens,&start,&stop);
2864 for (k = 0; k < 7; k++) {
2865 for (i = 0; i < 8; i++) {
2866 if (k && (lens[i] % (heads * sectors))) {
2867 printf(_("Partition %d doesn't end on cylinder boundary\n"), i+1);
2870 for (j = 0; j < i; j++)
2872 if (starts[j] == starts[i]+lens[i]) {
2873 starts[j] = starts[i]; lens[j] += lens[i];
2875 } else if (starts[i] == starts[j]+lens[j]){
2879 if (starts[i] < starts[j]+lens[j] &&
2880 starts[j] < starts[i]+lens[i]) {
2882 if (starts[j] > starto)
2884 endo = starts[i]+lens[i];
2885 if (starts[j]+lens[j] < endo)
2886 endo = starts[j]+lens[j];
2887 printf(_("Partition %d overlaps with others in "
2888 "sectors %d-%d\n"), i+1, starto, endo);
2895 for (i = 0; i < 8; i++) {
2901 qsort(array,SIZE(array),sizeof(array[0]),
2902 (int (*)(const void *,const void *)) verify_sun_cmp);
2903 if (array[0] == -1) {
2904 printf(_("No partitions defined\n"));
2907 stop = cylinders * heads * sectors;
2908 if (starts[array[0]])
2909 printf(_("Unused gap - sectors 0-%d\n"),starts[array[0]]);
2910 for (i = 0; i < 7 && array[i+1] != -1; i++) {
2911 printf(_("Unused gap - sectors %d-%d\n"),starts[array[i]]+lens[array[i]],starts[array[i+1]]);
2913 start = starts[array[i]]+lens[array[i]];
2915 printf(_("Unused gap - sectors %d-%d\n"),start,stop);
2919 add_sun_partition(int n, int sys) {
2920 uint start, stop, stop2;
2921 uint starts[8], lens[8];
2927 if (sunlabel->partitions[n].num_sectors && sunlabel->infos[n].id) {
2928 printf(_("Partition %d is already defined. Delete "
2929 "it before re-adding it.\n"), n + 1);
2933 fetch_sun(starts,lens,&start,&stop);
2934 if (stop <= start) {
2938 printf(_("Other partitions already cover the whole disk.\nDelete "
2939 "some/shrink them before retry.\n"));
2943 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
2946 first = read_int(0, 0, 0, 0, mesg);
2948 first = read_int(scround(start), scround(stop)+1,
2949 scround(stop), 0, mesg);
2950 if (display_in_cyl_units)
2951 first *= units_per_sector;
2953 /* Starting sector has to be properly aligned */
2954 first = (first + heads * sectors - 1) / (heads * sectors);
2955 if (n == 2 && first != 0)
2957 It is highly recommended that the third partition covers the whole disk\n\
2958 and is of type `Whole disk'\n");
2959 /* ewt asks to add: "don't start a partition at cyl 0"
2960 However, edmundo@rano.demon.co.uk writes:
2961 "In addition to having a Sun partition table, to be able to
2962 boot from the disc, the first partition, /dev/sdX1, must
2963 start at cylinder 0. This means that /dev/sdX1 contains
2964 the partition table and the boot block, as these are the
2965 first two sectors of the disc. Therefore you must be
2966 careful what you use /dev/sdX1 for. In particular, you must
2967 not use a partition starting at cylinder 0 for Linux swap,
2968 as that would overwrite the partition table and the boot
2969 block. You may, however, use such a partition for a UFS
2970 or EXT2 file system, as these file systems leave the first
2971 1024 bytes undisturbed. */
2972 /* On the other hand, one should not use partitions
2973 starting at block 0 in an md, or the label will
2975 for (i = 0; i < partitions; i++)
2976 if (lens[i] && starts[i] <= first
2977 && starts[i] + lens[i] > first)
2979 if (i < partitions && !whole_disk) {
2980 if (n == 2 && !first) {
2984 printf(_("Sector %d is already allocated\n"), first);
2988 stop = cylinders * heads * sectors;
2990 for (i = 0; i < partitions; i++) {
2991 if (starts[i] > first && starts[i] < stop)
2994 snprintf(mesg, sizeof(mesg),
2995 _("Last %s or +size or +sizeM or +sizeK"),
2996 str_units(SINGULAR));
2998 last = read_int(scround(stop2), scround(stop2), scround(stop2),
3000 else if (n == 2 && !first)
3001 last = read_int(scround(first), scround(stop2), scround(stop2),
3002 scround(first), mesg);
3004 last = read_int(scround(first), scround(stop), scround(stop),
3005 scround(first), mesg);
3006 if (display_in_cyl_units)
3007 last *= units_per_sector;
3008 if (n == 2 && !first) {
3009 if (last >= stop2) {
3012 } else if (last > stop) {
3014 _("You haven't covered the whole disk with the 3rd partition, but your value\n"
3015 "%d %s covers some other partition. Your entry has been changed\n"
3017 scround(last), str_units(SINGULAR),
3018 scround(stop), str_units(SINGULAR));
3021 } else if (!whole_disk && last > stop)
3024 if (whole_disk) sys = WHOLE_DISK;
3025 set_sun_partition(n, first, last, sys);
3029 sun_delete_partition(int i) {
3032 if (i == 2 && sunlabel->infos[i].id == WHOLE_DISK &&
3033 !sunlabel->partitions[i].start_cylinder &&
3034 (nsec = SUN_SSWAP32(sunlabel->partitions[i].num_sectors))
3035 == heads * sectors * cylinders)
3036 printf(_("If you want to maintain SunOS/Solaris compatibility, "
3037 "consider leaving this\n"
3038 "partition as Whole disk (5), starting at 0, with %u "
3039 "sectors\n"), nsec);
3040 sunlabel->infos[i].id = 0;
3041 sunlabel->partitions[i].num_sectors = 0;
3045 sun_change_sysid(int i, int sys) {
3046 if (sys == LINUX_SWAP && !sunlabel->partitions[i].start_cylinder) {
3048 _("It is highly recommended that the partition at offset 0\n"
3049 "is UFS, EXT2FS filesystem or SunOS swap. Putting Linux swap\n"
3050 "there may destroy your partition table and bootblock.\n"
3051 "Type YES if you're very sure you would like that partition\n"
3052 "tagged with 82 (Linux swap): "));
3053 if (strcmp (line_ptr, _("YES\n")))
3059 /* swaps are not mountable by default */
3060 sunlabel->infos[i].flags |= 0x01;
3063 /* assume other types are mountable;
3064 user can change it anyway */
3065 sunlabel->infos[i].flags &= ~0x01;
3068 sunlabel->infos[i].id = sys;
3072 sun_list_table(int xtra) {
3075 w = strlen(disk_device);
3078 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d rpm\n"
3079 "%d cylinders, %d alternate cylinders, %d physical cylinders\n"
3080 "%d extra sects/cyl, interleave %d:1\n"
3082 "Units = %s of %d * 512 bytes\n\n"),
3083 disk_device, heads, sectors, SUN_SSWAP16(sunlabel->rspeed),
3084 cylinders, SUN_SSWAP16(sunlabel->nacyl),
3085 SUN_SSWAP16(sunlabel->pcylcount),
3086 SUN_SSWAP16(sunlabel->sparecyl),
3087 SUN_SSWAP16(sunlabel->ilfact),
3089 str_units(PLURAL), units_per_sector);
3092 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d cylinders\n"
3093 "Units = %s of %d * 512 bytes\n\n"),
3094 disk_device, heads, sectors, cylinders,
3095 str_units(PLURAL), units_per_sector);
3097 printf(_("%*s Flag Start End Blocks Id System\n"),
3098 w + 1, _("Device"));
3099 for (i = 0 ; i < partitions; i++) {
3100 if (sunlabel->partitions[i].num_sectors) {
3101 uint32_t start = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
3102 uint32_t len = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
3104 "%s %c%c %9ld %9ld %9ld%c %2x %s\n",
3105 /* device */ partname(disk_device, i+1, w),
3106 /* flags */ (sunlabel->infos[i].flags & 0x01) ? 'u' : ' ',
3107 (sunlabel->infos[i].flags & 0x10) ? 'r' : ' ',
3108 /* start */ (long) scround(start),
3109 /* end */ (long) scround(start+len),
3110 /* odd flag on end */ (long) len / 2, len & 1 ? '+' : ' ',
3111 /* type id */ sunlabel->infos[i].id,
3112 /* type name */ partition_type(sunlabel->infos[i].id));
3117 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3120 sun_set_alt_cyl(void) {
3122 SUN_SSWAP16(read_int(0,SUN_SSWAP16(sunlabel->nacyl), 65535, 0,
3123 _("Number of alternate cylinders")));
3127 sun_set_ncyl(int cyl) {
3128 sunlabel->ncyl = SUN_SSWAP16(cyl);
3132 sun_set_xcyl(void) {
3133 sunlabel->sparecyl =
3134 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->sparecyl), sectors, 0,
3135 _("Extra sectors per cylinder")));
3139 sun_set_ilfact(void) {
3141 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->ilfact), 32, 0,
3142 _("Interleave factor")));
3146 sun_set_rspeed(void) {
3148 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->rspeed), 100000, 0,
3149 _("Rotation speed (rpm)")));
3153 sun_set_pcylcount(void) {
3154 sunlabel->pcylcount =
3155 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->pcylcount), 65535, 0,
3156 _("Number of physical cylinders")));
3158 #endif /* CONFIG_FEATURE_FDISK_ADVANCED */
3161 sun_write_table(void) {
3162 unsigned short *ush = (unsigned short *)sunlabel;
3163 unsigned short csum = 0;
3165 while(ush < (unsigned short *)(&sunlabel->csum))
3167 sunlabel->csum = csum;
3168 if (lseek(fd, 0, SEEK_SET) < 0)
3169 fdisk_fatal(unable_to_seek);
3170 if (write(fd, sunlabel, SECTOR_SIZE) != SECTOR_SIZE)
3171 fdisk_fatal(unable_to_write);
3173 #endif /* SUN_LABEL */
3175 /* DOS partition types */
3177 static const struct systypes i386_sys_types[] = {
3180 {"\x04" "FAT16 <32M"},
3181 {"\x05" "Extended"}, /* DOS 3.3+ extended partition */
3182 {"\x06" "FAT16"}, /* DOS 16-bit >=32M */
3183 {"\x07" "HPFS/NTFS"}, /* OS/2 IFS, eg, HPFS or NTFS or QNX */
3184 {"\x0a" "OS/2 Boot Manager"},/* OS/2 Boot Manager */
3185 {"\x0b" "Win95 FAT32"},
3186 {"\x0c" "Win95 FAT32 (LBA)"},/* LBA really is `Extended Int 13h' */
3187 {"\x0e" "Win95 FAT16 (LBA)"},
3188 {"\x0f" "Win95 Ext'd (LBA)"},
3189 {"\x11" "Hidden FAT12"},
3190 {"\x12" "Compaq diagnostics"},
3191 {"\x14" "Hidden FAT16 <32M"},
3192 {"\x16" "Hidden FAT16"},
3193 {"\x17" "Hidden HPFS/NTFS"},
3194 {"\x1b" "Hidden Win95 FAT32"},
3195 {"\x1c" "Hidden Win95 FAT32 (LBA)"},
3196 {"\x1e" "Hidden Win95 FAT16 (LBA)"},
3197 {"\x3c" "PartitionMagic recovery"},
3198 {"\x41" "PPC PReP Boot"},
3200 {"\x63" "GNU HURD or SysV"}, /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */
3201 {"\x80" "Old Minix"}, /* Minix 1.4a and earlier */
3202 {"\x81" "Minix / old Linux"},/* Minix 1.4b and later */
3203 {"\x82" "Linux swap"}, /* also Solaris */
3205 {"\x84" "OS/2 hidden C: drive"},
3206 {"\x85" "Linux extended"},
3207 {"\x86" "NTFS volume set"},
3208 {"\x87" "NTFS volume set"},
3209 {"\x8e" "Linux LVM"},
3210 {"\x9f" "BSD/OS"}, /* BSDI */
3211 {"\xa0" "IBM Thinkpad hibernation"},
3212 {"\xa5" "FreeBSD"}, /* various BSD flavours */
3214 {"\xa8" "Darwin UFS"},
3216 {"\xab" "Darwin boot"},
3218 {"\xb8" "BSDI swap"},
3219 {"\xbe" "Solaris boot"},
3221 {"\xee" "EFI GPT"}, /* Intel EFI GUID Partition Table */
3222 {"\xef" "EFI (FAT-12/16/32)"},/* Intel EFI System Partition */
3223 {"\xf0" "Linux/PA-RISC boot"},/* Linux/PA-RISC boot loader */
3224 {"\xf2" "DOS secondary"}, /* DOS 3.3+ secondary */
3225 {"\xfd" "Linux raid autodetect"},/* New (2.2.x) raid partition with
3226 autodetect using persistent
3228 #ifdef CONFIG_WEIRD_PARTITION_TYPES
3229 {"\x02" "XENIX root"},
3230 {"\x03" "XENIX usr"},
3231 {"\x08" "AIX"}, /* AIX boot (AIX -- PS/2 port) or SplitDrive */
3232 {"\x09" "AIX bootable"}, /* AIX data or Coherent */
3234 {"\x18" "AST SmartSleep"},
3237 {"\x40" "Venix 80286"},
3239 {"\x4e" "QNX4.x 2nd part"},
3240 {"\x4f" "QNX4.x 3rd part"},
3241 {"\x50" "OnTrack DM"},
3242 {"\x51" "OnTrack DM6 Aux1"}, /* (or Novell) */
3243 {"\x52" "CP/M"}, /* CP/M or Microport SysV/AT */
3244 {"\x53" "OnTrack DM6 Aux3"},
3245 {"\x54" "OnTrackDM6"},
3246 {"\x55" "EZ-Drive"},
3247 {"\x56" "Golden Bow"},
3248 {"\x5c" "Priam Edisk"},
3249 {"\x61" "SpeedStor"},
3250 {"\x64" "Novell Netware 286"},
3251 {"\x65" "Novell Netware 386"},
3252 {"\x70" "DiskSecure Multi-Boot"},
3255 {"\x94" "Amoeba BBT"}, /* (bad block table) */
3256 {"\xa7" "NeXTSTEP"},
3257 {"\xbb" "Boot Wizard hidden"},
3258 {"\xc1" "DRDOS/sec (FAT-12)"},
3259 {"\xc4" "DRDOS/sec (FAT-16 < 32M)"},
3260 {"\xc6" "DRDOS/sec (FAT-16)"},
3262 {"\xda" "Non-FS data"},
3263 {"\xdb" "CP/M / CTOS / ..."},/* CP/M or Concurrent CP/M or
3264 Concurrent DOS or CTOS */
3265 {"\xde" "Dell Utility"}, /* Dell PowerEdge Server utilities */
3266 {"\xdf" "BootIt"}, /* BootIt EMBRM */
3267 {"\xe1" "DOS access"}, /* DOS access or SpeedStor 12-bit FAT
3268 extended partition */
3269 {"\xe3" "DOS R/O"}, /* DOS R/O or SpeedStor */
3270 {"\xe4" "SpeedStor"}, /* SpeedStor 16-bit FAT extended
3271 partition < 1024 cyl. */
3272 {"\xf1" "SpeedStor"},
3273 {"\xf4" "SpeedStor"}, /* SpeedStor large partition */
3274 {"\xfe" "LANstep"}, /* SpeedStor >1024 cyl. or LANstep */
3275 {"\xff" "BBT"}, /* Xenix Bad Block Table */
3282 /* A valid partition table sector ends in 0x55 0xaa */
3284 part_table_flag(const char *b) {
3285 return ((uint) b[510]) + (((uint) b[511]) << 8);
3289 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3291 write_part_table_flag(char *b) {
3296 /* start_sect and nr_sects are stored little endian on all machines */
3297 /* moreover, they are not aligned correctly */
3299 store4_little_endian(unsigned char *cp, unsigned int val) {
3300 cp[0] = (val & 0xff);
3301 cp[1] = ((val >> 8) & 0xff);
3302 cp[2] = ((val >> 16) & 0xff);
3303 cp[3] = ((val >> 24) & 0xff);
3305 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3308 read4_little_endian(const unsigned char *cp) {
3309 return (uint)(cp[0]) + ((uint)(cp[1]) << 8)
3310 + ((uint)(cp[2]) << 16) + ((uint)(cp[3]) << 24);
3313 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3315 set_start_sect(struct partition *p, unsigned int start_sect) {
3316 store4_little_endian(p->start4, start_sect);
3321 get_start_sect(const struct partition *p) {
3322 return read4_little_endian(p->start4);
3325 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3327 set_nr_sects(struct partition *p, int32_t nr_sects) {
3328 store4_little_endian(p->size4, nr_sects);
3333 get_nr_sects(const struct partition *p) {
3334 return read4_little_endian(p->size4);
3337 /* normally O_RDWR, -l option gives O_RDONLY */
3338 static int type_open = O_RDWR;
3341 static int ext_index, /* the prime extended partition */
3342 listing, /* no aborts for fdisk -l */
3343 dos_compatible_flag = ~0;
3344 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3345 static int dos_changed;
3346 static int nowarn; /* no warnings for fdisk -l/-s */
3351 static uint user_cylinders, user_heads, user_sectors;
3352 static uint pt_heads, pt_sectors;
3353 static uint kern_heads, kern_sectors;
3355 static off_t extended_offset; /* offset of link pointers */
3357 static unsigned long long total_number_of_sectors;
3360 static jmp_buf listingbuf;
3362 static void fdisk_fatal(enum failure why) {
3363 const char *message;
3367 longjmp(listingbuf, 1);
3371 case unable_to_open:
3372 message = "Unable to open %s\n";
3374 case unable_to_read:
3375 message = "Unable to read %s\n";
3377 case unable_to_seek:
3378 message = "Unable to seek on %s\n";
3380 case unable_to_write:
3381 message = "Unable to write %s\n";
3384 message = "BLKGETSIZE ioctl failed on %s\n";
3387 message = "Fatal error\n";
3390 fputc('\n', stderr);
3391 fprintf(stderr, message, disk_device);
3396 seek_sector(off_t secno) {
3397 off_t offset = secno * sector_size;
3398 if (lseek(fd, offset, SEEK_SET) == (off_t) -1)
3399 fdisk_fatal(unable_to_seek);
3402 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3404 write_sector(off_t secno, char *buf) {
3406 if (write(fd, buf, sector_size) != sector_size)
3407 fdisk_fatal(unable_to_write);
3411 /* Allocate a buffer and read a partition table sector */
3413 read_pte(struct pte *pe, off_t offset) {
3415 pe->offset = offset;
3416 pe->sectorbuffer = (char *) xmalloc(sector_size);
3417 seek_sector(offset);
3418 if (read(fd, pe->sectorbuffer, sector_size) != sector_size)
3419 fdisk_fatal(unable_to_read);
3420 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3423 pe->part_table = pe->ext_pointer = NULL;
3427 get_partition_start(const struct pte *pe) {
3428 return pe->offset + get_start_sect(pe->part_table);
3431 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3433 * Avoid warning about DOS partitions when no DOS partition was changed.
3434 * Here a heuristic "is probably dos partition".
3435 * We might also do the opposite and warn in all cases except
3436 * for "is probably nondos partition".
3439 is_dos_partition(int t) {
3440 return (t == 1 || t == 4 || t == 6 ||
3441 t == 0x0b || t == 0x0c || t == 0x0e ||
3442 t == 0x11 || t == 0x12 || t == 0x14 || t == 0x16 ||
3443 t == 0x1b || t == 0x1c || t == 0x1e || t == 0x24 ||
3444 t == 0xc1 || t == 0xc4 || t == 0xc6);
3449 #ifdef CONFIG_FEATURE_SUN_LABEL
3451 puts(_("Command action"));
3452 puts(_("\ta\ttoggle a read only flag")); /* sun */
3453 puts(_("\tb\tedit bsd disklabel"));
3454 puts(_("\tc\ttoggle the mountable flag")); /* sun */
3455 puts(_("\td\tdelete a partition"));
3456 puts(_("\tl\tlist known partition types"));
3457 puts(_("\tm\tprint this menu"));
3458 puts(_("\tn\tadd a new partition"));
3459 puts(_("\to\tcreate a new empty DOS partition table"));
3460 puts(_("\tp\tprint the partition table"));
3461 puts(_("\tq\tquit without saving changes"));
3462 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3463 puts(_("\tt\tchange a partition's system id"));
3464 puts(_("\tu\tchange display/entry units"));
3465 puts(_("\tv\tverify the partition table"));
3466 puts(_("\tw\twrite table to disk and exit"));
3467 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3468 puts(_("\tx\textra functionality (experts only)"));
3472 #ifdef CONFIG_FEATURE_SGI_LABEL
3474 puts(_("Command action"));
3475 puts(_("\ta\tselect bootable partition")); /* sgi flavour */
3476 puts(_("\tb\tedit bootfile entry")); /* sgi */
3477 puts(_("\tc\tselect sgi swap partition")); /* sgi flavour */
3478 puts(_("\td\tdelete a partition"));
3479 puts(_("\tl\tlist known partition types"));
3480 puts(_("\tm\tprint this menu"));
3481 puts(_("\tn\tadd a new partition"));
3482 puts(_("\to\tcreate a new empty DOS partition table"));
3483 puts(_("\tp\tprint the partition table"));
3484 puts(_("\tq\tquit without saving changes"));
3485 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3486 puts(_("\tt\tchange a partition's system id"));
3487 puts(_("\tu\tchange display/entry units"));
3488 puts(_("\tv\tverify the partition table"));
3489 puts(_("\tw\twrite table to disk and exit"));
3492 #ifdef CONFIG_FEATURE_AIX_LABEL
3494 puts(_("Command action"));
3495 puts(_("\tm\tprint this menu"));
3496 puts(_("\to\tcreate a new empty DOS partition table"));
3497 puts(_("\tq\tquit without saving changes"));
3498 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3502 puts(_("Command action"));
3503 puts(_("\ta\ttoggle a bootable flag"));
3504 puts(_("\tb\tedit bsd disklabel"));
3505 puts(_("\tc\ttoggle the dos compatibility flag"));
3506 puts(_("\td\tdelete a partition"));
3507 puts(_("\tl\tlist known partition types"));
3508 puts(_("\tm\tprint this menu"));
3509 puts(_("\tn\tadd a new partition"));
3510 puts(_("\to\tcreate a new empty DOS partition table"));
3511 puts(_("\tp\tprint the partition table"));
3512 puts(_("\tq\tquit without saving changes"));
3513 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3514 puts(_("\tt\tchange a partition's system id"));
3515 puts(_("\tu\tchange display/entry units"));
3516 puts(_("\tv\tverify the partition table"));
3517 puts(_("\tw\twrite table to disk and exit"));
3518 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3519 puts(_("\tx\textra functionality (experts only)"));
3523 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3526 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3529 #ifdef CONFIG_FEATURE_SUN_LABEL
3531 puts(_("Command action"));
3532 puts(_("\ta\tchange number of alternate cylinders")); /*sun*/
3533 puts(_("\tc\tchange number of cylinders"));
3534 puts(_("\td\tprint the raw data in the partition table"));
3535 puts(_("\te\tchange number of extra sectors per cylinder"));/*sun*/
3536 puts(_("\th\tchange number of heads"));
3537 puts(_("\ti\tchange interleave factor")); /*sun*/
3538 puts(_("\to\tchange rotation speed (rpm)")); /*sun*/
3539 puts(_("\tm\tprint this menu"));
3540 puts(_("\tp\tprint the partition table"));
3541 puts(_("\tq\tquit without saving changes"));
3542 puts(_("\tr\treturn to main menu"));
3543 puts(_("\ts\tchange number of sectors/track"));
3544 puts(_("\tv\tverify the partition table"));
3545 puts(_("\tw\twrite table to disk and exit"));
3546 puts(_("\ty\tchange number of physical cylinders")); /*sun*/
3549 #ifdef CONFIG_FEATURE_SGI_LABEL
3551 puts(_("Command action"));
3552 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3553 puts(_("\tc\tchange number of cylinders"));
3554 puts(_("\td\tprint the raw data in the partition table"));
3555 puts(_("\te\tlist extended partitions")); /* !sun */
3556 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3557 puts(_("\th\tchange number of heads"));
3558 puts(_("\tm\tprint this menu"));
3559 puts(_("\tp\tprint the partition table"));
3560 puts(_("\tq\tquit without saving changes"));
3561 puts(_("\tr\treturn to main menu"));
3562 puts(_("\ts\tchange number of sectors/track"));
3563 puts(_("\tv\tverify the partition table"));
3564 puts(_("\tw\twrite table to disk and exit"));
3567 #ifdef CONFIG_FEATURE_AIX_LABEL
3569 puts(_("Command action"));
3570 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3571 puts(_("\tc\tchange number of cylinders"));
3572 puts(_("\td\tprint the raw data in the partition table"));
3573 puts(_("\te\tlist extended partitions")); /* !sun */
3574 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3575 puts(_("\th\tchange number of heads"));
3576 puts(_("\tm\tprint this menu"));
3577 puts(_("\tp\tprint the partition table"));
3578 puts(_("\tq\tquit without saving changes"));
3579 puts(_("\tr\treturn to main menu"));
3580 puts(_("\ts\tchange number of sectors/track"));
3581 puts(_("\tv\tverify the partition table"));
3582 puts(_("\tw\twrite table to disk and exit"));
3586 puts(_("Command action"));
3587 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3588 puts(_("\tc\tchange number of cylinders"));
3589 puts(_("\td\tprint the raw data in the partition table"));
3590 puts(_("\te\tlist extended partitions")); /* !sun */
3591 puts(_("\tf\tfix partition order")); /* !sun, !aix, !sgi */
3592 #ifdef CONFIG_FEATURE_SGI_LABEL
3593 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3595 puts(_("\th\tchange number of heads"));
3596 puts(_("\tm\tprint this menu"));
3597 puts(_("\tp\tprint the partition table"));
3598 puts(_("\tq\tquit without saving changes"));
3599 puts(_("\tr\treturn to main menu"));
3600 puts(_("\ts\tchange number of sectors/track"));
3601 puts(_("\tv\tverify the partition table"));
3602 puts(_("\tw\twrite table to disk and exit"));
3605 #endif /* ADVANCED mode */
3607 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3608 static const struct systypes *
3609 get_sys_types(void) {
3611 #ifdef CONFIG_FEATURE_SUN_LABEL
3612 sun_label ? sun_sys_types :
3614 #ifdef CONFIG_FEATURE_SGI_LABEL
3615 sgi_label ? sgi_sys_types :
3620 #define get_sys_types() i386_sys_types
3621 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3623 static const char *partition_type(unsigned char type)
3626 const struct systypes *types = get_sys_types();
3628 for (i=0; types[i].name; i++)
3629 if (types[i].name[0] == type)
3630 return types[i].name + 1;
3632 return _("Unknown");
3636 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3640 #ifdef CONFIG_FEATURE_SUN_LABEL
3641 sun_label ? sunlabel->infos[i].id :
3643 #ifdef CONFIG_FEATURE_SGI_LABEL
3644 sgi_label ? sgi_get_sysid(i) :
3646 ptes[i].part_table->sys_ind);
3649 void list_types(const struct systypes *sys)
3651 uint last[4], done = 0, next = 0, size;
3654 for (i = 0; sys[i].name; i++);
3657 for (i = 3; i >= 0; i--)
3658 last[3 - i] = done += (size + i - done) / (i + 1);
3662 printf("%c%2x %-15.15s", i ? ' ' : '\n',
3663 sys[next].name[0], partition_type(sys[next].name[0]));
3664 next = last[i++] + done;
3665 if (i > 3 || next >= last[i]) {
3669 } while (done < last[0]);
3672 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3675 is_cleared_partition(const struct partition *p) {
3676 return !(!p || p->boot_ind || p->head || p->sector || p->cyl ||
3677 p->sys_ind || p->end_head || p->end_sector || p->end_cyl ||
3678 get_start_sect(p) || get_nr_sects(p));
3682 clear_partition(struct partition *p) {
3685 memset(p, 0, sizeof(struct partition));
3688 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3690 set_partition(int i, int doext, off_t start, off_t stop, int sysid) {
3691 struct partition *p;
3695 p = ptes[i].ext_pointer;
3696 offset = extended_offset;
3698 p = ptes[i].part_table;
3699 offset = ptes[i].offset;
3703 set_start_sect(p, start - offset);
3704 set_nr_sects(p, stop - start + 1);
3705 if (dos_compatible_flag && (start/(sectors*heads) > 1023))
3706 start = heads*sectors*1024 - 1;
3707 set_hsc(p->head, p->sector, p->cyl, start);
3708 if (dos_compatible_flag && (stop/(sectors*heads) > 1023))
3709 stop = heads*sectors*1024 - 1;
3710 set_hsc(p->end_head, p->end_sector, p->end_cyl, stop);
3711 ptes[i].changed = 1;
3716 test_c(const char **m, const char *mesg) {
3719 fprintf(stderr, _("You must set"));
3721 fprintf(stderr, " %s", *m);
3729 warn_geometry(void) {
3730 const char *m = NULL;
3734 prev = test_c(&m, _("heads"));
3736 prev = test_c(&m, _("sectors"));
3738 prev = test_c(&m, _("cylinders"));
3742 fprintf(stderr, "%s%s.\n"
3743 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3744 "You can do this from the extra functions menu.\n"
3746 , prev ? _(" and ") : " ", m);
3751 static void update_units(void)
3753 int cyl_units = heads * sectors;
3755 if (display_in_cyl_units && cyl_units)
3756 units_per_sector = cyl_units;
3758 units_per_sector = 1; /* in sectors */
3761 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3763 warn_cylinders(void) {
3764 if (dos_label && cylinders > 1024 && !nowarn)
3765 fprintf(stderr, _("\n"
3766 "The number of cylinders for this disk is set to %d.\n"
3767 "There is nothing wrong with that, but this is larger than 1024,\n"
3768 "and could in certain setups cause problems with:\n"
3769 "1) software that runs at boot time (e.g., old versions of LILO)\n"
3770 "2) booting and partitioning software from other OSs\n"
3771 " (e.g., DOS FDISK, OS/2 FDISK)\n"),
3777 read_extended(int ext) {
3780 struct partition *p, *q;
3784 pex->ext_pointer = pex->part_table;
3786 p = pex->part_table;
3787 if (!get_start_sect(p)) {
3789 _("Bad offset in primary extended partition\n"));
3793 while (IS_EXTENDED (p->sys_ind)) {
3794 struct pte *pe = &ptes[partitions];
3796 if (partitions >= MAXIMUM_PARTS) {
3797 /* This is not a Linux restriction, but
3798 this program uses arrays of size MAXIMUM_PARTS.
3799 Do not try to `improve' this test. */
3800 struct pte *pre = &ptes[partitions-1];
3801 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3803 _("Warning: deleting partitions after %d\n"),
3807 clear_partition(pre->ext_pointer);
3811 read_pte(pe, extended_offset + get_start_sect(p));
3813 if (!extended_offset)
3814 extended_offset = get_start_sect(p);
3816 q = p = pt_offset(pe->sectorbuffer, 0);
3817 for (i = 0; i < 4; i++, p++) if (get_nr_sects(p)) {
3818 if (IS_EXTENDED (p->sys_ind)) {
3819 if (pe->ext_pointer)
3821 _("Warning: extra link "
3822 "pointer in partition table"
3823 " %d\n"), partitions + 1);
3825 pe->ext_pointer = p;
3826 } else if (p->sys_ind) {
3829 _("Warning: ignoring extra "
3830 "data in partition table"
3831 " %d\n"), partitions + 1);
3837 /* very strange code here... */
3838 if (!pe->part_table) {
3839 if (q != pe->ext_pointer)
3842 pe->part_table = q + 1;
3844 if (!pe->ext_pointer) {
3845 if (q != pe->part_table)
3846 pe->ext_pointer = q;
3848 pe->ext_pointer = q + 1;
3851 p = pe->ext_pointer;
3855 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3856 /* remove empty links */
3858 for (i = 4; i < partitions; i++) {
3859 struct pte *pe = &ptes[i];
3861 if (!get_nr_sects(pe->part_table) &&
3862 (partitions > 5 || ptes[4].part_table->sys_ind)) {
3863 printf("omitting empty partition (%d)\n", i+1);
3864 delete_partition(i);
3865 goto remove; /* numbering changed */
3871 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3873 create_doslabel(void) {
3877 _("Building a new DOS disklabel. Changes will remain in memory only,\n"
3878 "until you decide to write them. After that, of course, the previous\n"
3879 "content won't be recoverable.\n\n"));
3880 #ifdef CONFIG_FEATURE_SUN_LABEL
3881 sun_nolabel(); /* otherwise always recognised as sun */
3883 #ifdef CONFIG_FEATURE_SGI_LABEL
3884 sgi_nolabel(); /* otherwise always recognised as sgi */
3886 #ifdef CONFIG_FEATURE_AIX_LABEL
3889 #ifdef CONFIG_FEATURE_OSF_LABEL
3891 possibly_osf_label = 0;
3895 for (i = 510-64; i < 510; i++)
3897 write_part_table_flag(MBRbuffer);
3898 extended_offset = 0;
3899 set_all_unchanged();
3901 get_boot(create_empty_dos);
3903 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3906 get_sectorsize(void) {
3907 if (!user_set_sector_size &&
3908 get_kernel_revision() >= MAKE_VERSION(2,3,3)) {
3910 if (ioctl(fd, BLKSSZGET, &arg) == 0)
3912 if (sector_size != DEFAULT_SECTOR_SIZE)
3913 printf(_("Note: sector size is %d (not %d)\n"),
3914 sector_size, DEFAULT_SECTOR_SIZE);
3919 get_kernel_geometry(void) {
3920 struct hd_geometry geometry;
3922 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
3923 kern_heads = geometry.heads;
3924 kern_sectors = geometry.sectors;
3925 /* never use geometry.cylinders - it is truncated */
3930 get_partition_table_geometry(void) {
3931 const unsigned char *bufp = MBRbuffer;
3932 struct partition *p;
3933 int i, h, s, hh, ss;
3937 if (!(valid_part_table_flag(bufp)))
3941 for (i=0; i<4; i++) {
3942 p = pt_offset(bufp, i);
3943 if (p->sys_ind != 0) {
3944 h = p->end_head + 1;
3945 s = (p->end_sector & 077);
3950 } else if (hh != h || ss != s)
3955 if (!first && !bad) {
3962 get_geometry(void) {
3964 unsigned long long bytes; /* really u64 */
3967 sec_fac = sector_size / 512;
3968 #ifdef CONFIG_FEATURE_SUN_LABEL
3969 guess_device_type();
3971 heads = cylinders = sectors = 0;
3972 kern_heads = kern_sectors = 0;
3973 pt_heads = pt_sectors = 0;
3975 get_kernel_geometry();
3976 get_partition_table_geometry();
3978 heads = user_heads ? user_heads :
3979 pt_heads ? pt_heads :
3980 kern_heads ? kern_heads : 255;
3981 sectors = user_sectors ? user_sectors :
3982 pt_sectors ? pt_sectors :
3983 kern_sectors ? kern_sectors : 63;
3984 if (ioctl(fd, BLKGETSIZE64, &bytes) == 0) {
3987 unsigned long longsectors;
3989 if (ioctl(fd, BLKGETSIZE, &longsectors))
3991 bytes = ((unsigned long long) longsectors) << 9;
3994 total_number_of_sectors = (bytes >> 9);
3997 if (dos_compatible_flag)
3998 sector_offset = sectors;
4000 cylinders = total_number_of_sectors / (heads * sectors * sec_fac);
4002 cylinders = user_cylinders;
4006 * Read MBR. Returns:
4007 * -1: no 0xaa55 flag present (possibly entire disk BSD)
4008 * 0: found or created label
4012 get_boot(enum action what) {
4017 for (i = 0; i < 4; i++) {
4018 struct pte *pe = &ptes[i];
4020 pe->part_table = pt_offset(MBRbuffer, i);
4021 pe->ext_pointer = NULL;
4023 pe->sectorbuffer = MBRbuffer;
4024 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4025 pe->changed = (what == create_empty_dos);
4029 #ifdef CONFIG_FEATURE_SUN_LABEL
4030 if (what == create_empty_sun && check_sun_label())
4034 memset(MBRbuffer, 0, 512);
4036 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4037 if (what == create_empty_dos)
4038 goto got_dos_table; /* skip reading disk */
4040 if ((fd = open(disk_device, type_open)) < 0) {
4041 if ((fd = open(disk_device, O_RDONLY)) < 0) {
4042 if (what == try_only)
4044 fdisk_fatal(unable_to_open);
4046 printf(_("You will not be able to write "
4047 "the partition table.\n"));
4050 if (512 != read(fd, MBRbuffer, 512)) {
4051 if (what == try_only)
4053 fdisk_fatal(unable_to_read);
4056 if ((fd = open(disk_device, O_RDONLY)) < 0)
4058 if (512 != read(fd, MBRbuffer, 512))
4066 #ifdef CONFIG_FEATURE_SUN_LABEL
4067 if (check_sun_label())
4071 #ifdef CONFIG_FEATURE_SGI_LABEL
4072 if (check_sgi_label())
4076 #ifdef CONFIG_FEATURE_AIX_LABEL
4077 if (check_aix_label())
4081 #ifdef CONFIG_FEATURE_OSF_LABEL
4082 if (check_osf_label()) {
4083 possibly_osf_label = 1;
4084 if (!valid_part_table_flag(MBRbuffer)) {
4088 printf(_("This disk has both DOS and BSD magic.\n"
4089 "Give the 'b' command to go to BSD mode.\n"));
4093 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4097 if (!valid_part_table_flag(MBRbuffer)) {
4098 #ifndef CONFIG_FEATURE_FDISK_WRITABLE
4104 _("Device contains neither a valid DOS "
4105 "partition table, nor Sun, SGI or OSF "
4108 #ifdef CONFIG_FEATURE_SUN_LABEL
4117 case create_empty_dos:
4118 #ifdef CONFIG_FEATURE_SUN_LABEL
4119 case create_empty_sun:
4123 fprintf(stderr, _("Internal error\n"));
4126 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
4129 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4134 for (i = 0; i < 4; i++) {
4135 struct pte *pe = &ptes[i];
4137 if (IS_EXTENDED (pe->part_table->sys_ind)) {
4138 if (partitions != 4)
4139 fprintf(stderr, _("Ignoring extra extended "
4140 "partition %d\n"), i + 1);
4146 for (i = 3; i < partitions; i++) {
4147 struct pte *pe = &ptes[i];
4149 if (!valid_part_table_flag(pe->sectorbuffer)) {
4151 _("Warning: invalid flag 0x%04x of partition "
4152 "table %d will be corrected by w(rite)\n"),
4153 part_table_flag(pe->sectorbuffer), i + 1);
4154 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4163 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4165 * Print the message MESG, then read an integer between LOW and HIGH (inclusive).
4166 * If the user hits Enter, DFLT is returned.
4167 * Answers like +10 are interpreted as offsets from BASE.
4169 * There is no default if DFLT is not between LOW and HIGH.
4172 read_int(uint low, uint dflt, uint high, uint base, char *mesg)
4176 static char *ms = NULL;
4177 static int mslen = 0;
4179 if (!ms || strlen(mesg)+100 > mslen) {
4180 mslen = strlen(mesg)+200;
4181 ms = xrealloc(ms,mslen);
4184 if (dflt < low || dflt > high)
4188 snprintf(ms, mslen, _("%s (%u-%u, default %u): "),
4189 mesg, low, high, dflt);
4191 snprintf(ms, mslen, "%s (%u-%u): ",
4195 int use_default = default_ok;
4197 /* ask question and read answer */
4198 while (read_chars(ms) != '\n' && !isdigit(*line_ptr)
4199 && *line_ptr != '-' && *line_ptr != '+')
4202 if (*line_ptr == '+' || *line_ptr == '-') {
4203 int minus = (*line_ptr == '-');
4206 i = atoi(line_ptr+1);
4208 while (isdigit(*++line_ptr))
4211 switch (*line_ptr) {
4214 if (!display_in_cyl_units)
4215 i *= heads * sectors;
4229 absolute = 1000000000;
4235 unsigned long long bytes;
4238 bytes = (unsigned long long) i * absolute;
4239 unit = sector_size * units_per_sector;
4240 bytes += unit/2; /* round */
4249 while (isdigit(*line_ptr)) {
4255 printf(_("Using default value %u\n"), i = dflt);
4256 if (i >= low && i <= high)
4259 printf(_("Value out of range.\n"));
4265 get_partition(int warn, int max) {
4269 i = read_int(1, 0, max, 0, _("Partition number")) - 1;
4273 if ((!sun_label && !sgi_label && !pe->part_table->sys_ind)
4274 #ifdef CONFIG_FEATURE_SUN_LABEL
4276 (!sunlabel->partitions[i].num_sectors ||
4277 !sunlabel->infos[i].id))
4279 #ifdef CONFIG_FEATURE_SGI_LABEL
4280 || (sgi_label && (!sgi_get_num_sectors(i)))
4284 _("Warning: partition %d has empty type\n"),
4291 get_existing_partition(int warn, int max) {
4295 for (i = 0; i < max; i++) {
4296 struct pte *pe = &ptes[i];
4297 struct partition *p = pe->part_table;
4299 if (p && !is_cleared_partition(p)) {
4306 printf(_("Selected partition %d\n"), pno+1);
4309 printf(_("No partition is defined yet!\n"));
4313 return get_partition(warn, max);
4317 get_nonexisting_partition(int warn, int max) {
4321 for (i = 0; i < max; i++) {
4322 struct pte *pe = &ptes[i];
4323 struct partition *p = pe->part_table;
4325 if (p && is_cleared_partition(p)) {
4332 printf(_("Selected partition %d\n"), pno+1);
4335 printf(_("All primary partitions have been defined already!\n"));
4339 return get_partition(warn, max);
4343 void change_units(void)
4345 display_in_cyl_units = !display_in_cyl_units;
4347 printf(_("Changing display/entry units to %s\n"),
4352 toggle_active(int i) {
4353 struct pte *pe = &ptes[i];
4354 struct partition *p = pe->part_table;
4356 if (IS_EXTENDED (p->sys_ind) && !p->boot_ind)
4358 _("WARNING: Partition %d is an extended partition\n"),
4360 p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG);
4365 toggle_dos_compatibility_flag(void) {
4366 dos_compatible_flag = ~dos_compatible_flag;
4367 if (dos_compatible_flag) {
4368 sector_offset = sectors;
4369 printf(_("DOS Compatibility flag is set\n"));
4373 printf(_("DOS Compatibility flag is not set\n"));
4378 delete_partition(int i) {
4379 struct pte *pe = &ptes[i];
4380 struct partition *p = pe->part_table;
4381 struct partition *q = pe->ext_pointer;
4383 /* Note that for the fifth partition (i == 4) we don't actually
4384 * decrement partitions.
4387 if (warn_geometry())
4388 return; /* C/H/S not set */
4391 #ifdef CONFIG_FEATURE_SUN_LABEL
4393 sun_delete_partition(i);
4397 #ifdef CONFIG_FEATURE_SGI_LABEL
4399 sgi_delete_partition(i);
4405 if (IS_EXTENDED (p->sys_ind) && i == ext_index) {
4407 ptes[ext_index].ext_pointer = NULL;
4408 extended_offset = 0;
4414 if (!q->sys_ind && i > 4) {
4415 /* the last one in the chain - just delete */
4418 clear_partition(ptes[i].ext_pointer);
4419 ptes[i].changed = 1;
4421 /* not the last one - further ones will be moved down */
4423 /* delete this link in the chain */
4424 p = ptes[i-1].ext_pointer;
4426 set_start_sect(p, get_start_sect(q));
4427 set_nr_sects(p, get_nr_sects(q));
4428 ptes[i-1].changed = 1;
4429 } else if (partitions > 5) { /* 5 will be moved to 4 */
4430 /* the first logical in a longer chain */
4433 if (pe->part_table) /* prevent SEGFAULT */
4434 set_start_sect(pe->part_table,
4435 get_partition_start(pe) -
4437 pe->offset = extended_offset;
4441 if (partitions > 5) {
4443 while (i < partitions) {
4444 ptes[i] = ptes[i+1];
4448 /* the only logical: clear only */
4449 clear_partition(ptes[i].part_table);
4454 change_sysid(void) {
4455 int i, sys, origsys;
4456 struct partition *p;
4458 #ifdef CONFIG_FEATURE_SGI_LABEL
4459 /* If sgi_label then don't use get_existing_partition,
4460 let the user select a partition, since get_existing_partition()
4461 only works for Linux like partition tables. */
4463 i = get_existing_partition(0, partitions);
4465 i = get_partition(0, partitions);
4468 i = get_existing_partition(0, partitions);
4472 p = ptes[i].part_table;
4473 origsys = sys = get_sysid(i);
4475 /* if changing types T to 0 is allowed, then
4476 the reverse change must be allowed, too */
4477 if (!sys && !sgi_label && !sun_label && !get_nr_sects(p))
4478 printf(_("Partition %d does not exist yet!\n"), i + 1);
4480 sys = read_hex (get_sys_types());
4482 if (!sys && !sgi_label && !sun_label) {
4483 printf(_("Type 0 means free space to many systems\n"
4484 "(but not to Linux). Having partitions of\n"
4485 "type 0 is probably unwise. You can delete\n"
4486 "a partition using the `d' command.\n"));
4490 if (!sun_label && !sgi_label) {
4491 if (IS_EXTENDED (sys) != IS_EXTENDED (p->sys_ind)) {
4492 printf(_("You cannot change a partition into"
4493 " an extended one or vice versa\n"
4494 "Delete it first.\n"));
4500 #ifdef CONFIG_FEATURE_SUN_LABEL
4501 if (sun_label && i == 2 && sys != WHOLE_DISK)
4502 printf(_("Consider leaving partition 3 "
4503 "as Whole disk (5),\n"
4504 "as SunOS/Solaris expects it and "
4505 "even Linux likes it.\n\n"));
4507 #ifdef CONFIG_FEATURE_SGI_LABEL
4508 if (sgi_label && ((i == 10 && sys != ENTIRE_DISK)
4509 || (i == 8 && sys != 0)))
4510 printf(_("Consider leaving partition 9 "
4511 "as volume header (0),\nand "
4512 "partition 11 as entire volume (6)"
4513 "as IRIX expects it.\n\n"));
4517 #ifdef CONFIG_FEATURE_SUN_LABEL
4519 sun_change_sysid(i, sys);
4522 #ifdef CONFIG_FEATURE_SGI_LABEL
4524 sgi_change_sysid(i, sys);
4528 printf (_("Changed system type of partition %d "
4529 "to %x (%s)\n"), i + 1, sys,
4530 partition_type(sys));
4531 ptes[i].changed = 1;
4532 if (is_dos_partition(origsys) ||
4533 is_dos_partition(sys))
4539 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
4542 /* check_consistency() and long2chs() added Sat Mar 6 12:28:16 1993,
4543 * faith@cs.unc.edu, based on code fragments from pfdisk by Gordon W. Ross,
4544 * Jan. 1990 (version 1.2.1 by Gordon W. Ross Aug. 1990; Modified by S.
4545 * Lubkin Oct. 1991). */
4547 static void long2chs(ulong ls, uint *c, uint *h, uint *s) {
4548 int spc = heads * sectors;
4553 *s = ls % sectors + 1; /* sectors count from 1 */
4556 static void check_consistency(const struct partition *p, int partition) {
4557 uint pbc, pbh, pbs; /* physical beginning c, h, s */
4558 uint pec, peh, pes; /* physical ending c, h, s */
4559 uint lbc, lbh, lbs; /* logical beginning c, h, s */
4560 uint lec, leh, les; /* logical ending c, h, s */
4562 if (!heads || !sectors || (partition >= 4))
4563 return; /* do not check extended partitions */
4565 /* physical beginning c, h, s */
4566 pbc = (p->cyl & 0xff) | ((p->sector << 2) & 0x300);
4568 pbs = p->sector & 0x3f;
4570 /* physical ending c, h, s */
4571 pec = (p->end_cyl & 0xff) | ((p->end_sector << 2) & 0x300);
4573 pes = p->end_sector & 0x3f;
4575 /* compute logical beginning (c, h, s) */
4576 long2chs(get_start_sect(p), &lbc, &lbh, &lbs);
4578 /* compute logical ending (c, h, s) */
4579 long2chs(get_start_sect(p) + get_nr_sects(p) - 1, &lec, &leh, &les);
4581 /* Same physical / logical beginning? */
4582 if (cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) {
4583 printf(_("Partition %d has different physical/logical "
4584 "beginnings (non-Linux?):\n"), partition + 1);
4585 printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs);
4586 printf(_("logical=(%d, %d, %d)\n"),lbc, lbh, lbs);
4589 /* Same physical / logical ending? */
4590 if (cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) {
4591 printf(_("Partition %d has different physical/logical "
4592 "endings:\n"), partition + 1);
4593 printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
4594 printf(_("logical=(%d, %d, %d)\n"),lec, leh, les);
4598 /* Beginning on cylinder boundary? */
4599 if (pbh != !pbc || pbs != 1) {
4600 printf(_("Partition %i does not start on cylinder "
4601 "boundary:\n"), partition + 1);
4602 printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs);
4603 printf(_("should be (%d, %d, 1)\n"), pbc, !pbc);
4607 /* Ending on cylinder boundary? */
4608 if (peh != (heads - 1) || pes != sectors) {
4609 printf(_("Partition %i does not end on cylinder boundary.\n"),
4612 printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
4613 printf(_("should be (%d, %d, %d)\n"),
4614 pec, heads - 1, sectors);
4620 list_disk_geometry(void) {
4621 long long bytes = (total_number_of_sectors << 9);
4622 long megabytes = bytes/1000000;
4624 if (megabytes < 10000)
4625 printf(_("\nDisk %s: %ld MB, %lld bytes\n"),
4626 disk_device, megabytes, bytes);
4628 printf(_("\nDisk %s: %ld.%ld GB, %lld bytes\n"),
4629 disk_device, megabytes/1000, (megabytes/100)%10, bytes);
4630 printf(_("%d heads, %d sectors/track, %d cylinders"),
4631 heads, sectors, cylinders);
4632 if (units_per_sector == 1)
4633 printf(_(", total %llu sectors"),
4634 total_number_of_sectors / (sector_size/512));
4635 printf(_("\nUnits = %s of %d * %d = %d bytes\n\n"),
4637 units_per_sector, sector_size, units_per_sector * sector_size);
4641 * Check whether partition entries are ordered by their starting positions.
4642 * Return 0 if OK. Return i if partition i should have been earlier.
4643 * Two separate checks: primary and logical partitions.
4646 wrong_p_order(int *prev) {
4647 const struct pte *pe;
4648 const struct partition *p;
4649 off_t last_p_start_pos = 0, p_start_pos;
4652 for (i = 0 ; i < partitions; i++) {
4655 last_p_start_pos = 0;
4658 if ((p = pe->part_table)->sys_ind) {
4659 p_start_pos = get_partition_start(pe);
4661 if (last_p_start_pos > p_start_pos) {
4667 last_p_start_pos = p_start_pos;
4674 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
4676 * Fix the chain of logicals.
4677 * extended_offset is unchanged, the set of sectors used is unchanged
4678 * The chain is sorted so that sectors increase, and so that
4679 * starting sectors increase.
4681 * After this it may still be that cfdisk doesnt like the table.
4682 * (This is because cfdisk considers expanded parts, from link to
4683 * end of partition, and these may still overlap.)
4685 * sfdisk /dev/hda > ohda; sfdisk /dev/hda < ohda
4689 fix_chain_of_logicals(void) {
4690 int j, oj, ojj, sj, sjj;
4691 struct partition *pj,*pjj,tmp;
4693 /* Stage 1: sort sectors but leave sector of part 4 */
4694 /* (Its sector is the global extended_offset.) */
4696 for (j = 5; j < partitions-1; j++) {
4697 oj = ptes[j].offset;
4698 ojj = ptes[j+1].offset;
4700 ptes[j].offset = ojj;
4701 ptes[j+1].offset = oj;
4702 pj = ptes[j].part_table;
4703 set_start_sect(pj, get_start_sect(pj)+oj-ojj);
4704 pjj = ptes[j+1].part_table;
4705 set_start_sect(pjj, get_start_sect(pjj)+ojj-oj);
4706 set_start_sect(ptes[j-1].ext_pointer,
4707 ojj-extended_offset);
4708 set_start_sect(ptes[j].ext_pointer,
4709 oj-extended_offset);
4714 /* Stage 2: sort starting sectors */
4716 for (j = 4; j < partitions-1; j++) {
4717 pj = ptes[j].part_table;
4718 pjj = ptes[j+1].part_table;
4719 sj = get_start_sect(pj);
4720 sjj = get_start_sect(pjj);
4721 oj = ptes[j].offset;
4722 ojj = ptes[j+1].offset;
4723 if (oj+sj > ojj+sjj) {
4727 set_start_sect(pj, ojj+sjj-oj);
4728 set_start_sect(pjj, oj+sj-ojj);
4733 /* Probably something was changed */
4734 for (j = 4; j < partitions; j++)
4735 ptes[j].changed = 1;
4740 fix_partition_table_order(void) {
4741 struct pte *pei, *pek;
4744 if (!wrong_p_order(NULL)) {
4745 printf(_("Nothing to do. Ordering is correct already.\n\n"));
4749 while ((i = wrong_p_order(&k)) != 0 && i < 4) {
4750 /* partition i should have come earlier, move it */
4751 /* We have to move data in the MBR */
4752 struct partition *pi, *pk, *pe, pbuf;
4756 pe = pei->ext_pointer;
4757 pei->ext_pointer = pek->ext_pointer;
4758 pek->ext_pointer = pe;
4760 pi = pei->part_table;
4761 pk = pek->part_table;
4763 memmove(&pbuf, pi, sizeof(struct partition));
4764 memmove(pi, pk, sizeof(struct partition));
4765 memmove(pk, &pbuf, sizeof(struct partition));
4767 pei->changed = pek->changed = 1;
4771 fix_chain_of_logicals();
4779 list_table(int xtra) {
4780 const struct partition *p;
4783 #ifdef CONFIG_FEATURE_SUN_LABEL
4785 sun_list_table(xtra);
4790 #ifdef CONFIG_FEATURE_SGI_LABEL
4792 sgi_list_table(xtra);
4797 list_disk_geometry();
4799 #ifdef CONFIG_FEATURE_OSF_LABEL
4801 xbsd_print_disklabel(xtra);
4806 /* Heuristic: we list partition 3 of /dev/foo as /dev/foo3,
4807 but if the device name ends in a digit, say /dev/foo1,
4808 then the partition is called /dev/foo1p3. */
4809 w = strlen(disk_device);
4810 if (w && isdigit(disk_device[w-1]))
4815 printf(_("%*s Boot Start End Blocks Id System\n"),
4818 for (i = 0; i < partitions; i++) {
4819 const struct pte *pe = &ptes[i];
4822 if (p && !is_cleared_partition(p)) {
4823 off_t psects = get_nr_sects(p);
4824 off_t pblocks = psects;
4825 unsigned int podd = 0;
4827 if (sector_size < 1024) {
4828 pblocks /= (1024 / sector_size);
4829 podd = psects % (1024 / sector_size);
4831 if (sector_size > 1024)
4832 pblocks *= (sector_size / 1024);
4834 "%s %c %11llu %11llu %11llu%c %2x %s\n",
4835 partname(disk_device, i+1, w+2),
4836 /* boot flag */ !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG
4838 /* start */ (unsigned long long) cround(get_partition_start(pe)),
4839 /* end */ (unsigned long long) cround(get_partition_start(pe) + psects
4840 - (psects ? 1 : 0)),
4841 /* odd flag on end */ (unsigned long long) pblocks, podd ? '+' : ' ',
4842 /* type id */ p->sys_ind,
4843 /* type name */ partition_type(p->sys_ind));
4844 check_consistency(p, i);
4848 /* Is partition table in disk order? It need not be, but... */
4849 /* partition table entries are not checked for correct order if this
4850 is a sgi, sun or aix labeled disk... */
4851 if (dos_label && wrong_p_order(NULL)) {
4852 printf(_("\nPartition table entries are not in disk order\n"));
4856 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
4858 x_list_table(int extend) {
4859 const struct pte *pe;
4860 const struct partition *p;
4863 printf(_("\nDisk %s: %d heads, %d sectors, %d cylinders\n\n"),
4864 disk_device, heads, sectors, cylinders);
4865 printf(_("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n"));
4866 for (i = 0 ; i < partitions; i++) {
4868 p = (extend ? pe->ext_pointer : pe->part_table);
4870 printf("%2d %02x%4d%4d%5d%4d%4d%5d%11u%11u %02x\n",
4871 i + 1, p->boot_ind, p->head,
4873 cylinder(p->sector, p->cyl), p->end_head,
4874 sector(p->end_sector),
4875 cylinder(p->end_sector, p->end_cyl),
4876 get_start_sect(p), get_nr_sects(p), p->sys_ind);
4878 check_consistency(p, i);
4884 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4886 fill_bounds(off_t *first, off_t *last) {
4888 const struct pte *pe = &ptes[0];
4889 const struct partition *p;
4891 for (i = 0; i < partitions; pe++,i++) {
4893 if (!p->sys_ind || IS_EXTENDED (p->sys_ind)) {
4894 first[i] = 0xffffffff;
4897 first[i] = get_partition_start(pe);
4898 last[i] = first[i] + get_nr_sects(p) - 1;
4904 check(int n, uint h, uint s, uint c, off_t start) {
4905 off_t total, real_s, real_c;
4907 real_s = sector(s) - 1;
4908 real_c = cylinder(s, c);
4909 total = (real_c * sectors + real_s) * heads + h;
4911 fprintf(stderr, _("Warning: partition %d contains sector 0\n"), n);
4914 _("Partition %d: head %d greater than maximum %d\n"),
4916 if (real_s >= sectors)
4917 fprintf(stderr, _("Partition %d: sector %d greater than "
4918 "maximum %d\n"), n, s, sectors);
4919 if (real_c >= cylinders)
4920 fprintf(stderr, _("Partitions %d: cylinder %llu greater than "
4921 "maximum %d\n"), n, (unsigned long long)real_c + 1, cylinders);
4922 if (cylinders <= 1024 && start != total)
4924 _("Partition %d: previous sectors %llu disagrees with "
4925 "total %llu\n"), n, (unsigned long long)start, (unsigned long long)total);
4932 off_t first[partitions], last[partitions];
4933 struct partition *p;
4935 if (warn_geometry())
4938 #ifdef CONFIG_FEATURE_SUN_LABEL
4944 #ifdef CONFIG_FEATURE_SGI_LABEL
4951 fill_bounds(first, last);
4952 for (i = 0; i < partitions; i++) {
4953 struct pte *pe = &ptes[i];
4956 if (p->sys_ind && !IS_EXTENDED (p->sys_ind)) {
4957 check_consistency(p, i);
4958 if (get_partition_start(pe) < first[i])
4959 printf(_("Warning: bad start-of-data in "
4960 "partition %d\n"), i + 1);
4961 check(i + 1, p->end_head, p->end_sector, p->end_cyl,
4963 total += last[i] + 1 - first[i];
4964 for (j = 0; j < i; j++)
4965 if ((first[i] >= first[j] && first[i] <= last[j])
4966 || ((last[i] <= last[j] && last[i] >= first[j]))) {
4967 printf(_("Warning: partition %d overlaps "
4968 "partition %d.\n"), j + 1, i + 1);
4969 total += first[i] >= first[j] ?
4970 first[i] : first[j];
4971 total -= last[i] <= last[j] ?
4977 if (extended_offset) {
4978 struct pte *pex = &ptes[ext_index];
4979 off_t e_last = get_start_sect(pex->part_table) +
4980 get_nr_sects(pex->part_table) - 1;
4982 for (i = 4; i < partitions; i++) {
4984 p = ptes[i].part_table;
4986 if (i != 4 || i + 1 < partitions)
4987 printf(_("Warning: partition %d "
4988 "is empty\n"), i + 1);
4990 else if (first[i] < extended_offset ||
4992 printf(_("Logical partition %d not entirely in "
4993 "partition %d\n"), i + 1, ext_index + 1);
4997 if (total > heads * sectors * cylinders)
4998 printf(_("Total allocated sectors %d greater than the maximum "
4999 "%d\n"), total, heads * sectors * cylinders);
5000 else if ((total = heads * sectors * cylinders - total) != 0)
5001 printf(_("%d unallocated sectors\n"), total);
5005 add_partition(int n, int sys) {
5006 char mesg[256]; /* 48 does not suffice in Japanese */
5008 struct partition *p = ptes[n].part_table;
5009 struct partition *q = ptes[ext_index].part_table;
5011 off_t start, stop = 0, limit, temp,
5012 first[partitions], last[partitions];
5014 if (p && p->sys_ind) {
5015 printf(_("Partition %d is already defined. Delete "
5016 "it before re-adding it.\n"), n + 1);
5019 fill_bounds(first, last);
5021 start = sector_offset;
5022 if (display_in_cyl_units || !total_number_of_sectors)
5023 llimit = heads * sectors * cylinders - 1;
5025 llimit = total_number_of_sectors - 1;
5027 if (limit != llimit)
5029 if (extended_offset) {
5030 first[ext_index] = extended_offset;
5031 last[ext_index] = get_start_sect(q) +
5032 get_nr_sects(q) - 1;
5035 start = extended_offset + sector_offset;
5036 limit = get_start_sect(q) + get_nr_sects(q) - 1;
5038 if (display_in_cyl_units)
5039 for (i = 0; i < partitions; i++)
5040 first[i] = (cround(first[i]) - 1) * units_per_sector;
5042 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
5045 for (i = 0; i < partitions; i++) {
5048 if (start == ptes[i].offset)
5049 start += sector_offset;
5050 lastplusoff = last[i] + ((n<4) ? 0 : sector_offset);
5051 if (start >= first[i] && start <= lastplusoff)
5052 start = lastplusoff + 1;
5056 if (start >= temp+units_per_sector && readed) {
5057 printf(_("Sector %llu is already allocated\n"), (unsigned long long)temp);
5061 if (!readed && start == temp) {
5064 saved_start = start;
5065 start = read_int(cround(saved_start), cround(saved_start), cround(limit),
5067 if (display_in_cyl_units) {
5068 start = (start - 1) * units_per_sector;
5069 if (start < saved_start) start = saved_start;
5073 } while (start != temp || !readed);
5074 if (n > 4) { /* NOT for fifth partition */
5075 struct pte *pe = &ptes[n];
5077 pe->offset = start - sector_offset;
5078 if (pe->offset == extended_offset) { /* must be corrected */
5080 if (sector_offset == 1)
5085 for (i = 0; i < partitions; i++) {
5086 struct pte *pe = &ptes[i];
5088 if (start < pe->offset && limit >= pe->offset)
5089 limit = pe->offset - 1;
5090 if (start < first[i] && limit >= first[i])
5091 limit = first[i] - 1;
5093 if (start > limit) {
5094 printf(_("No free sectors available\n"));
5099 if (cround(start) == cround(limit)) {
5102 snprintf(mesg, sizeof(mesg),
5103 _("Last %s or +size or +sizeM or +sizeK"),
5104 str_units(SINGULAR));
5105 stop = read_int(cround(start), cround(limit), cround(limit),
5106 cround(start), mesg);
5107 if (display_in_cyl_units) {
5108 stop = stop * units_per_sector - 1;
5114 set_partition(n, 0, start, stop, sys);
5116 set_partition(n - 1, 1, ptes[n].offset, stop, EXTENDED);
5118 if (IS_EXTENDED (sys)) {
5119 struct pte *pe4 = &ptes[4];
5120 struct pte *pen = &ptes[n];
5123 pen->ext_pointer = p;
5124 pe4->offset = extended_offset = start;
5125 pe4->sectorbuffer = xcalloc(1, sector_size);
5126 pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
5127 pe4->ext_pointer = pe4->part_table + 1;
5135 if (partitions > 5 || ptes[4].part_table->sys_ind) {
5136 struct pte *pe = &ptes[partitions];
5138 pe->sectorbuffer = xcalloc(1, sector_size);
5139 pe->part_table = pt_offset(pe->sectorbuffer, 0);
5140 pe->ext_pointer = pe->part_table + 1;
5145 add_partition(partitions - 1, LINUX_NATIVE);
5149 new_partition(void) {
5150 int i, free_primary = 0;
5152 if (warn_geometry())
5155 #ifdef CONFIG_FEATURE_SUN_LABEL
5157 add_sun_partition(get_partition(0, partitions), LINUX_NATIVE);
5161 #ifdef CONFIG_FEATURE_SGI_LABEL
5163 sgi_add_partition(get_partition(0, partitions), LINUX_NATIVE);
5167 #ifdef CONFIG_FEATURE_AIX_LABEL
5169 printf(_("\tSorry - this fdisk cannot handle AIX disk labels."
5170 "\n\tIf you want to add DOS-type partitions, create"
5171 "\n\ta new empty DOS partition table first. (Use o.)"
5173 "This will destroy the present disk contents.\n"));
5178 for (i = 0; i < 4; i++)
5179 free_primary += !ptes[i].part_table->sys_ind;
5181 if (!free_primary && partitions >= MAXIMUM_PARTS) {
5182 printf(_("The maximum number of partitions has been created\n"));
5186 if (!free_primary) {
5187 if (extended_offset)
5190 printf(_("You must delete some partition and add "
5191 "an extended partition first\n"));
5193 char c, line[LINE_LENGTH];
5194 snprintf(line, sizeof(line), "%s\n %s\n p primary "
5195 "partition (1-4)\n",
5196 "Command action", (extended_offset ?
5197 "l logical (5 or over)" : "e extended"));
5199 if ((c = read_char(line)) == 'p' || c == 'P') {
5200 i = get_nonexisting_partition(0, 4);
5202 add_partition(i, LINUX_NATIVE);
5205 else if (c == 'l' && extended_offset) {
5209 else if (c == 'e' && !extended_offset) {
5210 i = get_nonexisting_partition(0, 4);
5212 add_partition(i, EXTENDED);
5216 printf(_("Invalid partition number "
5217 "for type `%c'\n"), c);
5228 if (ptes[i].changed)
5229 ptes[3].changed = 1;
5230 for (i = 3; i < partitions; i++) {
5231 struct pte *pe = &ptes[i];
5234 write_part_table_flag(pe->sectorbuffer);
5235 write_sector(pe->offset, pe->sectorbuffer);
5239 #ifdef CONFIG_FEATURE_SGI_LABEL
5240 else if (sgi_label) {
5241 /* no test on change? the printf below might be mistaken */
5245 #ifdef CONFIG_FEATURE_SUN_LABEL
5246 else if (sun_label) {
5250 if (ptes[i].changed)
5257 printf(_("The partition table has been altered!\n\n"));
5258 reread_partition_table(1);
5262 reread_partition_table(int leave) {
5266 printf(_("Calling ioctl() to re-read partition table.\n"));
5269 if ((i = ioctl(fd, BLKRRPART)) != 0) {
5272 /* some kernel versions (1.2.x) seem to have trouble
5273 rereading the partition table, but if asked to do it
5274 twice, the second time works. - biro@yggdrasil.com */
5277 if ((i = ioctl(fd, BLKRRPART)) != 0)
5282 printf(_("\nWARNING: Re-reading the partition table "
5283 "failed with error %d: %s.\n"
5284 "The kernel still uses the old table.\n"
5285 "The new table will be used "
5286 "at the next reboot.\n"),
5287 error, strerror(error));
5292 _("\nWARNING: If you have created or modified any DOS 6.x\n"
5293 "partitions, please see the fdisk manual page for additional\n"
5299 printf(_("Syncing disks.\n"));
5301 sleep(4); /* for sync() */
5305 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
5307 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
5308 #define MAX_PER_LINE 16
5310 print_buffer(char pbuffer[]) {
5314 for (i = 0, l = 0; i < sector_size; i++, l++) {
5316 printf("0x%03X:", i);
5317 printf(" %02X", (unsigned char) pbuffer[i]);
5318 if (l == MAX_PER_LINE - 1) {
5333 printf(_("Device: %s\n"), disk_device);
5334 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
5335 if (sun_label || sgi_label)
5336 print_buffer(MBRbuffer);
5339 for (i = 3; i < partitions; i++)
5340 print_buffer(ptes[i].sectorbuffer);
5345 struct pte *pe = &ptes[i];
5346 struct partition *p = pe->part_table;
5349 if (warn_geometry())
5351 if (!p->sys_ind || !get_nr_sects(p) || IS_EXTENDED (p->sys_ind)) {
5352 printf(_("Partition %d has no data area\n"), i + 1);
5355 first = get_partition_start(pe);
5356 new = read_int(first, first, first + get_nr_sects(p) - 1, first,
5357 _("New beginning of data")) - pe->offset;
5359 if (new != get_nr_sects(p)) {
5360 first = get_nr_sects(p) + get_start_sect(p) - new;
5361 set_nr_sects(p, first);
5362 set_start_sect(p, new);
5373 c = tolower(read_char(_("Expert command (m for help): ")));
5376 #ifdef CONFIG_FEATURE_SUN_LABEL
5383 move_begin(get_partition(0, partitions));
5386 user_cylinders = cylinders =
5387 read_int(1, cylinders, 1048576, 0,
5388 _("Number of cylinders"));
5389 #ifdef CONFIG_FEATURE_SUN_LABEL
5391 sun_set_ncyl(cylinders);
5400 #ifdef CONFIG_FEATURE_SGI_LABEL
5405 #ifdef CONFIG_FEATURE_SUN_LABEL
5415 fix_partition_table_order();
5418 #ifdef CONFIG_FEATURE_SGI_LABEL
5423 user_heads = heads = read_int(1, heads, 256, 0,
5424 _("Number of heads"));
5428 #ifdef CONFIG_FEATURE_SUN_LABEL
5434 #ifdef CONFIG_FEATURE_SUN_LABEL
5440 #ifdef CONFIG_FEATURE_SUN_LABEL
5454 user_sectors = sectors = read_int(1, sectors, 63, 0,
5455 _("Number of sectors"));
5456 if (dos_compatible_flag) {
5457 sector_offset = sectors;
5458 fprintf(stderr, _("Warning: setting "
5459 "sector offset for DOS "
5468 write_table(); /* does not return */
5471 #ifdef CONFIG_FEATURE_SUN_LABEL
5473 sun_set_pcylcount();
5481 #endif /* ADVANCED mode */
5484 is_ide_cdrom_or_tape(const char *device) {
5487 struct stat statbuf;
5490 /* No device was given explicitly, and we are trying some
5491 likely things. But opening /dev/hdc may produce errors like
5492 "hdc: tray open or drive not ready"
5493 if it happens to be a CD-ROM drive. It even happens that
5494 the process hangs on the attempt to read a music CD.
5495 So try to be careful. This only works since 2.1.73. */
5497 if (strncmp("/dev/hd", device, 7))
5500 snprintf(buf, sizeof(buf), "/proc/ide/%s/media", device+5);
5501 procf = fopen(buf, "r");
5502 if (procf != NULL && fgets(buf, sizeof(buf), procf))
5503 is_ide = (!strncmp(buf, "cdrom", 5) ||
5504 !strncmp(buf, "tape", 4));
5506 /* Now when this proc file does not exist, skip the
5507 device when it is read-only. */
5508 if (stat(device, &statbuf) == 0)
5509 is_ide = ((statbuf.st_mode & 0222) == 0);
5517 try(const char *device, int user_specified) {
5520 disk_device = device;
5521 if (setjmp(listingbuf))
5523 if (!user_specified)
5524 if (is_ide_cdrom_or_tape(device))
5526 if ((fd = open(disk_device, type_open)) >= 0) {
5527 gb = get_boot(try_only);
5528 if (gb > 0) { /* I/O error */
5530 } else if (gb < 0) { /* no DOS signature */
5531 list_disk_geometry();
5534 #ifdef CONFIG_FEATURE_OSF_LABEL
5535 if (btrydev(device) < 0)
5538 _("Disk %s doesn't contain a valid "
5539 "partition table\n"), device);
5544 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5545 if (!sun_label && partitions > 4)
5546 delete_partition(ext_index);
5550 /* Ignore other errors, since we try IDE
5551 and SCSI hard disks which may not be
5552 installed on the system. */
5553 if (errno == EACCES) {
5554 fprintf(stderr, _("Cannot open %s\n"), device);
5560 /* for fdisk -l: try all things in /proc/partitions
5561 that look like a partition name (do not end in a digit) */
5565 char line[100], ptname[100], devname[120], *s;
5568 procpt = bb_wfopen(PROC_PARTITIONS, "r");
5570 while (fgets(line, sizeof(line), procpt)) {
5571 if (sscanf (line, " %d %d %d %[^\n ]",
5572 &ma, &mi, &sz, ptname) != 4)
5574 for (s = ptname; *s; s++);
5577 sprintf(devname, "/dev/%s", ptname);
5580 #ifdef CONFIG_FEATURE_CLEAN_UP
5585 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5587 unknown_command(int c) {
5588 printf(_("%c: unknown command\n"), c);
5592 int fdisk_main(int argc, char **argv) {
5594 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5597 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5603 * fdisk -l [-b sectorsize] [-u] device ...
5604 * fdisk -s [partition] ...
5605 * fdisk [-b sectorsize] [-u] device
5607 * Options -C, -H, -S set the geometry.
5610 while ((c = getopt(argc, argv, "b:C:H:lS:uvV"
5611 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5617 /* Ugly: this sector size is really per device,
5618 so cannot be combined with multiple disks,
5619 and te same goes for the C/H/S options.
5621 sector_size = atoi(optarg);
5622 if (sector_size != 512 && sector_size != 1024 &&
5623 sector_size != 2048)
5626 user_set_sector_size = 1;
5629 user_cylinders = atoi(optarg);
5632 user_heads = atoi(optarg);
5633 if (user_heads <= 0 || user_heads >= 256)
5637 user_sectors = atoi(optarg);
5638 if (user_sectors <= 0 || user_sectors >= 64)
5642 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5646 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5652 display_in_cyl_units = 0;
5656 printf("fdisk v" UTIL_LINUX_VERSION "\n");
5664 printf(_("This kernel finds the sector size itself - "
5665 "-b option ignored\n"));
5667 if (user_set_sector_size && argc-optind != 1)
5668 printf(_("Warning: the -b (set sector size) option should"
5669 " be used with one specified device\n"));
5672 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5676 type_open = O_RDONLY;
5677 if (argc > optind) {
5680 /* avoid gcc warning:
5681 variable `k' might be clobbered by `longjmp' */
5685 for (k=optind; k<argc; k++)
5688 /* we no longer have default device names */
5689 /* but, we can use /proc/partitions instead */
5693 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5697 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5703 type_open = O_RDONLY;
5705 opts = argc - optind;
5709 for (j = optind; j < argc; j++) {
5710 disk_device = argv[j];
5711 if ((fd = open(disk_device, type_open)) < 0)
5712 fdisk_fatal(unable_to_open);
5713 if (ioctl(fd, BLKGETSIZE, &size))
5714 fdisk_fatal(ioctl_error);
5717 printf("%ld\n", size/2);
5719 printf("%s: %ld\n", argv[j], size/2);
5725 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5726 if (argc-optind == 1)
5727 disk_device = argv[optind];
5733 #ifdef CONFIG_FEATURE_OSF_LABEL
5735 /* OSF label, and no DOS label */
5736 printf(_("Detected an OSF/1 disklabel on %s, entering "
5737 "disklabel mode.\n"),
5741 /* If we return we may want to make an empty DOS label? */
5747 c = tolower(read_char(_("Command (m for help): ")));
5751 toggle_active(get_partition(1, partitions));
5752 #ifdef CONFIG_FEATURE_SUN_LABEL
5754 toggle_sunflags(get_partition(1, partitions),
5757 #ifdef CONFIG_FEATURE_SGI_LABEL
5759 sgi_set_bootpartition(
5760 get_partition(1, partitions));
5766 #ifdef CONFIG_FEATURE_SGI_LABEL
5768 printf(_("\nThe current boot file is: %s\n"),
5769 sgi_get_bootfile());
5770 if (read_chars(_("Please enter the name of the "
5771 "new boot file: ")) == '\n')
5772 printf(_("Boot file unchanged\n"));
5774 sgi_set_bootfile(line_ptr);
5777 #ifdef CONFIG_FEATURE_OSF_LABEL
5783 toggle_dos_compatibility_flag();
5784 #ifdef CONFIG_FEATURE_SUN_LABEL
5786 toggle_sunflags(get_partition(1, partitions),
5789 #ifdef CONFIG_FEATURE_SGI_LABEL
5791 sgi_set_swappartition(
5792 get_partition(1, partitions));
5800 #ifdef CONFIG_FEATURE_SGI_LABEL
5801 /* If sgi_label then don't use get_existing_partition,
5802 let the user select a partition, since
5803 get_existing_partition() only works for Linux-like
5806 j = get_existing_partition(1, partitions);
5808 j = get_partition(1, partitions);
5811 j = get_existing_partition(1, partitions);
5814 delete_partition(j);
5818 #ifdef CONFIG_FEATURE_SGI_LABEL
5825 list_types(get_sys_types());
5844 #ifdef CONFIG_FEATURE_SUN_LABEL
5858 write_table(); /* does not return */
5860 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
5862 #ifdef CONFIG_FEATURE_SGI_LABEL
5865 _("\n\tSorry, no experts menu for SGI "
5866 "partition tables available.\n\n"));
5879 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */