1 /* fdisk.c -- Partition table manipulator for Linux.
3 * Copyright (C) 1992 A. V. Le Blanc (LeBlanc@mcc.ac.uk)
4 * Copyright (C) 2001,2002 Vladimir Oleynik <dzo@simtreas.ru> (Busybox port)
6 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
9 #define UTIL_LINUX_VERSION "2.12"
11 #define PROC_PARTITIONS "/proc/partitions"
14 #include <sys/types.h>
15 #include <sys/stat.h> /* stat */
24 #include <assert.h> /* assert */
27 #include <sys/ioctl.h>
28 #include <sys/param.h>
29 #include <sys/sysmacros.h> /* major */
31 #include <stdint.h> /* for uint32_t, uint16_t, uint8_t, int16_t, etc */
33 /* Copied from linux/major.h */
34 #define FLOPPY_MAJOR 2
36 #include <sys/utsname.h>
40 #define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r))
44 #define BLKRRPART _IO(0x12,95) /* re-read partition table */
45 #define BLKGETSIZE _IO(0x12,96) /* return device size */
46 #define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */
47 #define BLKSSZGET _IO(0x12,104) /* get block device sector size */
49 /* Avoid conflicts with the 2.6 kernel headers, which define
50 * _IOR rather differently */
52 #define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size))
53 #define BLKGETSIZE64 _IOR(0x12,114,uint64_t)
59 #define DEFAULT_SECTOR_SIZE 512
60 #define MAX_SECTOR_SIZE 2048
61 #define SECTOR_SIZE 512 /* still used in BSD code */
62 #define MAXIMUM_PARTS 60
64 #define ACTIVE_FLAG 0x80
67 #define WIN98_EXTENDED 0x0f
68 #define LINUX_PARTITION 0x81
69 #define LINUX_SWAP 0x82
70 #define LINUX_NATIVE 0x83
71 #define LINUX_EXTENDED 0x85
72 #define LINUX_LVM 0x8e
73 #define LINUX_RAID 0xfd
78 #define IS_EXTENDED(i) \
79 ((i) == EXTENDED || (i) == WIN98_EXTENDED || (i) == LINUX_EXTENDED)
81 #define SIZE(a) (sizeof(a)/sizeof((a)[0]))
83 #define cround(n) (display_in_cyl_units ? ((n)/units_per_sector)+1 : (n))
84 #define scround(x) (((x)+units_per_sector-1)/units_per_sector)
86 #ifdef CONFIG_FEATURE_SUN_LABEL
87 #define SCSI_IOCTL_GET_IDLUN 0x5382
91 /* including <linux/hdreg.h> also fails */
94 unsigned char sectors;
95 unsigned short cylinders;
99 #define HDIO_GETGEO 0x0301 /* get device geometry */
106 static uint sector_size = DEFAULT_SECTOR_SIZE;
107 static uint user_set_sector_size;
108 static uint sector_offset = 1;
111 * Raw disk label. For DOS-type partition tables the MBR,
112 * with descriptions of the primary partitions.
114 #if (MAX_SECTOR_SIZE) > (BUFSIZ+1)
115 static char MBRbuffer[MAX_SECTOR_SIZE];
117 # define MBRbuffer bb_common_bufsiz1
120 #ifdef CONFIG_FEATURE_SUN_LABEL
121 static int sun_label; /* looking at sun disklabel */
125 #ifdef CONFIG_FEATURE_SGI_LABEL
126 static int sgi_label; /* looking at sgi disklabel */
130 #ifdef CONFIG_FEATURE_AIX_LABEL
131 static int aix_label; /* looking at aix disklabel */
135 #ifdef CONFIG_FEATURE_OSF_LABEL
136 static int osf_label; /* looking at OSF/1 disklabel */
137 static int possibly_osf_label;
142 #define dos_label (!sun_label && !sgi_label && !aix_label && !osf_label)
144 static uint heads, sectors, cylinders;
145 static void update_units(void);
149 * return partition name - uses static storage unless buf is supplied
152 partname(const char *dev, int pno, int lth)
154 static char buffer[80];
161 bufsiz = sizeof(buffer);
166 if (isdigit(dev[w-1]))
169 /* devfs kludge - note: fdisk partition names are not supposed
170 to equal kernel names, so there is no reason to do this */
171 if (strcmp(dev + w - 4, "disc") == 0) {
179 snprintf(bufp, bufsiz, "%*.*s%s%-2u",
180 lth-wp-2, w, dev, p, pno);
182 snprintf(bufp, bufsiz, "%.*s%s%-2u", w, dev, p, pno);
188 unsigned char boot_ind; /* 0x80 - active */
189 unsigned char head; /* starting head */
190 unsigned char sector; /* starting sector */
191 unsigned char cyl; /* starting cylinder */
192 unsigned char sys_ind; /* What partition type */
193 unsigned char end_head; /* end head */
194 unsigned char end_sector; /* end sector */
195 unsigned char end_cyl; /* end cylinder */
196 unsigned char start4[4]; /* starting sector counting from 0 */
197 unsigned char size4[4]; /* nr of sectors in partition */
201 ioctl_error, unable_to_open, unable_to_read, unable_to_seek,
205 enum action { fdisk, require, try_only, create_empty_dos, create_empty_sun };
207 static const char *disk_device;
208 static int fd; /* the disk */
209 static int partitions = 4; /* maximum partition + 1 */
210 static uint display_in_cyl_units = 1;
211 static uint units_per_sector = 1;
212 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
213 static char *line_ptr;
214 static void change_units(void);
215 static void reread_partition_table(int leave);
216 static void delete_partition(int i);
217 static int get_partition(int warn, int max);
218 static void list_types(const struct systypes *sys);
219 static uint read_int(uint low, uint dflt, uint high, uint base, char *mesg);
221 static const char *partition_type(unsigned char type);
222 static void fdisk_fatal(enum failure why) ATTRIBUTE_NORETURN;
223 static void get_geometry(void);
224 static int get_boot(enum action what);
229 #define hex_val(c) ({ \
231 isdigit(_c) ? _c - '0' : \
232 tolower(_c) + 10 - 'a'; \
236 #define LINE_LENGTH 800
237 #define pt_offset(b, n) ((struct partition *)((b) + 0x1be + \
238 (n) * sizeof(struct partition)))
239 #define sector(s) ((s) & 0x3f)
240 #define cylinder(s, c) ((c) | (((s) & 0xc0) << 2))
242 #define hsc2sector(h,s,c) (sector(s) - 1 + sectors * \
243 ((h) + heads * cylinder(s,c)))
244 #define set_hsc(h,s,c,sector) { \
245 s = sector % sectors + 1; \
247 h = sector % heads; \
250 s |= (sector >> 2) & 0xc0; \
254 static int32_t get_start_sect(const struct partition *p);
255 static int32_t get_nr_sects(const struct partition *p);
258 * per partition table entry data
260 * The four primary partitions have the same sectorbuffer (MBRbuffer)
261 * and have NULL ext_pointer.
262 * Each logical partition table entry has two pointers, one for the
263 * partition and one link to the next one.
266 struct partition *part_table; /* points into sectorbuffer */
267 struct partition *ext_pointer; /* points into sectorbuffer */
268 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
269 char changed; /* boolean */
271 off_t offset; /* disk sector number */
272 char *sectorbuffer; /* disk sector contents */
273 } ptes[MAXIMUM_PARTS];
276 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
278 set_all_unchanged(void)
282 for (i = 0; i < MAXIMUM_PARTS; i++)
291 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
293 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_OSF_LABEL)
294 static struct partition *
295 get_part_table(int i)
297 return ptes[i].part_table;
303 { /* n==1: use singular */
305 return display_in_cyl_units ? _("cylinder") : _("sector");
307 return display_in_cyl_units ? _("cylinders") : _("sectors");
311 valid_part_table_flag(const char *mbuffer) {
312 const unsigned char *b = (const unsigned char *)mbuffer;
313 return (b[510] == 0x55 && b[511] == 0xaa);
316 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
317 static char line_buffer[LINE_LENGTH];
319 /* read line; return 0 or first char */
323 static int got_eof = 0;
325 fflush (stdout); /* requested by niles@scyld.com */
326 line_ptr = line_buffer;
327 if (!fgets(line_buffer, LINE_LENGTH, stdin)) {
329 got_eof++; /* user typed ^D ? */
331 fprintf(stderr, _("\ngot EOF thrice - exiting..\n"));
336 while (*line_ptr && !isgraph(*line_ptr))
342 read_char(const char *mesg)
346 } while (!read_line());
351 read_chars(const char *mesg)
362 read_hex(const struct systypes *sys)
367 read_char(_("Hex code (type L to list codes): "));
368 if (*line_ptr == 'l' || *line_ptr == 'L')
370 else if (isxdigit (*line_ptr)) {
373 hex = hex << 4 | hex_val(*line_ptr++);
374 while (isxdigit(*line_ptr));
379 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
381 #ifdef CONFIG_FEATURE_AIX_LABEL
383 * Copyright (C) Andreas Neuper, Sep 1998.
384 * This file may be redistributed under
385 * the terms of the GNU Public License.
389 unsigned int magic; /* expect AIX_LABEL_MAGIC */
390 unsigned int fillbytes1[124];
391 unsigned int physical_volume_id;
392 unsigned int fillbytes2[124];
395 #define AIX_LABEL_MAGIC 0xc9c2d4c1
396 #define AIX_LABEL_MAGIC_SWAPPED 0xc1d4c2c9
397 #define AIX_INFO_MAGIC 0x00072959
398 #define AIX_INFO_MAGIC_SWAPPED 0x59290700
400 #define aixlabel ((aix_partition *)MBRbuffer)
405 * 1999-03-20 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
406 * Internationalization
408 * 2003-03-20 Phillip Kesling <pkesling@sgi.com>
412 static int aix_other_endian;
413 static short aix_volumes = 1;
416 * only dealing with free blocks here
423 _("\n\tThere is a valid AIX label on this disk.\n"
424 "\tUnfortunately Linux cannot handle these\n"
425 "\tdisks at the moment. Nevertheless some\n"
427 "\t1. fdisk will destroy its contents on write.\n"
428 "\t2. Be sure that this disk is NOT a still vital\n"
429 "\t part of a volume group. (Otherwise you may\n"
430 "\t erase the other disks as well, if unmirrored.)\n"
431 "\t3. Before deleting this physical volume be sure\n"
432 "\t to remove the disk logically from your AIX\n"
433 "\t machine. (Otherwise you become an AIXpert).")
443 memset(MBRbuffer, 0, sizeof(MBRbuffer)); /* avoid fdisk cores */
448 check_aix_label(void)
450 if (aixlabel->magic != AIX_LABEL_MAGIC &&
451 aixlabel->magic != AIX_LABEL_MAGIC_SWAPPED) {
453 aix_other_endian = 0;
456 aix_other_endian = (aixlabel->magic == AIX_LABEL_MAGIC_SWAPPED);
462 aix_nolabel(); /* %% */
463 aix_label = 1; /* %% */
466 #endif /* AIX_LABEL */
468 #ifdef CONFIG_FEATURE_OSF_LABEL
470 * Copyright (c) 1987, 1988 Regents of the University of California.
471 * All rights reserved.
473 * Redistribution and use in source and binary forms, with or without
474 * modification, are permitted provided that the following conditions
476 * 1. Redistributions of source code must retain the above copyright
477 * notice, this list of conditions and the following disclaimer.
478 * 2. Redistributions in binary form must reproduce the above copyright
479 * notice, this list of conditions and the following disclaimer in the
480 * documentation and/or other materials provided with the distribution.
481 * 3. All advertising materials mentioning features or use of this software
482 * must display the following acknowledgment:
483 * This product includes software developed by the University of
484 * California, Berkeley and its contributors.
485 * 4. Neither the name of the University nor the names of its contributors
486 * may be used to endorse or promote products derived from this software
487 * without specific prior written permission.
489 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
490 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
491 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
492 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
493 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
494 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
495 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
496 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
497 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
498 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
503 #ifndef BSD_DISKMAGIC
504 #define BSD_DISKMAGIC ((uint32_t) 0x82564557)
507 #ifndef BSD_MAXPARTITIONS
508 #define BSD_MAXPARTITIONS 16
511 #define BSD_LINUX_BOOTDIR "/usr/ucb/mdec"
513 #if defined (i386) || defined (__sparc__) || defined (__arm__) || defined (__mips__) || defined (__s390__) || defined (__sh__) || defined(__x86_64__)
514 #define BSD_LABELSECTOR 1
515 #define BSD_LABELOFFSET 0
516 #elif defined (__alpha__) || defined (__powerpc__) || defined (__ia64__) || defined (__hppa__)
517 #define BSD_LABELSECTOR 0
518 #define BSD_LABELOFFSET 64
519 #elif defined (__s390__) || defined (__s390x__)
520 #define BSD_LABELSECTOR 1
521 #define BSD_LABELOFFSET 0
523 #error unknown architecture
526 #define BSD_BBSIZE 8192 /* size of boot area, with label */
527 #define BSD_SBSIZE 8192 /* max size of fs superblock */
529 struct xbsd_disklabel {
530 uint32_t d_magic; /* the magic number */
531 int16_t d_type; /* drive type */
532 int16_t d_subtype; /* controller/d_type specific */
533 char d_typename[16]; /* type name, e.g. "eagle" */
534 char d_packname[16]; /* pack identifier */
536 uint32_t d_secsize; /* # of bytes per sector */
537 uint32_t d_nsectors; /* # of data sectors per track */
538 uint32_t d_ntracks; /* # of tracks per cylinder */
539 uint32_t d_ncylinders; /* # of data cylinders per unit */
540 uint32_t d_secpercyl; /* # of data sectors per cylinder */
541 uint32_t d_secperunit; /* # of data sectors per unit */
543 * Spares (bad sector replacements) below
544 * are not counted in d_nsectors or d_secpercyl.
545 * Spare sectors are assumed to be physical sectors
546 * which occupy space at the end of each track and/or cylinder.
548 uint16_t d_sparespertrack; /* # of spare sectors per track */
549 uint16_t d_sparespercyl; /* # of spare sectors per cylinder */
551 * Alternate cylinders include maintenance, replacement,
552 * configuration description areas, etc.
554 uint32_t d_acylinders; /* # of alt. cylinders per unit */
556 /* hardware characteristics: */
558 * d_interleave, d_trackskew and d_cylskew describe perturbations
559 * in the media format used to compensate for a slow controller.
560 * Interleave is physical sector interleave, set up by the formatter
561 * or controller when formatting. When interleaving is in use,
562 * logically adjacent sectors are not physically contiguous,
563 * but instead are separated by some number of sectors.
564 * It is specified as the ratio of physical sectors traversed
565 * per logical sector. Thus an interleave of 1:1 implies contiguous
566 * layout, while 2:1 implies that logical sector 0 is separated
567 * by one sector from logical sector 1.
568 * d_trackskew is the offset of sector 0 on track N
569 * relative to sector 0 on track N-1 on the same cylinder.
570 * Finally, d_cylskew is the offset of sector 0 on cylinder N
571 * relative to sector 0 on cylinder N-1.
573 uint16_t d_rpm; /* rotational speed */
574 uint16_t d_interleave; /* hardware sector interleave */
575 uint16_t d_trackskew; /* sector 0 skew, per track */
576 uint16_t d_cylskew; /* sector 0 skew, per cylinder */
577 uint32_t d_headswitch; /* head switch time, usec */
578 uint32_t d_trkseek; /* track-to-track seek, usec */
579 uint32_t d_flags; /* generic flags */
581 uint32_t d_drivedata[NDDATA]; /* drive-type specific information */
583 uint32_t d_spare[NSPARE]; /* reserved for future use */
584 uint32_t d_magic2; /* the magic number (again) */
585 uint16_t d_checksum; /* xor of data incl. partitions */
586 /* filesystem and partition information: */
587 uint16_t d_npartitions; /* number of partitions in following */
588 uint32_t d_bbsize; /* size of boot area at sn0, bytes */
589 uint32_t d_sbsize; /* max size of fs superblock, bytes */
590 struct xbsd_partition { /* the partition table */
591 uint32_t p_size; /* number of sectors in partition */
592 uint32_t p_offset; /* starting sector */
593 uint32_t p_fsize; /* filesystem basic fragment size */
594 uint8_t p_fstype; /* filesystem type, see below */
595 uint8_t p_frag; /* filesystem fragments per block */
596 uint16_t p_cpg; /* filesystem cylinders per group */
597 } d_partitions[BSD_MAXPARTITIONS]; /* actually may be more */
601 #define BSD_DTYPE_SMD 1 /* SMD, XSMD; VAX hp/up */
602 #define BSD_DTYPE_MSCP 2 /* MSCP */
603 #define BSD_DTYPE_DEC 3 /* other DEC (rk, rl) */
604 #define BSD_DTYPE_SCSI 4 /* SCSI */
605 #define BSD_DTYPE_ESDI 5 /* ESDI interface */
606 #define BSD_DTYPE_ST506 6 /* ST506 etc. */
607 #define BSD_DTYPE_HPIB 7 /* CS/80 on HP-IB */
608 #define BSD_DTYPE_HPFL 8 /* HP Fiber-link */
609 #define BSD_DTYPE_FLOPPY 10 /* floppy */
611 /* d_subtype values: */
612 #define BSD_DSTYPE_INDOSPART 0x8 /* is inside dos partition */
613 #define BSD_DSTYPE_DOSPART(s) ((s) & 3) /* dos partition number */
614 #define BSD_DSTYPE_GEOMETRY 0x10 /* drive params in label */
617 static const char * const xbsd_dktypenames[] = {
631 #define BSD_DKMAXTYPES (sizeof(xbsd_dktypenames) / sizeof(xbsd_dktypenames[0]) - 1)
635 * Filesystem type and version.
636 * Used to interpret other filesystem-specific
637 * per-partition information.
639 #define BSD_FS_UNUSED 0 /* unused */
640 #define BSD_FS_SWAP 1 /* swap */
641 #define BSD_FS_V6 2 /* Sixth Edition */
642 #define BSD_FS_V7 3 /* Seventh Edition */
643 #define BSD_FS_SYSV 4 /* System V */
644 #define BSD_FS_V71K 5 /* V7 with 1K blocks (4.1, 2.9) */
645 #define BSD_FS_V8 6 /* Eighth Edition, 4K blocks */
646 #define BSD_FS_BSDFFS 7 /* 4.2BSD fast file system */
647 #define BSD_FS_BSDLFS 9 /* 4.4BSD log-structured file system */
648 #define BSD_FS_OTHER 10 /* in use, but unknown/unsupported */
649 #define BSD_FS_HPFS 11 /* OS/2 high-performance file system */
650 #define BSD_FS_ISO9660 12 /* ISO-9660 filesystem (cdrom) */
651 #define BSD_FS_ISOFS BSD_FS_ISO9660
652 #define BSD_FS_BOOT 13 /* partition contains bootstrap */
653 #define BSD_FS_ADOS 14 /* AmigaDOS fast file system */
654 #define BSD_FS_HFS 15 /* Macintosh HFS */
655 #define BSD_FS_ADVFS 16 /* Digital Unix AdvFS */
657 /* this is annoying, but it's also the way it is :-( */
659 #define BSD_FS_EXT2 8 /* ext2 file system */
661 #define BSD_FS_MSDOS 8 /* MS-DOS file system */
665 static const struct systypes xbsd_fstypes[] = {
666 { "\x00" "unused" }, /* BSD_FS_UNUSED */
667 { "\x01" "swap" }, /* BSD_FS_SWAP */
668 { "\x02" "Version 6" }, /* BSD_FS_V6 */
669 { "\x03" "Version 7" }, /* BSD_FS_V7 */
670 { "\x04" "System V" }, /* BSD_FS_SYSV */
671 { "\x05" "4.1BSD" }, /* BSD_FS_V71K */
672 { "\x06" "Eighth Edition" }, /* BSD_FS_V8 */
673 { "\x07" "4.2BSD" }, /* BSD_FS_BSDFFS */
675 { "\x08" "ext2" }, /* BSD_FS_EXT2 */
677 { "\x08" "MS-DOS" }, /* BSD_FS_MSDOS */
679 { "\x09" "4.4LFS" }, /* BSD_FS_BSDLFS */
680 { "\x0a" "unknown" }, /* BSD_FS_OTHER */
681 { "\x0b" "HPFS" }, /* BSD_FS_HPFS */
682 { "\x0c" "ISO-9660" }, /* BSD_FS_ISO9660 */
683 { "\x0d" "boot" }, /* BSD_FS_BOOT */
684 { "\x0e" "ADOS" }, /* BSD_FS_ADOS */
685 { "\x0f" "HFS" }, /* BSD_FS_HFS */
686 { "\x10" "AdvFS" }, /* BSD_FS_ADVFS */
689 #define BSD_FSMAXTYPES (SIZE(xbsd_fstypes)-1)
694 * flags shared by various drives:
696 #define BSD_D_REMOVABLE 0x01 /* removable media */
697 #define BSD_D_ECC 0x02 /* supports ECC */
698 #define BSD_D_BADSECT 0x04 /* supports bad sector forw. */
699 #define BSD_D_RAMDISK 0x08 /* disk emulator */
700 #define BSD_D_CHAIN 0x10 /* can do back-back transfers */
701 #define BSD_D_DOSPART 0x20 /* within MSDOS partition */
703 #endif /* OSF_LABEL */
706 * Copyright (C) Andreas Neuper, Sep 1998.
707 * This file may be modified and redistributed under
708 * the terms of the GNU Public License.
711 struct device_parameter { /* 48 bytes */
715 unsigned char sparecyl;
716 unsigned short pcylcount;
717 unsigned short head_vol0;
718 unsigned short ntrks; /* tracks in cyl 0 or vol 0 */
719 unsigned char cmd_tag_queue_depth;
720 unsigned char unused0;
721 unsigned short unused1;
722 unsigned short nsect; /* sectors/tracks in cyl 0 or vol 0 */
723 unsigned short bytes;
724 unsigned short ilfact;
725 unsigned int flags; /* controller flags */
726 unsigned int datarate;
727 unsigned int retries_on_error;
728 unsigned int ms_per_word;
729 unsigned short xylogics_gap1;
730 unsigned short xylogics_syncdelay;
731 unsigned short xylogics_readdelay;
732 unsigned short xylogics_gap2;
733 unsigned short xylogics_readgate;
734 unsigned short xylogics_writecont;
737 #define SGI_VOLHDR 0x00
738 /* 1 and 2 were used for drive types no longer supported by SGI */
739 #define SGI_SWAP 0x03
740 /* 4 and 5 were for filesystem types SGI haven't ever supported on MIPS CPUs */
741 #define SGI_VOLUME 0x06
743 #define SGI_LVOL 0x08
744 #define SGI_RLVOL 0x09
746 #define SGI_XFSLOG 0x0b
749 #define ENTIRE_DISK SGI_VOLUME
753 #define SECTOR_SLIP 0x01
754 #define SECTOR_FWD 0x02
755 #define TRACK_FWD 0x04
756 #define TRACK_MULTIVOL 0x08
757 #define IGNORE_ERRORS 0x10
759 #define ENABLE_CMDTAGQ 0x40
762 unsigned int magic; /* expect SGI_LABEL_MAGIC */
763 unsigned short boot_part; /* active boot partition */
764 unsigned short swap_part; /* active swap partition */
765 unsigned char boot_file[16]; /* name of the bootfile */
766 struct device_parameter devparam; /* 1 * 48 bytes */
767 struct volume_directory { /* 15 * 16 bytes */
768 unsigned char vol_file_name[8]; /* a character array */
769 unsigned int vol_file_start; /* number of logical block */
770 unsigned int vol_file_size; /* number of bytes */
772 struct sgi_partition { /* 16 * 12 bytes */
773 unsigned int num_sectors; /* number of blocks */
774 unsigned int start_sector; /* must be cylinder aligned */
778 unsigned int fillbytes;
782 unsigned int magic; /* looks like a magic number */
791 unsigned char scsi_string[50];
792 unsigned char serial[137];
793 unsigned short check1816;
794 unsigned char installer[225];
797 #define SGI_LABEL_MAGIC 0x0be5a941
798 #define SGI_LABEL_MAGIC_SWAPPED 0x41a9e50b
799 #define SGI_INFO_MAGIC 0x00072959
800 #define SGI_INFO_MAGIC_SWAPPED 0x59290700
801 #define SGI_SSWAP16(x) (sgi_other_endian ? __swap16(x) \
803 #define SGI_SSWAP32(x) (sgi_other_endian ? __swap32(x) \
806 #define sgilabel ((sgi_partition *)MBRbuffer)
807 #define sgiparam (sgilabel->devparam)
810 unsigned char info[128]; /* Informative text string */
811 unsigned char spare0[14];
813 unsigned char spare1;
815 unsigned char spare2;
818 unsigned char spare1[246]; /* Boot information etc. */
819 unsigned short rspeed; /* Disk rotational speed */
820 unsigned short pcylcount; /* Physical cylinder count */
821 unsigned short sparecyl; /* extra sects per cylinder */
822 unsigned char spare2[4]; /* More magic... */
823 unsigned short ilfact; /* Interleave factor */
824 unsigned short ncyl; /* Data cylinder count */
825 unsigned short nacyl; /* Alt. cylinder count */
826 unsigned short ntrks; /* Tracks per cylinder */
827 unsigned short nsect; /* Sectors per track */
828 unsigned char spare3[4]; /* Even more magic... */
829 struct sun_partition {
830 uint32_t start_cylinder;
831 uint32_t num_sectors;
833 unsigned short magic; /* Magic number */
834 unsigned short csum; /* Label xor'd checksum */
838 #define SUN_LABEL_MAGIC 0xDABE
839 #define SUN_LABEL_MAGIC_SWAPPED 0xBEDA
840 #define sunlabel ((sun_partition *)MBRbuffer)
841 #define SUN_SSWAP16(x) (sun_other_endian ? __swap16(x) \
843 #define SUN_SSWAP32(x) (sun_other_endian ? __swap32(x) \
847 #ifdef CONFIG_FEATURE_OSF_LABEL
850 19990319 - Arnaldo Carvalho de Melo <acme@conectiva.com.br> - i18n/nls
852 20000101 - David Huggins-Daines <dhuggins@linuxcare.com> - Better
853 support for OSF/1 disklabels on Alpha.
854 Also fixed unaligned accesses in alpha_bootblock_checksum()
857 #define FREEBSD_PARTITION 0xa5
858 #define NETBSD_PARTITION 0xa9
860 static void xbsd_delete_part(void);
861 static void xbsd_new_part(void);
862 static void xbsd_write_disklabel(void);
863 static int xbsd_create_disklabel(void);
864 static void xbsd_edit_disklabel(void);
865 static void xbsd_write_bootstrap(void);
866 static void xbsd_change_fstype(void);
867 static int xbsd_get_part_index(int max);
868 static int xbsd_check_new_partition(int *i);
869 static void xbsd_list_types(void);
870 static u_short xbsd_dkcksum(struct xbsd_disklabel *lp);
871 static int xbsd_initlabel(struct partition *p, struct xbsd_disklabel *d);
872 static int xbsd_readlabel(struct partition *p, struct xbsd_disklabel *d);
873 static int xbsd_writelabel(struct partition *p, struct xbsd_disklabel *d);
875 #if defined (__alpha__)
876 static void alpha_bootblock_checksum(char *boot);
879 #if !defined (__alpha__)
880 static int xbsd_translate_fstype(int linux_type);
881 static void xbsd_link_part(void);
882 static struct partition *xbsd_part;
883 static int xbsd_part_index;
886 #if defined (__alpha__)
887 /* We access this through a uint64_t * when checksumming */
888 static char disklabelbuffer[BSD_BBSIZE] ATTRIBUTE_ALIGNED(8);
890 static char disklabelbuffer[BSD_BBSIZE];
893 static struct xbsd_disklabel xbsd_dlabel;
895 #define bsd_cround(n) \
896 (display_in_cyl_units ? ((n)/xbsd_dlabel.d_secpercyl) + 1 : (n))
899 * Test whether the whole disk has BSD disk label magic.
901 * Note: often reformatting with DOS-type label leaves the BSD magic,
902 * so this does not mean that there is a BSD disk label.
905 check_osf_label(void)
907 if (xbsd_readlabel(NULL, &xbsd_dlabel) == 0)
912 static void xbsd_print_disklabel(int);
915 btrydev(const char * dev)
917 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
919 printf(_("\nBSD label for device: %s\n"), dev);
920 xbsd_print_disklabel (0);
927 puts (_("Command action"));
928 puts (_("\td\tdelete a BSD partition"));
929 puts (_("\te\tedit drive data"));
930 puts (_("\ti\tinstall bootstrap"));
931 puts (_("\tl\tlist known filesystem types"));
932 puts (_("\tm\tprint this menu"));
933 puts (_("\tn\tadd a new BSD partition"));
934 puts (_("\tp\tprint BSD partition table"));
935 puts (_("\tq\tquit without saving changes"));
936 puts (_("\tr\treturn to main menu"));
937 puts (_("\ts\tshow complete disklabel"));
938 puts (_("\tt\tchange a partition's filesystem id"));
939 puts (_("\tu\tchange units (cylinders/sectors)"));
940 puts (_("\tw\twrite disklabel to disk"));
941 #if !defined (__alpha__)
942 puts (_("\tx\tlink BSD partition to non-BSD partition"));
946 #if !defined (__alpha__)
954 is_bsd_partition_type(int type)
956 return (type == FREEBSD_PARTITION ||
957 type == hidden(FREEBSD_PARTITION) ||
958 type == NETBSD_PARTITION ||
959 type == hidden(NETBSD_PARTITION));
966 #if !defined (__alpha__)
970 for (t = 0; t < 4; t++) {
971 p = get_part_table(t);
972 if (p && is_bsd_partition_type(p->sys_ind)) {
975 ss = get_start_sect(xbsd_part);
977 fprintf(stderr, _("Partition %s has invalid starting sector 0.\n"),
978 partname(disk_device, t+1, 0));
981 printf(_("Reading disklabel of %s at sector %d.\n"),
982 partname(disk_device, t+1, 0), ss + BSD_LABELSECTOR);
983 if (xbsd_readlabel(xbsd_part, &xbsd_dlabel) == 0)
984 if (xbsd_create_disklabel() == 0)
991 printf(_("There is no *BSD partition on %s.\n"), disk_device);
995 #elif defined (__alpha__)
997 if (xbsd_readlabel(NULL, &xbsd_dlabel) == 0)
998 if (xbsd_create_disklabel() == 0)
1005 switch (tolower(read_char(_("BSD disklabel command (m for help): ")))) {
1010 xbsd_edit_disklabel();
1013 xbsd_write_bootstrap();
1022 xbsd_print_disklabel(0);
1030 xbsd_print_disklabel(1);
1033 xbsd_change_fstype();
1039 xbsd_write_disklabel();
1041 #if !defined (__alpha__)
1054 xbsd_delete_part(void)
1058 i = xbsd_get_part_index(xbsd_dlabel.d_npartitions);
1059 xbsd_dlabel.d_partitions[i].p_size = 0;
1060 xbsd_dlabel.d_partitions[i].p_offset = 0;
1061 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
1062 if (xbsd_dlabel.d_npartitions == i + 1)
1063 while (xbsd_dlabel.d_partitions[xbsd_dlabel.d_npartitions-1].p_size == 0)
1064 xbsd_dlabel.d_npartitions--;
1074 if (!xbsd_check_new_partition(&i))
1077 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
1078 begin = get_start_sect(xbsd_part);
1079 end = begin + get_nr_sects(xbsd_part) - 1;
1082 end = xbsd_dlabel.d_secperunit - 1;
1085 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
1086 begin = read_int(bsd_cround(begin), bsd_cround(begin), bsd_cround(end),
1089 if (display_in_cyl_units)
1090 begin = (begin - 1) * xbsd_dlabel.d_secpercyl;
1092 snprintf(mesg, sizeof(mesg), _("Last %s or +size or +sizeM or +sizeK"),
1093 str_units(SINGULAR));
1094 end = read_int(bsd_cround (begin), bsd_cround (end), bsd_cround (end),
1095 bsd_cround (begin), mesg);
1097 if (display_in_cyl_units)
1098 end = end * xbsd_dlabel.d_secpercyl - 1;
1100 xbsd_dlabel.d_partitions[i].p_size = end - begin + 1;
1101 xbsd_dlabel.d_partitions[i].p_offset = begin;
1102 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
1106 xbsd_print_disklabel(int show_all)
1108 struct xbsd_disklabel *lp = &xbsd_dlabel;
1109 struct xbsd_partition *pp;
1113 #if defined (__alpha__)
1114 printf("# %s:\n", disk_device);
1116 printf("# %s:\n", partname(disk_device, xbsd_part_index+1, 0));
1118 if ((unsigned) lp->d_type < BSD_DKMAXTYPES)
1119 printf(_("type: %s\n"), xbsd_dktypenames[lp->d_type]);
1121 printf(_("type: %d\n"), lp->d_type);
1122 printf(_("disk: %.*s\n"), (int) sizeof(lp->d_typename), lp->d_typename);
1123 printf(_("label: %.*s\n"), (int) sizeof(lp->d_packname), lp->d_packname);
1124 printf(_("flags:"));
1125 if (lp->d_flags & BSD_D_REMOVABLE)
1126 printf(_(" removable"));
1127 if (lp->d_flags & BSD_D_ECC)
1129 if (lp->d_flags & BSD_D_BADSECT)
1130 printf(_(" badsect"));
1132 /* On various machines the fields of *lp are short/int/long */
1133 /* In order to avoid problems, we cast them all to long. */
1134 printf(_("bytes/sector: %ld\n"), (long) lp->d_secsize);
1135 printf(_("sectors/track: %ld\n"), (long) lp->d_nsectors);
1136 printf(_("tracks/cylinder: %ld\n"), (long) lp->d_ntracks);
1137 printf(_("sectors/cylinder: %ld\n"), (long) lp->d_secpercyl);
1138 printf(_("cylinders: %ld\n"), (long) lp->d_ncylinders);
1139 printf(_("rpm: %d\n"), lp->d_rpm);
1140 printf(_("interleave: %d\n"), lp->d_interleave);
1141 printf(_("trackskew: %d\n"), lp->d_trackskew);
1142 printf(_("cylinderskew: %d\n"), lp->d_cylskew);
1143 printf(_("headswitch: %ld\t\t# milliseconds\n"),
1144 (long) lp->d_headswitch);
1145 printf(_("track-to-track seek: %ld\t# milliseconds\n"),
1146 (long) lp->d_trkseek);
1147 printf(_("drivedata: "));
1148 for (i = NDDATA - 1; i >= 0; i--)
1149 if (lp->d_drivedata[i])
1153 for (j = 0; j <= i; j++)
1154 printf("%ld ", (long) lp->d_drivedata[j]);
1156 printf(_("\n%d partitions:\n"), lp->d_npartitions);
1157 printf(_("# start end size fstype [fsize bsize cpg]\n"));
1158 pp = lp->d_partitions;
1159 for (i = 0; i < lp->d_npartitions; i++, pp++) {
1161 if (display_in_cyl_units && lp->d_secpercyl) {
1162 printf(" %c: %8ld%c %8ld%c %8ld%c ",
1164 (long) pp->p_offset / lp->d_secpercyl + 1,
1165 (pp->p_offset % lp->d_secpercyl) ? '*' : ' ',
1166 (long) (pp->p_offset + pp->p_size + lp->d_secpercyl - 1) / lp->d_secpercyl,
1167 ((pp->p_offset + pp->p_size) % lp->d_secpercyl) ? '*' : ' ',
1168 (long) pp->p_size / lp->d_secpercyl,
1169 (pp->p_size % lp->d_secpercyl) ? '*' : ' '
1172 printf(" %c: %8ld %8ld %8ld ",
1174 (long) pp->p_offset,
1175 (long) pp->p_offset + pp->p_size - 1,
1180 if ((unsigned) pp->p_fstype < BSD_FSMAXTYPES)
1181 printf("%8.8s", xbsd_fstypes[pp->p_fstype].name);
1183 printf("%8x", pp->p_fstype);
1185 switch (pp->p_fstype) {
1187 printf(" %5ld %5ld %5.5s ",
1188 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, "");
1191 printf(" %5ld %5ld %5d ",
1192 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, pp->p_cpg);
1195 printf("%22.22s", "");
1204 xbsd_write_disklabel(void)
1206 #if defined (__alpha__)
1207 printf(_("Writing disklabel to %s.\n"), disk_device);
1208 xbsd_writelabel(NULL, &xbsd_dlabel);
1210 printf(_("Writing disklabel to %s.\n"),
1211 partname(disk_device, xbsd_part_index + 1, 0));
1212 xbsd_writelabel(xbsd_part, &xbsd_dlabel);
1214 reread_partition_table(0); /* no exit yet */
1218 xbsd_create_disklabel(void)
1222 #if defined (__alpha__)
1223 fprintf(stderr, _("%s contains no disklabel.\n"), disk_device);
1225 fprintf(stderr, _("%s contains no disklabel.\n"),
1226 partname(disk_device, xbsd_part_index + 1, 0));
1230 c = read_char(_("Do you want to create a disklabel? (y/n) "));
1231 if (c == 'y' || c == 'Y') {
1233 #if defined (__alpha__) || defined (__powerpc__) || defined (__hppa__) || \
1234 defined (__s390__) || defined (__s390x__)
1237 xbsd_part, &xbsd_dlabel/* not used, xbsd_part_index*/
1240 xbsd_print_disklabel (1);
1244 } else if (c == 'n')
1250 edit_int(int def, char *mesg)
1253 fputs(mesg, stdout);
1254 printf(" (%d): ", def);
1258 while (!isdigit(*line_ptr)); /* FIXME: ?!! */
1259 return atoi(line_ptr);
1263 xbsd_edit_disklabel(void)
1265 struct xbsd_disklabel *d;
1269 #if defined (__alpha__) || defined (__ia64__)
1270 d->d_secsize = (u_long) edit_int((u_long) d->d_secsize ,_("bytes/sector"));
1271 d->d_nsectors = (u_long) edit_int((u_long) d->d_nsectors ,_("sectors/track"));
1272 d->d_ntracks = (u_long) edit_int((u_long) d->d_ntracks ,_("tracks/cylinder"));
1273 d->d_ncylinders = (u_long) edit_int((u_long) d->d_ncylinders ,_("cylinders"));
1276 /* d->d_secpercyl can be != d->d_nsectors * d->d_ntracks */
1278 d->d_secpercyl = (u_long) edit_int((u_long) d->d_nsectors * d->d_ntracks,
1279 _("sectors/cylinder"));
1280 if (d->d_secpercyl <= d->d_nsectors * d->d_ntracks)
1283 printf(_("Must be <= sectors/track * tracks/cylinder (default).\n"));
1285 d->d_rpm = (u_short) edit_int((u_short) d->d_rpm ,_("rpm"));
1286 d->d_interleave = (u_short) edit_int((u_short) d->d_interleave,_("interleave"));
1287 d->d_trackskew = (u_short) edit_int((u_short) d->d_trackskew ,_("trackskew"));
1288 d->d_cylskew = (u_short) edit_int((u_short) d->d_cylskew ,_("cylinderskew"));
1289 d->d_headswitch = (u_long) edit_int((u_long) d->d_headswitch ,_("headswitch"));
1290 d->d_trkseek = (u_long) edit_int((u_long) d->d_trkseek ,_("track-to-track seek"));
1292 d->d_secperunit = d->d_secpercyl * d->d_ncylinders;
1296 xbsd_get_bootstrap (char *path, void *ptr, int size)
1300 if ((fdb = open (path, O_RDONLY)) < 0) {
1304 if (read(fdb, ptr, size) < 0) {
1309 printf(" ... %s\n", path);
1317 printf(_("\nSyncing disks.\n"));
1319 sleep(4); /* What? */
1323 xbsd_write_bootstrap(void)
1325 char *bootdir = BSD_LINUX_BOOTDIR;
1326 char path[MAXPATHLEN];
1328 struct xbsd_disklabel dl;
1332 if (xbsd_dlabel.d_type == BSD_DTYPE_SCSI)
1337 printf(_("Bootstrap: %sboot -> boot%s (%s): "),
1338 dkbasename, dkbasename, dkbasename);
1340 line_ptr[strlen(line_ptr)-1] = '\0';
1341 dkbasename = line_ptr;
1343 snprintf(path, sizeof(path), "%s/%sboot", bootdir, dkbasename);
1344 if (!xbsd_get_bootstrap(path, disklabelbuffer, (int) xbsd_dlabel.d_secsize))
1347 /* We need a backup of the disklabel (xbsd_dlabel might have changed). */
1348 d = &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE];
1349 bcopy(d, &dl, sizeof(struct xbsd_disklabel));
1351 /* The disklabel will be overwritten by 0's from bootxx anyway */
1352 memset(d, 0, sizeof(struct xbsd_disklabel));
1354 snprintf(path, sizeof(path), "%s/boot%s", bootdir, dkbasename);
1355 if (!xbsd_get_bootstrap (path, &disklabelbuffer[xbsd_dlabel.d_secsize],
1356 (int) xbsd_dlabel.d_bbsize - xbsd_dlabel.d_secsize))
1359 e = d + sizeof(struct xbsd_disklabel);
1360 for (p = d; p < e; p++)
1362 fprintf(stderr, _("Bootstrap overlaps with disk label!\n"));
1366 bcopy(&dl, d, sizeof(struct xbsd_disklabel));
1368 #if defined (__powerpc__) || defined (__hppa__)
1370 #elif defined (__alpha__)
1372 alpha_bootblock_checksum(disklabelbuffer);
1374 sector = get_start_sect(xbsd_part);
1377 if (lseek(fd, sector * SECTOR_SIZE, SEEK_SET) == -1)
1378 fdisk_fatal(unable_to_seek);
1379 if (BSD_BBSIZE != write(fd, disklabelbuffer, BSD_BBSIZE))
1380 fdisk_fatal(unable_to_write);
1382 #if defined (__alpha__)
1383 printf(_("Bootstrap installed on %s.\n"), disk_device);
1385 printf(_("Bootstrap installed on %s.\n"),
1386 partname (disk_device, xbsd_part_index+1, 0));
1393 xbsd_change_fstype(void)
1397 i = xbsd_get_part_index(xbsd_dlabel.d_npartitions);
1398 xbsd_dlabel.d_partitions[i].p_fstype = read_hex(xbsd_fstypes);
1402 xbsd_get_part_index(int max)
1407 snprintf(prompt, sizeof(prompt), _("Partition (a-%c): "), 'a' + max - 1);
1409 l = tolower(read_char(prompt));
1410 while (l < 'a' || l > 'a' + max - 1);
1415 xbsd_check_new_partition(int *i)
1417 /* room for more? various BSD flavours have different maxima */
1418 if (xbsd_dlabel.d_npartitions == BSD_MAXPARTITIONS) {
1421 for (t = 0; t < BSD_MAXPARTITIONS; t++)
1422 if (xbsd_dlabel.d_partitions[t].p_size == 0)
1425 if (t == BSD_MAXPARTITIONS) {
1426 fprintf(stderr, _("The maximum number of partitions "
1427 "has been created\n"));
1432 *i = xbsd_get_part_index (BSD_MAXPARTITIONS);
1434 if (*i >= xbsd_dlabel.d_npartitions)
1435 xbsd_dlabel.d_npartitions = (*i) + 1;
1437 if (xbsd_dlabel.d_partitions[*i].p_size != 0) {
1438 fprintf(stderr, _("This partition already exists.\n"));
1446 xbsd_list_types(void)
1448 list_types(xbsd_fstypes);
1452 xbsd_dkcksum(struct xbsd_disklabel *lp)
1454 u_short *start, *end;
1457 start = (u_short *) lp;
1458 end = (u_short *) &lp->d_partitions[lp->d_npartitions];
1465 xbsd_initlabel(struct partition *p, struct xbsd_disklabel *d)
1467 struct xbsd_partition *pp;
1470 memset(d, 0, sizeof(struct xbsd_disklabel));
1472 d->d_magic = BSD_DISKMAGIC;
1474 if (strncmp(disk_device, "/dev/sd", 7) == 0)
1475 d->d_type = BSD_DTYPE_SCSI;
1477 d->d_type = BSD_DTYPE_ST506;
1479 #if 0 /* not used (at least not written to disk) by NetBSD/i386 1.0 */
1480 d->d_subtype = BSD_DSTYPE_INDOSPART & pindex;
1483 #if !defined (__alpha__)
1484 d->d_flags = BSD_D_DOSPART;
1488 d->d_secsize = SECTOR_SIZE; /* bytes/sector */
1489 d->d_nsectors = sectors; /* sectors/track */
1490 d->d_ntracks = heads; /* tracks/cylinder (heads) */
1491 d->d_ncylinders = cylinders;
1492 d->d_secpercyl = sectors * heads;/* sectors/cylinder */
1493 if (d->d_secpercyl == 0)
1494 d->d_secpercyl = 1; /* avoid segfaults */
1495 d->d_secperunit = d->d_secpercyl * d->d_ncylinders;
1498 d->d_interleave = 1;
1501 d->d_headswitch = 0;
1504 d->d_magic2 = BSD_DISKMAGIC;
1505 d->d_bbsize = BSD_BBSIZE;
1506 d->d_sbsize = BSD_SBSIZE;
1508 #if !defined (__alpha__)
1509 d->d_npartitions = 4;
1510 pp = &d->d_partitions[2]; /* Partition C should be
1511 the NetBSD partition */
1512 pp->p_offset = get_start_sect(p);
1513 pp->p_size = get_nr_sects(p);
1514 pp->p_fstype = BSD_FS_UNUSED;
1515 pp = &d->d_partitions[3]; /* Partition D should be
1518 pp->p_size = d->d_secperunit;
1519 pp->p_fstype = BSD_FS_UNUSED;
1520 #elif defined (__alpha__)
1521 d->d_npartitions = 3;
1522 pp = &d->d_partitions[2]; /* Partition C should be
1525 pp->p_size = d->d_secperunit;
1526 pp->p_fstype = BSD_FS_UNUSED;
1533 * Read a xbsd_disklabel from sector 0 or from the starting sector of p.
1534 * If it has the right magic, return 1.
1537 xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d)
1541 /* p is used only to get the starting sector */
1542 #if !defined (__alpha__)
1543 sector = (p ? get_start_sect(p) : 0);
1544 #elif defined (__alpha__)
1548 if (lseek(fd, sector * SECTOR_SIZE, SEEK_SET) == -1)
1549 fdisk_fatal(unable_to_seek);
1550 if (BSD_BBSIZE != read(fd, disklabelbuffer, BSD_BBSIZE))
1551 fdisk_fatal(unable_to_read);
1553 bcopy(&disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
1554 d, sizeof(struct xbsd_disklabel));
1556 if (d->d_magic != BSD_DISKMAGIC || d->d_magic2 != BSD_DISKMAGIC)
1559 for (t = d->d_npartitions; t < BSD_MAXPARTITIONS; t++) {
1560 d->d_partitions[t].p_size = 0;
1561 d->d_partitions[t].p_offset = 0;
1562 d->d_partitions[t].p_fstype = BSD_FS_UNUSED;
1565 if (d->d_npartitions > BSD_MAXPARTITIONS)
1566 fprintf(stderr, _("Warning: too many partitions "
1567 "(%d, maximum is %d).\n"),
1568 d->d_npartitions, BSD_MAXPARTITIONS);
1573 xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d)
1575 unsigned int sector;
1577 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
1578 sector = get_start_sect(p) + BSD_LABELSECTOR;
1580 sector = BSD_LABELSECTOR;
1584 d->d_checksum = xbsd_dkcksum (d);
1586 /* This is necessary if we want to write the bootstrap later,
1587 otherwise we'd write the old disklabel with the bootstrap.
1589 bcopy(d, &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
1590 sizeof(struct xbsd_disklabel));
1592 #if defined (__alpha__) && BSD_LABELSECTOR == 0
1593 alpha_bootblock_checksum (disklabelbuffer);
1594 if (lseek(fd, 0, SEEK_SET) == -1)
1595 fdisk_fatal(unable_to_seek);
1596 if (BSD_BBSIZE != write(fd, disklabelbuffer, BSD_BBSIZE))
1597 fdisk_fatal(unable_to_write);
1599 if (lseek(fd, sector * SECTOR_SIZE + BSD_LABELOFFSET, SEEK_SET) == -1)
1600 fdisk_fatal(unable_to_seek);
1601 if (sizeof(struct xbsd_disklabel) != write(fd, d, sizeof(struct xbsd_disklabel)))
1602 fdisk_fatal(unable_to_write);
1609 #if !defined (__alpha__)
1611 xbsd_translate_fstype(int linux_type)
1613 switch (linux_type) {
1614 case 0x01: /* DOS 12-bit FAT */
1615 case 0x04: /* DOS 16-bit <32M */
1616 case 0x06: /* DOS 16-bit >=32M */
1617 case 0xe1: /* DOS access */
1618 case 0xe3: /* DOS R/O */
1619 case 0xf2: /* DOS secondary */
1620 return BSD_FS_MSDOS;
1621 case 0x07: /* OS/2 HPFS */
1624 return BSD_FS_OTHER;
1629 xbsd_link_part(void)
1632 struct partition *p;
1634 k = get_partition(1, partitions);
1636 if (!xbsd_check_new_partition(&i))
1639 p = get_part_table(k);
1641 xbsd_dlabel.d_partitions[i].p_size = get_nr_sects(p);
1642 xbsd_dlabel.d_partitions[i].p_offset = get_start_sect(p);
1643 xbsd_dlabel.d_partitions[i].p_fstype = xbsd_translate_fstype(p->sys_ind);
1647 #if defined (__alpha__)
1649 #if !defined(__GLIBC__)
1650 typedef unsigned long long uint64_t;
1654 alpha_bootblock_checksum(char *boot)
1659 dp = (uint64_t *)boot;
1661 for (i = 0; i < 63; i++)
1665 #endif /* __alpha__ */
1667 #endif /* OSF_LABEL */
1669 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
1670 static inline unsigned short
1671 __swap16(unsigned short x)
1673 return (((uint16_t)(x) & 0xFF) << 8) | (((uint16_t)(x) & 0xFF00) >> 8);
1676 static inline uint32_t
1677 __swap32(uint32_t x)
1679 return (((x & 0xFF) << 24) |
1680 ((x & 0xFF00) << 8) |
1681 ((x & 0xFF0000) >> 8) |
1682 ((x & 0xFF000000) >> 24));
1686 #ifdef CONFIG_FEATURE_SGI_LABEL
1691 * Copyright (C) Andreas Neuper, Sep 1998.
1692 * This file may be modified and redistributed under
1693 * the terms of the GNU Public License.
1695 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
1696 * Internationalization
1700 static int sgi_other_endian;
1702 static short sgi_volumes = 1;
1705 * only dealing with free blocks here
1712 static freeblocks freelist[17]; /* 16 partitions can produce 17 vacant slots */
1715 setfreelist(int i, unsigned int f, unsigned int l)
1717 freelist[i].first = f;
1718 freelist[i].last = l;
1722 add2freelist(unsigned int f, unsigned int l)
1725 for (i = 0; i < 17 ; i++)
1726 if (freelist[i].last == 0)
1728 setfreelist(i, f, l);
1736 for (i = 0; i < 17 ; i++)
1737 setfreelist(i, 0, 0);
1741 isinfreelist(unsigned int b)
1745 for (i = 0; i < 17 ; i++)
1746 if (freelist[i].first <= b && freelist[i].last >= b)
1747 return freelist[i].last;
1750 /* return last vacant block of this stride (never 0). */
1751 /* the '>=' is not quite correct, but simplifies the code */
1753 * end of free blocks section
1756 static const struct systypes sgi_sys_types[] = {
1757 /* SGI_VOLHDR */ { "\x00" "SGI volhdr" },
1758 /* 0x01 */ { "\x01" "SGI trkrepl" },
1759 /* 0x02 */ { "\x02" "SGI secrepl" },
1760 /* SGI_SWAP */ { "\x03" "SGI raw" },
1761 /* 0x04 */ { "\x04" "SGI bsd" },
1762 /* 0x05 */ { "\x05" "SGI sysv" },
1763 /* ENTIRE_DISK */ { "\x06" "SGI volume" },
1764 /* SGI_EFS */ { "\x07" "SGI efs" },
1765 /* 0x08 */ { "\x08" "SGI lvol" },
1766 /* 0x09 */ { "\x09" "SGI rlvol" },
1767 /* SGI_XFS */ { "\x0a" "SGI xfs" },
1768 /* SGI_XFSLOG */ { "\x0b" "SGI xfslog" },
1769 /* SGI_XLV */ { "\x0c" "SGI xlv" },
1770 /* SGI_XVM */ { "\x0d" "SGI xvm" },
1771 /* LINUX_SWAP */ { "\x82" "Linux swap" },
1772 /* LINUX_NATIVE */ { "\x83" "Linux native" },
1773 /* LINUX_LVM */ { "\x8d" "Linux LVM" },
1774 /* LINUX_RAID */ { "\xfd" "Linux RAID" },
1782 return SGI_SSWAP16(sgilabel->devparam.nsect);
1788 return SGI_SSWAP16(sgilabel->devparam.ntrks);
1794 sgilabel->magic = 0;
1800 two_s_complement_32bit_sum(unsigned int* base, int size /* in bytes */)
1803 unsigned int sum = 0;
1805 size /= sizeof(unsigned int);
1806 for (i = 0; i < size; i++)
1807 sum -= SGI_SSWAP32(base[i]);
1812 check_sgi_label(void)
1814 if (sizeof(sgilabel) > 512) {
1816 _("According to MIPS Computer Systems, Inc the "
1817 "Label must not contain more than 512 bytes\n"));
1821 if (sgilabel->magic != SGI_LABEL_MAGIC
1822 && sgilabel->magic != SGI_LABEL_MAGIC_SWAPPED) {
1824 sgi_other_endian = 0;
1828 sgi_other_endian = (sgilabel->magic == SGI_LABEL_MAGIC_SWAPPED);
1830 * test for correct checksum
1832 if (two_s_complement_32bit_sum((unsigned int*)sgilabel,
1833 sizeof(*sgilabel))) {
1835 _("Detected sgi disklabel with wrong checksum.\n"));
1845 sgi_get_start_sector(int i)
1847 return SGI_SSWAP32(sgilabel->partitions[i].start_sector);
1851 sgi_get_num_sectors(int i)
1853 return SGI_SSWAP32(sgilabel->partitions[i].num_sectors);
1857 sgi_get_sysid(int i)
1859 return SGI_SSWAP32(sgilabel->partitions[i].id);
1863 sgi_get_bootpartition(void)
1865 return SGI_SSWAP16(sgilabel->boot_part);
1869 sgi_get_swappartition(void)
1871 return SGI_SSWAP16(sgilabel->swap_part);
1875 sgi_list_table(int xtra)
1878 int kpi = 0; /* kernel partition ID */
1881 printf(_("\nDisk %s (SGI disk label): %d heads, %d sectors\n"
1882 "%d cylinders, %d physical cylinders\n"
1883 "%d extra sects/cyl, interleave %d:1\n"
1885 "Units = %s of %d * 512 bytes\n\n"),
1886 disk_device, heads, sectors, cylinders,
1887 SGI_SSWAP16(sgiparam.pcylcount),
1888 SGI_SSWAP16(sgiparam.sparecyl),
1889 SGI_SSWAP16(sgiparam.ilfact),
1891 str_units(PLURAL), units_per_sector);
1893 printf( _("\nDisk %s (SGI disk label): "
1894 "%d heads, %d sectors, %d cylinders\n"
1895 "Units = %s of %d * 512 bytes\n\n"),
1896 disk_device, heads, sectors, cylinders,
1897 str_units(PLURAL), units_per_sector );
1900 w = strlen(disk_device);
1901 wd = strlen(_("Device"));
1905 printf(_("----- partitions -----\n"
1906 "Pt# %*s Info Start End Sectors Id System\n"),
1907 w + 2, _("Device"));
1908 for (i = 0 ; i < partitions; i++) {
1909 if( sgi_get_num_sectors(i) || debug ) {
1910 uint32_t start = sgi_get_start_sector(i);
1911 uint32_t len = sgi_get_num_sectors(i);
1912 kpi++; /* only count nonempty partitions */
1914 "%2d: %s %4s %9ld %9ld %9ld %2x %s\n",
1915 /* fdisk part number */ i+1,
1916 /* device */ partname(disk_device, kpi, w+3),
1917 /* flags */ (sgi_get_swappartition() == i) ? "swap" :
1918 /* flags */ (sgi_get_bootpartition() == i) ? "boot" : " ",
1919 /* start */ (long) scround(start),
1920 /* end */ (long) scround(start+len)-1,
1921 /* no odd flag on end */(long) len,
1922 /* type id */ sgi_get_sysid(i),
1923 /* type name */ partition_type(sgi_get_sysid(i)));
1926 printf(_("----- Bootinfo -----\nBootfile: %s\n"
1927 "----- Directory Entries -----\n"),
1928 sgilabel->boot_file);
1929 for (i = 0 ; i < sgi_volumes; i++) {
1930 if (sgilabel->directory[i].vol_file_size) {
1931 uint32_t start = SGI_SSWAP32(sgilabel->directory[i].vol_file_start);
1932 uint32_t len = SGI_SSWAP32(sgilabel->directory[i].vol_file_size);
1933 unsigned char *name = sgilabel->directory[i].vol_file_name;
1935 printf(_("%2d: %-10s sector%5u size%8u\n"),
1936 i, (char*)name, (unsigned int) start, (unsigned int) len);
1942 sgi_set_bootpartition(int i)
1944 sgilabel->boot_part = SGI_SSWAP16(((short)i));
1948 sgi_get_lastblock(void)
1950 return heads * sectors * cylinders;
1954 sgi_set_swappartition(int i)
1956 sgilabel->swap_part = SGI_SSWAP16(((short)i));
1960 sgi_check_bootfile(const char* aFile)
1962 if (strlen(aFile) < 3) /* "/a\n" is minimum */ {
1963 printf(_("\nInvalid Bootfile!\n"
1964 "\tThe bootfile must be an absolute non-zero pathname,\n"
1965 "\te.g. \"/unix\" or \"/unix.save\".\n"));
1968 if (strlen(aFile) > 16) {
1969 printf(_("\n\tName of Bootfile too long: "
1970 "16 bytes maximum.\n"));
1973 if (aFile[0] != '/') {
1974 printf(_("\n\tBootfile must have a "
1975 "fully qualified pathname.\n"));
1980 if (strncmp(aFile, (char*)sgilabel->boot_file, 16)) {
1981 printf(_("\n\tBe aware, that the bootfile is not checked for existence.\n\t"
1982 "SGI's default is \"/unix\" and for backup \"/unix.save\".\n"));
1983 /* filename is correct and did change */
1986 return 0; /* filename did not change */
1990 sgi_get_bootfile(void)
1992 return (char*)sgilabel->boot_file;
1996 sgi_set_bootfile(const char* aFile)
2000 if (sgi_check_bootfile(aFile)) {
2002 if ((aFile[i] != '\n') /* in principle caught again by next line */
2003 && (strlen(aFile) > i))
2004 sgilabel->boot_file[i] = aFile[i];
2006 sgilabel->boot_file[i] = 0;
2009 printf(_("\n\tBootfile is changed to \"%s\".\n"), sgilabel->boot_file);
2014 create_sgiinfo(void)
2016 /* I keep SGI's habit to write the sgilabel to the second block */
2017 sgilabel->directory[0].vol_file_start = SGI_SSWAP32(2);
2018 sgilabel->directory[0].vol_file_size = SGI_SSWAP32(sizeof(sgiinfo));
2019 strncpy((char*)sgilabel->directory[0].vol_file_name, "sgilabel", 8);
2022 static sgiinfo *fill_sgiinfo(void);
2025 sgi_write_table(void)
2028 sgilabel->csum = SGI_SSWAP32(two_s_complement_32bit_sum(
2029 (unsigned int*)sgilabel, sizeof(*sgilabel)));
2030 assert(two_s_complement_32bit_sum(
2031 (unsigned int*)sgilabel, sizeof(*sgilabel)) == 0);
2033 if (lseek(fd, 0, SEEK_SET) < 0)
2034 fdisk_fatal(unable_to_seek);
2035 if (write(fd, sgilabel, SECTOR_SIZE) != SECTOR_SIZE)
2036 fdisk_fatal(unable_to_write);
2037 if (!strncmp((char*)sgilabel->directory[0].vol_file_name, "sgilabel", 8)) {
2039 * keep this habit of first writing the "sgilabel".
2040 * I never tested whether it works without (AN 981002).
2042 sgiinfo *info = fill_sgiinfo();
2043 int infostartblock = SGI_SSWAP32(sgilabel->directory[0].vol_file_start);
2044 if (lseek(fd, infostartblock*SECTOR_SIZE, SEEK_SET) < 0)
2045 fdisk_fatal(unable_to_seek);
2046 if (write(fd, info, SECTOR_SIZE) != SECTOR_SIZE)
2047 fdisk_fatal(unable_to_write);
2053 compare_start(int *x, int *y)
2056 * sort according to start sectors
2057 * and prefers largest partition:
2058 * entry zero is entire disk entry
2060 unsigned int i = *x;
2061 unsigned int j = *y;
2062 unsigned int a = sgi_get_start_sector(i);
2063 unsigned int b = sgi_get_start_sector(j);
2064 unsigned int c = sgi_get_num_sectors(i);
2065 unsigned int d = sgi_get_num_sectors(j);
2068 return (d > c) ? 1 : (d == c) ? 0 : -1;
2069 return (a > b) ? 1 : -1;
2074 verify_sgi(int verbose)
2076 int Index[16]; /* list of valid partitions */
2077 int sortcount = 0; /* number of used partitions, i.e. non-zero lengths */
2078 int entire = 0, i = 0;
2079 unsigned int start = 0;
2080 long long gap = 0; /* count unused blocks */
2081 unsigned int lastblock = sgi_get_lastblock();
2084 for (i = 0; i < 16; i++) {
2085 if (sgi_get_num_sectors(i) != 0) {
2086 Index[sortcount++] = i;
2087 if (sgi_get_sysid(i) == ENTIRE_DISK) {
2088 if (entire++ == 1) {
2090 printf(_("More than one entire disk entry present.\n"));
2095 if (sortcount == 0) {
2097 printf(_("No partitions defined\n"));
2098 return (lastblock > 0) ? 1 : (lastblock == 0) ? 0 : -1;
2100 qsort(Index, sortcount, sizeof(Index[0]), (void*)compare_start);
2101 if (sgi_get_sysid(Index[0]) == ENTIRE_DISK) {
2102 if ((Index[0] != 10) && verbose)
2103 printf(_("IRIX likes when Partition 11 covers the entire disk.\n"));
2104 if ((sgi_get_start_sector(Index[0]) != 0) && verbose)
2105 printf(_("The entire disk partition should start "
2107 "not at diskblock %d.\n"),
2108 sgi_get_start_sector(Index[0]));
2109 if (debug) /* I do not understand how some disks fulfil it */
2110 if ((sgi_get_num_sectors(Index[0]) != lastblock) && verbose)
2111 printf(_("The entire disk partition is only %d diskblock large,\n"
2112 "but the disk is %d diskblocks long.\n"),
2113 sgi_get_num_sectors(Index[0]), lastblock);
2114 lastblock = sgi_get_num_sectors(Index[0]);
2117 printf(_("One Partition (#11) should cover the entire disk.\n"));
2119 printf("sysid=%d\tpartition=%d\n",
2120 sgi_get_sysid(Index[0]), Index[0]+1);
2122 for (i = 1, start = 0; i < sortcount; i++) {
2123 int cylsize = sgi_get_nsect() * sgi_get_ntrks();
2125 if ((sgi_get_start_sector(Index[i]) % cylsize) != 0) {
2126 if (debug) /* I do not understand how some disks fulfil it */
2128 printf(_("Partition %d does not start on cylinder boundary.\n"),
2131 if (sgi_get_num_sectors(Index[i]) % cylsize != 0) {
2132 if (debug) /* I do not understand how some disks fulfil it */
2134 printf(_("Partition %d does not end on cylinder boundary.\n"),
2137 /* We cannot handle several "entire disk" entries. */
2138 if (sgi_get_sysid(Index[i]) == ENTIRE_DISK) continue;
2139 if (start > sgi_get_start_sector(Index[i])) {
2141 printf(_("The Partition %d and %d overlap by %d sectors.\n"),
2142 Index[i-1]+1, Index[i]+1,
2143 start - sgi_get_start_sector(Index[i]));
2144 if (gap > 0) gap = -gap;
2145 if (gap == 0) gap = -1;
2147 if (start < sgi_get_start_sector(Index[i])) {
2149 printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"),
2150 sgi_get_start_sector(Index[i]) - start,
2151 start, sgi_get_start_sector(Index[i])-1);
2152 gap += sgi_get_start_sector(Index[i]) - start;
2153 add2freelist(start, sgi_get_start_sector(Index[i]));
2155 start = sgi_get_start_sector(Index[i])
2156 + sgi_get_num_sectors(Index[i]);
2159 printf("%2d:%12d\t%12d\t%12d\n", Index[i],
2160 sgi_get_start_sector(Index[i]),
2161 sgi_get_num_sectors(Index[i]),
2162 sgi_get_sysid(Index[i]));
2165 if (start < lastblock) {
2167 printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"),
2168 lastblock - start, start, lastblock-1);
2169 gap += lastblock - start;
2170 add2freelist(start, lastblock);
2173 * Done with arithmetics
2174 * Go for details now
2177 if (!sgi_get_num_sectors(sgi_get_bootpartition())) {
2178 printf(_("\nThe boot partition does not exist.\n"));
2180 if (!sgi_get_num_sectors(sgi_get_swappartition())) {
2181 printf(_("\nThe swap partition does not exist.\n"));
2183 if ((sgi_get_sysid(sgi_get_swappartition()) != SGI_SWAP)
2184 && (sgi_get_sysid(sgi_get_swappartition()) != LINUX_SWAP))
2185 printf(_("\nThe swap partition has no swap type.\n"));
2187 if (sgi_check_bootfile("/unix"))
2188 printf(_("\tYou have chosen an unusual boot file name.\n"));
2190 return (gap > 0) ? 1 : (gap == 0) ? 0 : -1;
2197 * returned value is:
2198 * = 0 : disk is properly filled to the rim
2199 * < 0 : there is an overlap
2200 * > 0 : there is still some vacant space
2202 return verify_sgi(0);
2206 sgi_change_sysid(int i, int sys)
2208 if( sgi_get_num_sectors(i) == 0 ) { /* caught already before, ... */
2209 printf(_("Sorry You may change the Tag of non-empty partitions.\n"));
2212 if (((sys != ENTIRE_DISK ) && (sys != SGI_VOLHDR))
2213 && (sgi_get_start_sector(i) < 1) ) {
2215 _("It is highly recommended that the partition at offset 0\n"
2216 "is of type \"SGI volhdr\", the IRIX system will rely on it to\n"
2217 "retrieve from its directory standalone tools like sash and fx.\n"
2218 "Only the \"SGI volume\" entire disk section may violate this.\n"
2219 "Type YES if you are sure about tagging this partition differently.\n"));
2220 if (strcmp(line_ptr, _("YES\n")))
2223 sgilabel->partitions[i].id = SGI_SSWAP32(sys);
2226 /* returns partition index of first entry marked as entire disk */
2232 for (i = 0; i < 16; i++)
2233 if (sgi_get_sysid(i) == SGI_VOLUME)
2239 sgi_set_partition(int i, unsigned int start, unsigned int length, int sys)
2241 sgilabel->partitions[i].id = SGI_SSWAP32(sys);
2242 sgilabel->partitions[i].num_sectors = SGI_SSWAP32(length);
2243 sgilabel->partitions[i].start_sector = SGI_SSWAP32(start);
2245 if (sgi_gaps() < 0) /* rebuild freelist */
2246 printf(_("Do You know, You got a partition overlap on the disk?\n"));
2250 sgi_set_entire(void)
2254 for (n = 10; n < partitions; n++) {
2255 if(!sgi_get_num_sectors(n) ) {
2256 sgi_set_partition(n, 0, sgi_get_lastblock(), SGI_VOLUME);
2263 sgi_set_volhdr(void)
2267 for (n = 8; n < partitions; n++) {
2268 if (!sgi_get_num_sectors(n)) {
2270 * 5 cylinders is an arbitrary value I like
2271 * IRIX 5.3 stored files in the volume header
2272 * (like sash, symmon, fx, ide) with ca. 3200
2275 if (heads * sectors * 5 < sgi_get_lastblock())
2276 sgi_set_partition(n, 0, heads * sectors * 5, SGI_VOLHDR);
2283 sgi_delete_partition(int i)
2285 sgi_set_partition(i, 0, 0, 0);
2289 sgi_add_partition(int n, int sys)
2292 unsigned int first = 0, last = 0;
2296 } else if (n == 8) {
2299 if(sgi_get_num_sectors(n)) {
2300 printf(_("Partition %d is already defined. Delete "
2301 "it before re-adding it.\n"), n + 1);
2304 if ((sgi_entire() == -1) && (sys != SGI_VOLUME)) {
2305 printf(_("Attempting to generate entire disk entry automatically.\n"));
2309 if ((sgi_gaps() == 0) && (sys != SGI_VOLUME)) {
2310 printf(_("The entire disk is already covered with partitions.\n"));
2313 if (sgi_gaps() < 0) {
2314 printf(_("You got a partition overlap on the disk. Fix it first!\n"));
2317 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
2319 if(sys == SGI_VOLUME) {
2320 last = sgi_get_lastblock();
2321 first = read_int(0, 0, last-1, 0, mesg);
2323 printf(_("It is highly recommended that eleventh partition\n"
2324 "covers the entire disk and is of type `SGI volume'\n"));
2327 first = freelist[0].first;
2328 last = freelist[0].last;
2329 first = read_int(scround(first), scround(first), scround(last)-1,
2332 if (display_in_cyl_units)
2333 first *= units_per_sector;
2335 first = first; /* align to cylinder if you know how ... */
2337 last = isinfreelist(first);
2339 printf(_("You will get a partition overlap on the disk. "
2340 "Fix it first!\n"));
2344 snprintf(mesg, sizeof(mesg), _(" Last %s"), str_units(SINGULAR));
2345 last = read_int(scround(first), scround(last)-1, scround(last)-1,
2346 scround(first), mesg)+1;
2347 if (display_in_cyl_units)
2348 last *= units_per_sector;
2350 last = last; /* align to cylinder if You know how ... */
2351 if ( (sys == SGI_VOLUME) && (first != 0 || last != sgi_get_lastblock() ) )
2352 printf(_("It is highly recommended that eleventh partition\n"
2353 "covers the entire disk and is of type `SGI volume'\n"));
2354 sgi_set_partition(n, first, last-first, sys);
2357 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
2359 create_sgilabel(void)
2361 struct hd_geometry geometry;
2368 long longsectors; /* the number of sectors on the device */
2369 int res; /* the result from the ioctl */
2370 int sec_fac; /* the sector factor */
2372 sec_fac = sector_size / 512; /* determine the sector factor */
2375 _("Building a new SGI disklabel. Changes will remain in memory only,\n"
2376 "until you decide to write them. After that, of course, the previous\n"
2377 "content will be unrecoverably lost.\n\n"));
2379 sgi_other_endian = (BYTE_ORDER == LITTLE_ENDIAN);
2380 res = ioctl(fd, BLKGETSIZE, &longsectors);
2381 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
2382 heads = geometry.heads;
2383 sectors = geometry.sectors;
2385 /* the get device size ioctl was successful */
2386 cylinders = longsectors / (heads * sectors);
2387 cylinders /= sec_fac;
2389 /* otherwise print error and use truncated version */
2390 cylinders = geometry.cylinders;
2392 _("Warning: BLKGETSIZE ioctl failed on %s. "
2393 "Using geometry cylinder value of %d.\n"
2394 "This value may be truncated for devices"
2395 " > 33.8 GB.\n"), disk_device, cylinders);
2398 for (i = 0; i < 4; i++) {
2400 if (valid_part_table_flag(MBRbuffer)) {
2401 if(get_part_table(i)->sys_ind) {
2402 old[i].sysid = get_part_table(i)->sys_ind;
2403 old[i].start = get_start_sect(get_part_table(i));
2404 old[i].nsect = get_nr_sects(get_part_table(i));
2405 printf(_("Trying to keep parameters of partition %d.\n"), i);
2407 printf(_("ID=%02x\tSTART=%d\tLENGTH=%d\n"),
2408 old[i].sysid, old[i].start, old[i].nsect);
2413 memset(MBRbuffer, 0, sizeof(MBRbuffer));
2414 sgilabel->magic = SGI_SSWAP32(SGI_LABEL_MAGIC);
2415 sgilabel->boot_part = SGI_SSWAP16(0);
2416 sgilabel->swap_part = SGI_SSWAP16(1);
2418 /* sizeof(sgilabel->boot_file) = 16 > 6 */
2419 memset(sgilabel->boot_file, 0, 16);
2420 strcpy((char*)sgilabel->boot_file, "/unix");
2422 sgilabel->devparam.skew = (0);
2423 sgilabel->devparam.gap1 = (0);
2424 sgilabel->devparam.gap2 = (0);
2425 sgilabel->devparam.sparecyl = (0);
2426 sgilabel->devparam.pcylcount = SGI_SSWAP16(geometry.cylinders);
2427 sgilabel->devparam.head_vol0 = SGI_SSWAP16(0);
2428 sgilabel->devparam.ntrks = SGI_SSWAP16(geometry.heads);
2429 /* tracks/cylinder (heads) */
2430 sgilabel->devparam.cmd_tag_queue_depth = (0);
2431 sgilabel->devparam.unused0 = (0);
2432 sgilabel->devparam.unused1 = SGI_SSWAP16(0);
2433 sgilabel->devparam.nsect = SGI_SSWAP16(geometry.sectors);
2435 sgilabel->devparam.bytes = SGI_SSWAP16(512);
2436 sgilabel->devparam.ilfact = SGI_SSWAP16(1);
2437 sgilabel->devparam.flags = SGI_SSWAP32(TRACK_FWD|
2438 IGNORE_ERRORS|RESEEK);
2439 sgilabel->devparam.datarate = SGI_SSWAP32(0);
2440 sgilabel->devparam.retries_on_error = SGI_SSWAP32(1);
2441 sgilabel->devparam.ms_per_word = SGI_SSWAP32(0);
2442 sgilabel->devparam.xylogics_gap1 = SGI_SSWAP16(0);
2443 sgilabel->devparam.xylogics_syncdelay = SGI_SSWAP16(0);
2444 sgilabel->devparam.xylogics_readdelay = SGI_SSWAP16(0);
2445 sgilabel->devparam.xylogics_gap2 = SGI_SSWAP16(0);
2446 sgilabel->devparam.xylogics_readgate = SGI_SSWAP16(0);
2447 sgilabel->devparam.xylogics_writecont = SGI_SSWAP16(0);
2448 memset( &(sgilabel->directory), 0, sizeof(struct volume_directory)*15 );
2449 memset( &(sgilabel->partitions), 0, sizeof(struct sgi_partition)*16 );
2455 for (i = 0; i < 4; i++) {
2457 sgi_set_partition(i, old[i].start, old[i].nsect, old[i].sysid);
2465 /* do nothing in the beginning */
2467 #endif /* CONFIG_FEATURE_FDISK_ADVANCED */
2469 /* _____________________________________________________________
2475 sgiinfo *info = calloc(1, sizeof(sgiinfo));
2477 info->magic = SGI_SSWAP32(SGI_INFO_MAGIC);
2478 info->b1 = SGI_SSWAP32(-1);
2479 info->b2 = SGI_SSWAP16(-1);
2480 info->b3 = SGI_SSWAP16(1);
2481 /* You may want to replace this string !!!!!!! */
2482 strcpy( (char*)info->scsi_string, "IBM OEM 0662S12 3 30" );
2483 strcpy( (char*)info->serial, "0000" );
2484 info->check1816 = SGI_SSWAP16(18*256 +16 );
2485 strcpy( (char*)info->installer, "Sfx version 5.3, Oct 18, 1994" );
2488 #endif /* SGI_LABEL */
2491 #ifdef CONFIG_FEATURE_SUN_LABEL
2495 * I think this is mostly, or entirely, due to
2496 * Jakub Jelinek (jj@sunsite.mff.cuni.cz), July 1996
2498 * Merged with fdisk for other architectures, aeb, June 1998.
2500 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
2501 * Internationalization
2505 static int sun_other_endian;
2506 static int scsi_disk;
2510 #define IDE0_MAJOR 3
2513 #define IDE1_MAJOR 22
2517 guess_device_type(void)
2519 struct stat bootstat;
2521 if (fstat(fd, &bootstat) < 0) {
2524 } else if (S_ISBLK(bootstat.st_mode)
2525 && (major(bootstat.st_rdev) == IDE0_MAJOR ||
2526 major(bootstat.st_rdev) == IDE1_MAJOR)) {
2529 } else if (S_ISBLK(bootstat.st_mode)
2530 && major(bootstat.st_rdev) == FLOPPY_MAJOR) {
2539 static const struct systypes sun_sys_types[] = {
2540 { "\x00" "Empty" }, /* 0 */
2541 { "\x01" "Boot" }, /* 1 */
2542 { "\x02" "SunOS root" }, /* 2 */
2543 { "\x03" "SunOS swap" }, /* SUNOS_SWAP */
2544 { "\x04" "SunOS usr" }, /* 4 */
2545 { "\x05" "Whole disk" }, /* WHOLE_DISK */
2546 { "\x06" "SunOS stand" }, /* 6 */
2547 { "\x07" "SunOS var" }, /* 7 */
2548 { "\x08" "SunOS home" }, /* 8 */
2549 { "\x82" "Linux swap" }, /* LINUX_SWAP */
2550 { "\x83" "Linux native" }, /* LINUX_NATIVE */
2551 { "\x8e" "Linux LVM" }, /* 0x8e */
2552 /* New (2.2.x) raid partition with autodetect using persistent superblock */
2553 { "\xfd" "Linux raid autodetect" }, /* 0xfd */
2559 set_sun_partition(int i, uint start, uint stop, int sysid)
2561 sunlabel->infos[i].id = sysid;
2562 sunlabel->partitions[i].start_cylinder =
2563 SUN_SSWAP32(start / (heads * sectors));
2564 sunlabel->partitions[i].num_sectors =
2565 SUN_SSWAP32(stop - start);
2573 sunlabel->magic = 0;
2578 check_sun_label(void)
2580 unsigned short *ush;
2583 if (sunlabel->magic != SUN_LABEL_MAGIC
2584 && sunlabel->magic != SUN_LABEL_MAGIC_SWAPPED) {
2586 sun_other_endian = 0;
2589 sun_other_endian = (sunlabel->magic == SUN_LABEL_MAGIC_SWAPPED);
2590 ush = ((unsigned short *) (sunlabel + 1)) - 1;
2591 for (csum = 0; ush >= (unsigned short *)sunlabel;) csum ^= *ush--;
2593 fprintf(stderr,_("Detected sun disklabel with wrong checksum.\n"
2594 "Probably you'll have to set all the values,\n"
2595 "e.g. heads, sectors, cylinders and partitions\n"
2596 "or force a fresh label (s command in main menu)\n"));
2598 heads = SUN_SSWAP16(sunlabel->ntrks);
2599 cylinders = SUN_SSWAP16(sunlabel->ncyl);
2600 sectors = SUN_SSWAP16(sunlabel->nsect);
2608 static const struct sun_predefined_drives {
2611 unsigned short sparecyl;
2612 unsigned short ncyl;
2613 unsigned short nacyl;
2614 unsigned short pcylcount;
2615 unsigned short ntrks;
2616 unsigned short nsect;
2617 unsigned short rspeed;
2619 { "Quantum","ProDrive 80S",1,832,2,834,6,34,3662},
2620 { "Quantum","ProDrive 105S",1,974,2,1019,6,35,3662},
2621 { "CDC","Wren IV 94171-344",3,1545,2,1549,9,46,3600},
2622 { "IBM","DPES-31080",0,4901,2,4903,4,108,5400},
2623 { "IBM","DORS-32160",0,1015,2,1017,67,62,5400},
2624 { "IBM","DNES-318350",0,11199,2,11474,10,320,7200},
2625 { "SEAGATE","ST34371",0,3880,2,3882,16,135,7228},
2626 { "","SUN0104",1,974,2,1019,6,35,3662},
2627 { "","SUN0207",4,1254,2,1272,9,36,3600},
2628 { "","SUN0327",3,1545,2,1549,9,46,3600},
2629 { "","SUN0340",0,1538,2,1544,6,72,4200},
2630 { "","SUN0424",2,1151,2,2500,9,80,4400},
2631 { "","SUN0535",0,1866,2,2500,7,80,5400},
2632 { "","SUN0669",5,1614,2,1632,15,54,3600},
2633 { "","SUN1.0G",5,1703,2,1931,15,80,3597},
2634 { "","SUN1.05",0,2036,2,2038,14,72,5400},
2635 { "","SUN1.3G",6,1965,2,3500,17,80,5400},
2636 { "","SUN2.1G",0,2733,2,3500,19,80,5400},
2637 { "IOMEGA","Jaz",0,1019,2,1021,64,32,5394},
2640 static const struct sun_predefined_drives *
2641 sun_autoconfigure_scsi(void)
2643 const struct sun_predefined_drives *p = NULL;
2645 #ifdef SCSI_IOCTL_GET_IDLUN
2655 if (!ioctl(fd, SCSI_IOCTL_GET_IDLUN, &id)) {
2657 "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n",
2659 ((id[0]>>24)&0xff)-/*PROC_SCSI_SCSI+PROC_SCSI_FILE*/33,
2661 /* This is very wrong (works only if you have one HBA),
2662 but I haven't found a way how to get hostno
2663 from the current kernel */
2670 pfd = fopen("/proc/scsi/scsi","r");
2672 while (fgets(buffer2, 2048, pfd)) {
2673 if (!strcmp(buffer, buffer2)) {
2674 if (fgets(buffer2,2048,pfd)) {
2675 q = strstr(buffer2,"Vendor: ");
2680 *q++ = 0; /* truncate vendor name */
2681 q = strstr(q,"Model: ");
2686 q = strstr(q," Rev: ");
2689 for (i = 0; i < SIZE(sun_drives); i++) {
2690 if (*sun_drives[i].vendor && strcasecmp(sun_drives[i].vendor, vendor))
2692 if (!strstr(model, sun_drives[i].model))
2694 printf(_("Autoconfigure found a %s%s%s\n"),sun_drives[i].vendor,(*sun_drives[i].vendor) ? " " : "",sun_drives[i].model);
2713 create_sunlabel(void)
2715 struct hd_geometry geometry;
2719 const struct sun_predefined_drives *p = NULL;
2722 _("Building a new sun disklabel. Changes will remain in memory only,\n"
2723 "until you decide to write them. After that, of course, the previous\n"
2724 "content won't be recoverable.\n\n"));
2725 #if BYTE_ORDER == LITTLE_ENDIAN
2726 sun_other_endian = 1;
2728 sun_other_endian = 0;
2730 memset(MBRbuffer, 0, sizeof(MBRbuffer));
2731 sunlabel->magic = SUN_SSWAP16(SUN_LABEL_MAGIC);
2733 puts(_("Drive type\n"
2734 " ? auto configure\n"
2735 " 0 custom (with hardware detected defaults)"));
2736 for (i = 0; i < SIZE(sun_drives); i++) {
2737 printf(" %c %s%s%s\n",
2738 i + 'a', sun_drives[i].vendor,
2739 (*sun_drives[i].vendor) ? " " : "",
2740 sun_drives[i].model);
2743 c = read_char(_("Select type (? for auto, 0 for custom): "));
2744 if (c >= 'a' && c < 'a' + SIZE(sun_drives)) {
2745 p = sun_drives + c - 'a';
2747 } else if (c >= 'A' && c < 'A' + SIZE(sun_drives)) {
2748 p = sun_drives + c - 'A';
2750 } else if (c == '0') {
2752 } else if (c == '?' && scsi_disk) {
2753 p = sun_autoconfigure_scsi();
2755 printf(_("Autoconfigure failed.\n"));
2762 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
2763 heads = geometry.heads;
2764 sectors = geometry.sectors;
2765 cylinders = geometry.cylinders;
2772 sunlabel->nacyl = 0;
2773 sunlabel->pcylcount = SUN_SSWAP16(cylinders);
2774 sunlabel->rspeed = SUN_SSWAP16(300);
2775 sunlabel->ilfact = SUN_SSWAP16(1);
2776 sunlabel->sparecyl = 0;
2778 heads = read_int(1,heads,1024,0,_("Heads"));
2779 sectors = read_int(1,sectors,1024,0,_("Sectors/track"));
2781 cylinders = read_int(1,cylinders-2,65535,0,_("Cylinders"));
2783 cylinders = read_int(1,0,65535,0,_("Cylinders"));
2784 sunlabel->nacyl = SUN_SSWAP16(read_int(0,2,65535,0, _("Alternate cylinders")));
2785 sunlabel->pcylcount = SUN_SSWAP16(read_int(0,cylinders+SUN_SSWAP16(sunlabel->nacyl), 65535,0, _("Physical cylinders")));
2786 sunlabel->rspeed = SUN_SSWAP16(read_int(1,5400,100000,0, _("Rotation speed (rpm)")));
2787 sunlabel->ilfact = SUN_SSWAP16(read_int(1,1,32,0, _("Interleave factor")));
2788 sunlabel->sparecyl = SUN_SSWAP16(read_int(0,0,sectors,0, _("Extra sectors per cylinder")));
2791 sunlabel->sparecyl = SUN_SSWAP16(p->sparecyl);
2792 sunlabel->ncyl = SUN_SSWAP16(p->ncyl);
2793 sunlabel->nacyl = SUN_SSWAP16(p->nacyl);
2794 sunlabel->pcylcount = SUN_SSWAP16(p->pcylcount);
2795 sunlabel->ntrks = SUN_SSWAP16(p->ntrks);
2796 sunlabel->nsect = SUN_SSWAP16(p->nsect);
2797 sunlabel->rspeed = SUN_SSWAP16(p->rspeed);
2798 sunlabel->ilfact = SUN_SSWAP16(1);
2799 cylinders = p->ncyl;
2802 puts(_("You may change all the disk params from the x menu"));
2805 snprintf((char *)(sunlabel->info), sizeof(sunlabel->info),
2806 "%s%s%s cyl %d alt %d hd %d sec %d",
2807 p ? p->vendor : "", (p && *p->vendor) ? " " : "",
2808 p ? p->model : (floppy ? _("3,5\" floppy") : _("Linux custom")),
2809 cylinders, SUN_SSWAP16(sunlabel->nacyl), heads, sectors);
2811 sunlabel->ntrks = SUN_SSWAP16(heads);
2812 sunlabel->nsect = SUN_SSWAP16(sectors);
2813 sunlabel->ncyl = SUN_SSWAP16(cylinders);
2815 set_sun_partition(0, 0, cylinders * heads * sectors, LINUX_NATIVE);
2817 if (cylinders * heads * sectors >= 150 * 2048) {
2818 ndiv = cylinders - (50 * 2048 / (heads * sectors)); /* 50M swap */
2820 ndiv = cylinders * 2 / 3;
2821 set_sun_partition(0, 0, ndiv * heads * sectors, LINUX_NATIVE);
2822 set_sun_partition(1, ndiv * heads * sectors, cylinders * heads * sectors, LINUX_SWAP);
2823 sunlabel->infos[1].flags |= 0x01; /* Not mountable */
2825 set_sun_partition(2, 0, cylinders * heads * sectors, WHOLE_DISK);
2827 unsigned short *ush = (unsigned short *)sunlabel;
2828 unsigned short csum = 0;
2829 while (ush < (unsigned short *)(&sunlabel->csum))
2831 sunlabel->csum = csum;
2834 set_all_unchanged();
2836 get_boot(create_empty_sun);
2840 toggle_sunflags(int i, unsigned char mask)
2842 if (sunlabel->infos[i].flags & mask)
2843 sunlabel->infos[i].flags &= ~mask;
2845 sunlabel->infos[i].flags |= mask;
2850 fetch_sun(uint *starts, uint *lens, uint *start, uint *stop)
2852 int i, continuous = 1;
2855 *stop = cylinders * heads * sectors;
2856 for (i = 0; i < partitions; i++) {
2857 if (sunlabel->partitions[i].num_sectors
2858 && sunlabel->infos[i].id
2859 && sunlabel->infos[i].id != WHOLE_DISK) {
2860 starts[i] = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
2861 lens[i] = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
2863 if (starts[i] == *start)
2865 else if (starts[i] + lens[i] >= *stop)
2869 /* There will be probably more gaps
2870 than one, so lets check afterwards */
2879 static uint *verify_sun_starts;
2882 verify_sun_cmp(int *a, int *b)
2884 if (*a == -1) return 1;
2885 if (*b == -1) return -1;
2886 if (verify_sun_starts[*a] > verify_sun_starts[*b]) return 1;
2893 uint starts[8], lens[8], start, stop;
2894 int i,j,k,starto,endo;
2897 verify_sun_starts = starts;
2898 fetch_sun(starts,lens,&start,&stop);
2899 for (k = 0; k < 7; k++) {
2900 for (i = 0; i < 8; i++) {
2901 if (k && (lens[i] % (heads * sectors))) {
2902 printf(_("Partition %d doesn't end on cylinder boundary\n"), i+1);
2905 for (j = 0; j < i; j++)
2907 if (starts[j] == starts[i]+lens[i]) {
2908 starts[j] = starts[i]; lens[j] += lens[i];
2910 } else if (starts[i] == starts[j]+lens[j]){
2914 if (starts[i] < starts[j]+lens[j]
2915 && starts[j] < starts[i]+lens[i]) {
2917 if (starts[j] > starto)
2919 endo = starts[i]+lens[i];
2920 if (starts[j]+lens[j] < endo)
2921 endo = starts[j]+lens[j];
2922 printf(_("Partition %d overlaps with others in "
2923 "sectors %d-%d\n"), i+1, starto, endo);
2930 for (i = 0; i < 8; i++) {
2936 qsort(array,SIZE(array),sizeof(array[0]),
2937 (int (*)(const void *,const void *)) verify_sun_cmp);
2938 if (array[0] == -1) {
2939 printf(_("No partitions defined\n"));
2942 stop = cylinders * heads * sectors;
2943 if (starts[array[0]])
2944 printf(_("Unused gap - sectors 0-%d\n"),starts[array[0]]);
2945 for (i = 0; i < 7 && array[i+1] != -1; i++) {
2946 printf(_("Unused gap - sectors %d-%d\n"),starts[array[i]]+lens[array[i]],starts[array[i+1]]);
2948 start = starts[array[i]] + lens[array[i]];
2950 printf(_("Unused gap - sectors %d-%d\n"),start,stop);
2954 add_sun_partition(int n, int sys)
2956 uint start, stop, stop2;
2957 uint starts[8], lens[8];
2963 if (sunlabel->partitions[n].num_sectors && sunlabel->infos[n].id) {
2964 printf(_("Partition %d is already defined. Delete "
2965 "it before re-adding it.\n"), n + 1);
2969 fetch_sun(starts,lens,&start,&stop);
2970 if (stop <= start) {
2974 printf(_("Other partitions already cover the whole disk.\nDelete "
2975 "some/shrink them before retry.\n"));
2979 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
2982 first = read_int(0, 0, 0, 0, mesg);
2984 first = read_int(scround(start), scround(stop)+1,
2985 scround(stop), 0, mesg);
2986 if (display_in_cyl_units)
2987 first *= units_per_sector;
2989 /* Starting sector has to be properly aligned */
2990 first = (first + heads * sectors - 1) / (heads * sectors);
2991 if (n == 2 && first != 0)
2993 It is highly recommended that the third partition covers the whole disk\n\
2994 and is of type `Whole disk'\n");
2995 /* ewt asks to add: "don't start a partition at cyl 0"
2996 However, edmundo@rano.demon.co.uk writes:
2997 "In addition to having a Sun partition table, to be able to
2998 boot from the disc, the first partition, /dev/sdX1, must
2999 start at cylinder 0. This means that /dev/sdX1 contains
3000 the partition table and the boot block, as these are the
3001 first two sectors of the disc. Therefore you must be
3002 careful what you use /dev/sdX1 for. In particular, you must
3003 not use a partition starting at cylinder 0 for Linux swap,
3004 as that would overwrite the partition table and the boot
3005 block. You may, however, use such a partition for a UFS
3006 or EXT2 file system, as these file systems leave the first
3007 1024 bytes undisturbed. */
3008 /* On the other hand, one should not use partitions
3009 starting at block 0 in an md, or the label will
3011 for (i = 0; i < partitions; i++)
3012 if (lens[i] && starts[i] <= first && starts[i] + lens[i] > first)
3014 if (i < partitions && !whole_disk) {
3015 if (n == 2 && !first) {
3019 printf(_("Sector %d is already allocated\n"), first);
3023 stop = cylinders * heads * sectors;
3025 for (i = 0; i < partitions; i++) {
3026 if (starts[i] > first && starts[i] < stop)
3029 snprintf(mesg, sizeof(mesg),
3030 _("Last %s or +size or +sizeM or +sizeK"),
3031 str_units(SINGULAR));
3033 last = read_int(scround(stop2), scround(stop2), scround(stop2),
3035 else if (n == 2 && !first)
3036 last = read_int(scround(first), scround(stop2), scround(stop2),
3037 scround(first), mesg);
3039 last = read_int(scround(first), scround(stop), scround(stop),
3040 scround(first), mesg);
3041 if (display_in_cyl_units)
3042 last *= units_per_sector;
3043 if (n == 2 && !first) {
3044 if (last >= stop2) {
3047 } else if (last > stop) {
3048 printf(_("You haven't covered the whole disk with "
3049 "the 3rd partition, but your value\n"
3050 "%d %s covers some other partition. "
3051 "Your entry has been changed\n"
3053 scround(last), str_units(SINGULAR),
3054 scround(stop), str_units(SINGULAR));
3057 } else if (!whole_disk && last > stop)
3062 set_sun_partition(n, first, last, sys);
3066 sun_delete_partition(int i)
3071 && sunlabel->infos[i].id == WHOLE_DISK
3072 && !sunlabel->partitions[i].start_cylinder
3073 && (nsec = SUN_SSWAP32(sunlabel->partitions[i].num_sectors)) == heads * sectors * cylinders)
3074 printf(_("If you want to maintain SunOS/Solaris compatibility, "
3075 "consider leaving this\n"
3076 "partition as Whole disk (5), starting at 0, with %u "
3077 "sectors\n"), nsec);
3078 sunlabel->infos[i].id = 0;
3079 sunlabel->partitions[i].num_sectors = 0;
3083 sun_change_sysid(int i, int sys)
3085 if (sys == LINUX_SWAP && !sunlabel->partitions[i].start_cylinder) {
3087 _("It is highly recommended that the partition at offset 0\n"
3088 "is UFS, EXT2FS filesystem or SunOS swap. Putting Linux swap\n"
3089 "there may destroy your partition table and bootblock.\n"
3090 "Type YES if you're very sure you would like that partition\n"
3091 "tagged with 82 (Linux swap): "));
3092 if (strcmp (line_ptr, _("YES\n")))
3098 /* swaps are not mountable by default */
3099 sunlabel->infos[i].flags |= 0x01;
3102 /* assume other types are mountable;
3103 user can change it anyway */
3104 sunlabel->infos[i].flags &= ~0x01;
3107 sunlabel->infos[i].id = sys;
3111 sun_list_table(int xtra)
3115 w = strlen(disk_device);
3118 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d rpm\n"
3119 "%d cylinders, %d alternate cylinders, %d physical cylinders\n"
3120 "%d extra sects/cyl, interleave %d:1\n"
3122 "Units = %s of %d * 512 bytes\n\n"),
3123 disk_device, heads, sectors, SUN_SSWAP16(sunlabel->rspeed),
3124 cylinders, SUN_SSWAP16(sunlabel->nacyl),
3125 SUN_SSWAP16(sunlabel->pcylcount),
3126 SUN_SSWAP16(sunlabel->sparecyl),
3127 SUN_SSWAP16(sunlabel->ilfact),
3129 str_units(PLURAL), units_per_sector);
3132 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d cylinders\n"
3133 "Units = %s of %d * 512 bytes\n\n"),
3134 disk_device, heads, sectors, cylinders,
3135 str_units(PLURAL), units_per_sector);
3137 printf(_("%*s Flag Start End Blocks Id System\n"),
3138 w + 1, _("Device"));
3139 for (i = 0 ; i < partitions; i++) {
3140 if (sunlabel->partitions[i].num_sectors) {
3141 uint32_t start = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
3142 uint32_t len = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
3143 printf("%s %c%c %9ld %9ld %9ld%c %2x %s\n",
3144 partname(disk_device, i+1, w), /* device */
3145 (sunlabel->infos[i].flags & 0x01) ? 'u' : ' ', /* flags */
3146 (sunlabel->infos[i].flags & 0x10) ? 'r' : ' ',
3147 (long) scround(start), /* start */
3148 (long) scround(start+len), /* end */
3149 (long) len / 2, len & 1 ? '+' : ' ', /* odd flag on end */
3150 sunlabel->infos[i].id, /* type id */
3151 partition_type(sunlabel->infos[i].id)); /* type name */
3156 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3159 sun_set_alt_cyl(void)
3162 SUN_SSWAP16(read_int(0,SUN_SSWAP16(sunlabel->nacyl), 65535, 0,
3163 _("Number of alternate cylinders")));
3167 sun_set_ncyl(int cyl)
3169 sunlabel->ncyl = SUN_SSWAP16(cyl);
3175 sunlabel->sparecyl =
3176 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->sparecyl), sectors, 0,
3177 _("Extra sectors per cylinder")));
3181 sun_set_ilfact(void)
3184 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->ilfact), 32, 0,
3185 _("Interleave factor")));
3189 sun_set_rspeed(void)
3192 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->rspeed), 100000, 0,
3193 _("Rotation speed (rpm)")));
3197 sun_set_pcylcount(void)
3199 sunlabel->pcylcount =
3200 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->pcylcount), 65535, 0,
3201 _("Number of physical cylinders")));
3203 #endif /* CONFIG_FEATURE_FDISK_ADVANCED */
3206 sun_write_table(void)
3208 unsigned short *ush = (unsigned short *)sunlabel;
3209 unsigned short csum = 0;
3211 while (ush < (unsigned short *)(&sunlabel->csum))
3213 sunlabel->csum = csum;
3214 if (lseek(fd, 0, SEEK_SET) < 0)
3215 fdisk_fatal(unable_to_seek);
3216 if (write(fd, sunlabel, SECTOR_SIZE) != SECTOR_SIZE)
3217 fdisk_fatal(unable_to_write);
3219 #endif /* SUN_LABEL */
3221 /* DOS partition types */
3223 static const struct systypes i386_sys_types[] = {
3226 { "\x04" "FAT16 <32M" },
3227 { "\x05" "Extended" }, /* DOS 3.3+ extended partition */
3228 { "\x06" "FAT16" }, /* DOS 16-bit >=32M */
3229 { "\x07" "HPFS/NTFS" }, /* OS/2 IFS, eg, HPFS or NTFS or QNX */
3230 { "\x0a" "OS/2 Boot Manager" },/* OS/2 Boot Manager */
3231 { "\x0b" "Win95 FAT32" },
3232 { "\x0c" "Win95 FAT32 (LBA)" },/* LBA really is `Extended Int 13h' */
3233 { "\x0e" "Win95 FAT16 (LBA)" },
3234 { "\x0f" "Win95 Ext'd (LBA)" },
3235 { "\x11" "Hidden FAT12" },
3236 { "\x12" "Compaq diagnostics" },
3237 { "\x14" "Hidden FAT16 <32M" },
3238 { "\x16" "Hidden FAT16" },
3239 { "\x17" "Hidden HPFS/NTFS" },
3240 { "\x1b" "Hidden Win95 FAT32" },
3241 { "\x1c" "Hidden Win95 FAT32 (LBA)" },
3242 { "\x1e" "Hidden Win95 FAT16 (LBA)" },
3243 { "\x3c" "PartitionMagic recovery" },
3244 { "\x41" "PPC PReP Boot" },
3246 { "\x63" "GNU HURD or SysV" }, /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */
3247 { "\x80" "Old Minix" }, /* Minix 1.4a and earlier */
3248 { "\x81" "Minix / old Linux" },/* Minix 1.4b and later */
3249 { "\x82" "Linux swap" }, /* also Solaris */
3251 { "\x84" "OS/2 hidden C: drive" },
3252 { "\x85" "Linux extended" },
3253 { "\x86" "NTFS volume set" },
3254 { "\x87" "NTFS volume set" },
3255 { "\x8e" "Linux LVM" },
3256 { "\x9f" "BSD/OS" }, /* BSDI */
3257 { "\xa0" "IBM Thinkpad hibernation" },
3258 { "\xa5" "FreeBSD" }, /* various BSD flavours */
3259 { "\xa6" "OpenBSD" },
3260 { "\xa8" "Darwin UFS" },
3261 { "\xa9" "NetBSD" },
3262 { "\xab" "Darwin boot" },
3263 { "\xb7" "BSDI fs" },
3264 { "\xb8" "BSDI swap" },
3265 { "\xbe" "Solaris boot" },
3266 { "\xeb" "BeOS fs" },
3267 { "\xee" "EFI GPT" }, /* Intel EFI GUID Partition Table */
3268 { "\xef" "EFI (FAT-12/16/32)" },/* Intel EFI System Partition */
3269 { "\xf0" "Linux/PA-RISC boot" },/* Linux/PA-RISC boot loader */
3270 { "\xf2" "DOS secondary" }, /* DOS 3.3+ secondary */
3271 { "\xfd" "Linux raid autodetect" },/* New (2.2.x) raid partition with
3272 autodetect using persistent
3274 #ifdef CONFIG_WEIRD_PARTITION_TYPES
3275 { "\x02" "XENIX root" },
3276 { "\x03" "XENIX usr" },
3277 { "\x08" "AIX" }, /* AIX boot (AIX -- PS/2 port) or SplitDrive */
3278 { "\x09" "AIX bootable" }, /* AIX data or Coherent */
3280 { "\x18" "AST SmartSleep" },
3281 { "\x24" "NEC DOS" },
3282 { "\x39" "Plan 9" },
3283 { "\x40" "Venix 80286" },
3284 { "\x4d" "QNX4.x" },
3285 { "\x4e" "QNX4.x 2nd part" },
3286 { "\x4f" "QNX4.x 3rd part" },
3287 { "\x50" "OnTrack DM" },
3288 { "\x51" "OnTrack DM6 Aux1" }, /* (or Novell) */
3289 { "\x52" "CP/M" }, /* CP/M or Microport SysV/AT */
3290 { "\x53" "OnTrack DM6 Aux3" },
3291 { "\x54" "OnTrackDM6" },
3292 { "\x55" "EZ-Drive" },
3293 { "\x56" "Golden Bow" },
3294 { "\x5c" "Priam Edisk" },
3295 { "\x61" "SpeedStor" },
3296 { "\x64" "Novell Netware 286" },
3297 { "\x65" "Novell Netware 386" },
3298 { "\x70" "DiskSecure Multi-Boot" },
3300 { "\x93" "Amoeba" },
3301 { "\x94" "Amoeba BBT" }, /* (bad block table) */
3302 { "\xa7" "NeXTSTEP" },
3303 { "\xbb" "Boot Wizard hidden" },
3304 { "\xc1" "DRDOS/sec (FAT-12)" },
3305 { "\xc4" "DRDOS/sec (FAT-16 < 32M)" },
3306 { "\xc6" "DRDOS/sec (FAT-16)" },
3307 { "\xc7" "Syrinx" },
3308 { "\xda" "Non-FS data" },
3309 { "\xdb" "CP/M / CTOS / ..." },/* CP/M or Concurrent CP/M or
3310 Concurrent DOS or CTOS */
3311 { "\xde" "Dell Utility" }, /* Dell PowerEdge Server utilities */
3312 { "\xdf" "BootIt" }, /* BootIt EMBRM */
3313 { "\xe1" "DOS access" }, /* DOS access or SpeedStor 12-bit FAT
3314 extended partition */
3315 { "\xe3" "DOS R/O" }, /* DOS R/O or SpeedStor */
3316 { "\xe4" "SpeedStor" }, /* SpeedStor 16-bit FAT extended
3317 partition < 1024 cyl. */
3318 { "\xf1" "SpeedStor" },
3319 { "\xf4" "SpeedStor" }, /* SpeedStor large partition */
3320 { "\xfe" "LANstep" }, /* SpeedStor >1024 cyl. or LANstep */
3321 { "\xff" "BBT" }, /* Xenix Bad Block Table */
3328 /* A valid partition table sector ends in 0x55 0xaa */
3330 part_table_flag(const char *b)
3332 return ((uint) b[510]) + (((uint) b[511]) << 8);
3336 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3338 write_part_table_flag(char *b)
3344 /* start_sect and nr_sects are stored little endian on all machines */
3345 /* moreover, they are not aligned correctly */
3347 store4_little_endian(unsigned char *cp, unsigned int val)
3349 cp[0] = (val & 0xff);
3350 cp[1] = ((val >> 8) & 0xff);
3351 cp[2] = ((val >> 16) & 0xff);
3352 cp[3] = ((val >> 24) & 0xff);
3354 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3357 read4_little_endian(const unsigned char *cp)
3359 return (uint)(cp[0]) + ((uint)(cp[1]) << 8)
3360 + ((uint)(cp[2]) << 16) + ((uint)(cp[3]) << 24);
3363 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3365 set_start_sect(struct partition *p, unsigned int start_sect)
3367 store4_little_endian(p->start4, start_sect);
3372 get_start_sect(const struct partition *p)
3374 return read4_little_endian(p->start4);
3377 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3379 set_nr_sects(struct partition *p, int32_t nr_sects)
3381 store4_little_endian(p->size4, nr_sects);
3386 get_nr_sects(const struct partition *p)
3388 return read4_little_endian(p->size4);
3391 /* normally O_RDWR, -l option gives O_RDONLY */
3392 static int type_open = O_RDWR;
3395 static int ext_index; /* the prime extended partition */
3396 static int listing; /* no aborts for fdisk -l */
3397 static int dos_compatible_flag = ~0;
3398 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3399 static int dos_changed;
3400 static int nowarn; /* no warnings for fdisk -l/-s */
3405 static uint user_cylinders, user_heads, user_sectors;
3406 static uint pt_heads, pt_sectors;
3407 static uint kern_heads, kern_sectors;
3409 static off_t extended_offset; /* offset of link pointers */
3411 static unsigned long long total_number_of_sectors;
3414 static jmp_buf listingbuf;
3416 static void fdisk_fatal(enum failure why)
3418 const char *message;
3422 longjmp(listingbuf, 1);
3426 case unable_to_open:
3427 message = "Unable to open %s\n";
3429 case unable_to_read:
3430 message = "Unable to read %s\n";
3432 case unable_to_seek:
3433 message = "Unable to seek on %s\n";
3435 case unable_to_write:
3436 message = "Unable to write %s\n";
3439 message = "BLKGETSIZE ioctl failed on %s\n";
3442 message = "Fatal error\n";
3445 fputc('\n', stderr);
3446 fprintf(stderr, message, disk_device);
3451 seek_sector(off_t secno)
3453 off_t offset = secno * sector_size;
3454 if (lseek(fd, offset, SEEK_SET) == (off_t) -1)
3455 fdisk_fatal(unable_to_seek);
3458 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3460 write_sector(off_t secno, char *buf)
3463 if (write(fd, buf, sector_size) != sector_size)
3464 fdisk_fatal(unable_to_write);
3468 /* Allocate a buffer and read a partition table sector */
3470 read_pte(struct pte *pe, off_t offset)
3472 pe->offset = offset;
3473 pe->sectorbuffer = (char *) xmalloc(sector_size);
3474 seek_sector(offset);
3475 if (read(fd, pe->sectorbuffer, sector_size) != sector_size)
3476 fdisk_fatal(unable_to_read);
3477 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3480 pe->part_table = pe->ext_pointer = NULL;
3484 get_partition_start(const struct pte *pe)
3486 return pe->offset + get_start_sect(pe->part_table);
3489 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3491 * Avoid warning about DOS partitions when no DOS partition was changed.
3492 * Here a heuristic "is probably dos partition".
3493 * We might also do the opposite and warn in all cases except
3494 * for "is probably nondos partition".
3497 is_dos_partition(int t)
3499 return (t == 1 || t == 4 || t == 6 ||
3500 t == 0x0b || t == 0x0c || t == 0x0e ||
3501 t == 0x11 || t == 0x12 || t == 0x14 || t == 0x16 ||
3502 t == 0x1b || t == 0x1c || t == 0x1e || t == 0x24 ||
3503 t == 0xc1 || t == 0xc4 || t == 0xc6);
3509 #ifdef CONFIG_FEATURE_SUN_LABEL
3511 puts(_("Command action"));
3512 puts(_("\ta\ttoggle a read only flag")); /* sun */
3513 puts(_("\tb\tedit bsd disklabel"));
3514 puts(_("\tc\ttoggle the mountable flag")); /* sun */
3515 puts(_("\td\tdelete a partition"));
3516 puts(_("\tl\tlist known partition types"));
3517 puts(_("\tm\tprint this menu"));
3518 puts(_("\tn\tadd a new partition"));
3519 puts(_("\to\tcreate a new empty DOS partition table"));
3520 puts(_("\tp\tprint the partition table"));
3521 puts(_("\tq\tquit without saving changes"));
3522 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3523 puts(_("\tt\tchange a partition's system id"));
3524 puts(_("\tu\tchange display/entry units"));
3525 puts(_("\tv\tverify the partition table"));
3526 puts(_("\tw\twrite table to disk and exit"));
3527 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3528 puts(_("\tx\textra functionality (experts only)"));
3532 #ifdef CONFIG_FEATURE_SGI_LABEL
3534 puts(_("Command action"));
3535 puts(_("\ta\tselect bootable partition")); /* sgi flavour */
3536 puts(_("\tb\tedit bootfile entry")); /* sgi */
3537 puts(_("\tc\tselect sgi swap partition")); /* sgi flavour */
3538 puts(_("\td\tdelete a partition"));
3539 puts(_("\tl\tlist known partition types"));
3540 puts(_("\tm\tprint this menu"));
3541 puts(_("\tn\tadd a new partition"));
3542 puts(_("\to\tcreate a new empty DOS partition table"));
3543 puts(_("\tp\tprint the partition table"));
3544 puts(_("\tq\tquit without saving changes"));
3545 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3546 puts(_("\tt\tchange a partition's system id"));
3547 puts(_("\tu\tchange display/entry units"));
3548 puts(_("\tv\tverify the partition table"));
3549 puts(_("\tw\twrite table to disk and exit"));
3552 #ifdef CONFIG_FEATURE_AIX_LABEL
3554 puts(_("Command action"));
3555 puts(_("\tm\tprint this menu"));
3556 puts(_("\to\tcreate a new empty DOS partition table"));
3557 puts(_("\tq\tquit without saving changes"));
3558 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3562 puts(_("Command action"));
3563 puts(_("\ta\ttoggle a bootable flag"));
3564 puts(_("\tb\tedit bsd disklabel"));
3565 puts(_("\tc\ttoggle the dos compatibility flag"));
3566 puts(_("\td\tdelete a partition"));
3567 puts(_("\tl\tlist known partition types"));
3568 puts(_("\tm\tprint this menu"));
3569 puts(_("\tn\tadd a new partition"));
3570 puts(_("\to\tcreate a new empty DOS partition table"));
3571 puts(_("\tp\tprint the partition table"));
3572 puts(_("\tq\tquit without saving changes"));
3573 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3574 puts(_("\tt\tchange a partition's system id"));
3575 puts(_("\tu\tchange display/entry units"));
3576 puts(_("\tv\tverify the partition table"));
3577 puts(_("\tw\twrite table to disk and exit"));
3578 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3579 puts(_("\tx\textra functionality (experts only)"));
3583 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3586 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3590 #ifdef CONFIG_FEATURE_SUN_LABEL
3592 puts(_("Command action"));
3593 puts(_("\ta\tchange number of alternate cylinders")); /*sun*/
3594 puts(_("\tc\tchange number of cylinders"));
3595 puts(_("\td\tprint the raw data in the partition table"));
3596 puts(_("\te\tchange number of extra sectors per cylinder"));/*sun*/
3597 puts(_("\th\tchange number of heads"));
3598 puts(_("\ti\tchange interleave factor")); /*sun*/
3599 puts(_("\to\tchange rotation speed (rpm)")); /*sun*/
3600 puts(_("\tm\tprint this menu"));
3601 puts(_("\tp\tprint the partition table"));
3602 puts(_("\tq\tquit without saving changes"));
3603 puts(_("\tr\treturn to main menu"));
3604 puts(_("\ts\tchange number of sectors/track"));
3605 puts(_("\tv\tverify the partition table"));
3606 puts(_("\tw\twrite table to disk and exit"));
3607 puts(_("\ty\tchange number of physical cylinders")); /*sun*/
3610 #ifdef CONFIG_FEATURE_SGI_LABEL
3612 puts(_("Command action"));
3613 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3614 puts(_("\tc\tchange number of cylinders"));
3615 puts(_("\td\tprint the raw data in the partition table"));
3616 puts(_("\te\tlist extended partitions")); /* !sun */
3617 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3618 puts(_("\th\tchange number of heads"));
3619 puts(_("\tm\tprint this menu"));
3620 puts(_("\tp\tprint the partition table"));
3621 puts(_("\tq\tquit without saving changes"));
3622 puts(_("\tr\treturn to main menu"));
3623 puts(_("\ts\tchange number of sectors/track"));
3624 puts(_("\tv\tverify the partition table"));
3625 puts(_("\tw\twrite table to disk and exit"));
3628 #ifdef CONFIG_FEATURE_AIX_LABEL
3630 puts(_("Command action"));
3631 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3632 puts(_("\tc\tchange number of cylinders"));
3633 puts(_("\td\tprint the raw data in the partition table"));
3634 puts(_("\te\tlist extended partitions")); /* !sun */
3635 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3636 puts(_("\th\tchange number of heads"));
3637 puts(_("\tm\tprint this menu"));
3638 puts(_("\tp\tprint the partition table"));
3639 puts(_("\tq\tquit without saving changes"));
3640 puts(_("\tr\treturn to main menu"));
3641 puts(_("\ts\tchange number of sectors/track"));
3642 puts(_("\tv\tverify the partition table"));
3643 puts(_("\tw\twrite table to disk and exit"));
3647 puts(_("Command action"));
3648 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3649 puts(_("\tc\tchange number of cylinders"));
3650 puts(_("\td\tprint the raw data in the partition table"));
3651 puts(_("\te\tlist extended partitions")); /* !sun */
3652 puts(_("\tf\tfix partition order")); /* !sun, !aix, !sgi */
3653 #ifdef CONFIG_FEATURE_SGI_LABEL
3654 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3656 puts(_("\th\tchange number of heads"));
3657 puts(_("\tm\tprint this menu"));
3658 puts(_("\tp\tprint the partition table"));
3659 puts(_("\tq\tquit without saving changes"));
3660 puts(_("\tr\treturn to main menu"));
3661 puts(_("\ts\tchange number of sectors/track"));
3662 puts(_("\tv\tverify the partition table"));
3663 puts(_("\tw\twrite table to disk and exit"));
3666 #endif /* ADVANCED mode */
3668 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3669 static const struct systypes *
3673 #ifdef CONFIG_FEATURE_SUN_LABEL
3674 sun_label ? sun_sys_types :
3676 #ifdef CONFIG_FEATURE_SGI_LABEL
3677 sgi_label ? sgi_sys_types :
3682 #define get_sys_types() i386_sys_types
3683 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3685 static const char *partition_type(unsigned char type)
3688 const struct systypes *types = get_sys_types();
3690 for (i = 0; types[i].name; i++)
3691 if ((unsigned char )types[i].name[0] == type)
3692 return types[i].name + 1;
3694 return _("Unknown");
3698 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3703 #ifdef CONFIG_FEATURE_SUN_LABEL
3704 sun_label ? sunlabel->infos[i].id :
3706 #ifdef CONFIG_FEATURE_SGI_LABEL
3707 sgi_label ? sgi_get_sysid(i) :
3709 ptes[i].part_table->sys_ind);
3712 void list_types(const struct systypes *sys)
3714 uint last[4], done = 0, next = 0, size;
3717 for (i = 0; sys[i].name; i++);
3720 for (i = 3; i >= 0; i--)
3721 last[3 - i] = done += (size + i - done) / (i + 1);
3725 printf("%c%2x %-15.15s", i ? ' ' : '\n',
3726 (unsigned char)sys[next].name[0],
3727 partition_type((unsigned char)sys[next].name[0]));
3728 next = last[i++] + done;
3729 if (i > 3 || next >= last[i]) {
3733 } while (done < last[0]);
3736 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3739 is_cleared_partition(const struct partition *p)
3741 return !(!p || p->boot_ind || p->head || p->sector || p->cyl ||
3742 p->sys_ind || p->end_head || p->end_sector || p->end_cyl ||
3743 get_start_sect(p) || get_nr_sects(p));
3747 clear_partition(struct partition *p)
3751 memset(p, 0, sizeof(struct partition));
3754 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3756 set_partition(int i, int doext, off_t start, off_t stop, int sysid)
3758 struct partition *p;
3762 p = ptes[i].ext_pointer;
3763 offset = extended_offset;
3765 p = ptes[i].part_table;
3766 offset = ptes[i].offset;
3770 set_start_sect(p, start - offset);
3771 set_nr_sects(p, stop - start + 1);
3772 if (dos_compatible_flag && (start/(sectors*heads) > 1023))
3773 start = heads*sectors*1024 - 1;
3774 set_hsc(p->head, p->sector, p->cyl, start);
3775 if (dos_compatible_flag && (stop/(sectors*heads) > 1023))
3776 stop = heads*sectors*1024 - 1;
3777 set_hsc(p->end_head, p->end_sector, p->end_cyl, stop);
3778 ptes[i].changed = 1;
3783 test_c(const char **m, const char *mesg)
3787 fprintf(stderr, _("You must set"));
3789 fprintf(stderr, " %s", *m);
3799 const char *m = NULL;
3803 prev = test_c(&m, _("heads"));
3805 prev = test_c(&m, _("sectors"));
3807 prev = test_c(&m, _("cylinders"));
3811 fprintf(stderr, "%s%s.\n"
3812 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3813 "You can do this from the extra functions menu.\n"
3815 , prev ? _(" and ") : " ", m);
3820 static void update_units(void)
3822 int cyl_units = heads * sectors;
3824 if (display_in_cyl_units && cyl_units)
3825 units_per_sector = cyl_units;
3827 units_per_sector = 1; /* in sectors */
3830 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3832 warn_cylinders(void)
3834 if (dos_label && cylinders > 1024 && !nowarn)
3835 fprintf(stderr, _("\n"
3836 "The number of cylinders for this disk is set to %d.\n"
3837 "There is nothing wrong with that, but this is larger than 1024,\n"
3838 "and could in certain setups cause problems with:\n"
3839 "1) software that runs at boot time (e.g., old versions of LILO)\n"
3840 "2) booting and partitioning software from other OSs\n"
3841 " (e.g., DOS FDISK, OS/2 FDISK)\n"),
3847 read_extended(int ext)
3851 struct partition *p, *q;
3855 pex->ext_pointer = pex->part_table;
3857 p = pex->part_table;
3858 if (!get_start_sect(p)) {
3860 _("Bad offset in primary extended partition\n"));
3864 while (IS_EXTENDED(p->sys_ind)) {
3865 struct pte *pe = &ptes[partitions];
3867 if (partitions >= MAXIMUM_PARTS) {
3868 /* This is not a Linux restriction, but
3869 this program uses arrays of size MAXIMUM_PARTS.
3870 Do not try to `improve' this test. */
3871 struct pte *pre = &ptes[partitions-1];
3872 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3874 _("Warning: deleting partitions after %d\n"),
3878 clear_partition(pre->ext_pointer);
3882 read_pte(pe, extended_offset + get_start_sect(p));
3884 if (!extended_offset)
3885 extended_offset = get_start_sect(p);
3887 q = p = pt_offset(pe->sectorbuffer, 0);
3888 for (i = 0; i < 4; i++, p++) if (get_nr_sects(p)) {
3889 if (IS_EXTENDED(p->sys_ind)) {
3890 if (pe->ext_pointer)
3892 _("Warning: extra link "
3893 "pointer in partition table"
3894 " %d\n"), partitions + 1);
3896 pe->ext_pointer = p;
3897 } else if (p->sys_ind) {
3900 _("Warning: ignoring extra "
3901 "data in partition table"
3902 " %d\n"), partitions + 1);
3908 /* very strange code here... */
3909 if (!pe->part_table) {
3910 if (q != pe->ext_pointer)
3913 pe->part_table = q + 1;
3915 if (!pe->ext_pointer) {
3916 if (q != pe->part_table)
3917 pe->ext_pointer = q;
3919 pe->ext_pointer = q + 1;
3922 p = pe->ext_pointer;
3926 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3927 /* remove empty links */
3929 for (i = 4; i < partitions; i++) {
3930 struct pte *pe = &ptes[i];
3932 if (!get_nr_sects(pe->part_table) &&
3933 (partitions > 5 || ptes[4].part_table->sys_ind)) {
3934 printf("omitting empty partition (%d)\n", i+1);
3935 delete_partition(i);
3936 goto remove; /* numbering changed */
3942 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3944 create_doslabel(void)
3949 _("Building a new DOS disklabel. Changes will remain in memory only,\n"
3950 "until you decide to write them. After that, of course, the previous\n"
3951 "content won't be recoverable.\n\n"));
3952 #ifdef CONFIG_FEATURE_SUN_LABEL
3953 sun_nolabel(); /* otherwise always recognised as sun */
3955 #ifdef CONFIG_FEATURE_SGI_LABEL
3956 sgi_nolabel(); /* otherwise always recognised as sgi */
3958 #ifdef CONFIG_FEATURE_AIX_LABEL
3961 #ifdef CONFIG_FEATURE_OSF_LABEL
3963 possibly_osf_label = 0;
3967 for (i = 510-64; i < 510; i++)
3969 write_part_table_flag(MBRbuffer);
3970 extended_offset = 0;
3971 set_all_unchanged();
3973 get_boot(create_empty_dos);
3975 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3978 get_sectorsize(void)
3980 if (!user_set_sector_size
3981 && get_kernel_revision() >= MAKE_VERSION(2,3,3)) {
3983 if (ioctl(fd, BLKSSZGET, &arg) == 0)
3985 if (sector_size != DEFAULT_SECTOR_SIZE)
3986 printf(_("Note: sector size is %d (not %d)\n"),
3987 sector_size, DEFAULT_SECTOR_SIZE);
3992 get_kernel_geometry(void)
3994 struct hd_geometry geometry;
3996 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
3997 kern_heads = geometry.heads;
3998 kern_sectors = geometry.sectors;
3999 /* never use geometry.cylinders - it is truncated */
4004 get_partition_table_geometry(void)
4006 const unsigned char *bufp = (const unsigned char *)MBRbuffer;
4007 struct partition *p;
4008 int i, h, s, hh, ss;
4012 if (!(valid_part_table_flag((char*)bufp)))
4016 for (i = 0; i < 4; i++) {
4017 p = pt_offset(bufp, i);
4018 if (p->sys_ind != 0) {
4019 h = p->end_head + 1;
4020 s = (p->end_sector & 077);
4025 } else if (hh != h || ss != s)
4030 if (!first && !bad) {
4040 unsigned long long bytes; /* really u64 */
4043 sec_fac = sector_size / 512;
4044 #ifdef CONFIG_FEATURE_SUN_LABEL
4045 guess_device_type();
4047 heads = cylinders = sectors = 0;
4048 kern_heads = kern_sectors = 0;
4049 pt_heads = pt_sectors = 0;
4051 get_kernel_geometry();
4052 get_partition_table_geometry();
4054 heads = user_heads ? user_heads :
4055 pt_heads ? pt_heads :
4056 kern_heads ? kern_heads : 255;
4057 sectors = user_sectors ? user_sectors :
4058 pt_sectors ? pt_sectors :
4059 kern_sectors ? kern_sectors : 63;
4060 if (ioctl(fd, BLKGETSIZE64, &bytes) == 0) {
4063 unsigned long longsectors;
4065 if (ioctl(fd, BLKGETSIZE, &longsectors))
4067 bytes = ((unsigned long long) longsectors) << 9;
4070 total_number_of_sectors = (bytes >> 9);
4073 if (dos_compatible_flag)
4074 sector_offset = sectors;
4076 cylinders = total_number_of_sectors / (heads * sectors * sec_fac);
4078 cylinders = user_cylinders;
4082 * Read MBR. Returns:
4083 * -1: no 0xaa55 flag present (possibly entire disk BSD)
4084 * 0: found or created label
4088 get_boot(enum action what)
4094 for (i = 0; i < 4; i++) {
4095 struct pte *pe = &ptes[i];
4097 pe->part_table = pt_offset(MBRbuffer, i);
4098 pe->ext_pointer = NULL;
4100 pe->sectorbuffer = MBRbuffer;
4101 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4102 pe->changed = (what == create_empty_dos);
4106 #ifdef CONFIG_FEATURE_SUN_LABEL
4107 if (what == create_empty_sun && check_sun_label())
4111 memset(MBRbuffer, 0, 512);
4113 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4114 if (what == create_empty_dos)
4115 goto got_dos_table; /* skip reading disk */
4117 if ((fd = open(disk_device, type_open)) < 0) {
4118 if ((fd = open(disk_device, O_RDONLY)) < 0) {
4119 if (what == try_only)
4121 fdisk_fatal(unable_to_open);
4123 printf(_("You will not be able to write "
4124 "the partition table.\n"));
4127 if (512 != read(fd, MBRbuffer, 512)) {
4128 if (what == try_only)
4130 fdisk_fatal(unable_to_read);
4133 if ((fd = open(disk_device, O_RDONLY)) < 0)
4135 if (512 != read(fd, MBRbuffer, 512))
4143 #ifdef CONFIG_FEATURE_SUN_LABEL
4144 if (check_sun_label())
4148 #ifdef CONFIG_FEATURE_SGI_LABEL
4149 if (check_sgi_label())
4153 #ifdef CONFIG_FEATURE_AIX_LABEL
4154 if (check_aix_label())
4158 #ifdef CONFIG_FEATURE_OSF_LABEL
4159 if (check_osf_label()) {
4160 possibly_osf_label = 1;
4161 if (!valid_part_table_flag(MBRbuffer)) {
4165 printf(_("This disk has both DOS and BSD magic.\n"
4166 "Give the 'b' command to go to BSD mode.\n"));
4170 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4174 if (!valid_part_table_flag(MBRbuffer)) {
4175 #ifndef CONFIG_FEATURE_FDISK_WRITABLE
4181 _("Device contains neither a valid DOS "
4182 "partition table, nor Sun, SGI or OSF "
4185 #ifdef CONFIG_FEATURE_SUN_LABEL
4194 case create_empty_dos:
4195 #ifdef CONFIG_FEATURE_SUN_LABEL
4196 case create_empty_sun:
4200 fprintf(stderr, _("Internal error\n"));
4203 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
4206 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4211 for (i = 0; i < 4; i++) {
4212 struct pte *pe = &ptes[i];
4214 if (IS_EXTENDED(pe->part_table->sys_ind)) {
4215 if (partitions != 4)
4216 fprintf(stderr, _("Ignoring extra extended "
4217 "partition %d\n"), i + 1);
4223 for (i = 3; i < partitions; i++) {
4224 struct pte *pe = &ptes[i];
4226 if (!valid_part_table_flag(pe->sectorbuffer)) {
4228 _("Warning: invalid flag 0x%04x of partition "
4229 "table %d will be corrected by w(rite)\n"),
4230 part_table_flag(pe->sectorbuffer), i + 1);
4231 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4240 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4242 * Print the message MESG, then read an integer between LOW and HIGH (inclusive).
4243 * If the user hits Enter, DFLT is returned.
4244 * Answers like +10 are interpreted as offsets from BASE.
4246 * There is no default if DFLT is not between LOW and HIGH.
4249 read_int(uint low, uint dflt, uint high, uint base, char *mesg)
4253 static char *ms = NULL;
4254 static int mslen = 0;
4256 if (!ms || strlen(mesg)+100 > mslen) {
4257 mslen = strlen(mesg)+200;
4258 ms = xrealloc(ms,mslen);
4261 if (dflt < low || dflt > high)
4265 snprintf(ms, mslen, _("%s (%u-%u, default %u): "),
4266 mesg, low, high, dflt);
4268 snprintf(ms, mslen, "%s (%u-%u): ", mesg, low, high);
4271 int use_default = default_ok;
4273 /* ask question and read answer */
4274 while (read_chars(ms) != '\n' && !isdigit(*line_ptr)
4275 && *line_ptr != '-' && *line_ptr != '+')
4278 if (*line_ptr == '+' || *line_ptr == '-') {
4279 int minus = (*line_ptr == '-');
4282 i = atoi(line_ptr+1);
4284 while (isdigit(*++line_ptr))
4287 switch (*line_ptr) {
4290 if (!display_in_cyl_units)
4291 i *= heads * sectors;
4305 absolute = 1000000000;
4311 unsigned long long bytes;
4314 bytes = (unsigned long long) i * absolute;
4315 unit = sector_size * units_per_sector;
4316 bytes += unit/2; /* round */
4325 while (isdigit(*line_ptr)) {
4331 printf(_("Using default value %u\n"), i = dflt);
4332 if (i >= low && i <= high)
4335 printf(_("Value out of range.\n"));
4341 get_partition(int warn, int max)
4346 i = read_int(1, 0, max, 0, _("Partition number")) - 1;
4350 if ((!sun_label && !sgi_label && !pe->part_table->sys_ind)
4351 #ifdef CONFIG_FEATURE_SUN_LABEL
4353 (!sunlabel->partitions[i].num_sectors ||
4354 !sunlabel->infos[i].id))
4356 #ifdef CONFIG_FEATURE_SGI_LABEL
4357 || (sgi_label && (!sgi_get_num_sectors(i)))
4361 _("Warning: partition %d has empty type\n"),
4368 get_existing_partition(int warn, int max)
4373 for (i = 0; i < max; i++) {
4374 struct pte *pe = &ptes[i];
4375 struct partition *p = pe->part_table;
4377 if (p && !is_cleared_partition(p)) {
4384 printf(_("Selected partition %d\n"), pno+1);
4387 printf(_("No partition is defined yet!\n"));
4391 return get_partition(warn, max);
4395 get_nonexisting_partition(int warn, int max)
4400 for (i = 0; i < max; i++) {
4401 struct pte *pe = &ptes[i];
4402 struct partition *p = pe->part_table;
4404 if (p && is_cleared_partition(p)) {
4411 printf(_("Selected partition %d\n"), pno+1);
4414 printf(_("All primary partitions have been defined already!\n"));
4418 return get_partition(warn, max);
4422 void change_units(void)
4424 display_in_cyl_units = !display_in_cyl_units;
4426 printf(_("Changing display/entry units to %s\n"),
4431 toggle_active(int i)
4433 struct pte *pe = &ptes[i];
4434 struct partition *p = pe->part_table;
4436 if (IS_EXTENDED(p->sys_ind) && !p->boot_ind)
4438 _("WARNING: Partition %d is an extended partition\n"),
4440 p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG);
4445 toggle_dos_compatibility_flag(void)
4447 dos_compatible_flag = ~dos_compatible_flag;
4448 if (dos_compatible_flag) {
4449 sector_offset = sectors;
4450 printf(_("DOS Compatibility flag is set\n"));
4454 printf(_("DOS Compatibility flag is not set\n"));
4459 delete_partition(int i)
4461 struct pte *pe = &ptes[i];
4462 struct partition *p = pe->part_table;
4463 struct partition *q = pe->ext_pointer;
4465 /* Note that for the fifth partition (i == 4) we don't actually
4466 * decrement partitions.
4469 if (warn_geometry())
4470 return; /* C/H/S not set */
4473 #ifdef CONFIG_FEATURE_SUN_LABEL
4475 sun_delete_partition(i);
4479 #ifdef CONFIG_FEATURE_SGI_LABEL
4481 sgi_delete_partition(i);
4487 if (IS_EXTENDED(p->sys_ind) && i == ext_index) {
4489 ptes[ext_index].ext_pointer = NULL;
4490 extended_offset = 0;
4496 if (!q->sys_ind && i > 4) {
4497 /* the last one in the chain - just delete */
4500 clear_partition(ptes[i].ext_pointer);
4501 ptes[i].changed = 1;
4503 /* not the last one - further ones will be moved down */
4505 /* delete this link in the chain */
4506 p = ptes[i-1].ext_pointer;
4508 set_start_sect(p, get_start_sect(q));
4509 set_nr_sects(p, get_nr_sects(q));
4510 ptes[i-1].changed = 1;
4511 } else if (partitions > 5) { /* 5 will be moved to 4 */
4512 /* the first logical in a longer chain */
4515 if (pe->part_table) /* prevent SEGFAULT */
4516 set_start_sect(pe->part_table,
4517 get_partition_start(pe) -
4519 pe->offset = extended_offset;
4523 if (partitions > 5) {
4525 while (i < partitions) {
4526 ptes[i] = ptes[i+1];
4530 /* the only logical: clear only */
4531 clear_partition(ptes[i].part_table);
4538 int i, sys, origsys;
4539 struct partition *p;
4541 #ifdef CONFIG_FEATURE_SGI_LABEL
4542 /* If sgi_label then don't use get_existing_partition,
4543 let the user select a partition, since get_existing_partition()
4544 only works for Linux like partition tables. */
4546 i = get_existing_partition(0, partitions);
4548 i = get_partition(0, partitions);
4551 i = get_existing_partition(0, partitions);
4555 p = ptes[i].part_table;
4556 origsys = sys = get_sysid(i);
4558 /* if changing types T to 0 is allowed, then
4559 the reverse change must be allowed, too */
4560 if (!sys && !sgi_label && !sun_label && !get_nr_sects(p))
4561 printf(_("Partition %d does not exist yet!\n"), i + 1);
4563 sys = read_hex (get_sys_types());
4565 if (!sys && !sgi_label && !sun_label) {
4566 printf(_("Type 0 means free space to many systems\n"
4567 "(but not to Linux). Having partitions of\n"
4568 "type 0 is probably unwise. You can delete\n"
4569 "a partition using the `d' command.\n"));
4573 if (!sun_label && !sgi_label) {
4574 if (IS_EXTENDED(sys) != IS_EXTENDED(p->sys_ind)) {
4575 printf(_("You cannot change a partition into"
4576 " an extended one or vice versa\n"
4577 "Delete it first.\n"));
4583 #ifdef CONFIG_FEATURE_SUN_LABEL
4584 if (sun_label && i == 2 && sys != WHOLE_DISK)
4585 printf(_("Consider leaving partition 3 "
4586 "as Whole disk (5),\n"
4587 "as SunOS/Solaris expects it and "
4588 "even Linux likes it.\n\n"));
4590 #ifdef CONFIG_FEATURE_SGI_LABEL
4591 if (sgi_label && ((i == 10 && sys != ENTIRE_DISK)
4592 || (i == 8 && sys != 0)))
4593 printf(_("Consider leaving partition 9 "
4594 "as volume header (0),\nand "
4595 "partition 11 as entire volume (6)"
4596 "as IRIX expects it.\n\n"));
4600 #ifdef CONFIG_FEATURE_SUN_LABEL
4602 sun_change_sysid(i, sys);
4605 #ifdef CONFIG_FEATURE_SGI_LABEL
4607 sgi_change_sysid(i, sys);
4611 printf(_("Changed system type of partition %d "
4612 "to %x (%s)\n"), i + 1, sys,
4613 partition_type(sys));
4614 ptes[i].changed = 1;
4615 if (is_dos_partition(origsys) ||
4616 is_dos_partition(sys))
4622 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
4625 /* check_consistency() and long2chs() added Sat Mar 6 12:28:16 1993,
4626 * faith@cs.unc.edu, based on code fragments from pfdisk by Gordon W. Ross,
4627 * Jan. 1990 (version 1.2.1 by Gordon W. Ross Aug. 1990; Modified by S.
4628 * Lubkin Oct. 1991). */
4631 long2chs(ulong ls, uint *c, uint *h, uint *s)
4633 int spc = heads * sectors;
4638 *s = ls % sectors + 1; /* sectors count from 1 */
4642 check_consistency(const struct partition *p, int partition)
4644 uint pbc, pbh, pbs; /* physical beginning c, h, s */
4645 uint pec, peh, pes; /* physical ending c, h, s */
4646 uint lbc, lbh, lbs; /* logical beginning c, h, s */
4647 uint lec, leh, les; /* logical ending c, h, s */
4649 if (!heads || !sectors || (partition >= 4))
4650 return; /* do not check extended partitions */
4652 /* physical beginning c, h, s */
4653 pbc = (p->cyl & 0xff) | ((p->sector << 2) & 0x300);
4655 pbs = p->sector & 0x3f;
4657 /* physical ending c, h, s */
4658 pec = (p->end_cyl & 0xff) | ((p->end_sector << 2) & 0x300);
4660 pes = p->end_sector & 0x3f;
4662 /* compute logical beginning (c, h, s) */
4663 long2chs(get_start_sect(p), &lbc, &lbh, &lbs);
4665 /* compute logical ending (c, h, s) */
4666 long2chs(get_start_sect(p) + get_nr_sects(p) - 1, &lec, &leh, &les);
4668 /* Same physical / logical beginning? */
4669 if (cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) {
4670 printf(_("Partition %d has different physical/logical "
4671 "beginnings (non-Linux?):\n"), partition + 1);
4672 printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs);
4673 printf(_("logical=(%d, %d, %d)\n"),lbc, lbh, lbs);
4676 /* Same physical / logical ending? */
4677 if (cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) {
4678 printf(_("Partition %d has different physical/logical "
4679 "endings:\n"), partition + 1);
4680 printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
4681 printf(_("logical=(%d, %d, %d)\n"),lec, leh, les);
4685 /* Beginning on cylinder boundary? */
4686 if (pbh != !pbc || pbs != 1) {
4687 printf(_("Partition %i does not start on cylinder "
4688 "boundary:\n"), partition + 1);
4689 printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs);
4690 printf(_("should be (%d, %d, 1)\n"), pbc, !pbc);
4694 /* Ending on cylinder boundary? */
4695 if (peh != (heads - 1) || pes != sectors) {
4696 printf(_("Partition %i does not end on cylinder boundary.\n"),
4699 printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
4700 printf(_("should be (%d, %d, %d)\n"),
4701 pec, heads - 1, sectors);
4707 list_disk_geometry(void)
4709 long long bytes = (total_number_of_sectors << 9);
4710 long megabytes = bytes/1000000;
4712 if (megabytes < 10000)
4713 printf(_("\nDisk %s: %ld MB, %lld bytes\n"),
4714 disk_device, megabytes, bytes);
4716 printf(_("\nDisk %s: %ld.%ld GB, %lld bytes\n"),
4717 disk_device, megabytes/1000, (megabytes/100)%10, bytes);
4718 printf(_("%d heads, %d sectors/track, %d cylinders"),
4719 heads, sectors, cylinders);
4720 if (units_per_sector == 1)
4721 printf(_(", total %llu sectors"),
4722 total_number_of_sectors / (sector_size/512));
4723 printf(_("\nUnits = %s of %d * %d = %d bytes\n\n"),
4725 units_per_sector, sector_size, units_per_sector * sector_size);
4729 * Check whether partition entries are ordered by their starting positions.
4730 * Return 0 if OK. Return i if partition i should have been earlier.
4731 * Two separate checks: primary and logical partitions.
4734 wrong_p_order(int *prev)
4736 const struct pte *pe;
4737 const struct partition *p;
4738 off_t last_p_start_pos = 0, p_start_pos;
4741 for (i = 0 ; i < partitions; i++) {
4744 last_p_start_pos = 0;
4747 if ((p = pe->part_table)->sys_ind) {
4748 p_start_pos = get_partition_start(pe);
4750 if (last_p_start_pos > p_start_pos) {
4756 last_p_start_pos = p_start_pos;
4763 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
4765 * Fix the chain of logicals.
4766 * extended_offset is unchanged, the set of sectors used is unchanged
4767 * The chain is sorted so that sectors increase, and so that
4768 * starting sectors increase.
4770 * After this it may still be that cfdisk doesnt like the table.
4771 * (This is because cfdisk considers expanded parts, from link to
4772 * end of partition, and these may still overlap.)
4774 * sfdisk /dev/hda > ohda; sfdisk /dev/hda < ohda
4778 fix_chain_of_logicals(void)
4780 int j, oj, ojj, sj, sjj;
4781 struct partition *pj,*pjj,tmp;
4783 /* Stage 1: sort sectors but leave sector of part 4 */
4784 /* (Its sector is the global extended_offset.) */
4786 for (j = 5; j < partitions-1; j++) {
4787 oj = ptes[j].offset;
4788 ojj = ptes[j+1].offset;
4790 ptes[j].offset = ojj;
4791 ptes[j+1].offset = oj;
4792 pj = ptes[j].part_table;
4793 set_start_sect(pj, get_start_sect(pj)+oj-ojj);
4794 pjj = ptes[j+1].part_table;
4795 set_start_sect(pjj, get_start_sect(pjj)+ojj-oj);
4796 set_start_sect(ptes[j-1].ext_pointer,
4797 ojj-extended_offset);
4798 set_start_sect(ptes[j].ext_pointer,
4799 oj-extended_offset);
4804 /* Stage 2: sort starting sectors */
4806 for (j = 4; j < partitions-1; j++) {
4807 pj = ptes[j].part_table;
4808 pjj = ptes[j+1].part_table;
4809 sj = get_start_sect(pj);
4810 sjj = get_start_sect(pjj);
4811 oj = ptes[j].offset;
4812 ojj = ptes[j+1].offset;
4813 if (oj+sj > ojj+sjj) {
4817 set_start_sect(pj, ojj+sjj-oj);
4818 set_start_sect(pjj, oj+sj-ojj);
4823 /* Probably something was changed */
4824 for (j = 4; j < partitions; j++)
4825 ptes[j].changed = 1;
4830 fix_partition_table_order(void)
4832 struct pte *pei, *pek;
4835 if (!wrong_p_order(NULL)) {
4836 printf(_("Nothing to do. Ordering is correct already.\n\n"));
4840 while ((i = wrong_p_order(&k)) != 0 && i < 4) {
4841 /* partition i should have come earlier, move it */
4842 /* We have to move data in the MBR */
4843 struct partition *pi, *pk, *pe, pbuf;
4847 pe = pei->ext_pointer;
4848 pei->ext_pointer = pek->ext_pointer;
4849 pek->ext_pointer = pe;
4851 pi = pei->part_table;
4852 pk = pek->part_table;
4854 memmove(&pbuf, pi, sizeof(struct partition));
4855 memmove(pi, pk, sizeof(struct partition));
4856 memmove(pk, &pbuf, sizeof(struct partition));
4858 pei->changed = pek->changed = 1;
4862 fix_chain_of_logicals();
4870 list_table(int xtra)
4872 const struct partition *p;
4875 #ifdef CONFIG_FEATURE_SUN_LABEL
4877 sun_list_table(xtra);
4882 #ifdef CONFIG_FEATURE_SGI_LABEL
4884 sgi_list_table(xtra);
4889 list_disk_geometry();
4891 #ifdef CONFIG_FEATURE_OSF_LABEL
4893 xbsd_print_disklabel(xtra);
4898 /* Heuristic: we list partition 3 of /dev/foo as /dev/foo3,
4899 but if the device name ends in a digit, say /dev/foo1,
4900 then the partition is called /dev/foo1p3. */
4901 w = strlen(disk_device);
4902 if (w && isdigit(disk_device[w-1]))
4907 printf(_("%*s Boot Start End Blocks Id System\n"),
4910 for (i = 0; i < partitions; i++) {
4911 const struct pte *pe = &ptes[i];
4914 if (p && !is_cleared_partition(p)) {
4915 off_t psects = get_nr_sects(p);
4916 off_t pblocks = psects;
4917 unsigned int podd = 0;
4919 if (sector_size < 1024) {
4920 pblocks /= (1024 / sector_size);
4921 podd = psects % (1024 / sector_size);
4923 if (sector_size > 1024)
4924 pblocks *= (sector_size / 1024);
4926 "%s %c %11llu %11llu %11llu%c %2x %s\n",
4927 partname(disk_device, i+1, w+2),
4928 /* boot flag */ !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG
4930 /* start */ (unsigned long long) cround(get_partition_start(pe)),
4931 /* end */ (unsigned long long) cround(get_partition_start(pe) + psects
4932 - (psects ? 1 : 0)),
4933 /* odd flag on end */ (unsigned long long) pblocks, podd ? '+' : ' ',
4934 /* type id */ p->sys_ind,
4935 /* type name */ partition_type(p->sys_ind));
4936 check_consistency(p, i);
4940 /* Is partition table in disk order? It need not be, but... */
4941 /* partition table entries are not checked for correct order if this
4942 is a sgi, sun or aix labeled disk... */
4943 if (dos_label && wrong_p_order(NULL)) {
4944 printf(_("\nPartition table entries are not in disk order\n"));
4948 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
4950 x_list_table(int extend)
4952 const struct pte *pe;
4953 const struct partition *p;
4956 printf(_("\nDisk %s: %d heads, %d sectors, %d cylinders\n\n"),
4957 disk_device, heads, sectors, cylinders);
4958 printf(_("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n"));
4959 for (i = 0 ; i < partitions; i++) {
4961 p = (extend ? pe->ext_pointer : pe->part_table);
4963 printf("%2d %02x%4d%4d%5d%4d%4d%5d%11u%11u %02x\n",
4964 i + 1, p->boot_ind, p->head,
4966 cylinder(p->sector, p->cyl), p->end_head,
4967 sector(p->end_sector),
4968 cylinder(p->end_sector, p->end_cyl),
4969 get_start_sect(p), get_nr_sects(p), p->sys_ind);
4971 check_consistency(p, i);
4977 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4979 fill_bounds(off_t *first, off_t *last)
4982 const struct pte *pe = &ptes[0];
4983 const struct partition *p;
4985 for (i = 0; i < partitions; pe++,i++) {
4987 if (!p->sys_ind || IS_EXTENDED(p->sys_ind)) {
4988 first[i] = 0xffffffff;
4991 first[i] = get_partition_start(pe);
4992 last[i] = first[i] + get_nr_sects(p) - 1;
4998 check(int n, uint h, uint s, uint c, off_t start)
5000 off_t total, real_s, real_c;
5002 real_s = sector(s) - 1;
5003 real_c = cylinder(s, c);
5004 total = (real_c * sectors + real_s) * heads + h;
5006 fprintf(stderr, _("Warning: partition %d contains sector 0\n"), n);
5009 _("Partition %d: head %d greater than maximum %d\n"),
5011 if (real_s >= sectors)
5012 fprintf(stderr, _("Partition %d: sector %d greater than "
5013 "maximum %d\n"), n, s, sectors);
5014 if (real_c >= cylinders)
5015 fprintf(stderr, _("Partitions %d: cylinder %llu greater than "
5016 "maximum %d\n"), n, (unsigned long long)real_c + 1, cylinders);
5017 if (cylinders <= 1024 && start != total)
5019 _("Partition %d: previous sectors %llu disagrees with "
5020 "total %llu\n"), n, (unsigned long long)start, (unsigned long long)total);
5028 off_t first[partitions], last[partitions];
5029 struct partition *p;
5031 if (warn_geometry())
5034 #ifdef CONFIG_FEATURE_SUN_LABEL
5040 #ifdef CONFIG_FEATURE_SGI_LABEL
5047 fill_bounds(first, last);
5048 for (i = 0; i < partitions; i++) {
5049 struct pte *pe = &ptes[i];
5052 if (p->sys_ind && !IS_EXTENDED(p->sys_ind)) {
5053 check_consistency(p, i);
5054 if (get_partition_start(pe) < first[i])
5055 printf(_("Warning: bad start-of-data in "
5056 "partition %d\n"), i + 1);
5057 check(i + 1, p->end_head, p->end_sector, p->end_cyl,
5059 total += last[i] + 1 - first[i];
5060 for (j = 0; j < i; j++)
5061 if ((first[i] >= first[j] && first[i] <= last[j])
5062 || ((last[i] <= last[j] && last[i] >= first[j]))) {
5063 printf(_("Warning: partition %d overlaps "
5064 "partition %d.\n"), j + 1, i + 1);
5065 total += first[i] >= first[j] ?
5066 first[i] : first[j];
5067 total -= last[i] <= last[j] ?
5073 if (extended_offset) {
5074 struct pte *pex = &ptes[ext_index];
5075 off_t e_last = get_start_sect(pex->part_table) +
5076 get_nr_sects(pex->part_table) - 1;
5078 for (i = 4; i < partitions; i++) {
5080 p = ptes[i].part_table;
5082 if (i != 4 || i + 1 < partitions)
5083 printf(_("Warning: partition %d "
5084 "is empty\n"), i + 1);
5086 else if (first[i] < extended_offset ||
5088 printf(_("Logical partition %d not entirely in "
5089 "partition %d\n"), i + 1, ext_index + 1);
5093 if (total > heads * sectors * cylinders)
5094 printf(_("Total allocated sectors %d greater than the maximum "
5095 "%d\n"), total, heads * sectors * cylinders);
5096 else if ((total = heads * sectors * cylinders - total) != 0)
5097 printf(_("%d unallocated sectors\n"), total);
5101 add_partition(int n, int sys)
5103 char mesg[256]; /* 48 does not suffice in Japanese */
5105 struct partition *p = ptes[n].part_table;
5106 struct partition *q = ptes[ext_index].part_table;
5108 off_t start, stop = 0, limit, temp,
5109 first[partitions], last[partitions];
5111 if (p && p->sys_ind) {
5112 printf(_("Partition %d is already defined. Delete "
5113 "it before re-adding it.\n"), n + 1);
5116 fill_bounds(first, last);
5118 start = sector_offset;
5119 if (display_in_cyl_units || !total_number_of_sectors)
5120 llimit = heads * sectors * cylinders - 1;
5122 llimit = total_number_of_sectors - 1;
5124 if (limit != llimit)
5126 if (extended_offset) {
5127 first[ext_index] = extended_offset;
5128 last[ext_index] = get_start_sect(q) +
5129 get_nr_sects(q) - 1;
5132 start = extended_offset + sector_offset;
5133 limit = get_start_sect(q) + get_nr_sects(q) - 1;
5135 if (display_in_cyl_units)
5136 for (i = 0; i < partitions; i++)
5137 first[i] = (cround(first[i]) - 1) * units_per_sector;
5139 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
5142 for (i = 0; i < partitions; i++) {
5145 if (start == ptes[i].offset)
5146 start += sector_offset;
5147 lastplusoff = last[i] + ((n < 4) ? 0 : sector_offset);
5148 if (start >= first[i] && start <= lastplusoff)
5149 start = lastplusoff + 1;
5153 if (start >= temp+units_per_sector && readed) {
5154 printf(_("Sector %llu is already allocated\n"), (unsigned long long)temp);
5158 if (!readed && start == temp) {
5161 saved_start = start;
5162 start = read_int(cround(saved_start), cround(saved_start), cround(limit),
5164 if (display_in_cyl_units) {
5165 start = (start - 1) * units_per_sector;
5166 if (start < saved_start) start = saved_start;
5170 } while (start != temp || !readed);
5171 if (n > 4) { /* NOT for fifth partition */
5172 struct pte *pe = &ptes[n];
5174 pe->offset = start - sector_offset;
5175 if (pe->offset == extended_offset) { /* must be corrected */
5177 if (sector_offset == 1)
5182 for (i = 0; i < partitions; i++) {
5183 struct pte *pe = &ptes[i];
5185 if (start < pe->offset && limit >= pe->offset)
5186 limit = pe->offset - 1;
5187 if (start < first[i] && limit >= first[i])
5188 limit = first[i] - 1;
5190 if (start > limit) {
5191 printf(_("No free sectors available\n"));
5196 if (cround(start) == cround(limit)) {
5199 snprintf(mesg, sizeof(mesg),
5200 _("Last %s or +size or +sizeM or +sizeK"),
5201 str_units(SINGULAR));
5202 stop = read_int(cround(start), cround(limit), cround(limit),
5203 cround(start), mesg);
5204 if (display_in_cyl_units) {
5205 stop = stop * units_per_sector - 1;
5211 set_partition(n, 0, start, stop, sys);
5213 set_partition(n - 1, 1, ptes[n].offset, stop, EXTENDED);
5215 if (IS_EXTENDED(sys)) {
5216 struct pte *pe4 = &ptes[4];
5217 struct pte *pen = &ptes[n];
5220 pen->ext_pointer = p;
5221 pe4->offset = extended_offset = start;
5222 pe4->sectorbuffer = xcalloc(1, sector_size);
5223 pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
5224 pe4->ext_pointer = pe4->part_table + 1;
5233 if (partitions > 5 || ptes[4].part_table->sys_ind) {
5234 struct pte *pe = &ptes[partitions];
5236 pe->sectorbuffer = xcalloc(1, sector_size);
5237 pe->part_table = pt_offset(pe->sectorbuffer, 0);
5238 pe->ext_pointer = pe->part_table + 1;
5243 add_partition(partitions - 1, LINUX_NATIVE);
5249 int i, free_primary = 0;
5251 if (warn_geometry())
5254 #ifdef CONFIG_FEATURE_SUN_LABEL
5256 add_sun_partition(get_partition(0, partitions), LINUX_NATIVE);
5260 #ifdef CONFIG_FEATURE_SGI_LABEL
5262 sgi_add_partition(get_partition(0, partitions), LINUX_NATIVE);
5266 #ifdef CONFIG_FEATURE_AIX_LABEL
5268 printf(_("\tSorry - this fdisk cannot handle AIX disk labels."
5269 "\n\tIf you want to add DOS-type partitions, create"
5270 "\n\ta new empty DOS partition table first. (Use o.)"
5272 "This will destroy the present disk contents.\n"));
5277 for (i = 0; i < 4; i++)
5278 free_primary += !ptes[i].part_table->sys_ind;
5280 if (!free_primary && partitions >= MAXIMUM_PARTS) {
5281 printf(_("The maximum number of partitions has been created\n"));
5285 if (!free_primary) {
5286 if (extended_offset)
5289 printf(_("You must delete some partition and add "
5290 "an extended partition first\n"));
5292 char c, line[LINE_LENGTH];
5293 snprintf(line, sizeof(line), "%s\n %s\n p primary "
5294 "partition (1-4)\n",
5295 "Command action", (extended_offset ?
5296 "l logical (5 or over)" : "e extended"));
5298 if ((c = read_char(line)) == 'p' || c == 'P') {
5299 i = get_nonexisting_partition(0, 4);
5301 add_partition(i, LINUX_NATIVE);
5304 else if (c == 'l' && extended_offset) {
5308 else if (c == 'e' && !extended_offset) {
5309 i = get_nonexisting_partition(0, 4);
5311 add_partition(i, EXTENDED);
5315 printf(_("Invalid partition number "
5316 "for type `%c'\n"), c);
5327 for (i = 0; i < 3; i++)
5328 if (ptes[i].changed)
5329 ptes[3].changed = 1;
5330 for (i = 3; i < partitions; i++) {
5331 struct pte *pe = &ptes[i];
5334 write_part_table_flag(pe->sectorbuffer);
5335 write_sector(pe->offset, pe->sectorbuffer);
5339 #ifdef CONFIG_FEATURE_SGI_LABEL
5340 else if (sgi_label) {
5341 /* no test on change? the printf below might be mistaken */
5345 #ifdef CONFIG_FEATURE_SUN_LABEL
5346 else if (sun_label) {
5349 for (i = 0; i < 8; i++)
5350 if (ptes[i].changed)
5357 printf(_("The partition table has been altered!\n\n"));
5358 reread_partition_table(1);
5362 reread_partition_table(int leave)
5367 printf(_("Calling ioctl() to re-read partition table.\n"));
5370 if ((i = ioctl(fd, BLKRRPART)) != 0) {
5373 /* some kernel versions (1.2.x) seem to have trouble
5374 rereading the partition table, but if asked to do it
5375 twice, the second time works. - biro@yggdrasil.com */
5378 if ((i = ioctl(fd, BLKRRPART)) != 0)
5383 printf(_("\nWARNING: Re-reading the partition table "
5384 "failed with error %d: %s.\n"
5385 "The kernel still uses the old table.\n"
5386 "The new table will be used "
5387 "at the next reboot.\n"),
5388 error, strerror(error));
5393 _("\nWARNING: If you have created or modified any DOS 6.x\n"
5394 "partitions, please see the fdisk manual page for additional\n"
5400 printf(_("Syncing disks.\n"));
5402 sleep(4); /* for sync() */
5406 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
5408 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
5409 #define MAX_PER_LINE 16
5411 print_buffer(char *pbuffer)
5415 for (i = 0, l = 0; i < sector_size; i++, l++) {
5417 printf("0x%03X:", i);
5418 printf(" %02X", (unsigned char) pbuffer[i]);
5419 if (l == MAX_PER_LINE - 1) {
5435 printf(_("Device: %s\n"), disk_device);
5436 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
5437 if (sun_label || sgi_label)
5438 print_buffer(MBRbuffer);
5441 for (i = 3; i < partitions; i++)
5442 print_buffer(ptes[i].sectorbuffer);
5448 struct pte *pe = &ptes[i];
5449 struct partition *p = pe->part_table;
5452 if (warn_geometry())
5454 if (!p->sys_ind || !get_nr_sects(p) || IS_EXTENDED(p->sys_ind)) {
5455 printf(_("Partition %d has no data area\n"), i + 1);
5458 first = get_partition_start(pe);
5459 new = read_int(first, first, first + get_nr_sects(p) - 1, first,
5460 _("New beginning of data")) - pe->offset;
5462 if (new != get_nr_sects(p)) {
5463 first = get_nr_sects(p) + get_start_sect(p) - new;
5464 set_nr_sects(p, first);
5465 set_start_sect(p, new);
5477 c = tolower(read_char(_("Expert command (m for help): ")));
5480 #ifdef CONFIG_FEATURE_SUN_LABEL
5487 move_begin(get_partition(0, partitions));
5490 user_cylinders = cylinders =
5491 read_int(1, cylinders, 1048576, 0,
5492 _("Number of cylinders"));
5493 #ifdef CONFIG_FEATURE_SUN_LABEL
5495 sun_set_ncyl(cylinders);
5504 #ifdef CONFIG_FEATURE_SGI_LABEL
5509 #ifdef CONFIG_FEATURE_SUN_LABEL
5519 fix_partition_table_order();
5522 #ifdef CONFIG_FEATURE_SGI_LABEL
5527 user_heads = heads = read_int(1, heads, 256, 0,
5528 _("Number of heads"));
5532 #ifdef CONFIG_FEATURE_SUN_LABEL
5538 #ifdef CONFIG_FEATURE_SUN_LABEL
5544 #ifdef CONFIG_FEATURE_SUN_LABEL
5558 user_sectors = sectors = read_int(1, sectors, 63, 0,
5559 _("Number of sectors"));
5560 if (dos_compatible_flag) {
5561 sector_offset = sectors;
5562 fprintf(stderr, _("Warning: setting "
5563 "sector offset for DOS "
5572 write_table(); /* does not return */
5575 #ifdef CONFIG_FEATURE_SUN_LABEL
5577 sun_set_pcylcount();
5585 #endif /* ADVANCED mode */
5588 is_ide_cdrom_or_tape(const char *device)
5592 struct stat statbuf;
5595 /* No device was given explicitly, and we are trying some
5596 likely things. But opening /dev/hdc may produce errors like
5597 "hdc: tray open or drive not ready"
5598 if it happens to be a CD-ROM drive. It even happens that
5599 the process hangs on the attempt to read a music CD.
5600 So try to be careful. This only works since 2.1.73. */
5602 if (strncmp("/dev/hd", device, 7))
5605 snprintf(buf, sizeof(buf), "/proc/ide/%s/media", device+5);
5606 procf = fopen(buf, "r");
5607 if (procf != NULL && fgets(buf, sizeof(buf), procf))
5608 is_ide = (!strncmp(buf, "cdrom", 5) ||
5609 !strncmp(buf, "tape", 4));
5611 /* Now when this proc file does not exist, skip the
5612 device when it is read-only. */
5613 if (stat(device, &statbuf) == 0)
5614 is_ide = ((statbuf.st_mode & 0222) == 0);
5622 try(const char *device, int user_specified)
5626 disk_device = device;
5627 if (setjmp(listingbuf))
5629 if (!user_specified)
5630 if (is_ide_cdrom_or_tape(device))
5632 if ((fd = open(disk_device, type_open)) >= 0) {
5633 gb = get_boot(try_only);
5634 if (gb > 0) { /* I/O error */
5636 } else if (gb < 0) { /* no DOS signature */
5637 list_disk_geometry();
5640 #ifdef CONFIG_FEATURE_OSF_LABEL
5641 if (btrydev(device) < 0)
5644 _("Disk %s doesn't contain a valid "
5645 "partition table\n"), device);
5650 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5651 if (!sun_label && partitions > 4)
5652 delete_partition(ext_index);
5656 /* Ignore other errors, since we try IDE
5657 and SCSI hard disks which may not be
5658 installed on the system. */
5659 if (errno == EACCES) {
5660 fprintf(stderr, _("Cannot open %s\n"), device);
5666 /* for fdisk -l: try all things in /proc/partitions
5667 that look like a partition name (do not end in a digit) */
5672 char line[100], ptname[100], devname[120], *s;
5675 procpt = bb_wfopen(PROC_PARTITIONS, "r");
5677 while (fgets(line, sizeof(line), procpt)) {
5678 if (sscanf(line, " %d %d %d %[^\n ]",
5679 &ma, &mi, &sz, ptname) != 4)
5681 for (s = ptname; *s; s++);
5684 sprintf(devname, "/dev/%s", ptname);
5687 #ifdef CONFIG_FEATURE_CLEAN_UP
5692 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5694 unknown_command(int c)
5696 printf(_("%c: unknown command\n"), c);
5700 int fdisk_main(int argc, char **argv)
5703 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5706 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5712 * fdisk -l [-b sectorsize] [-u] device ...
5713 * fdisk -s [partition] ...
5714 * fdisk [-b sectorsize] [-u] device
5716 * Options -C, -H, -S set the geometry.
5719 while ((c = getopt(argc, argv, "b:C:H:lS:uvV"
5720 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5726 /* Ugly: this sector size is really per device,
5727 so cannot be combined with multiple disks,
5728 and te same goes for the C/H/S options.
5730 sector_size = atoi(optarg);
5731 if (sector_size != 512 && sector_size != 1024 &&
5732 sector_size != 2048)
5735 user_set_sector_size = 1;
5738 user_cylinders = atoi(optarg);
5741 user_heads = atoi(optarg);
5742 if (user_heads <= 0 || user_heads >= 256)
5746 user_sectors = atoi(optarg);
5747 if (user_sectors <= 0 || user_sectors >= 64)
5751 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5755 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5761 display_in_cyl_units = 0;
5765 printf("fdisk v" UTIL_LINUX_VERSION "\n");
5773 printf(_("This kernel finds the sector size itself - "
5774 "-b option ignored\n"));
5776 if (user_set_sector_size && argc-optind != 1)
5777 printf(_("Warning: the -b (set sector size) option should"
5778 " be used with one specified device\n"));
5781 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5785 type_open = O_RDONLY;
5786 if (argc > optind) {
5789 /* avoid gcc warning:
5790 variable `k' might be clobbered by `longjmp' */
5794 for (k = optind; k < argc; k++)
5797 /* we no longer have default device names */
5798 /* but, we can use /proc/partitions instead */
5802 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5806 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5812 type_open = O_RDONLY;
5814 opts = argc - optind;
5818 for (j = optind; j < argc; j++) {
5819 disk_device = argv[j];
5820 if ((fd = open(disk_device, type_open)) < 0)
5821 fdisk_fatal(unable_to_open);
5822 if (ioctl(fd, BLKGETSIZE, &size))
5823 fdisk_fatal(ioctl_error);
5826 printf("%ld\n", size/2);
5828 printf("%s: %ld\n", argv[j], size/2);
5834 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5835 if (argc-optind == 1)
5836 disk_device = argv[optind];
5842 #ifdef CONFIG_FEATURE_OSF_LABEL
5844 /* OSF label, and no DOS label */
5845 printf(_("Detected an OSF/1 disklabel on %s, entering "
5846 "disklabel mode.\n"),
5850 /* If we return we may want to make an empty DOS label? */
5856 c = tolower(read_char(_("Command (m for help): ")));
5860 toggle_active(get_partition(1, partitions));
5861 #ifdef CONFIG_FEATURE_SUN_LABEL
5863 toggle_sunflags(get_partition(1, partitions),
5866 #ifdef CONFIG_FEATURE_SGI_LABEL
5868 sgi_set_bootpartition(
5869 get_partition(1, partitions));
5875 #ifdef CONFIG_FEATURE_SGI_LABEL
5877 printf(_("\nThe current boot file is: %s\n"),
5878 sgi_get_bootfile());
5879 if (read_chars(_("Please enter the name of the "
5880 "new boot file: ")) == '\n')
5881 printf(_("Boot file unchanged\n"));
5883 sgi_set_bootfile(line_ptr);
5886 #ifdef CONFIG_FEATURE_OSF_LABEL
5892 toggle_dos_compatibility_flag();
5893 #ifdef CONFIG_FEATURE_SUN_LABEL
5895 toggle_sunflags(get_partition(1, partitions),
5898 #ifdef CONFIG_FEATURE_SGI_LABEL
5900 sgi_set_swappartition(
5901 get_partition(1, partitions));
5909 #ifdef CONFIG_FEATURE_SGI_LABEL
5910 /* If sgi_label then don't use get_existing_partition,
5911 let the user select a partition, since
5912 get_existing_partition() only works for Linux-like
5915 j = get_existing_partition(1, partitions);
5917 j = get_partition(1, partitions);
5920 j = get_existing_partition(1, partitions);
5923 delete_partition(j);
5927 #ifdef CONFIG_FEATURE_SGI_LABEL
5934 list_types(get_sys_types());
5953 #ifdef CONFIG_FEATURE_SUN_LABEL
5967 write_table(); /* does not return */
5969 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
5971 #ifdef CONFIG_FEATURE_SGI_LABEL
5974 _("\n\tSorry, no experts menu for SGI "
5975 "partition tables available.\n\n"));
5988 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */