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>
42 #define BLKRRPART _IO(0x12,95) /* re-read partition table */
43 #define BLKGETSIZE _IO(0x12,96) /* return device size */
44 #define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */
45 #define BLKSSZGET _IO(0x12,104) /* get block device sector size */
47 /* Avoid conflicts with the 2.6 kernel headers, which define
48 * _IOR rather differently */
50 #define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size))
51 #define BLKGETSIZE64 _IOR(0x12,114,uint64_t)
57 #define DEFAULT_SECTOR_SIZE 512
58 #define MAX_SECTOR_SIZE 2048
59 #define SECTOR_SIZE 512 /* still used in BSD code */
60 #define MAXIMUM_PARTS 60
62 #define ACTIVE_FLAG 0x80
65 #define WIN98_EXTENDED 0x0f
66 #define LINUX_PARTITION 0x81
67 #define LINUX_SWAP 0x82
68 #define LINUX_NATIVE 0x83
69 #define LINUX_EXTENDED 0x85
70 #define LINUX_LVM 0x8e
71 #define LINUX_RAID 0xfd
76 #define IS_EXTENDED(i) \
77 ((i) == EXTENDED || (i) == WIN98_EXTENDED || (i) == LINUX_EXTENDED)
79 #define SIZE(a) (sizeof(a)/sizeof((a)[0]))
81 #define cround(n) (display_in_cyl_units ? ((n)/units_per_sector)+1 : (n))
82 #define scround(x) (((x)+units_per_sector-1)/units_per_sector)
84 #ifdef CONFIG_FEATURE_SUN_LABEL
85 #define SCSI_IOCTL_GET_IDLUN 0x5382
89 /* including <linux/hdreg.h> also fails */
92 unsigned char sectors;
93 unsigned short cylinders;
97 #define HDIO_GETGEO 0x0301 /* get device geometry */
104 static uint sector_size = DEFAULT_SECTOR_SIZE;
105 static uint user_set_sector_size;
106 static uint sector_offset = 1;
109 * Raw disk label. For DOS-type partition tables the MBR,
110 * with descriptions of the primary partitions.
112 #if (MAX_SECTOR_SIZE) > (BUFSIZ+1)
113 static char MBRbuffer[MAX_SECTOR_SIZE];
115 # define MBRbuffer bb_common_bufsiz1
118 #ifdef CONFIG_FEATURE_SUN_LABEL
119 static int sun_label; /* looking at sun disklabel */
123 #ifdef CONFIG_FEATURE_SGI_LABEL
124 static int sgi_label; /* looking at sgi disklabel */
128 #ifdef CONFIG_FEATURE_AIX_LABEL
129 static int aix_label; /* looking at aix disklabel */
133 #ifdef CONFIG_FEATURE_OSF_LABEL
134 static int osf_label; /* looking at OSF/1 disklabel */
135 static int possibly_osf_label;
140 #define dos_label (!sun_label && !sgi_label && !aix_label && !osf_label)
142 static uint heads, sectors, cylinders;
143 static void update_units(void);
147 * return partition name - uses static storage unless buf is supplied
150 partname(const char *dev, int pno, int lth)
152 static char buffer[80];
159 bufsiz = sizeof(buffer);
164 if (isdigit(dev[w-1]))
167 /* devfs kludge - note: fdisk partition names are not supposed
168 to equal kernel names, so there is no reason to do this */
169 if (strcmp(dev + w - 4, "disc") == 0) {
177 snprintf(bufp, bufsiz, "%*.*s%s%-2u",
178 lth-wp-2, w, dev, p, pno);
180 snprintf(bufp, bufsiz, "%.*s%s%-2u", w, dev, p, pno);
186 unsigned char boot_ind; /* 0x80 - active */
187 unsigned char head; /* starting head */
188 unsigned char sector; /* starting sector */
189 unsigned char cyl; /* starting cylinder */
190 unsigned char sys_ind; /* What partition type */
191 unsigned char end_head; /* end head */
192 unsigned char end_sector; /* end sector */
193 unsigned char end_cyl; /* end cylinder */
194 unsigned char start4[4]; /* starting sector counting from 0 */
195 unsigned char size4[4]; /* nr of sectors in partition */
199 ioctl_error, unable_to_open, unable_to_read, unable_to_seek,
203 enum action { fdisk, require, try_only, create_empty_dos, create_empty_sun };
205 static const char *disk_device;
206 static int fd; /* the disk */
207 static int partitions = 4; /* maximum partition + 1 */
208 static uint display_in_cyl_units = 1;
209 static uint units_per_sector = 1;
210 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
211 static char *line_ptr;
212 static void change_units(void);
213 static void reread_partition_table(int leave);
214 static void delete_partition(int i);
215 static int get_partition(int warn, int max);
216 static void list_types(const struct systypes *sys);
217 static uint read_int(uint low, uint dflt, uint high, uint base, char *mesg);
219 static const char *partition_type(unsigned char type);
220 static void fdisk_fatal(enum failure why) ATTRIBUTE_NORETURN;
221 static void get_geometry(void);
222 static int get_boot(enum action what);
227 #define hex_val(c) ({ \
229 isdigit(_c) ? _c - '0' : \
230 tolower(_c) + 10 - 'a'; \
234 #define LINE_LENGTH 800
235 #define pt_offset(b, n) ((struct partition *)((b) + 0x1be + \
236 (n) * sizeof(struct partition)))
237 #define sector(s) ((s) & 0x3f)
238 #define cylinder(s, c) ((c) | (((s) & 0xc0) << 2))
240 #define hsc2sector(h,s,c) (sector(s) - 1 + sectors * \
241 ((h) + heads * cylinder(s,c)))
242 #define set_hsc(h,s,c,sector) { \
243 s = sector % sectors + 1; \
245 h = sector % heads; \
248 s |= (sector >> 2) & 0xc0; \
252 static int32_t get_start_sect(const struct partition *p);
253 static int32_t get_nr_sects(const struct partition *p);
256 * per partition table entry data
258 * The four primary partitions have the same sectorbuffer (MBRbuffer)
259 * and have NULL ext_pointer.
260 * Each logical partition table entry has two pointers, one for the
261 * partition and one link to the next one.
264 struct partition *part_table; /* points into sectorbuffer */
265 struct partition *ext_pointer; /* points into sectorbuffer */
266 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
267 char changed; /* boolean */
269 off_t offset; /* disk sector number */
270 char *sectorbuffer; /* disk sector contents */
271 } ptes[MAXIMUM_PARTS];
274 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
276 set_all_unchanged(void)
280 for (i = 0; i < MAXIMUM_PARTS; i++)
289 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
291 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_OSF_LABEL)
292 static struct partition *
293 get_part_table(int i)
295 return ptes[i].part_table;
301 { /* n==1: use singular */
303 return display_in_cyl_units ? _("cylinder") : _("sector");
305 return display_in_cyl_units ? _("cylinders") : _("sectors");
309 valid_part_table_flag(const char *mbuffer) {
310 const unsigned char *b = (const unsigned char *)mbuffer;
311 return (b[510] == 0x55 && b[511] == 0xaa);
314 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
315 static char line_buffer[LINE_LENGTH];
317 /* read line; return 0 or first char */
321 static int got_eof = 0;
323 fflush (stdout); /* requested by niles@scyld.com */
324 line_ptr = line_buffer;
325 if (!fgets(line_buffer, LINE_LENGTH, stdin)) {
327 got_eof++; /* user typed ^D ? */
329 fprintf(stderr, _("\ngot EOF thrice - exiting..\n"));
334 while (*line_ptr && !isgraph(*line_ptr))
340 read_char(const char *mesg)
344 } while (!read_line());
349 read_chars(const char *mesg)
360 read_hex(const struct systypes *sys)
365 read_char(_("Hex code (type L to list codes): "));
366 if (*line_ptr == 'l' || *line_ptr == 'L')
368 else if (isxdigit (*line_ptr)) {
371 hex = hex << 4 | hex_val(*line_ptr++);
372 while (isxdigit(*line_ptr));
377 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
379 #ifdef CONFIG_FEATURE_AIX_LABEL
381 * Copyright (C) Andreas Neuper, Sep 1998.
382 * This file may be redistributed under
383 * the terms of the GNU Public License.
387 unsigned int magic; /* expect AIX_LABEL_MAGIC */
388 unsigned int fillbytes1[124];
389 unsigned int physical_volume_id;
390 unsigned int fillbytes2[124];
393 #define AIX_LABEL_MAGIC 0xc9c2d4c1
394 #define AIX_LABEL_MAGIC_SWAPPED 0xc1d4c2c9
395 #define AIX_INFO_MAGIC 0x00072959
396 #define AIX_INFO_MAGIC_SWAPPED 0x59290700
398 #define aixlabel ((aix_partition *)MBRbuffer)
403 * 1999-03-20 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
404 * Internationalization
406 * 2003-03-20 Phillip Kesling <pkesling@sgi.com>
410 static int aix_other_endian;
411 static short aix_volumes = 1;
414 * only dealing with free blocks here
421 _("\n\tThere is a valid AIX label on this disk.\n"
422 "\tUnfortunately Linux cannot handle these\n"
423 "\tdisks at the moment. Nevertheless some\n"
425 "\t1. fdisk will destroy its contents on write.\n"
426 "\t2. Be sure that this disk is NOT a still vital\n"
427 "\t part of a volume group. (Otherwise you may\n"
428 "\t erase the other disks as well, if unmirrored.)\n"
429 "\t3. Before deleting this physical volume be sure\n"
430 "\t to remove the disk logically from your AIX\n"
431 "\t machine. (Otherwise you become an AIXpert).")
441 memset(MBRbuffer, 0, sizeof(MBRbuffer)); /* avoid fdisk cores */
446 check_aix_label(void)
448 if (aixlabel->magic != AIX_LABEL_MAGIC &&
449 aixlabel->magic != AIX_LABEL_MAGIC_SWAPPED) {
451 aix_other_endian = 0;
454 aix_other_endian = (aixlabel->magic == AIX_LABEL_MAGIC_SWAPPED);
460 aix_nolabel(); /* %% */
461 aix_label = 1; /* %% */
464 #endif /* AIX_LABEL */
466 #ifdef CONFIG_FEATURE_OSF_LABEL
468 * Copyright (c) 1987, 1988 Regents of the University of California.
469 * All rights reserved.
471 * Redistribution and use in source and binary forms, with or without
472 * modification, are permitted provided that the following conditions
474 * 1. Redistributions of source code must retain the above copyright
475 * notice, this list of conditions and the following disclaimer.
476 * 2. Redistributions in binary form must reproduce the above copyright
477 * notice, this list of conditions and the following disclaimer in the
478 * documentation and/or other materials provided with the distribution.
479 * 3. All advertising materials mentioning features or use of this software
480 * must display the following acknowledgment:
481 * This product includes software developed by the University of
482 * California, Berkeley and its contributors.
483 * 4. Neither the name of the University nor the names of its contributors
484 * may be used to endorse or promote products derived from this software
485 * without specific prior written permission.
487 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
488 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
489 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
490 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
491 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
492 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
493 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
494 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
495 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
496 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
501 #ifndef BSD_DISKMAGIC
502 #define BSD_DISKMAGIC ((uint32_t) 0x82564557)
505 #ifndef BSD_MAXPARTITIONS
506 #define BSD_MAXPARTITIONS 16
509 #define BSD_LINUX_BOOTDIR "/usr/ucb/mdec"
511 #if defined (i386) || defined (__sparc__) || defined (__arm__) || defined (__mips__) || defined (__s390__) || defined (__sh__) || defined(__x86_64__)
512 #define BSD_LABELSECTOR 1
513 #define BSD_LABELOFFSET 0
514 #elif defined (__alpha__) || defined (__powerpc__) || defined (__ia64__) || defined (__hppa__)
515 #define BSD_LABELSECTOR 0
516 #define BSD_LABELOFFSET 64
517 #elif defined (__s390__) || defined (__s390x__)
518 #define BSD_LABELSECTOR 1
519 #define BSD_LABELOFFSET 0
521 #error unknown architecture
524 #define BSD_BBSIZE 8192 /* size of boot area, with label */
525 #define BSD_SBSIZE 8192 /* max size of fs superblock */
527 struct xbsd_disklabel {
528 uint32_t d_magic; /* the magic number */
529 int16_t d_type; /* drive type */
530 int16_t d_subtype; /* controller/d_type specific */
531 char d_typename[16]; /* type name, e.g. "eagle" */
532 char d_packname[16]; /* pack identifier */
534 uint32_t d_secsize; /* # of bytes per sector */
535 uint32_t d_nsectors; /* # of data sectors per track */
536 uint32_t d_ntracks; /* # of tracks per cylinder */
537 uint32_t d_ncylinders; /* # of data cylinders per unit */
538 uint32_t d_secpercyl; /* # of data sectors per cylinder */
539 uint32_t d_secperunit; /* # of data sectors per unit */
541 * Spares (bad sector replacements) below
542 * are not counted in d_nsectors or d_secpercyl.
543 * Spare sectors are assumed to be physical sectors
544 * which occupy space at the end of each track and/or cylinder.
546 uint16_t d_sparespertrack; /* # of spare sectors per track */
547 uint16_t d_sparespercyl; /* # of spare sectors per cylinder */
549 * Alternate cylinders include maintenance, replacement,
550 * configuration description areas, etc.
552 uint32_t d_acylinders; /* # of alt. cylinders per unit */
554 /* hardware characteristics: */
556 * d_interleave, d_trackskew and d_cylskew describe perturbations
557 * in the media format used to compensate for a slow controller.
558 * Interleave is physical sector interleave, set up by the formatter
559 * or controller when formatting. When interleaving is in use,
560 * logically adjacent sectors are not physically contiguous,
561 * but instead are separated by some number of sectors.
562 * It is specified as the ratio of physical sectors traversed
563 * per logical sector. Thus an interleave of 1:1 implies contiguous
564 * layout, while 2:1 implies that logical sector 0 is separated
565 * by one sector from logical sector 1.
566 * d_trackskew is the offset of sector 0 on track N
567 * relative to sector 0 on track N-1 on the same cylinder.
568 * Finally, d_cylskew is the offset of sector 0 on cylinder N
569 * relative to sector 0 on cylinder N-1.
571 uint16_t d_rpm; /* rotational speed */
572 uint16_t d_interleave; /* hardware sector interleave */
573 uint16_t d_trackskew; /* sector 0 skew, per track */
574 uint16_t d_cylskew; /* sector 0 skew, per cylinder */
575 uint32_t d_headswitch; /* head switch time, usec */
576 uint32_t d_trkseek; /* track-to-track seek, usec */
577 uint32_t d_flags; /* generic flags */
579 uint32_t d_drivedata[NDDATA]; /* drive-type specific information */
581 uint32_t d_spare[NSPARE]; /* reserved for future use */
582 uint32_t d_magic2; /* the magic number (again) */
583 uint16_t d_checksum; /* xor of data incl. partitions */
584 /* filesystem and partition information: */
585 uint16_t d_npartitions; /* number of partitions in following */
586 uint32_t d_bbsize; /* size of boot area at sn0, bytes */
587 uint32_t d_sbsize; /* max size of fs superblock, bytes */
588 struct xbsd_partition { /* the partition table */
589 uint32_t p_size; /* number of sectors in partition */
590 uint32_t p_offset; /* starting sector */
591 uint32_t p_fsize; /* filesystem basic fragment size */
592 uint8_t p_fstype; /* filesystem type, see below */
593 uint8_t p_frag; /* filesystem fragments per block */
594 uint16_t p_cpg; /* filesystem cylinders per group */
595 } d_partitions[BSD_MAXPARTITIONS]; /* actually may be more */
599 #define BSD_DTYPE_SMD 1 /* SMD, XSMD; VAX hp/up */
600 #define BSD_DTYPE_MSCP 2 /* MSCP */
601 #define BSD_DTYPE_DEC 3 /* other DEC (rk, rl) */
602 #define BSD_DTYPE_SCSI 4 /* SCSI */
603 #define BSD_DTYPE_ESDI 5 /* ESDI interface */
604 #define BSD_DTYPE_ST506 6 /* ST506 etc. */
605 #define BSD_DTYPE_HPIB 7 /* CS/80 on HP-IB */
606 #define BSD_DTYPE_HPFL 8 /* HP Fiber-link */
607 #define BSD_DTYPE_FLOPPY 10 /* floppy */
609 /* d_subtype values: */
610 #define BSD_DSTYPE_INDOSPART 0x8 /* is inside dos partition */
611 #define BSD_DSTYPE_DOSPART(s) ((s) & 3) /* dos partition number */
612 #define BSD_DSTYPE_GEOMETRY 0x10 /* drive params in label */
615 static const char * const xbsd_dktypenames[] = {
629 #define BSD_DKMAXTYPES (sizeof(xbsd_dktypenames) / sizeof(xbsd_dktypenames[0]) - 1)
633 * Filesystem type and version.
634 * Used to interpret other filesystem-specific
635 * per-partition information.
637 #define BSD_FS_UNUSED 0 /* unused */
638 #define BSD_FS_SWAP 1 /* swap */
639 #define BSD_FS_V6 2 /* Sixth Edition */
640 #define BSD_FS_V7 3 /* Seventh Edition */
641 #define BSD_FS_SYSV 4 /* System V */
642 #define BSD_FS_V71K 5 /* V7 with 1K blocks (4.1, 2.9) */
643 #define BSD_FS_V8 6 /* Eighth Edition, 4K blocks */
644 #define BSD_FS_BSDFFS 7 /* 4.2BSD fast file system */
645 #define BSD_FS_BSDLFS 9 /* 4.4BSD log-structured file system */
646 #define BSD_FS_OTHER 10 /* in use, but unknown/unsupported */
647 #define BSD_FS_HPFS 11 /* OS/2 high-performance file system */
648 #define BSD_FS_ISO9660 12 /* ISO-9660 filesystem (cdrom) */
649 #define BSD_FS_ISOFS BSD_FS_ISO9660
650 #define BSD_FS_BOOT 13 /* partition contains bootstrap */
651 #define BSD_FS_ADOS 14 /* AmigaDOS fast file system */
652 #define BSD_FS_HFS 15 /* Macintosh HFS */
653 #define BSD_FS_ADVFS 16 /* Digital Unix AdvFS */
655 /* this is annoying, but it's also the way it is :-( */
657 #define BSD_FS_EXT2 8 /* ext2 file system */
659 #define BSD_FS_MSDOS 8 /* MS-DOS file system */
663 static const struct systypes xbsd_fstypes[] = {
664 { "\x00" "unused" }, /* BSD_FS_UNUSED */
665 { "\x01" "swap" }, /* BSD_FS_SWAP */
666 { "\x02" "Version 6" }, /* BSD_FS_V6 */
667 { "\x03" "Version 7" }, /* BSD_FS_V7 */
668 { "\x04" "System V" }, /* BSD_FS_SYSV */
669 { "\x05" "4.1BSD" }, /* BSD_FS_V71K */
670 { "\x06" "Eighth Edition" }, /* BSD_FS_V8 */
671 { "\x07" "4.2BSD" }, /* BSD_FS_BSDFFS */
673 { "\x08" "ext2" }, /* BSD_FS_EXT2 */
675 { "\x08" "MS-DOS" }, /* BSD_FS_MSDOS */
677 { "\x09" "4.4LFS" }, /* BSD_FS_BSDLFS */
678 { "\x0a" "unknown" }, /* BSD_FS_OTHER */
679 { "\x0b" "HPFS" }, /* BSD_FS_HPFS */
680 { "\x0c" "ISO-9660" }, /* BSD_FS_ISO9660 */
681 { "\x0d" "boot" }, /* BSD_FS_BOOT */
682 { "\x0e" "ADOS" }, /* BSD_FS_ADOS */
683 { "\x0f" "HFS" }, /* BSD_FS_HFS */
684 { "\x10" "AdvFS" }, /* BSD_FS_ADVFS */
687 #define BSD_FSMAXTYPES (SIZE(xbsd_fstypes)-1)
692 * flags shared by various drives:
694 #define BSD_D_REMOVABLE 0x01 /* removable media */
695 #define BSD_D_ECC 0x02 /* supports ECC */
696 #define BSD_D_BADSECT 0x04 /* supports bad sector forw. */
697 #define BSD_D_RAMDISK 0x08 /* disk emulator */
698 #define BSD_D_CHAIN 0x10 /* can do back-back transfers */
699 #define BSD_D_DOSPART 0x20 /* within MSDOS partition */
701 #endif /* OSF_LABEL */
704 * Copyright (C) Andreas Neuper, Sep 1998.
705 * This file may be modified and redistributed under
706 * the terms of the GNU Public License.
709 struct device_parameter { /* 48 bytes */
713 unsigned char sparecyl;
714 unsigned short pcylcount;
715 unsigned short head_vol0;
716 unsigned short ntrks; /* tracks in cyl 0 or vol 0 */
717 unsigned char cmd_tag_queue_depth;
718 unsigned char unused0;
719 unsigned short unused1;
720 unsigned short nsect; /* sectors/tracks in cyl 0 or vol 0 */
721 unsigned short bytes;
722 unsigned short ilfact;
723 unsigned int flags; /* controller flags */
724 unsigned int datarate;
725 unsigned int retries_on_error;
726 unsigned int ms_per_word;
727 unsigned short xylogics_gap1;
728 unsigned short xylogics_syncdelay;
729 unsigned short xylogics_readdelay;
730 unsigned short xylogics_gap2;
731 unsigned short xylogics_readgate;
732 unsigned short xylogics_writecont;
735 #define SGI_VOLHDR 0x00
736 /* 1 and 2 were used for drive types no longer supported by SGI */
737 #define SGI_SWAP 0x03
738 /* 4 and 5 were for filesystem types SGI haven't ever supported on MIPS CPUs */
739 #define SGI_VOLUME 0x06
741 #define SGI_LVOL 0x08
742 #define SGI_RLVOL 0x09
744 #define SGI_XFSLOG 0x0b
747 #define ENTIRE_DISK SGI_VOLUME
751 #define SECTOR_SLIP 0x01
752 #define SECTOR_FWD 0x02
753 #define TRACK_FWD 0x04
754 #define TRACK_MULTIVOL 0x08
755 #define IGNORE_ERRORS 0x10
757 #define ENABLE_CMDTAGQ 0x40
760 unsigned int magic; /* expect SGI_LABEL_MAGIC */
761 unsigned short boot_part; /* active boot partition */
762 unsigned short swap_part; /* active swap partition */
763 unsigned char boot_file[16]; /* name of the bootfile */
764 struct device_parameter devparam; /* 1 * 48 bytes */
765 struct volume_directory { /* 15 * 16 bytes */
766 unsigned char vol_file_name[8]; /* a character array */
767 unsigned int vol_file_start; /* number of logical block */
768 unsigned int vol_file_size; /* number of bytes */
770 struct sgi_partition { /* 16 * 12 bytes */
771 unsigned int num_sectors; /* number of blocks */
772 unsigned int start_sector; /* must be cylinder aligned */
776 unsigned int fillbytes;
780 unsigned int magic; /* looks like a magic number */
789 unsigned char scsi_string[50];
790 unsigned char serial[137];
791 unsigned short check1816;
792 unsigned char installer[225];
795 #define SGI_LABEL_MAGIC 0x0be5a941
796 #define SGI_LABEL_MAGIC_SWAPPED 0x41a9e50b
797 #define SGI_INFO_MAGIC 0x00072959
798 #define SGI_INFO_MAGIC_SWAPPED 0x59290700
799 #define SGI_SSWAP16(x) (sgi_other_endian ? __swap16(x) \
801 #define SGI_SSWAP32(x) (sgi_other_endian ? __swap32(x) \
804 #define sgilabel ((sgi_partition *)MBRbuffer)
805 #define sgiparam (sgilabel->devparam)
808 unsigned char info[128]; /* Informative text string */
809 unsigned char spare0[14];
811 unsigned char spare1;
813 unsigned char spare2;
816 unsigned char spare1[246]; /* Boot information etc. */
817 unsigned short rspeed; /* Disk rotational speed */
818 unsigned short pcylcount; /* Physical cylinder count */
819 unsigned short sparecyl; /* extra sects per cylinder */
820 unsigned char spare2[4]; /* More magic... */
821 unsigned short ilfact; /* Interleave factor */
822 unsigned short ncyl; /* Data cylinder count */
823 unsigned short nacyl; /* Alt. cylinder count */
824 unsigned short ntrks; /* Tracks per cylinder */
825 unsigned short nsect; /* Sectors per track */
826 unsigned char spare3[4]; /* Even more magic... */
827 struct sun_partition {
828 uint32_t start_cylinder;
829 uint32_t num_sectors;
831 unsigned short magic; /* Magic number */
832 unsigned short csum; /* Label xor'd checksum */
836 #define SUN_LABEL_MAGIC 0xDABE
837 #define SUN_LABEL_MAGIC_SWAPPED 0xBEDA
838 #define sunlabel ((sun_partition *)MBRbuffer)
839 #define SUN_SSWAP16(x) (sun_other_endian ? __swap16(x) \
841 #define SUN_SSWAP32(x) (sun_other_endian ? __swap32(x) \
845 #ifdef CONFIG_FEATURE_OSF_LABEL
848 19990319 - Arnaldo Carvalho de Melo <acme@conectiva.com.br> - i18n/nls
850 20000101 - David Huggins-Daines <dhuggins@linuxcare.com> - Better
851 support for OSF/1 disklabels on Alpha.
852 Also fixed unaligned accesses in alpha_bootblock_checksum()
855 #define FREEBSD_PARTITION 0xa5
856 #define NETBSD_PARTITION 0xa9
858 static void xbsd_delete_part(void);
859 static void xbsd_new_part(void);
860 static void xbsd_write_disklabel(void);
861 static int xbsd_create_disklabel(void);
862 static void xbsd_edit_disklabel(void);
863 static void xbsd_write_bootstrap(void);
864 static void xbsd_change_fstype(void);
865 static int xbsd_get_part_index(int max);
866 static int xbsd_check_new_partition(int *i);
867 static void xbsd_list_types(void);
868 static u_short xbsd_dkcksum(struct xbsd_disklabel *lp);
869 static int xbsd_initlabel(struct partition *p, struct xbsd_disklabel *d);
870 static int xbsd_readlabel(struct partition *p, struct xbsd_disklabel *d);
871 static int xbsd_writelabel(struct partition *p, struct xbsd_disklabel *d);
873 #if defined (__alpha__)
874 static void alpha_bootblock_checksum(char *boot);
877 #if !defined (__alpha__)
878 static int xbsd_translate_fstype(int linux_type);
879 static void xbsd_link_part(void);
880 static struct partition *xbsd_part;
881 static int xbsd_part_index;
884 #if defined (__alpha__)
885 /* We access this through a uint64_t * when checksumming */
886 static char disklabelbuffer[BSD_BBSIZE] ATTRIBUTE_ALIGNED(8);
888 static char disklabelbuffer[BSD_BBSIZE];
891 static struct xbsd_disklabel xbsd_dlabel;
893 #define bsd_cround(n) \
894 (display_in_cyl_units ? ((n)/xbsd_dlabel.d_secpercyl) + 1 : (n))
897 * Test whether the whole disk has BSD disk label magic.
899 * Note: often reformatting with DOS-type label leaves the BSD magic,
900 * so this does not mean that there is a BSD disk label.
903 check_osf_label(void)
905 if (xbsd_readlabel(NULL, &xbsd_dlabel) == 0)
910 static void xbsd_print_disklabel(int);
913 btrydev(const char * dev)
915 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
917 printf(_("\nBSD label for device: %s\n"), dev);
918 xbsd_print_disklabel (0);
925 puts (_("Command action"));
926 puts (_("\td\tdelete a BSD partition"));
927 puts (_("\te\tedit drive data"));
928 puts (_("\ti\tinstall bootstrap"));
929 puts (_("\tl\tlist known filesystem types"));
930 puts (_("\tm\tprint this menu"));
931 puts (_("\tn\tadd a new BSD partition"));
932 puts (_("\tp\tprint BSD partition table"));
933 puts (_("\tq\tquit without saving changes"));
934 puts (_("\tr\treturn to main menu"));
935 puts (_("\ts\tshow complete disklabel"));
936 puts (_("\tt\tchange a partition's filesystem id"));
937 puts (_("\tu\tchange units (cylinders/sectors)"));
938 puts (_("\tw\twrite disklabel to disk"));
939 #if !defined (__alpha__)
940 puts (_("\tx\tlink BSD partition to non-BSD partition"));
944 #if !defined (__alpha__)
952 is_bsd_partition_type(int type)
954 return (type == FREEBSD_PARTITION ||
955 type == hidden(FREEBSD_PARTITION) ||
956 type == NETBSD_PARTITION ||
957 type == hidden(NETBSD_PARTITION));
964 #if !defined (__alpha__)
968 for (t = 0; t < 4; t++) {
969 p = get_part_table(t);
970 if (p && is_bsd_partition_type(p->sys_ind)) {
973 ss = get_start_sect(xbsd_part);
975 fprintf(stderr, _("Partition %s has invalid starting sector 0.\n"),
976 partname(disk_device, t+1, 0));
979 printf(_("Reading disklabel of %s at sector %d.\n"),
980 partname(disk_device, t+1, 0), ss + BSD_LABELSECTOR);
981 if (xbsd_readlabel(xbsd_part, &xbsd_dlabel) == 0)
982 if (xbsd_create_disklabel() == 0)
989 printf(_("There is no *BSD partition on %s.\n"), disk_device);
993 #elif defined (__alpha__)
995 if (xbsd_readlabel(NULL, &xbsd_dlabel) == 0)
996 if (xbsd_create_disklabel() == 0)
1003 switch (tolower(read_char(_("BSD disklabel command (m for help): ")))) {
1008 xbsd_edit_disklabel();
1011 xbsd_write_bootstrap();
1020 xbsd_print_disklabel(0);
1028 xbsd_print_disklabel(1);
1031 xbsd_change_fstype();
1037 xbsd_write_disklabel();
1039 #if !defined (__alpha__)
1052 xbsd_delete_part(void)
1056 i = xbsd_get_part_index(xbsd_dlabel.d_npartitions);
1057 xbsd_dlabel.d_partitions[i].p_size = 0;
1058 xbsd_dlabel.d_partitions[i].p_offset = 0;
1059 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
1060 if (xbsd_dlabel.d_npartitions == i + 1)
1061 while (xbsd_dlabel.d_partitions[xbsd_dlabel.d_npartitions-1].p_size == 0)
1062 xbsd_dlabel.d_npartitions--;
1072 if (!xbsd_check_new_partition(&i))
1075 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
1076 begin = get_start_sect(xbsd_part);
1077 end = begin + get_nr_sects(xbsd_part) - 1;
1080 end = xbsd_dlabel.d_secperunit - 1;
1083 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
1084 begin = read_int(bsd_cround(begin), bsd_cround(begin), bsd_cround(end),
1087 if (display_in_cyl_units)
1088 begin = (begin - 1) * xbsd_dlabel.d_secpercyl;
1090 snprintf(mesg, sizeof(mesg), _("Last %s or +size or +sizeM or +sizeK"),
1091 str_units(SINGULAR));
1092 end = read_int(bsd_cround (begin), bsd_cround (end), bsd_cround (end),
1093 bsd_cround (begin), mesg);
1095 if (display_in_cyl_units)
1096 end = end * xbsd_dlabel.d_secpercyl - 1;
1098 xbsd_dlabel.d_partitions[i].p_size = end - begin + 1;
1099 xbsd_dlabel.d_partitions[i].p_offset = begin;
1100 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
1104 xbsd_print_disklabel(int show_all)
1106 struct xbsd_disklabel *lp = &xbsd_dlabel;
1107 struct xbsd_partition *pp;
1111 #if defined (__alpha__)
1112 printf("# %s:\n", disk_device);
1114 printf("# %s:\n", partname(disk_device, xbsd_part_index+1, 0));
1116 if ((unsigned) lp->d_type < BSD_DKMAXTYPES)
1117 printf(_("type: %s\n"), xbsd_dktypenames[lp->d_type]);
1119 printf(_("type: %d\n"), lp->d_type);
1120 printf(_("disk: %.*s\n"), (int) sizeof(lp->d_typename), lp->d_typename);
1121 printf(_("label: %.*s\n"), (int) sizeof(lp->d_packname), lp->d_packname);
1122 printf(_("flags:"));
1123 if (lp->d_flags & BSD_D_REMOVABLE)
1124 printf(_(" removable"));
1125 if (lp->d_flags & BSD_D_ECC)
1127 if (lp->d_flags & BSD_D_BADSECT)
1128 printf(_(" badsect"));
1130 /* On various machines the fields of *lp are short/int/long */
1131 /* In order to avoid problems, we cast them all to long. */
1132 printf(_("bytes/sector: %ld\n"), (long) lp->d_secsize);
1133 printf(_("sectors/track: %ld\n"), (long) lp->d_nsectors);
1134 printf(_("tracks/cylinder: %ld\n"), (long) lp->d_ntracks);
1135 printf(_("sectors/cylinder: %ld\n"), (long) lp->d_secpercyl);
1136 printf(_("cylinders: %ld\n"), (long) lp->d_ncylinders);
1137 printf(_("rpm: %d\n"), lp->d_rpm);
1138 printf(_("interleave: %d\n"), lp->d_interleave);
1139 printf(_("trackskew: %d\n"), lp->d_trackskew);
1140 printf(_("cylinderskew: %d\n"), lp->d_cylskew);
1141 printf(_("headswitch: %ld\t\t# milliseconds\n"),
1142 (long) lp->d_headswitch);
1143 printf(_("track-to-track seek: %ld\t# milliseconds\n"),
1144 (long) lp->d_trkseek);
1145 printf(_("drivedata: "));
1146 for (i = NDDATA - 1; i >= 0; i--)
1147 if (lp->d_drivedata[i])
1151 for (j = 0; j <= i; j++)
1152 printf("%ld ", (long) lp->d_drivedata[j]);
1154 printf(_("\n%d partitions:\n"), lp->d_npartitions);
1155 printf(_("# start end size fstype [fsize bsize cpg]\n"));
1156 pp = lp->d_partitions;
1157 for (i = 0; i < lp->d_npartitions; i++, pp++) {
1159 if (display_in_cyl_units && lp->d_secpercyl) {
1160 printf(" %c: %8ld%c %8ld%c %8ld%c ",
1162 (long) pp->p_offset / lp->d_secpercyl + 1,
1163 (pp->p_offset % lp->d_secpercyl) ? '*' : ' ',
1164 (long) (pp->p_offset + pp->p_size + lp->d_secpercyl - 1) / lp->d_secpercyl,
1165 ((pp->p_offset + pp->p_size) % lp->d_secpercyl) ? '*' : ' ',
1166 (long) pp->p_size / lp->d_secpercyl,
1167 (pp->p_size % lp->d_secpercyl) ? '*' : ' '
1170 printf(" %c: %8ld %8ld %8ld ",
1172 (long) pp->p_offset,
1173 (long) pp->p_offset + pp->p_size - 1,
1178 if ((unsigned) pp->p_fstype < BSD_FSMAXTYPES)
1179 printf("%8.8s", xbsd_fstypes[pp->p_fstype].name);
1181 printf("%8x", pp->p_fstype);
1183 switch (pp->p_fstype) {
1185 printf(" %5ld %5ld %5.5s ",
1186 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, "");
1189 printf(" %5ld %5ld %5d ",
1190 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, pp->p_cpg);
1193 printf("%22.22s", "");
1202 xbsd_write_disklabel(void)
1204 #if defined (__alpha__)
1205 printf(_("Writing disklabel to %s.\n"), disk_device);
1206 xbsd_writelabel(NULL, &xbsd_dlabel);
1208 printf(_("Writing disklabel to %s.\n"),
1209 partname(disk_device, xbsd_part_index + 1, 0));
1210 xbsd_writelabel(xbsd_part, &xbsd_dlabel);
1212 reread_partition_table(0); /* no exit yet */
1216 xbsd_create_disklabel(void)
1220 #if defined (__alpha__)
1221 fprintf(stderr, _("%s contains no disklabel.\n"), disk_device);
1223 fprintf(stderr, _("%s contains no disklabel.\n"),
1224 partname(disk_device, xbsd_part_index + 1, 0));
1228 c = read_char(_("Do you want to create a disklabel? (y/n) "));
1229 if (c == 'y' || c == 'Y') {
1231 #if defined (__alpha__) || defined (__powerpc__) || defined (__hppa__) || \
1232 defined (__s390__) || defined (__s390x__)
1235 xbsd_part, &xbsd_dlabel/* not used, xbsd_part_index*/
1238 xbsd_print_disklabel (1);
1242 } else if (c == 'n')
1248 edit_int(int def, char *mesg)
1251 fputs(mesg, stdout);
1252 printf(" (%d): ", def);
1256 while (!isdigit(*line_ptr)); /* FIXME: ?!! */
1257 return atoi(line_ptr);
1261 xbsd_edit_disklabel(void)
1263 struct xbsd_disklabel *d;
1267 #if defined (__alpha__) || defined (__ia64__)
1268 d->d_secsize = (u_long) edit_int((u_long) d->d_secsize ,_("bytes/sector"));
1269 d->d_nsectors = (u_long) edit_int((u_long) d->d_nsectors ,_("sectors/track"));
1270 d->d_ntracks = (u_long) edit_int((u_long) d->d_ntracks ,_("tracks/cylinder"));
1271 d->d_ncylinders = (u_long) edit_int((u_long) d->d_ncylinders ,_("cylinders"));
1274 /* d->d_secpercyl can be != d->d_nsectors * d->d_ntracks */
1276 d->d_secpercyl = (u_long) edit_int((u_long) d->d_nsectors * d->d_ntracks,
1277 _("sectors/cylinder"));
1278 if (d->d_secpercyl <= d->d_nsectors * d->d_ntracks)
1281 printf(_("Must be <= sectors/track * tracks/cylinder (default).\n"));
1283 d->d_rpm = (u_short) edit_int((u_short) d->d_rpm ,_("rpm"));
1284 d->d_interleave = (u_short) edit_int((u_short) d->d_interleave,_("interleave"));
1285 d->d_trackskew = (u_short) edit_int((u_short) d->d_trackskew ,_("trackskew"));
1286 d->d_cylskew = (u_short) edit_int((u_short) d->d_cylskew ,_("cylinderskew"));
1287 d->d_headswitch = (u_long) edit_int((u_long) d->d_headswitch ,_("headswitch"));
1288 d->d_trkseek = (u_long) edit_int((u_long) d->d_trkseek ,_("track-to-track seek"));
1290 d->d_secperunit = d->d_secpercyl * d->d_ncylinders;
1294 xbsd_get_bootstrap (char *path, void *ptr, int size)
1298 if ((fdb = open (path, O_RDONLY)) < 0) {
1302 if (read(fdb, ptr, size) < 0) {
1307 printf(" ... %s\n", path);
1315 printf(_("\nSyncing disks.\n"));
1317 sleep(4); /* What? */
1321 xbsd_write_bootstrap(void)
1323 char *bootdir = BSD_LINUX_BOOTDIR;
1324 char path[MAXPATHLEN];
1326 struct xbsd_disklabel dl;
1330 if (xbsd_dlabel.d_type == BSD_DTYPE_SCSI)
1335 printf(_("Bootstrap: %sboot -> boot%s (%s): "),
1336 dkbasename, dkbasename, dkbasename);
1338 line_ptr[strlen(line_ptr)-1] = '\0';
1339 dkbasename = line_ptr;
1341 snprintf(path, sizeof(path), "%s/%sboot", bootdir, dkbasename);
1342 if (!xbsd_get_bootstrap(path, disklabelbuffer, (int) xbsd_dlabel.d_secsize))
1345 /* We need a backup of the disklabel (xbsd_dlabel might have changed). */
1346 d = &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE];
1347 bcopy(d, &dl, sizeof(struct xbsd_disklabel));
1349 /* The disklabel will be overwritten by 0's from bootxx anyway */
1350 memset(d, 0, sizeof(struct xbsd_disklabel));
1352 snprintf(path, sizeof(path), "%s/boot%s", bootdir, dkbasename);
1353 if (!xbsd_get_bootstrap (path, &disklabelbuffer[xbsd_dlabel.d_secsize],
1354 (int) xbsd_dlabel.d_bbsize - xbsd_dlabel.d_secsize))
1357 e = d + sizeof(struct xbsd_disklabel);
1358 for (p = d; p < e; p++)
1360 fprintf(stderr, _("Bootstrap overlaps with disk label!\n"));
1364 bcopy(&dl, d, sizeof(struct xbsd_disklabel));
1366 #if defined (__powerpc__) || defined (__hppa__)
1368 #elif defined (__alpha__)
1370 alpha_bootblock_checksum(disklabelbuffer);
1372 sector = get_start_sect(xbsd_part);
1375 if (lseek(fd, sector * SECTOR_SIZE, SEEK_SET) == -1)
1376 fdisk_fatal(unable_to_seek);
1377 if (BSD_BBSIZE != write(fd, disklabelbuffer, BSD_BBSIZE))
1378 fdisk_fatal(unable_to_write);
1380 #if defined (__alpha__)
1381 printf(_("Bootstrap installed on %s.\n"), disk_device);
1383 printf(_("Bootstrap installed on %s.\n"),
1384 partname (disk_device, xbsd_part_index+1, 0));
1391 xbsd_change_fstype(void)
1395 i = xbsd_get_part_index(xbsd_dlabel.d_npartitions);
1396 xbsd_dlabel.d_partitions[i].p_fstype = read_hex(xbsd_fstypes);
1400 xbsd_get_part_index(int max)
1405 snprintf(prompt, sizeof(prompt), _("Partition (a-%c): "), 'a' + max - 1);
1407 l = tolower(read_char(prompt));
1408 while (l < 'a' || l > 'a' + max - 1);
1413 xbsd_check_new_partition(int *i)
1415 /* room for more? various BSD flavours have different maxima */
1416 if (xbsd_dlabel.d_npartitions == BSD_MAXPARTITIONS) {
1419 for (t = 0; t < BSD_MAXPARTITIONS; t++)
1420 if (xbsd_dlabel.d_partitions[t].p_size == 0)
1423 if (t == BSD_MAXPARTITIONS) {
1424 fprintf(stderr, _("The maximum number of partitions "
1425 "has been created\n"));
1430 *i = xbsd_get_part_index (BSD_MAXPARTITIONS);
1432 if (*i >= xbsd_dlabel.d_npartitions)
1433 xbsd_dlabel.d_npartitions = (*i) + 1;
1435 if (xbsd_dlabel.d_partitions[*i].p_size != 0) {
1436 fprintf(stderr, _("This partition already exists.\n"));
1444 xbsd_list_types(void)
1446 list_types(xbsd_fstypes);
1450 xbsd_dkcksum(struct xbsd_disklabel *lp)
1452 u_short *start, *end;
1455 start = (u_short *) lp;
1456 end = (u_short *) &lp->d_partitions[lp->d_npartitions];
1463 xbsd_initlabel(struct partition *p, struct xbsd_disklabel *d)
1465 struct xbsd_partition *pp;
1468 memset(d, 0, sizeof(struct xbsd_disklabel));
1470 d->d_magic = BSD_DISKMAGIC;
1472 if (strncmp(disk_device, "/dev/sd", 7) == 0)
1473 d->d_type = BSD_DTYPE_SCSI;
1475 d->d_type = BSD_DTYPE_ST506;
1477 #if 0 /* not used (at least not written to disk) by NetBSD/i386 1.0 */
1478 d->d_subtype = BSD_DSTYPE_INDOSPART & pindex;
1481 #if !defined (__alpha__)
1482 d->d_flags = BSD_D_DOSPART;
1486 d->d_secsize = SECTOR_SIZE; /* bytes/sector */
1487 d->d_nsectors = sectors; /* sectors/track */
1488 d->d_ntracks = heads; /* tracks/cylinder (heads) */
1489 d->d_ncylinders = cylinders;
1490 d->d_secpercyl = sectors * heads;/* sectors/cylinder */
1491 if (d->d_secpercyl == 0)
1492 d->d_secpercyl = 1; /* avoid segfaults */
1493 d->d_secperunit = d->d_secpercyl * d->d_ncylinders;
1496 d->d_interleave = 1;
1499 d->d_headswitch = 0;
1502 d->d_magic2 = BSD_DISKMAGIC;
1503 d->d_bbsize = BSD_BBSIZE;
1504 d->d_sbsize = BSD_SBSIZE;
1506 #if !defined (__alpha__)
1507 d->d_npartitions = 4;
1508 pp = &d->d_partitions[2]; /* Partition C should be
1509 the NetBSD partition */
1510 pp->p_offset = get_start_sect(p);
1511 pp->p_size = get_nr_sects(p);
1512 pp->p_fstype = BSD_FS_UNUSED;
1513 pp = &d->d_partitions[3]; /* Partition D should be
1516 pp->p_size = d->d_secperunit;
1517 pp->p_fstype = BSD_FS_UNUSED;
1518 #elif defined (__alpha__)
1519 d->d_npartitions = 3;
1520 pp = &d->d_partitions[2]; /* Partition C should be
1523 pp->p_size = d->d_secperunit;
1524 pp->p_fstype = BSD_FS_UNUSED;
1531 * Read a xbsd_disklabel from sector 0 or from the starting sector of p.
1532 * If it has the right magic, return 1.
1535 xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d)
1539 /* p is used only to get the starting sector */
1540 #if !defined (__alpha__)
1541 sector = (p ? get_start_sect(p) : 0);
1542 #elif defined (__alpha__)
1546 if (lseek(fd, sector * SECTOR_SIZE, SEEK_SET) == -1)
1547 fdisk_fatal(unable_to_seek);
1548 if (BSD_BBSIZE != read(fd, disklabelbuffer, BSD_BBSIZE))
1549 fdisk_fatal(unable_to_read);
1551 bcopy(&disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
1552 d, sizeof(struct xbsd_disklabel));
1554 if (d->d_magic != BSD_DISKMAGIC || d->d_magic2 != BSD_DISKMAGIC)
1557 for (t = d->d_npartitions; t < BSD_MAXPARTITIONS; t++) {
1558 d->d_partitions[t].p_size = 0;
1559 d->d_partitions[t].p_offset = 0;
1560 d->d_partitions[t].p_fstype = BSD_FS_UNUSED;
1563 if (d->d_npartitions > BSD_MAXPARTITIONS)
1564 fprintf(stderr, _("Warning: too many partitions "
1565 "(%d, maximum is %d).\n"),
1566 d->d_npartitions, BSD_MAXPARTITIONS);
1571 xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d)
1573 unsigned int sector;
1575 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
1576 sector = get_start_sect(p) + BSD_LABELSECTOR;
1578 sector = BSD_LABELSECTOR;
1582 d->d_checksum = xbsd_dkcksum (d);
1584 /* This is necessary if we want to write the bootstrap later,
1585 otherwise we'd write the old disklabel with the bootstrap.
1587 bcopy(d, &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
1588 sizeof(struct xbsd_disklabel));
1590 #if defined (__alpha__) && BSD_LABELSECTOR == 0
1591 alpha_bootblock_checksum (disklabelbuffer);
1592 if (lseek(fd, 0, SEEK_SET) == -1)
1593 fdisk_fatal(unable_to_seek);
1594 if (BSD_BBSIZE != write(fd, disklabelbuffer, BSD_BBSIZE))
1595 fdisk_fatal(unable_to_write);
1597 if (lseek(fd, sector * SECTOR_SIZE + BSD_LABELOFFSET, SEEK_SET) == -1)
1598 fdisk_fatal(unable_to_seek);
1599 if (sizeof(struct xbsd_disklabel) != write(fd, d, sizeof(struct xbsd_disklabel)))
1600 fdisk_fatal(unable_to_write);
1607 #if !defined (__alpha__)
1609 xbsd_translate_fstype(int linux_type)
1611 switch (linux_type) {
1612 case 0x01: /* DOS 12-bit FAT */
1613 case 0x04: /* DOS 16-bit <32M */
1614 case 0x06: /* DOS 16-bit >=32M */
1615 case 0xe1: /* DOS access */
1616 case 0xe3: /* DOS R/O */
1617 case 0xf2: /* DOS secondary */
1618 return BSD_FS_MSDOS;
1619 case 0x07: /* OS/2 HPFS */
1622 return BSD_FS_OTHER;
1627 xbsd_link_part(void)
1630 struct partition *p;
1632 k = get_partition(1, partitions);
1634 if (!xbsd_check_new_partition(&i))
1637 p = get_part_table(k);
1639 xbsd_dlabel.d_partitions[i].p_size = get_nr_sects(p);
1640 xbsd_dlabel.d_partitions[i].p_offset = get_start_sect(p);
1641 xbsd_dlabel.d_partitions[i].p_fstype = xbsd_translate_fstype(p->sys_ind);
1645 #if defined (__alpha__)
1647 #if !defined(__GLIBC__)
1648 typedef unsigned long long uint64_t;
1652 alpha_bootblock_checksum(char *boot)
1657 dp = (uint64_t *)boot;
1659 for (i = 0; i < 63; i++)
1663 #endif /* __alpha__ */
1665 #endif /* OSF_LABEL */
1667 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
1668 static inline unsigned short
1669 __swap16(unsigned short x)
1671 return (((uint16_t)(x) & 0xFF) << 8) | (((uint16_t)(x) & 0xFF00) >> 8);
1674 static inline uint32_t
1675 __swap32(uint32_t x)
1677 return (((x & 0xFF) << 24) |
1678 ((x & 0xFF00) << 8) |
1679 ((x & 0xFF0000) >> 8) |
1680 ((x & 0xFF000000) >> 24));
1684 #ifdef CONFIG_FEATURE_SGI_LABEL
1689 * Copyright (C) Andreas Neuper, Sep 1998.
1690 * This file may be modified and redistributed under
1691 * the terms of the GNU Public License.
1693 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
1694 * Internationalization
1698 static int sgi_other_endian;
1700 static short sgi_volumes = 1;
1703 * only dealing with free blocks here
1710 static freeblocks freelist[17]; /* 16 partitions can produce 17 vacant slots */
1713 setfreelist(int i, unsigned int f, unsigned int l)
1715 freelist[i].first = f;
1716 freelist[i].last = l;
1720 add2freelist(unsigned int f, unsigned int l)
1723 for (i = 0; i < 17 ; i++)
1724 if (freelist[i].last == 0)
1726 setfreelist(i, f, l);
1734 for (i = 0; i < 17 ; i++)
1735 setfreelist(i, 0, 0);
1739 isinfreelist(unsigned int b)
1743 for (i = 0; i < 17 ; i++)
1744 if (freelist[i].first <= b && freelist[i].last >= b)
1745 return freelist[i].last;
1748 /* return last vacant block of this stride (never 0). */
1749 /* the '>=' is not quite correct, but simplifies the code */
1751 * end of free blocks section
1754 static const struct systypes sgi_sys_types[] = {
1755 /* SGI_VOLHDR */ { "\x00" "SGI volhdr" },
1756 /* 0x01 */ { "\x01" "SGI trkrepl" },
1757 /* 0x02 */ { "\x02" "SGI secrepl" },
1758 /* SGI_SWAP */ { "\x03" "SGI raw" },
1759 /* 0x04 */ { "\x04" "SGI bsd" },
1760 /* 0x05 */ { "\x05" "SGI sysv" },
1761 /* ENTIRE_DISK */ { "\x06" "SGI volume" },
1762 /* SGI_EFS */ { "\x07" "SGI efs" },
1763 /* 0x08 */ { "\x08" "SGI lvol" },
1764 /* 0x09 */ { "\x09" "SGI rlvol" },
1765 /* SGI_XFS */ { "\x0a" "SGI xfs" },
1766 /* SGI_XFSLOG */ { "\x0b" "SGI xfslog" },
1767 /* SGI_XLV */ { "\x0c" "SGI xlv" },
1768 /* SGI_XVM */ { "\x0d" "SGI xvm" },
1769 /* LINUX_SWAP */ { "\x82" "Linux swap" },
1770 /* LINUX_NATIVE */ { "\x83" "Linux native" },
1771 /* LINUX_LVM */ { "\x8d" "Linux LVM" },
1772 /* LINUX_RAID */ { "\xfd" "Linux RAID" },
1780 return SGI_SSWAP16(sgilabel->devparam.nsect);
1786 return SGI_SSWAP16(sgilabel->devparam.ntrks);
1792 sgilabel->magic = 0;
1798 two_s_complement_32bit_sum(unsigned int* base, int size /* in bytes */)
1801 unsigned int sum = 0;
1803 size /= sizeof(unsigned int);
1804 for (i = 0; i < size; i++)
1805 sum -= SGI_SSWAP32(base[i]);
1810 check_sgi_label(void)
1812 if (sizeof(sgilabel) > 512) {
1814 _("According to MIPS Computer Systems, Inc the "
1815 "Label must not contain more than 512 bytes\n"));
1819 if (sgilabel->magic != SGI_LABEL_MAGIC
1820 && sgilabel->magic != SGI_LABEL_MAGIC_SWAPPED) {
1822 sgi_other_endian = 0;
1826 sgi_other_endian = (sgilabel->magic == SGI_LABEL_MAGIC_SWAPPED);
1828 * test for correct checksum
1830 if (two_s_complement_32bit_sum((unsigned int*)sgilabel,
1831 sizeof(*sgilabel))) {
1833 _("Detected sgi disklabel with wrong checksum.\n"));
1843 sgi_get_start_sector(int i)
1845 return SGI_SSWAP32(sgilabel->partitions[i].start_sector);
1849 sgi_get_num_sectors(int i)
1851 return SGI_SSWAP32(sgilabel->partitions[i].num_sectors);
1855 sgi_get_sysid(int i)
1857 return SGI_SSWAP32(sgilabel->partitions[i].id);
1861 sgi_get_bootpartition(void)
1863 return SGI_SSWAP16(sgilabel->boot_part);
1867 sgi_get_swappartition(void)
1869 return SGI_SSWAP16(sgilabel->swap_part);
1873 sgi_list_table(int xtra)
1876 int kpi = 0; /* kernel partition ID */
1879 printf(_("\nDisk %s (SGI disk label): %d heads, %d sectors\n"
1880 "%d cylinders, %d physical cylinders\n"
1881 "%d extra sects/cyl, interleave %d:1\n"
1883 "Units = %s of %d * 512 bytes\n\n"),
1884 disk_device, heads, sectors, cylinders,
1885 SGI_SSWAP16(sgiparam.pcylcount),
1886 SGI_SSWAP16(sgiparam.sparecyl),
1887 SGI_SSWAP16(sgiparam.ilfact),
1889 str_units(PLURAL), units_per_sector);
1891 printf( _("\nDisk %s (SGI disk label): "
1892 "%d heads, %d sectors, %d cylinders\n"
1893 "Units = %s of %d * 512 bytes\n\n"),
1894 disk_device, heads, sectors, cylinders,
1895 str_units(PLURAL), units_per_sector );
1898 w = strlen(disk_device);
1899 wd = strlen(_("Device"));
1903 printf(_("----- partitions -----\n"
1904 "Pt# %*s Info Start End Sectors Id System\n"),
1905 w + 2, _("Device"));
1906 for (i = 0 ; i < partitions; i++) {
1907 if( sgi_get_num_sectors(i) || debug ) {
1908 uint32_t start = sgi_get_start_sector(i);
1909 uint32_t len = sgi_get_num_sectors(i);
1910 kpi++; /* only count nonempty partitions */
1912 "%2d: %s %4s %9ld %9ld %9ld %2x %s\n",
1913 /* fdisk part number */ i+1,
1914 /* device */ partname(disk_device, kpi, w+3),
1915 /* flags */ (sgi_get_swappartition() == i) ? "swap" :
1916 /* flags */ (sgi_get_bootpartition() == i) ? "boot" : " ",
1917 /* start */ (long) scround(start),
1918 /* end */ (long) scround(start+len)-1,
1919 /* no odd flag on end */(long) len,
1920 /* type id */ sgi_get_sysid(i),
1921 /* type name */ partition_type(sgi_get_sysid(i)));
1924 printf(_("----- Bootinfo -----\nBootfile: %s\n"
1925 "----- Directory Entries -----\n"),
1926 sgilabel->boot_file);
1927 for (i = 0 ; i < sgi_volumes; i++) {
1928 if (sgilabel->directory[i].vol_file_size) {
1929 uint32_t start = SGI_SSWAP32(sgilabel->directory[i].vol_file_start);
1930 uint32_t len = SGI_SSWAP32(sgilabel->directory[i].vol_file_size);
1931 unsigned char *name = sgilabel->directory[i].vol_file_name;
1933 printf(_("%2d: %-10s sector%5u size%8u\n"),
1934 i, (char*)name, (unsigned int) start, (unsigned int) len);
1940 sgi_set_bootpartition(int i)
1942 sgilabel->boot_part = SGI_SSWAP16(((short)i));
1946 sgi_get_lastblock(void)
1948 return heads * sectors * cylinders;
1952 sgi_set_swappartition(int i)
1954 sgilabel->swap_part = SGI_SSWAP16(((short)i));
1958 sgi_check_bootfile(const char* aFile)
1960 if (strlen(aFile) < 3) /* "/a\n" is minimum */ {
1961 printf(_("\nInvalid Bootfile!\n"
1962 "\tThe bootfile must be an absolute non-zero pathname,\n"
1963 "\te.g. \"/unix\" or \"/unix.save\".\n"));
1966 if (strlen(aFile) > 16) {
1967 printf(_("\n\tName of Bootfile too long: "
1968 "16 bytes maximum.\n"));
1971 if (aFile[0] != '/') {
1972 printf(_("\n\tBootfile must have a "
1973 "fully qualified pathname.\n"));
1978 if (strncmp(aFile, (char*)sgilabel->boot_file, 16)) {
1979 printf(_("\n\tBe aware, that the bootfile is not checked for existence.\n\t"
1980 "SGI's default is \"/unix\" and for backup \"/unix.save\".\n"));
1981 /* filename is correct and did change */
1984 return 0; /* filename did not change */
1988 sgi_get_bootfile(void)
1990 return (char*)sgilabel->boot_file;
1994 sgi_set_bootfile(const char* aFile)
1998 if (sgi_check_bootfile(aFile)) {
2000 if ((aFile[i] != '\n') /* in principle caught again by next line */
2001 && (strlen(aFile) > i))
2002 sgilabel->boot_file[i] = aFile[i];
2004 sgilabel->boot_file[i] = 0;
2007 printf(_("\n\tBootfile is changed to \"%s\".\n"), sgilabel->boot_file);
2012 create_sgiinfo(void)
2014 /* I keep SGI's habit to write the sgilabel to the second block */
2015 sgilabel->directory[0].vol_file_start = SGI_SSWAP32(2);
2016 sgilabel->directory[0].vol_file_size = SGI_SSWAP32(sizeof(sgiinfo));
2017 strncpy((char*)sgilabel->directory[0].vol_file_name, "sgilabel", 8);
2020 static sgiinfo *fill_sgiinfo(void);
2023 sgi_write_table(void)
2026 sgilabel->csum = SGI_SSWAP32(two_s_complement_32bit_sum(
2027 (unsigned int*)sgilabel, sizeof(*sgilabel)));
2028 assert(two_s_complement_32bit_sum(
2029 (unsigned int*)sgilabel, sizeof(*sgilabel)) == 0);
2031 if (lseek(fd, 0, SEEK_SET) < 0)
2032 fdisk_fatal(unable_to_seek);
2033 if (write(fd, sgilabel, SECTOR_SIZE) != SECTOR_SIZE)
2034 fdisk_fatal(unable_to_write);
2035 if (!strncmp((char*)sgilabel->directory[0].vol_file_name, "sgilabel", 8)) {
2037 * keep this habit of first writing the "sgilabel".
2038 * I never tested whether it works without (AN 981002).
2040 sgiinfo *info = fill_sgiinfo();
2041 int infostartblock = SGI_SSWAP32(sgilabel->directory[0].vol_file_start);
2042 if (lseek(fd, infostartblock*SECTOR_SIZE, SEEK_SET) < 0)
2043 fdisk_fatal(unable_to_seek);
2044 if (write(fd, info, SECTOR_SIZE) != SECTOR_SIZE)
2045 fdisk_fatal(unable_to_write);
2051 compare_start(int *x, int *y)
2054 * sort according to start sectors
2055 * and prefers largest partition:
2056 * entry zero is entire disk entry
2058 unsigned int i = *x;
2059 unsigned int j = *y;
2060 unsigned int a = sgi_get_start_sector(i);
2061 unsigned int b = sgi_get_start_sector(j);
2062 unsigned int c = sgi_get_num_sectors(i);
2063 unsigned int d = sgi_get_num_sectors(j);
2066 return (d > c) ? 1 : (d == c) ? 0 : -1;
2067 return (a > b) ? 1 : -1;
2072 verify_sgi(int verbose)
2074 int Index[16]; /* list of valid partitions */
2075 int sortcount = 0; /* number of used partitions, i.e. non-zero lengths */
2076 int entire = 0, i = 0;
2077 unsigned int start = 0;
2078 long long gap = 0; /* count unused blocks */
2079 unsigned int lastblock = sgi_get_lastblock();
2082 for (i = 0; i < 16; i++) {
2083 if (sgi_get_num_sectors(i) != 0) {
2084 Index[sortcount++] = i;
2085 if (sgi_get_sysid(i) == ENTIRE_DISK) {
2086 if (entire++ == 1) {
2088 printf(_("More than one entire disk entry present.\n"));
2093 if (sortcount == 0) {
2095 printf(_("No partitions defined\n"));
2096 return (lastblock > 0) ? 1 : (lastblock == 0) ? 0 : -1;
2098 qsort(Index, sortcount, sizeof(Index[0]), (void*)compare_start);
2099 if (sgi_get_sysid(Index[0]) == ENTIRE_DISK) {
2100 if ((Index[0] != 10) && verbose)
2101 printf(_("IRIX likes when Partition 11 covers the entire disk.\n"));
2102 if ((sgi_get_start_sector(Index[0]) != 0) && verbose)
2103 printf(_("The entire disk partition should start "
2105 "not at diskblock %d.\n"),
2106 sgi_get_start_sector(Index[0]));
2107 if (debug) /* I do not understand how some disks fulfil it */
2108 if ((sgi_get_num_sectors(Index[0]) != lastblock) && verbose)
2109 printf(_("The entire disk partition is only %d diskblock large,\n"
2110 "but the disk is %d diskblocks long.\n"),
2111 sgi_get_num_sectors(Index[0]), lastblock);
2112 lastblock = sgi_get_num_sectors(Index[0]);
2115 printf(_("One Partition (#11) should cover the entire disk.\n"));
2117 printf("sysid=%d\tpartition=%d\n",
2118 sgi_get_sysid(Index[0]), Index[0]+1);
2120 for (i = 1, start = 0; i < sortcount; i++) {
2121 int cylsize = sgi_get_nsect() * sgi_get_ntrks();
2123 if ((sgi_get_start_sector(Index[i]) % cylsize) != 0) {
2124 if (debug) /* I do not understand how some disks fulfil it */
2126 printf(_("Partition %d does not start on cylinder boundary.\n"),
2129 if (sgi_get_num_sectors(Index[i]) % cylsize != 0) {
2130 if (debug) /* I do not understand how some disks fulfil it */
2132 printf(_("Partition %d does not end on cylinder boundary.\n"),
2135 /* We cannot handle several "entire disk" entries. */
2136 if (sgi_get_sysid(Index[i]) == ENTIRE_DISK) continue;
2137 if (start > sgi_get_start_sector(Index[i])) {
2139 printf(_("The Partition %d and %d overlap by %d sectors.\n"),
2140 Index[i-1]+1, Index[i]+1,
2141 start - sgi_get_start_sector(Index[i]));
2142 if (gap > 0) gap = -gap;
2143 if (gap == 0) gap = -1;
2145 if (start < sgi_get_start_sector(Index[i])) {
2147 printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"),
2148 sgi_get_start_sector(Index[i]) - start,
2149 start, sgi_get_start_sector(Index[i])-1);
2150 gap += sgi_get_start_sector(Index[i]) - start;
2151 add2freelist(start, sgi_get_start_sector(Index[i]));
2153 start = sgi_get_start_sector(Index[i])
2154 + sgi_get_num_sectors(Index[i]);
2157 printf("%2d:%12d\t%12d\t%12d\n", Index[i],
2158 sgi_get_start_sector(Index[i]),
2159 sgi_get_num_sectors(Index[i]),
2160 sgi_get_sysid(Index[i]));
2163 if (start < lastblock) {
2165 printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"),
2166 lastblock - start, start, lastblock-1);
2167 gap += lastblock - start;
2168 add2freelist(start, lastblock);
2171 * Done with arithmetics
2172 * Go for details now
2175 if (!sgi_get_num_sectors(sgi_get_bootpartition())) {
2176 printf(_("\nThe boot partition does not exist.\n"));
2178 if (!sgi_get_num_sectors(sgi_get_swappartition())) {
2179 printf(_("\nThe swap partition does not exist.\n"));
2181 if ((sgi_get_sysid(sgi_get_swappartition()) != SGI_SWAP)
2182 && (sgi_get_sysid(sgi_get_swappartition()) != LINUX_SWAP))
2183 printf(_("\nThe swap partition has no swap type.\n"));
2185 if (sgi_check_bootfile("/unix"))
2186 printf(_("\tYou have chosen an unusual boot file name.\n"));
2188 return (gap > 0) ? 1 : (gap == 0) ? 0 : -1;
2195 * returned value is:
2196 * = 0 : disk is properly filled to the rim
2197 * < 0 : there is an overlap
2198 * > 0 : there is still some vacant space
2200 return verify_sgi(0);
2204 sgi_change_sysid(int i, int sys)
2206 if( sgi_get_num_sectors(i) == 0 ) { /* caught already before, ... */
2207 printf(_("Sorry You may change the Tag of non-empty partitions.\n"));
2210 if (((sys != ENTIRE_DISK ) && (sys != SGI_VOLHDR))
2211 && (sgi_get_start_sector(i) < 1) ) {
2213 _("It is highly recommended that the partition at offset 0\n"
2214 "is of type \"SGI volhdr\", the IRIX system will rely on it to\n"
2215 "retrieve from its directory standalone tools like sash and fx.\n"
2216 "Only the \"SGI volume\" entire disk section may violate this.\n"
2217 "Type YES if you are sure about tagging this partition differently.\n"));
2218 if (strcmp(line_ptr, _("YES\n")))
2221 sgilabel->partitions[i].id = SGI_SSWAP32(sys);
2224 /* returns partition index of first entry marked as entire disk */
2230 for (i = 0; i < 16; i++)
2231 if (sgi_get_sysid(i) == SGI_VOLUME)
2237 sgi_set_partition(int i, unsigned int start, unsigned int length, int sys)
2239 sgilabel->partitions[i].id = SGI_SSWAP32(sys);
2240 sgilabel->partitions[i].num_sectors = SGI_SSWAP32(length);
2241 sgilabel->partitions[i].start_sector = SGI_SSWAP32(start);
2243 if (sgi_gaps() < 0) /* rebuild freelist */
2244 printf(_("Do You know, You got a partition overlap on the disk?\n"));
2248 sgi_set_entire(void)
2252 for (n = 10; n < partitions; n++) {
2253 if(!sgi_get_num_sectors(n) ) {
2254 sgi_set_partition(n, 0, sgi_get_lastblock(), SGI_VOLUME);
2261 sgi_set_volhdr(void)
2265 for (n = 8; n < partitions; n++) {
2266 if (!sgi_get_num_sectors(n)) {
2268 * 5 cylinders is an arbitrary value I like
2269 * IRIX 5.3 stored files in the volume header
2270 * (like sash, symmon, fx, ide) with ca. 3200
2273 if (heads * sectors * 5 < sgi_get_lastblock())
2274 sgi_set_partition(n, 0, heads * sectors * 5, SGI_VOLHDR);
2281 sgi_delete_partition(int i)
2283 sgi_set_partition(i, 0, 0, 0);
2287 sgi_add_partition(int n, int sys)
2290 unsigned int first = 0, last = 0;
2294 } else if (n == 8) {
2297 if(sgi_get_num_sectors(n)) {
2298 printf(_("Partition %d is already defined. Delete "
2299 "it before re-adding it.\n"), n + 1);
2302 if ((sgi_entire() == -1) && (sys != SGI_VOLUME)) {
2303 printf(_("Attempting to generate entire disk entry automatically.\n"));
2307 if ((sgi_gaps() == 0) && (sys != SGI_VOLUME)) {
2308 printf(_("The entire disk is already covered with partitions.\n"));
2311 if (sgi_gaps() < 0) {
2312 printf(_("You got a partition overlap on the disk. Fix it first!\n"));
2315 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
2317 if(sys == SGI_VOLUME) {
2318 last = sgi_get_lastblock();
2319 first = read_int(0, 0, last-1, 0, mesg);
2321 printf(_("It is highly recommended that eleventh partition\n"
2322 "covers the entire disk and is of type `SGI volume'\n"));
2325 first = freelist[0].first;
2326 last = freelist[0].last;
2327 first = read_int(scround(first), scround(first), scround(last)-1,
2330 if (display_in_cyl_units)
2331 first *= units_per_sector;
2333 first = first; /* align to cylinder if you know how ... */
2335 last = isinfreelist(first);
2337 printf(_("You will get a partition overlap on the disk. "
2338 "Fix it first!\n"));
2342 snprintf(mesg, sizeof(mesg), _(" Last %s"), str_units(SINGULAR));
2343 last = read_int(scround(first), scround(last)-1, scround(last)-1,
2344 scround(first), mesg)+1;
2345 if (display_in_cyl_units)
2346 last *= units_per_sector;
2348 last = last; /* align to cylinder if You know how ... */
2349 if ( (sys == SGI_VOLUME) && (first != 0 || last != sgi_get_lastblock() ) )
2350 printf(_("It is highly recommended that eleventh partition\n"
2351 "covers the entire disk and is of type `SGI volume'\n"));
2352 sgi_set_partition(n, first, last-first, sys);
2355 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
2357 create_sgilabel(void)
2359 struct hd_geometry geometry;
2366 long longsectors; /* the number of sectors on the device */
2367 int res; /* the result from the ioctl */
2368 int sec_fac; /* the sector factor */
2370 sec_fac = sector_size / 512; /* determine the sector factor */
2373 _("Building a new SGI disklabel. Changes will remain in memory only,\n"
2374 "until you decide to write them. After that, of course, the previous\n"
2375 "content will be unrecoverably lost.\n\n"));
2377 sgi_other_endian = (BYTE_ORDER == LITTLE_ENDIAN);
2378 res = ioctl(fd, BLKGETSIZE, &longsectors);
2379 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
2380 heads = geometry.heads;
2381 sectors = geometry.sectors;
2383 /* the get device size ioctl was successful */
2384 cylinders = longsectors / (heads * sectors);
2385 cylinders /= sec_fac;
2387 /* otherwise print error and use truncated version */
2388 cylinders = geometry.cylinders;
2390 _("Warning: BLKGETSIZE ioctl failed on %s. "
2391 "Using geometry cylinder value of %d.\n"
2392 "This value may be truncated for devices"
2393 " > 33.8 GB.\n"), disk_device, cylinders);
2396 for (i = 0; i < 4; i++) {
2398 if (valid_part_table_flag(MBRbuffer)) {
2399 if(get_part_table(i)->sys_ind) {
2400 old[i].sysid = get_part_table(i)->sys_ind;
2401 old[i].start = get_start_sect(get_part_table(i));
2402 old[i].nsect = get_nr_sects(get_part_table(i));
2403 printf(_("Trying to keep parameters of partition %d.\n"), i);
2405 printf(_("ID=%02x\tSTART=%d\tLENGTH=%d\n"),
2406 old[i].sysid, old[i].start, old[i].nsect);
2411 memset(MBRbuffer, 0, sizeof(MBRbuffer));
2412 sgilabel->magic = SGI_SSWAP32(SGI_LABEL_MAGIC);
2413 sgilabel->boot_part = SGI_SSWAP16(0);
2414 sgilabel->swap_part = SGI_SSWAP16(1);
2416 /* sizeof(sgilabel->boot_file) = 16 > 6 */
2417 memset(sgilabel->boot_file, 0, 16);
2418 strcpy((char*)sgilabel->boot_file, "/unix");
2420 sgilabel->devparam.skew = (0);
2421 sgilabel->devparam.gap1 = (0);
2422 sgilabel->devparam.gap2 = (0);
2423 sgilabel->devparam.sparecyl = (0);
2424 sgilabel->devparam.pcylcount = SGI_SSWAP16(geometry.cylinders);
2425 sgilabel->devparam.head_vol0 = SGI_SSWAP16(0);
2426 sgilabel->devparam.ntrks = SGI_SSWAP16(geometry.heads);
2427 /* tracks/cylinder (heads) */
2428 sgilabel->devparam.cmd_tag_queue_depth = (0);
2429 sgilabel->devparam.unused0 = (0);
2430 sgilabel->devparam.unused1 = SGI_SSWAP16(0);
2431 sgilabel->devparam.nsect = SGI_SSWAP16(geometry.sectors);
2433 sgilabel->devparam.bytes = SGI_SSWAP16(512);
2434 sgilabel->devparam.ilfact = SGI_SSWAP16(1);
2435 sgilabel->devparam.flags = SGI_SSWAP32(TRACK_FWD|
2436 IGNORE_ERRORS|RESEEK);
2437 sgilabel->devparam.datarate = SGI_SSWAP32(0);
2438 sgilabel->devparam.retries_on_error = SGI_SSWAP32(1);
2439 sgilabel->devparam.ms_per_word = SGI_SSWAP32(0);
2440 sgilabel->devparam.xylogics_gap1 = SGI_SSWAP16(0);
2441 sgilabel->devparam.xylogics_syncdelay = SGI_SSWAP16(0);
2442 sgilabel->devparam.xylogics_readdelay = SGI_SSWAP16(0);
2443 sgilabel->devparam.xylogics_gap2 = SGI_SSWAP16(0);
2444 sgilabel->devparam.xylogics_readgate = SGI_SSWAP16(0);
2445 sgilabel->devparam.xylogics_writecont = SGI_SSWAP16(0);
2446 memset( &(sgilabel->directory), 0, sizeof(struct volume_directory)*15 );
2447 memset( &(sgilabel->partitions), 0, sizeof(struct sgi_partition)*16 );
2453 for (i = 0; i < 4; i++) {
2455 sgi_set_partition(i, old[i].start, old[i].nsect, old[i].sysid);
2463 /* do nothing in the beginning */
2465 #endif /* CONFIG_FEATURE_FDISK_ADVANCED */
2467 /* _____________________________________________________________
2473 sgiinfo *info = calloc(1, sizeof(sgiinfo));
2475 info->magic = SGI_SSWAP32(SGI_INFO_MAGIC);
2476 info->b1 = SGI_SSWAP32(-1);
2477 info->b2 = SGI_SSWAP16(-1);
2478 info->b3 = SGI_SSWAP16(1);
2479 /* You may want to replace this string !!!!!!! */
2480 strcpy( (char*)info->scsi_string, "IBM OEM 0662S12 3 30" );
2481 strcpy( (char*)info->serial, "0000" );
2482 info->check1816 = SGI_SSWAP16(18*256 +16 );
2483 strcpy( (char*)info->installer, "Sfx version 5.3, Oct 18, 1994" );
2486 #endif /* SGI_LABEL */
2489 #ifdef CONFIG_FEATURE_SUN_LABEL
2493 * I think this is mostly, or entirely, due to
2494 * Jakub Jelinek (jj@sunsite.mff.cuni.cz), July 1996
2496 * Merged with fdisk for other architectures, aeb, June 1998.
2498 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
2499 * Internationalization
2503 static int sun_other_endian;
2504 static int scsi_disk;
2508 #define IDE0_MAJOR 3
2511 #define IDE1_MAJOR 22
2515 guess_device_type(void)
2517 struct stat bootstat;
2519 if (fstat(fd, &bootstat) < 0) {
2522 } else if (S_ISBLK(bootstat.st_mode)
2523 && (major(bootstat.st_rdev) == IDE0_MAJOR ||
2524 major(bootstat.st_rdev) == IDE1_MAJOR)) {
2527 } else if (S_ISBLK(bootstat.st_mode)
2528 && major(bootstat.st_rdev) == FLOPPY_MAJOR) {
2537 static const struct systypes sun_sys_types[] = {
2538 { "\x00" "Empty" }, /* 0 */
2539 { "\x01" "Boot" }, /* 1 */
2540 { "\x02" "SunOS root" }, /* 2 */
2541 { "\x03" "SunOS swap" }, /* SUNOS_SWAP */
2542 { "\x04" "SunOS usr" }, /* 4 */
2543 { "\x05" "Whole disk" }, /* WHOLE_DISK */
2544 { "\x06" "SunOS stand" }, /* 6 */
2545 { "\x07" "SunOS var" }, /* 7 */
2546 { "\x08" "SunOS home" }, /* 8 */
2547 { "\x82" "Linux swap" }, /* LINUX_SWAP */
2548 { "\x83" "Linux native" }, /* LINUX_NATIVE */
2549 { "\x8e" "Linux LVM" }, /* 0x8e */
2550 /* New (2.2.x) raid partition with autodetect using persistent superblock */
2551 { "\xfd" "Linux raid autodetect" }, /* 0xfd */
2557 set_sun_partition(int i, uint start, uint stop, int sysid)
2559 sunlabel->infos[i].id = sysid;
2560 sunlabel->partitions[i].start_cylinder =
2561 SUN_SSWAP32(start / (heads * sectors));
2562 sunlabel->partitions[i].num_sectors =
2563 SUN_SSWAP32(stop - start);
2571 sunlabel->magic = 0;
2576 check_sun_label(void)
2578 unsigned short *ush;
2581 if (sunlabel->magic != SUN_LABEL_MAGIC
2582 && sunlabel->magic != SUN_LABEL_MAGIC_SWAPPED) {
2584 sun_other_endian = 0;
2587 sun_other_endian = (sunlabel->magic == SUN_LABEL_MAGIC_SWAPPED);
2588 ush = ((unsigned short *) (sunlabel + 1)) - 1;
2589 for (csum = 0; ush >= (unsigned short *)sunlabel;) csum ^= *ush--;
2591 fprintf(stderr,_("Detected sun disklabel with wrong checksum.\n"
2592 "Probably you'll have to set all the values,\n"
2593 "e.g. heads, sectors, cylinders and partitions\n"
2594 "or force a fresh label (s command in main menu)\n"));
2596 heads = SUN_SSWAP16(sunlabel->ntrks);
2597 cylinders = SUN_SSWAP16(sunlabel->ncyl);
2598 sectors = SUN_SSWAP16(sunlabel->nsect);
2606 static const struct sun_predefined_drives {
2609 unsigned short sparecyl;
2610 unsigned short ncyl;
2611 unsigned short nacyl;
2612 unsigned short pcylcount;
2613 unsigned short ntrks;
2614 unsigned short nsect;
2615 unsigned short rspeed;
2617 { "Quantum","ProDrive 80S",1,832,2,834,6,34,3662},
2618 { "Quantum","ProDrive 105S",1,974,2,1019,6,35,3662},
2619 { "CDC","Wren IV 94171-344",3,1545,2,1549,9,46,3600},
2620 { "IBM","DPES-31080",0,4901,2,4903,4,108,5400},
2621 { "IBM","DORS-32160",0,1015,2,1017,67,62,5400},
2622 { "IBM","DNES-318350",0,11199,2,11474,10,320,7200},
2623 { "SEAGATE","ST34371",0,3880,2,3882,16,135,7228},
2624 { "","SUN0104",1,974,2,1019,6,35,3662},
2625 { "","SUN0207",4,1254,2,1272,9,36,3600},
2626 { "","SUN0327",3,1545,2,1549,9,46,3600},
2627 { "","SUN0340",0,1538,2,1544,6,72,4200},
2628 { "","SUN0424",2,1151,2,2500,9,80,4400},
2629 { "","SUN0535",0,1866,2,2500,7,80,5400},
2630 { "","SUN0669",5,1614,2,1632,15,54,3600},
2631 { "","SUN1.0G",5,1703,2,1931,15,80,3597},
2632 { "","SUN1.05",0,2036,2,2038,14,72,5400},
2633 { "","SUN1.3G",6,1965,2,3500,17,80,5400},
2634 { "","SUN2.1G",0,2733,2,3500,19,80,5400},
2635 { "IOMEGA","Jaz",0,1019,2,1021,64,32,5394},
2638 static const struct sun_predefined_drives *
2639 sun_autoconfigure_scsi(void)
2641 const struct sun_predefined_drives *p = NULL;
2643 #ifdef SCSI_IOCTL_GET_IDLUN
2653 if (!ioctl(fd, SCSI_IOCTL_GET_IDLUN, &id)) {
2655 "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n",
2657 ((id[0]>>24)&0xff)-/*PROC_SCSI_SCSI+PROC_SCSI_FILE*/33,
2659 /* This is very wrong (works only if you have one HBA),
2660 but I haven't found a way how to get hostno
2661 from the current kernel */
2668 pfd = fopen("/proc/scsi/scsi","r");
2670 while (fgets(buffer2, 2048, pfd)) {
2671 if (!strcmp(buffer, buffer2)) {
2672 if (fgets(buffer2,2048,pfd)) {
2673 q = strstr(buffer2,"Vendor: ");
2678 *q++ = 0; /* truncate vendor name */
2679 q = strstr(q,"Model: ");
2684 q = strstr(q," Rev: ");
2687 for (i = 0; i < SIZE(sun_drives); i++) {
2688 if (*sun_drives[i].vendor && strcasecmp(sun_drives[i].vendor, vendor))
2690 if (!strstr(model, sun_drives[i].model))
2692 printf(_("Autoconfigure found a %s%s%s\n"),sun_drives[i].vendor,(*sun_drives[i].vendor) ? " " : "",sun_drives[i].model);
2711 create_sunlabel(void)
2713 struct hd_geometry geometry;
2717 const struct sun_predefined_drives *p = NULL;
2720 _("Building a new sun disklabel. Changes will remain in memory only,\n"
2721 "until you decide to write them. After that, of course, the previous\n"
2722 "content won't be recoverable.\n\n"));
2723 #if BYTE_ORDER == LITTLE_ENDIAN
2724 sun_other_endian = 1;
2726 sun_other_endian = 0;
2728 memset(MBRbuffer, 0, sizeof(MBRbuffer));
2729 sunlabel->magic = SUN_SSWAP16(SUN_LABEL_MAGIC);
2731 puts(_("Drive type\n"
2732 " ? auto configure\n"
2733 " 0 custom (with hardware detected defaults)"));
2734 for (i = 0; i < SIZE(sun_drives); i++) {
2735 printf(" %c %s%s%s\n",
2736 i + 'a', sun_drives[i].vendor,
2737 (*sun_drives[i].vendor) ? " " : "",
2738 sun_drives[i].model);
2741 c = read_char(_("Select type (? for auto, 0 for custom): "));
2742 if (c >= 'a' && c < 'a' + SIZE(sun_drives)) {
2743 p = sun_drives + c - 'a';
2745 } else if (c >= 'A' && c < 'A' + SIZE(sun_drives)) {
2746 p = sun_drives + c - 'A';
2748 } else if (c == '0') {
2750 } else if (c == '?' && scsi_disk) {
2751 p = sun_autoconfigure_scsi();
2753 printf(_("Autoconfigure failed.\n"));
2760 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
2761 heads = geometry.heads;
2762 sectors = geometry.sectors;
2763 cylinders = geometry.cylinders;
2770 sunlabel->nacyl = 0;
2771 sunlabel->pcylcount = SUN_SSWAP16(cylinders);
2772 sunlabel->rspeed = SUN_SSWAP16(300);
2773 sunlabel->ilfact = SUN_SSWAP16(1);
2774 sunlabel->sparecyl = 0;
2776 heads = read_int(1,heads,1024,0,_("Heads"));
2777 sectors = read_int(1,sectors,1024,0,_("Sectors/track"));
2779 cylinders = read_int(1,cylinders-2,65535,0,_("Cylinders"));
2781 cylinders = read_int(1,0,65535,0,_("Cylinders"));
2782 sunlabel->nacyl = SUN_SSWAP16(read_int(0,2,65535,0, _("Alternate cylinders")));
2783 sunlabel->pcylcount = SUN_SSWAP16(read_int(0,cylinders+SUN_SSWAP16(sunlabel->nacyl), 65535,0, _("Physical cylinders")));
2784 sunlabel->rspeed = SUN_SSWAP16(read_int(1,5400,100000,0, _("Rotation speed (rpm)")));
2785 sunlabel->ilfact = SUN_SSWAP16(read_int(1,1,32,0, _("Interleave factor")));
2786 sunlabel->sparecyl = SUN_SSWAP16(read_int(0,0,sectors,0, _("Extra sectors per cylinder")));
2789 sunlabel->sparecyl = SUN_SSWAP16(p->sparecyl);
2790 sunlabel->ncyl = SUN_SSWAP16(p->ncyl);
2791 sunlabel->nacyl = SUN_SSWAP16(p->nacyl);
2792 sunlabel->pcylcount = SUN_SSWAP16(p->pcylcount);
2793 sunlabel->ntrks = SUN_SSWAP16(p->ntrks);
2794 sunlabel->nsect = SUN_SSWAP16(p->nsect);
2795 sunlabel->rspeed = SUN_SSWAP16(p->rspeed);
2796 sunlabel->ilfact = SUN_SSWAP16(1);
2797 cylinders = p->ncyl;
2800 puts(_("You may change all the disk params from the x menu"));
2803 snprintf((char *)(sunlabel->info), sizeof(sunlabel->info),
2804 "%s%s%s cyl %d alt %d hd %d sec %d",
2805 p ? p->vendor : "", (p && *p->vendor) ? " " : "",
2806 p ? p->model : (floppy ? _("3,5\" floppy") : _("Linux custom")),
2807 cylinders, SUN_SSWAP16(sunlabel->nacyl), heads, sectors);
2809 sunlabel->ntrks = SUN_SSWAP16(heads);
2810 sunlabel->nsect = SUN_SSWAP16(sectors);
2811 sunlabel->ncyl = SUN_SSWAP16(cylinders);
2813 set_sun_partition(0, 0, cylinders * heads * sectors, LINUX_NATIVE);
2815 if (cylinders * heads * sectors >= 150 * 2048) {
2816 ndiv = cylinders - (50 * 2048 / (heads * sectors)); /* 50M swap */
2818 ndiv = cylinders * 2 / 3;
2819 set_sun_partition(0, 0, ndiv * heads * sectors, LINUX_NATIVE);
2820 set_sun_partition(1, ndiv * heads * sectors, cylinders * heads * sectors, LINUX_SWAP);
2821 sunlabel->infos[1].flags |= 0x01; /* Not mountable */
2823 set_sun_partition(2, 0, cylinders * heads * sectors, WHOLE_DISK);
2825 unsigned short *ush = (unsigned short *)sunlabel;
2826 unsigned short csum = 0;
2827 while (ush < (unsigned short *)(&sunlabel->csum))
2829 sunlabel->csum = csum;
2832 set_all_unchanged();
2834 get_boot(create_empty_sun);
2838 toggle_sunflags(int i, unsigned char mask)
2840 if (sunlabel->infos[i].flags & mask)
2841 sunlabel->infos[i].flags &= ~mask;
2843 sunlabel->infos[i].flags |= mask;
2848 fetch_sun(uint *starts, uint *lens, uint *start, uint *stop)
2850 int i, continuous = 1;
2853 *stop = cylinders * heads * sectors;
2854 for (i = 0; i < partitions; i++) {
2855 if (sunlabel->partitions[i].num_sectors
2856 && sunlabel->infos[i].id
2857 && sunlabel->infos[i].id != WHOLE_DISK) {
2858 starts[i] = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
2859 lens[i] = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
2861 if (starts[i] == *start)
2863 else if (starts[i] + lens[i] >= *stop)
2867 /* There will be probably more gaps
2868 than one, so lets check afterwards */
2877 static uint *verify_sun_starts;
2880 verify_sun_cmp(int *a, int *b)
2882 if (*a == -1) return 1;
2883 if (*b == -1) return -1;
2884 if (verify_sun_starts[*a] > verify_sun_starts[*b]) return 1;
2891 uint starts[8], lens[8], start, stop;
2892 int i,j,k,starto,endo;
2895 verify_sun_starts = starts;
2896 fetch_sun(starts,lens,&start,&stop);
2897 for (k = 0; k < 7; k++) {
2898 for (i = 0; i < 8; i++) {
2899 if (k && (lens[i] % (heads * sectors))) {
2900 printf(_("Partition %d doesn't end on cylinder boundary\n"), i+1);
2903 for (j = 0; j < i; j++)
2905 if (starts[j] == starts[i]+lens[i]) {
2906 starts[j] = starts[i]; lens[j] += lens[i];
2908 } else if (starts[i] == starts[j]+lens[j]){
2912 if (starts[i] < starts[j]+lens[j]
2913 && starts[j] < starts[i]+lens[i]) {
2915 if (starts[j] > starto)
2917 endo = starts[i]+lens[i];
2918 if (starts[j]+lens[j] < endo)
2919 endo = starts[j]+lens[j];
2920 printf(_("Partition %d overlaps with others in "
2921 "sectors %d-%d\n"), i+1, starto, endo);
2928 for (i = 0; i < 8; i++) {
2934 qsort(array,SIZE(array),sizeof(array[0]),
2935 (int (*)(const void *,const void *)) verify_sun_cmp);
2936 if (array[0] == -1) {
2937 printf(_("No partitions defined\n"));
2940 stop = cylinders * heads * sectors;
2941 if (starts[array[0]])
2942 printf(_("Unused gap - sectors 0-%d\n"),starts[array[0]]);
2943 for (i = 0; i < 7 && array[i+1] != -1; i++) {
2944 printf(_("Unused gap - sectors %d-%d\n"),starts[array[i]]+lens[array[i]],starts[array[i+1]]);
2946 start = starts[array[i]] + lens[array[i]];
2948 printf(_("Unused gap - sectors %d-%d\n"),start,stop);
2952 add_sun_partition(int n, int sys)
2954 uint start, stop, stop2;
2955 uint starts[8], lens[8];
2961 if (sunlabel->partitions[n].num_sectors && sunlabel->infos[n].id) {
2962 printf(_("Partition %d is already defined. Delete "
2963 "it before re-adding it.\n"), n + 1);
2967 fetch_sun(starts,lens,&start,&stop);
2968 if (stop <= start) {
2972 printf(_("Other partitions already cover the whole disk.\nDelete "
2973 "some/shrink them before retry.\n"));
2977 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
2980 first = read_int(0, 0, 0, 0, mesg);
2982 first = read_int(scround(start), scround(stop)+1,
2983 scround(stop), 0, mesg);
2984 if (display_in_cyl_units)
2985 first *= units_per_sector;
2987 /* Starting sector has to be properly aligned */
2988 first = (first + heads * sectors - 1) / (heads * sectors);
2989 if (n == 2 && first != 0)
2991 It is highly recommended that the third partition covers the whole disk\n\
2992 and is of type `Whole disk'\n");
2993 /* ewt asks to add: "don't start a partition at cyl 0"
2994 However, edmundo@rano.demon.co.uk writes:
2995 "In addition to having a Sun partition table, to be able to
2996 boot from the disc, the first partition, /dev/sdX1, must
2997 start at cylinder 0. This means that /dev/sdX1 contains
2998 the partition table and the boot block, as these are the
2999 first two sectors of the disc. Therefore you must be
3000 careful what you use /dev/sdX1 for. In particular, you must
3001 not use a partition starting at cylinder 0 for Linux swap,
3002 as that would overwrite the partition table and the boot
3003 block. You may, however, use such a partition for a UFS
3004 or EXT2 file system, as these file systems leave the first
3005 1024 bytes undisturbed. */
3006 /* On the other hand, one should not use partitions
3007 starting at block 0 in an md, or the label will
3009 for (i = 0; i < partitions; i++)
3010 if (lens[i] && starts[i] <= first && starts[i] + lens[i] > first)
3012 if (i < partitions && !whole_disk) {
3013 if (n == 2 && !first) {
3017 printf(_("Sector %d is already allocated\n"), first);
3021 stop = cylinders * heads * sectors;
3023 for (i = 0; i < partitions; i++) {
3024 if (starts[i] > first && starts[i] < stop)
3027 snprintf(mesg, sizeof(mesg),
3028 _("Last %s or +size or +sizeM or +sizeK"),
3029 str_units(SINGULAR));
3031 last = read_int(scround(stop2), scround(stop2), scround(stop2),
3033 else if (n == 2 && !first)
3034 last = read_int(scround(first), scround(stop2), scround(stop2),
3035 scround(first), mesg);
3037 last = read_int(scround(first), scround(stop), scround(stop),
3038 scround(first), mesg);
3039 if (display_in_cyl_units)
3040 last *= units_per_sector;
3041 if (n == 2 && !first) {
3042 if (last >= stop2) {
3045 } else if (last > stop) {
3046 printf(_("You haven't covered the whole disk with "
3047 "the 3rd partition, but your value\n"
3048 "%d %s covers some other partition. "
3049 "Your entry has been changed\n"
3051 scround(last), str_units(SINGULAR),
3052 scround(stop), str_units(SINGULAR));
3055 } else if (!whole_disk && last > stop)
3060 set_sun_partition(n, first, last, sys);
3064 sun_delete_partition(int i)
3069 && sunlabel->infos[i].id == WHOLE_DISK
3070 && !sunlabel->partitions[i].start_cylinder
3071 && (nsec = SUN_SSWAP32(sunlabel->partitions[i].num_sectors)) == heads * sectors * cylinders)
3072 printf(_("If you want to maintain SunOS/Solaris compatibility, "
3073 "consider leaving this\n"
3074 "partition as Whole disk (5), starting at 0, with %u "
3075 "sectors\n"), nsec);
3076 sunlabel->infos[i].id = 0;
3077 sunlabel->partitions[i].num_sectors = 0;
3081 sun_change_sysid(int i, int sys)
3083 if (sys == LINUX_SWAP && !sunlabel->partitions[i].start_cylinder) {
3085 _("It is highly recommended that the partition at offset 0\n"
3086 "is UFS, EXT2FS filesystem or SunOS swap. Putting Linux swap\n"
3087 "there may destroy your partition table and bootblock.\n"
3088 "Type YES if you're very sure you would like that partition\n"
3089 "tagged with 82 (Linux swap): "));
3090 if (strcmp (line_ptr, _("YES\n")))
3096 /* swaps are not mountable by default */
3097 sunlabel->infos[i].flags |= 0x01;
3100 /* assume other types are mountable;
3101 user can change it anyway */
3102 sunlabel->infos[i].flags &= ~0x01;
3105 sunlabel->infos[i].id = sys;
3109 sun_list_table(int xtra)
3113 w = strlen(disk_device);
3116 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d rpm\n"
3117 "%d cylinders, %d alternate cylinders, %d physical cylinders\n"
3118 "%d extra sects/cyl, interleave %d:1\n"
3120 "Units = %s of %d * 512 bytes\n\n"),
3121 disk_device, heads, sectors, SUN_SSWAP16(sunlabel->rspeed),
3122 cylinders, SUN_SSWAP16(sunlabel->nacyl),
3123 SUN_SSWAP16(sunlabel->pcylcount),
3124 SUN_SSWAP16(sunlabel->sparecyl),
3125 SUN_SSWAP16(sunlabel->ilfact),
3127 str_units(PLURAL), units_per_sector);
3130 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d cylinders\n"
3131 "Units = %s of %d * 512 bytes\n\n"),
3132 disk_device, heads, sectors, cylinders,
3133 str_units(PLURAL), units_per_sector);
3135 printf(_("%*s Flag Start End Blocks Id System\n"),
3136 w + 1, _("Device"));
3137 for (i = 0 ; i < partitions; i++) {
3138 if (sunlabel->partitions[i].num_sectors) {
3139 uint32_t start = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
3140 uint32_t len = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
3141 printf("%s %c%c %9ld %9ld %9ld%c %2x %s\n",
3142 partname(disk_device, i+1, w), /* device */
3143 (sunlabel->infos[i].flags & 0x01) ? 'u' : ' ', /* flags */
3144 (sunlabel->infos[i].flags & 0x10) ? 'r' : ' ',
3145 (long) scround(start), /* start */
3146 (long) scround(start+len), /* end */
3147 (long) len / 2, len & 1 ? '+' : ' ', /* odd flag on end */
3148 sunlabel->infos[i].id, /* type id */
3149 partition_type(sunlabel->infos[i].id)); /* type name */
3154 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3157 sun_set_alt_cyl(void)
3160 SUN_SSWAP16(read_int(0,SUN_SSWAP16(sunlabel->nacyl), 65535, 0,
3161 _("Number of alternate cylinders")));
3165 sun_set_ncyl(int cyl)
3167 sunlabel->ncyl = SUN_SSWAP16(cyl);
3173 sunlabel->sparecyl =
3174 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->sparecyl), sectors, 0,
3175 _("Extra sectors per cylinder")));
3179 sun_set_ilfact(void)
3182 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->ilfact), 32, 0,
3183 _("Interleave factor")));
3187 sun_set_rspeed(void)
3190 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->rspeed), 100000, 0,
3191 _("Rotation speed (rpm)")));
3195 sun_set_pcylcount(void)
3197 sunlabel->pcylcount =
3198 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->pcylcount), 65535, 0,
3199 _("Number of physical cylinders")));
3201 #endif /* CONFIG_FEATURE_FDISK_ADVANCED */
3204 sun_write_table(void)
3206 unsigned short *ush = (unsigned short *)sunlabel;
3207 unsigned short csum = 0;
3209 while (ush < (unsigned short *)(&sunlabel->csum))
3211 sunlabel->csum = csum;
3212 if (lseek(fd, 0, SEEK_SET) < 0)
3213 fdisk_fatal(unable_to_seek);
3214 if (write(fd, sunlabel, SECTOR_SIZE) != SECTOR_SIZE)
3215 fdisk_fatal(unable_to_write);
3217 #endif /* SUN_LABEL */
3219 /* DOS partition types */
3221 static const struct systypes i386_sys_types[] = {
3224 { "\x04" "FAT16 <32M" },
3225 { "\x05" "Extended" }, /* DOS 3.3+ extended partition */
3226 { "\x06" "FAT16" }, /* DOS 16-bit >=32M */
3227 { "\x07" "HPFS/NTFS" }, /* OS/2 IFS, eg, HPFS or NTFS or QNX */
3228 { "\x0a" "OS/2 Boot Manager" },/* OS/2 Boot Manager */
3229 { "\x0b" "Win95 FAT32" },
3230 { "\x0c" "Win95 FAT32 (LBA)" },/* LBA really is `Extended Int 13h' */
3231 { "\x0e" "Win95 FAT16 (LBA)" },
3232 { "\x0f" "Win95 Ext'd (LBA)" },
3233 { "\x11" "Hidden FAT12" },
3234 { "\x12" "Compaq diagnostics" },
3235 { "\x14" "Hidden FAT16 <32M" },
3236 { "\x16" "Hidden FAT16" },
3237 { "\x17" "Hidden HPFS/NTFS" },
3238 { "\x1b" "Hidden Win95 FAT32" },
3239 { "\x1c" "Hidden Win95 FAT32 (LBA)" },
3240 { "\x1e" "Hidden Win95 FAT16 (LBA)" },
3241 { "\x3c" "PartitionMagic recovery" },
3242 { "\x41" "PPC PReP Boot" },
3244 { "\x63" "GNU HURD or SysV" }, /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */
3245 { "\x80" "Old Minix" }, /* Minix 1.4a and earlier */
3246 { "\x81" "Minix / old Linux" },/* Minix 1.4b and later */
3247 { "\x82" "Linux swap" }, /* also Solaris */
3249 { "\x84" "OS/2 hidden C: drive" },
3250 { "\x85" "Linux extended" },
3251 { "\x86" "NTFS volume set" },
3252 { "\x87" "NTFS volume set" },
3253 { "\x8e" "Linux LVM" },
3254 { "\x9f" "BSD/OS" }, /* BSDI */
3255 { "\xa0" "IBM Thinkpad hibernation" },
3256 { "\xa5" "FreeBSD" }, /* various BSD flavours */
3257 { "\xa6" "OpenBSD" },
3258 { "\xa8" "Darwin UFS" },
3259 { "\xa9" "NetBSD" },
3260 { "\xab" "Darwin boot" },
3261 { "\xb7" "BSDI fs" },
3262 { "\xb8" "BSDI swap" },
3263 { "\xbe" "Solaris boot" },
3264 { "\xeb" "BeOS fs" },
3265 { "\xee" "EFI GPT" }, /* Intel EFI GUID Partition Table */
3266 { "\xef" "EFI (FAT-12/16/32)" },/* Intel EFI System Partition */
3267 { "\xf0" "Linux/PA-RISC boot" },/* Linux/PA-RISC boot loader */
3268 { "\xf2" "DOS secondary" }, /* DOS 3.3+ secondary */
3269 { "\xfd" "Linux raid autodetect" },/* New (2.2.x) raid partition with
3270 autodetect using persistent
3272 #ifdef CONFIG_WEIRD_PARTITION_TYPES
3273 { "\x02" "XENIX root" },
3274 { "\x03" "XENIX usr" },
3275 { "\x08" "AIX" }, /* AIX boot (AIX -- PS/2 port) or SplitDrive */
3276 { "\x09" "AIX bootable" }, /* AIX data or Coherent */
3278 { "\x18" "AST SmartSleep" },
3279 { "\x24" "NEC DOS" },
3280 { "\x39" "Plan 9" },
3281 { "\x40" "Venix 80286" },
3282 { "\x4d" "QNX4.x" },
3283 { "\x4e" "QNX4.x 2nd part" },
3284 { "\x4f" "QNX4.x 3rd part" },
3285 { "\x50" "OnTrack DM" },
3286 { "\x51" "OnTrack DM6 Aux1" }, /* (or Novell) */
3287 { "\x52" "CP/M" }, /* CP/M or Microport SysV/AT */
3288 { "\x53" "OnTrack DM6 Aux3" },
3289 { "\x54" "OnTrackDM6" },
3290 { "\x55" "EZ-Drive" },
3291 { "\x56" "Golden Bow" },
3292 { "\x5c" "Priam Edisk" },
3293 { "\x61" "SpeedStor" },
3294 { "\x64" "Novell Netware 286" },
3295 { "\x65" "Novell Netware 386" },
3296 { "\x70" "DiskSecure Multi-Boot" },
3298 { "\x93" "Amoeba" },
3299 { "\x94" "Amoeba BBT" }, /* (bad block table) */
3300 { "\xa7" "NeXTSTEP" },
3301 { "\xbb" "Boot Wizard hidden" },
3302 { "\xc1" "DRDOS/sec (FAT-12)" },
3303 { "\xc4" "DRDOS/sec (FAT-16 < 32M)" },
3304 { "\xc6" "DRDOS/sec (FAT-16)" },
3305 { "\xc7" "Syrinx" },
3306 { "\xda" "Non-FS data" },
3307 { "\xdb" "CP/M / CTOS / ..." },/* CP/M or Concurrent CP/M or
3308 Concurrent DOS or CTOS */
3309 { "\xde" "Dell Utility" }, /* Dell PowerEdge Server utilities */
3310 { "\xdf" "BootIt" }, /* BootIt EMBRM */
3311 { "\xe1" "DOS access" }, /* DOS access or SpeedStor 12-bit FAT
3312 extended partition */
3313 { "\xe3" "DOS R/O" }, /* DOS R/O or SpeedStor */
3314 { "\xe4" "SpeedStor" }, /* SpeedStor 16-bit FAT extended
3315 partition < 1024 cyl. */
3316 { "\xf1" "SpeedStor" },
3317 { "\xf4" "SpeedStor" }, /* SpeedStor large partition */
3318 { "\xfe" "LANstep" }, /* SpeedStor >1024 cyl. or LANstep */
3319 { "\xff" "BBT" }, /* Xenix Bad Block Table */
3326 /* A valid partition table sector ends in 0x55 0xaa */
3328 part_table_flag(const char *b)
3330 return ((uint) b[510]) + (((uint) b[511]) << 8);
3334 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3336 write_part_table_flag(char *b)
3342 /* start_sect and nr_sects are stored little endian on all machines */
3343 /* moreover, they are not aligned correctly */
3345 store4_little_endian(unsigned char *cp, unsigned int val)
3347 cp[0] = (val & 0xff);
3348 cp[1] = ((val >> 8) & 0xff);
3349 cp[2] = ((val >> 16) & 0xff);
3350 cp[3] = ((val >> 24) & 0xff);
3352 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3355 read4_little_endian(const unsigned char *cp)
3357 return (uint)(cp[0]) + ((uint)(cp[1]) << 8)
3358 + ((uint)(cp[2]) << 16) + ((uint)(cp[3]) << 24);
3361 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3363 set_start_sect(struct partition *p, unsigned int start_sect)
3365 store4_little_endian(p->start4, start_sect);
3370 get_start_sect(const struct partition *p)
3372 return read4_little_endian(p->start4);
3375 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3377 set_nr_sects(struct partition *p, int32_t nr_sects)
3379 store4_little_endian(p->size4, nr_sects);
3384 get_nr_sects(const struct partition *p)
3386 return read4_little_endian(p->size4);
3389 /* normally O_RDWR, -l option gives O_RDONLY */
3390 static int type_open = O_RDWR;
3393 static int ext_index; /* the prime extended partition */
3394 static int listing; /* no aborts for fdisk -l */
3395 static int dos_compatible_flag = ~0;
3396 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3397 static int dos_changed;
3398 static int nowarn; /* no warnings for fdisk -l/-s */
3403 static uint user_cylinders, user_heads, user_sectors;
3404 static uint pt_heads, pt_sectors;
3405 static uint kern_heads, kern_sectors;
3407 static off_t extended_offset; /* offset of link pointers */
3409 static unsigned long long total_number_of_sectors;
3412 static jmp_buf listingbuf;
3414 static void fdisk_fatal(enum failure why)
3416 const char *message;
3420 longjmp(listingbuf, 1);
3424 case unable_to_open:
3425 message = "Unable to open %s\n";
3427 case unable_to_read:
3428 message = "Unable to read %s\n";
3430 case unable_to_seek:
3431 message = "Unable to seek on %s\n";
3433 case unable_to_write:
3434 message = "Unable to write %s\n";
3437 message = "BLKGETSIZE ioctl failed on %s\n";
3440 message = "Fatal error\n";
3443 fputc('\n', stderr);
3444 fprintf(stderr, message, disk_device);
3449 seek_sector(off_t secno)
3451 off_t offset = secno * sector_size;
3452 if (lseek(fd, offset, SEEK_SET) == (off_t) -1)
3453 fdisk_fatal(unable_to_seek);
3456 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3458 write_sector(off_t secno, char *buf)
3461 if (write(fd, buf, sector_size) != sector_size)
3462 fdisk_fatal(unable_to_write);
3466 /* Allocate a buffer and read a partition table sector */
3468 read_pte(struct pte *pe, off_t offset)
3470 pe->offset = offset;
3471 pe->sectorbuffer = (char *) xmalloc(sector_size);
3472 seek_sector(offset);
3473 if (read(fd, pe->sectorbuffer, sector_size) != sector_size)
3474 fdisk_fatal(unable_to_read);
3475 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3478 pe->part_table = pe->ext_pointer = NULL;
3482 get_partition_start(const struct pte *pe)
3484 return pe->offset + get_start_sect(pe->part_table);
3487 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3489 * Avoid warning about DOS partitions when no DOS partition was changed.
3490 * Here a heuristic "is probably dos partition".
3491 * We might also do the opposite and warn in all cases except
3492 * for "is probably nondos partition".
3495 is_dos_partition(int t)
3497 return (t == 1 || t == 4 || t == 6 ||
3498 t == 0x0b || t == 0x0c || t == 0x0e ||
3499 t == 0x11 || t == 0x12 || t == 0x14 || t == 0x16 ||
3500 t == 0x1b || t == 0x1c || t == 0x1e || t == 0x24 ||
3501 t == 0xc1 || t == 0xc4 || t == 0xc6);
3507 #ifdef CONFIG_FEATURE_SUN_LABEL
3509 puts(_("Command action"));
3510 puts(_("\ta\ttoggle a read only flag")); /* sun */
3511 puts(_("\tb\tedit bsd disklabel"));
3512 puts(_("\tc\ttoggle the mountable flag")); /* sun */
3513 puts(_("\td\tdelete a partition"));
3514 puts(_("\tl\tlist known partition types"));
3515 puts(_("\tm\tprint this menu"));
3516 puts(_("\tn\tadd a new partition"));
3517 puts(_("\to\tcreate a new empty DOS partition table"));
3518 puts(_("\tp\tprint the partition table"));
3519 puts(_("\tq\tquit without saving changes"));
3520 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3521 puts(_("\tt\tchange a partition's system id"));
3522 puts(_("\tu\tchange display/entry units"));
3523 puts(_("\tv\tverify the partition table"));
3524 puts(_("\tw\twrite table to disk and exit"));
3525 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3526 puts(_("\tx\textra functionality (experts only)"));
3530 #ifdef CONFIG_FEATURE_SGI_LABEL
3532 puts(_("Command action"));
3533 puts(_("\ta\tselect bootable partition")); /* sgi flavour */
3534 puts(_("\tb\tedit bootfile entry")); /* sgi */
3535 puts(_("\tc\tselect sgi swap partition")); /* sgi flavour */
3536 puts(_("\td\tdelete a partition"));
3537 puts(_("\tl\tlist known partition types"));
3538 puts(_("\tm\tprint this menu"));
3539 puts(_("\tn\tadd a new partition"));
3540 puts(_("\to\tcreate a new empty DOS partition table"));
3541 puts(_("\tp\tprint the partition table"));
3542 puts(_("\tq\tquit without saving changes"));
3543 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3544 puts(_("\tt\tchange a partition's system id"));
3545 puts(_("\tu\tchange display/entry units"));
3546 puts(_("\tv\tverify the partition table"));
3547 puts(_("\tw\twrite table to disk and exit"));
3550 #ifdef CONFIG_FEATURE_AIX_LABEL
3552 puts(_("Command action"));
3553 puts(_("\tm\tprint this menu"));
3554 puts(_("\to\tcreate a new empty DOS partition table"));
3555 puts(_("\tq\tquit without saving changes"));
3556 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3560 puts(_("Command action"));
3561 puts(_("\ta\ttoggle a bootable flag"));
3562 puts(_("\tb\tedit bsd disklabel"));
3563 puts(_("\tc\ttoggle the dos compatibility flag"));
3564 puts(_("\td\tdelete a partition"));
3565 puts(_("\tl\tlist known partition types"));
3566 puts(_("\tm\tprint this menu"));
3567 puts(_("\tn\tadd a new partition"));
3568 puts(_("\to\tcreate a new empty DOS partition table"));
3569 puts(_("\tp\tprint the partition table"));
3570 puts(_("\tq\tquit without saving changes"));
3571 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3572 puts(_("\tt\tchange a partition's system id"));
3573 puts(_("\tu\tchange display/entry units"));
3574 puts(_("\tv\tverify the partition table"));
3575 puts(_("\tw\twrite table to disk and exit"));
3576 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3577 puts(_("\tx\textra functionality (experts only)"));
3581 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3584 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3588 #ifdef CONFIG_FEATURE_SUN_LABEL
3590 puts(_("Command action"));
3591 puts(_("\ta\tchange number of alternate cylinders")); /*sun*/
3592 puts(_("\tc\tchange number of cylinders"));
3593 puts(_("\td\tprint the raw data in the partition table"));
3594 puts(_("\te\tchange number of extra sectors per cylinder"));/*sun*/
3595 puts(_("\th\tchange number of heads"));
3596 puts(_("\ti\tchange interleave factor")); /*sun*/
3597 puts(_("\to\tchange rotation speed (rpm)")); /*sun*/
3598 puts(_("\tm\tprint this menu"));
3599 puts(_("\tp\tprint the partition table"));
3600 puts(_("\tq\tquit without saving changes"));
3601 puts(_("\tr\treturn to main menu"));
3602 puts(_("\ts\tchange number of sectors/track"));
3603 puts(_("\tv\tverify the partition table"));
3604 puts(_("\tw\twrite table to disk and exit"));
3605 puts(_("\ty\tchange number of physical cylinders")); /*sun*/
3608 #ifdef CONFIG_FEATURE_SGI_LABEL
3610 puts(_("Command action"));
3611 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3612 puts(_("\tc\tchange number of cylinders"));
3613 puts(_("\td\tprint the raw data in the partition table"));
3614 puts(_("\te\tlist extended partitions")); /* !sun */
3615 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3616 puts(_("\th\tchange number of heads"));
3617 puts(_("\tm\tprint this menu"));
3618 puts(_("\tp\tprint the partition table"));
3619 puts(_("\tq\tquit without saving changes"));
3620 puts(_("\tr\treturn to main menu"));
3621 puts(_("\ts\tchange number of sectors/track"));
3622 puts(_("\tv\tverify the partition table"));
3623 puts(_("\tw\twrite table to disk and exit"));
3626 #ifdef CONFIG_FEATURE_AIX_LABEL
3628 puts(_("Command action"));
3629 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3630 puts(_("\tc\tchange number of cylinders"));
3631 puts(_("\td\tprint the raw data in the partition table"));
3632 puts(_("\te\tlist extended partitions")); /* !sun */
3633 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3634 puts(_("\th\tchange number of heads"));
3635 puts(_("\tm\tprint this menu"));
3636 puts(_("\tp\tprint the partition table"));
3637 puts(_("\tq\tquit without saving changes"));
3638 puts(_("\tr\treturn to main menu"));
3639 puts(_("\ts\tchange number of sectors/track"));
3640 puts(_("\tv\tverify the partition table"));
3641 puts(_("\tw\twrite table to disk and exit"));
3645 puts(_("Command action"));
3646 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3647 puts(_("\tc\tchange number of cylinders"));
3648 puts(_("\td\tprint the raw data in the partition table"));
3649 puts(_("\te\tlist extended partitions")); /* !sun */
3650 puts(_("\tf\tfix partition order")); /* !sun, !aix, !sgi */
3651 #ifdef CONFIG_FEATURE_SGI_LABEL
3652 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3654 puts(_("\th\tchange number of heads"));
3655 puts(_("\tm\tprint this menu"));
3656 puts(_("\tp\tprint the partition table"));
3657 puts(_("\tq\tquit without saving changes"));
3658 puts(_("\tr\treturn to main menu"));
3659 puts(_("\ts\tchange number of sectors/track"));
3660 puts(_("\tv\tverify the partition table"));
3661 puts(_("\tw\twrite table to disk and exit"));
3664 #endif /* ADVANCED mode */
3666 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3667 static const struct systypes *
3671 #ifdef CONFIG_FEATURE_SUN_LABEL
3672 sun_label ? sun_sys_types :
3674 #ifdef CONFIG_FEATURE_SGI_LABEL
3675 sgi_label ? sgi_sys_types :
3680 #define get_sys_types() i386_sys_types
3681 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3683 static const char *partition_type(unsigned char type)
3686 const struct systypes *types = get_sys_types();
3688 for (i = 0; types[i].name; i++)
3689 if ((unsigned char )types[i].name[0] == type)
3690 return types[i].name + 1;
3692 return _("Unknown");
3696 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3701 #ifdef CONFIG_FEATURE_SUN_LABEL
3702 sun_label ? sunlabel->infos[i].id :
3704 #ifdef CONFIG_FEATURE_SGI_LABEL
3705 sgi_label ? sgi_get_sysid(i) :
3707 ptes[i].part_table->sys_ind);
3710 void list_types(const struct systypes *sys)
3712 uint last[4], done = 0, next = 0, size;
3715 for (i = 0; sys[i].name; i++);
3718 for (i = 3; i >= 0; i--)
3719 last[3 - i] = done += (size + i - done) / (i + 1);
3723 printf("%c%2x %-15.15s", i ? ' ' : '\n',
3724 (unsigned char)sys[next].name[0],
3725 partition_type((unsigned char)sys[next].name[0]));
3726 next = last[i++] + done;
3727 if (i > 3 || next >= last[i]) {
3731 } while (done < last[0]);
3734 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3737 is_cleared_partition(const struct partition *p)
3739 return !(!p || p->boot_ind || p->head || p->sector || p->cyl ||
3740 p->sys_ind || p->end_head || p->end_sector || p->end_cyl ||
3741 get_start_sect(p) || get_nr_sects(p));
3745 clear_partition(struct partition *p)
3749 memset(p, 0, sizeof(struct partition));
3752 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3754 set_partition(int i, int doext, off_t start, off_t stop, int sysid)
3756 struct partition *p;
3760 p = ptes[i].ext_pointer;
3761 offset = extended_offset;
3763 p = ptes[i].part_table;
3764 offset = ptes[i].offset;
3768 set_start_sect(p, start - offset);
3769 set_nr_sects(p, stop - start + 1);
3770 if (dos_compatible_flag && (start/(sectors*heads) > 1023))
3771 start = heads*sectors*1024 - 1;
3772 set_hsc(p->head, p->sector, p->cyl, start);
3773 if (dos_compatible_flag && (stop/(sectors*heads) > 1023))
3774 stop = heads*sectors*1024 - 1;
3775 set_hsc(p->end_head, p->end_sector, p->end_cyl, stop);
3776 ptes[i].changed = 1;
3781 test_c(const char **m, const char *mesg)
3785 fprintf(stderr, _("You must set"));
3787 fprintf(stderr, " %s", *m);
3797 const char *m = NULL;
3801 prev = test_c(&m, _("heads"));
3803 prev = test_c(&m, _("sectors"));
3805 prev = test_c(&m, _("cylinders"));
3809 fprintf(stderr, "%s%s.\n"
3810 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3811 "You can do this from the extra functions menu.\n"
3813 , prev ? _(" and ") : " ", m);
3818 static void update_units(void)
3820 int cyl_units = heads * sectors;
3822 if (display_in_cyl_units && cyl_units)
3823 units_per_sector = cyl_units;
3825 units_per_sector = 1; /* in sectors */
3828 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3830 warn_cylinders(void)
3832 if (dos_label && cylinders > 1024 && !nowarn)
3833 fprintf(stderr, _("\n"
3834 "The number of cylinders for this disk is set to %d.\n"
3835 "There is nothing wrong with that, but this is larger than 1024,\n"
3836 "and could in certain setups cause problems with:\n"
3837 "1) software that runs at boot time (e.g., old versions of LILO)\n"
3838 "2) booting and partitioning software from other OSs\n"
3839 " (e.g., DOS FDISK, OS/2 FDISK)\n"),
3845 read_extended(int ext)
3849 struct partition *p, *q;
3853 pex->ext_pointer = pex->part_table;
3855 p = pex->part_table;
3856 if (!get_start_sect(p)) {
3858 _("Bad offset in primary extended partition\n"));
3862 while (IS_EXTENDED(p->sys_ind)) {
3863 struct pte *pe = &ptes[partitions];
3865 if (partitions >= MAXIMUM_PARTS) {
3866 /* This is not a Linux restriction, but
3867 this program uses arrays of size MAXIMUM_PARTS.
3868 Do not try to `improve' this test. */
3869 struct pte *pre = &ptes[partitions-1];
3870 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3872 _("Warning: deleting partitions after %d\n"),
3876 clear_partition(pre->ext_pointer);
3880 read_pte(pe, extended_offset + get_start_sect(p));
3882 if (!extended_offset)
3883 extended_offset = get_start_sect(p);
3885 q = p = pt_offset(pe->sectorbuffer, 0);
3886 for (i = 0; i < 4; i++, p++) if (get_nr_sects(p)) {
3887 if (IS_EXTENDED(p->sys_ind)) {
3888 if (pe->ext_pointer)
3890 _("Warning: extra link "
3891 "pointer in partition table"
3892 " %d\n"), partitions + 1);
3894 pe->ext_pointer = p;
3895 } else if (p->sys_ind) {
3898 _("Warning: ignoring extra "
3899 "data in partition table"
3900 " %d\n"), partitions + 1);
3906 /* very strange code here... */
3907 if (!pe->part_table) {
3908 if (q != pe->ext_pointer)
3911 pe->part_table = q + 1;
3913 if (!pe->ext_pointer) {
3914 if (q != pe->part_table)
3915 pe->ext_pointer = q;
3917 pe->ext_pointer = q + 1;
3920 p = pe->ext_pointer;
3924 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3925 /* remove empty links */
3927 for (i = 4; i < partitions; i++) {
3928 struct pte *pe = &ptes[i];
3930 if (!get_nr_sects(pe->part_table) &&
3931 (partitions > 5 || ptes[4].part_table->sys_ind)) {
3932 printf("omitting empty partition (%d)\n", i+1);
3933 delete_partition(i);
3934 goto remove; /* numbering changed */
3940 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3942 create_doslabel(void)
3947 _("Building a new DOS disklabel. Changes will remain in memory only,\n"
3948 "until you decide to write them. After that, of course, the previous\n"
3949 "content won't be recoverable.\n\n"));
3950 #ifdef CONFIG_FEATURE_SUN_LABEL
3951 sun_nolabel(); /* otherwise always recognised as sun */
3953 #ifdef CONFIG_FEATURE_SGI_LABEL
3954 sgi_nolabel(); /* otherwise always recognised as sgi */
3956 #ifdef CONFIG_FEATURE_AIX_LABEL
3959 #ifdef CONFIG_FEATURE_OSF_LABEL
3961 possibly_osf_label = 0;
3965 for (i = 510-64; i < 510; i++)
3967 write_part_table_flag(MBRbuffer);
3968 extended_offset = 0;
3969 set_all_unchanged();
3971 get_boot(create_empty_dos);
3973 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3976 get_sectorsize(void)
3978 if (!user_set_sector_size) {
3980 if (ioctl(fd, BLKSSZGET, &arg) == 0)
3982 if (sector_size != DEFAULT_SECTOR_SIZE)
3983 printf(_("Note: sector size is %d (not %d)\n"),
3984 sector_size, DEFAULT_SECTOR_SIZE);
3989 get_kernel_geometry(void)
3991 struct hd_geometry geometry;
3993 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
3994 kern_heads = geometry.heads;
3995 kern_sectors = geometry.sectors;
3996 /* never use geometry.cylinders - it is truncated */
4001 get_partition_table_geometry(void)
4003 const unsigned char *bufp = (const unsigned char *)MBRbuffer;
4004 struct partition *p;
4005 int i, h, s, hh, ss;
4009 if (!(valid_part_table_flag((char*)bufp)))
4013 for (i = 0; i < 4; i++) {
4014 p = pt_offset(bufp, i);
4015 if (p->sys_ind != 0) {
4016 h = p->end_head + 1;
4017 s = (p->end_sector & 077);
4022 } else if (hh != h || ss != s)
4027 if (!first && !bad) {
4037 unsigned long long bytes; /* really u64 */
4040 sec_fac = sector_size / 512;
4041 #ifdef CONFIG_FEATURE_SUN_LABEL
4042 guess_device_type();
4044 heads = cylinders = sectors = 0;
4045 kern_heads = kern_sectors = 0;
4046 pt_heads = pt_sectors = 0;
4048 get_kernel_geometry();
4049 get_partition_table_geometry();
4051 heads = user_heads ? user_heads :
4052 pt_heads ? pt_heads :
4053 kern_heads ? kern_heads : 255;
4054 sectors = user_sectors ? user_sectors :
4055 pt_sectors ? pt_sectors :
4056 kern_sectors ? kern_sectors : 63;
4057 if (ioctl(fd, BLKGETSIZE64, &bytes) == 0) {
4060 unsigned long longsectors;
4062 if (ioctl(fd, BLKGETSIZE, &longsectors))
4064 bytes = ((unsigned long long) longsectors) << 9;
4067 total_number_of_sectors = (bytes >> 9);
4070 if (dos_compatible_flag)
4071 sector_offset = sectors;
4073 cylinders = total_number_of_sectors / (heads * sectors * sec_fac);
4075 cylinders = user_cylinders;
4079 * Read MBR. Returns:
4080 * -1: no 0xaa55 flag present (possibly entire disk BSD)
4081 * 0: found or created label
4085 get_boot(enum action what)
4091 for (i = 0; i < 4; i++) {
4092 struct pte *pe = &ptes[i];
4094 pe->part_table = pt_offset(MBRbuffer, i);
4095 pe->ext_pointer = NULL;
4097 pe->sectorbuffer = MBRbuffer;
4098 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4099 pe->changed = (what == create_empty_dos);
4103 #ifdef CONFIG_FEATURE_SUN_LABEL
4104 if (what == create_empty_sun && check_sun_label())
4108 memset(MBRbuffer, 0, 512);
4110 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4111 if (what == create_empty_dos)
4112 goto got_dos_table; /* skip reading disk */
4114 if ((fd = open(disk_device, type_open)) < 0) {
4115 if ((fd = open(disk_device, O_RDONLY)) < 0) {
4116 if (what == try_only)
4118 fdisk_fatal(unable_to_open);
4120 printf(_("You will not be able to write "
4121 "the partition table.\n"));
4124 if (512 != read(fd, MBRbuffer, 512)) {
4125 if (what == try_only)
4127 fdisk_fatal(unable_to_read);
4130 if ((fd = open(disk_device, O_RDONLY)) < 0)
4132 if (512 != read(fd, MBRbuffer, 512))
4140 #ifdef CONFIG_FEATURE_SUN_LABEL
4141 if (check_sun_label())
4145 #ifdef CONFIG_FEATURE_SGI_LABEL
4146 if (check_sgi_label())
4150 #ifdef CONFIG_FEATURE_AIX_LABEL
4151 if (check_aix_label())
4155 #ifdef CONFIG_FEATURE_OSF_LABEL
4156 if (check_osf_label()) {
4157 possibly_osf_label = 1;
4158 if (!valid_part_table_flag(MBRbuffer)) {
4162 printf(_("This disk has both DOS and BSD magic.\n"
4163 "Give the 'b' command to go to BSD mode.\n"));
4167 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4171 if (!valid_part_table_flag(MBRbuffer)) {
4172 #ifndef CONFIG_FEATURE_FDISK_WRITABLE
4178 _("Device contains neither a valid DOS "
4179 "partition table, nor Sun, SGI or OSF "
4182 #ifdef CONFIG_FEATURE_SUN_LABEL
4191 case create_empty_dos:
4192 #ifdef CONFIG_FEATURE_SUN_LABEL
4193 case create_empty_sun:
4197 fprintf(stderr, _("Internal error\n"));
4200 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
4203 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4208 for (i = 0; i < 4; i++) {
4209 struct pte *pe = &ptes[i];
4211 if (IS_EXTENDED(pe->part_table->sys_ind)) {
4212 if (partitions != 4)
4213 fprintf(stderr, _("Ignoring extra extended "
4214 "partition %d\n"), i + 1);
4220 for (i = 3; i < partitions; i++) {
4221 struct pte *pe = &ptes[i];
4223 if (!valid_part_table_flag(pe->sectorbuffer)) {
4225 _("Warning: invalid flag 0x%04x of partition "
4226 "table %d will be corrected by w(rite)\n"),
4227 part_table_flag(pe->sectorbuffer), i + 1);
4228 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4237 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4239 * Print the message MESG, then read an integer between LOW and HIGH (inclusive).
4240 * If the user hits Enter, DFLT is returned.
4241 * Answers like +10 are interpreted as offsets from BASE.
4243 * There is no default if DFLT is not between LOW and HIGH.
4246 read_int(uint low, uint dflt, uint high, uint base, char *mesg)
4250 static char *ms = NULL;
4251 static int mslen = 0;
4253 if (!ms || strlen(mesg)+100 > mslen) {
4254 mslen = strlen(mesg)+200;
4255 ms = xrealloc(ms,mslen);
4258 if (dflt < low || dflt > high)
4262 snprintf(ms, mslen, _("%s (%u-%u, default %u): "),
4263 mesg, low, high, dflt);
4265 snprintf(ms, mslen, "%s (%u-%u): ", mesg, low, high);
4268 int use_default = default_ok;
4270 /* ask question and read answer */
4271 while (read_chars(ms) != '\n' && !isdigit(*line_ptr)
4272 && *line_ptr != '-' && *line_ptr != '+')
4275 if (*line_ptr == '+' || *line_ptr == '-') {
4276 int minus = (*line_ptr == '-');
4279 i = atoi(line_ptr+1);
4281 while (isdigit(*++line_ptr))
4284 switch (*line_ptr) {
4287 if (!display_in_cyl_units)
4288 i *= heads * sectors;
4302 absolute = 1000000000;
4308 unsigned long long bytes;
4311 bytes = (unsigned long long) i * absolute;
4312 unit = sector_size * units_per_sector;
4313 bytes += unit/2; /* round */
4322 while (isdigit(*line_ptr)) {
4328 printf(_("Using default value %u\n"), i = dflt);
4329 if (i >= low && i <= high)
4332 printf(_("Value out of range.\n"));
4338 get_partition(int warn, int max)
4343 i = read_int(1, 0, max, 0, _("Partition number")) - 1;
4347 if ((!sun_label && !sgi_label && !pe->part_table->sys_ind)
4348 #ifdef CONFIG_FEATURE_SUN_LABEL
4350 (!sunlabel->partitions[i].num_sectors ||
4351 !sunlabel->infos[i].id))
4353 #ifdef CONFIG_FEATURE_SGI_LABEL
4354 || (sgi_label && (!sgi_get_num_sectors(i)))
4358 _("Warning: partition %d has empty type\n"),
4365 get_existing_partition(int warn, int max)
4370 for (i = 0; i < max; i++) {
4371 struct pte *pe = &ptes[i];
4372 struct partition *p = pe->part_table;
4374 if (p && !is_cleared_partition(p)) {
4381 printf(_("Selected partition %d\n"), pno+1);
4384 printf(_("No partition is defined yet!\n"));
4388 return get_partition(warn, max);
4392 get_nonexisting_partition(int warn, int max)
4397 for (i = 0; i < max; i++) {
4398 struct pte *pe = &ptes[i];
4399 struct partition *p = pe->part_table;
4401 if (p && is_cleared_partition(p)) {
4408 printf(_("Selected partition %d\n"), pno+1);
4411 printf(_("All primary partitions have been defined already!\n"));
4415 return get_partition(warn, max);
4419 void change_units(void)
4421 display_in_cyl_units = !display_in_cyl_units;
4423 printf(_("Changing display/entry units to %s\n"),
4428 toggle_active(int i)
4430 struct pte *pe = &ptes[i];
4431 struct partition *p = pe->part_table;
4433 if (IS_EXTENDED(p->sys_ind) && !p->boot_ind)
4435 _("WARNING: Partition %d is an extended partition\n"),
4437 p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG);
4442 toggle_dos_compatibility_flag(void)
4444 dos_compatible_flag = ~dos_compatible_flag;
4445 if (dos_compatible_flag) {
4446 sector_offset = sectors;
4447 printf(_("DOS Compatibility flag is set\n"));
4451 printf(_("DOS Compatibility flag is not set\n"));
4456 delete_partition(int i)
4458 struct pte *pe = &ptes[i];
4459 struct partition *p = pe->part_table;
4460 struct partition *q = pe->ext_pointer;
4462 /* Note that for the fifth partition (i == 4) we don't actually
4463 * decrement partitions.
4466 if (warn_geometry())
4467 return; /* C/H/S not set */
4470 #ifdef CONFIG_FEATURE_SUN_LABEL
4472 sun_delete_partition(i);
4476 #ifdef CONFIG_FEATURE_SGI_LABEL
4478 sgi_delete_partition(i);
4484 if (IS_EXTENDED(p->sys_ind) && i == ext_index) {
4486 ptes[ext_index].ext_pointer = NULL;
4487 extended_offset = 0;
4493 if (!q->sys_ind && i > 4) {
4494 /* the last one in the chain - just delete */
4497 clear_partition(ptes[i].ext_pointer);
4498 ptes[i].changed = 1;
4500 /* not the last one - further ones will be moved down */
4502 /* delete this link in the chain */
4503 p = ptes[i-1].ext_pointer;
4505 set_start_sect(p, get_start_sect(q));
4506 set_nr_sects(p, get_nr_sects(q));
4507 ptes[i-1].changed = 1;
4508 } else if (partitions > 5) { /* 5 will be moved to 4 */
4509 /* the first logical in a longer chain */
4512 if (pe->part_table) /* prevent SEGFAULT */
4513 set_start_sect(pe->part_table,
4514 get_partition_start(pe) -
4516 pe->offset = extended_offset;
4520 if (partitions > 5) {
4522 while (i < partitions) {
4523 ptes[i] = ptes[i+1];
4527 /* the only logical: clear only */
4528 clear_partition(ptes[i].part_table);
4535 int i, sys, origsys;
4536 struct partition *p;
4538 #ifdef CONFIG_FEATURE_SGI_LABEL
4539 /* If sgi_label then don't use get_existing_partition,
4540 let the user select a partition, since get_existing_partition()
4541 only works for Linux like partition tables. */
4543 i = get_existing_partition(0, partitions);
4545 i = get_partition(0, partitions);
4548 i = get_existing_partition(0, partitions);
4552 p = ptes[i].part_table;
4553 origsys = sys = get_sysid(i);
4555 /* if changing types T to 0 is allowed, then
4556 the reverse change must be allowed, too */
4557 if (!sys && !sgi_label && !sun_label && !get_nr_sects(p))
4558 printf(_("Partition %d does not exist yet!\n"), i + 1);
4560 sys = read_hex (get_sys_types());
4562 if (!sys && !sgi_label && !sun_label) {
4563 printf(_("Type 0 means free space to many systems\n"
4564 "(but not to Linux). Having partitions of\n"
4565 "type 0 is probably unwise. You can delete\n"
4566 "a partition using the `d' command.\n"));
4570 if (!sun_label && !sgi_label) {
4571 if (IS_EXTENDED(sys) != IS_EXTENDED(p->sys_ind)) {
4572 printf(_("You cannot change a partition into"
4573 " an extended one or vice versa\n"
4574 "Delete it first.\n"));
4580 #ifdef CONFIG_FEATURE_SUN_LABEL
4581 if (sun_label && i == 2 && sys != WHOLE_DISK)
4582 printf(_("Consider leaving partition 3 "
4583 "as Whole disk (5),\n"
4584 "as SunOS/Solaris expects it and "
4585 "even Linux likes it.\n\n"));
4587 #ifdef CONFIG_FEATURE_SGI_LABEL
4588 if (sgi_label && ((i == 10 && sys != ENTIRE_DISK)
4589 || (i == 8 && sys != 0)))
4590 printf(_("Consider leaving partition 9 "
4591 "as volume header (0),\nand "
4592 "partition 11 as entire volume (6)"
4593 "as IRIX expects it.\n\n"));
4597 #ifdef CONFIG_FEATURE_SUN_LABEL
4599 sun_change_sysid(i, sys);
4602 #ifdef CONFIG_FEATURE_SGI_LABEL
4604 sgi_change_sysid(i, sys);
4608 printf(_("Changed system type of partition %d "
4609 "to %x (%s)\n"), i + 1, sys,
4610 partition_type(sys));
4611 ptes[i].changed = 1;
4612 if (is_dos_partition(origsys) ||
4613 is_dos_partition(sys))
4619 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
4622 /* check_consistency() and long2chs() added Sat Mar 6 12:28:16 1993,
4623 * faith@cs.unc.edu, based on code fragments from pfdisk by Gordon W. Ross,
4624 * Jan. 1990 (version 1.2.1 by Gordon W. Ross Aug. 1990; Modified by S.
4625 * Lubkin Oct. 1991). */
4628 long2chs(ulong ls, uint *c, uint *h, uint *s)
4630 int spc = heads * sectors;
4635 *s = ls % sectors + 1; /* sectors count from 1 */
4639 check_consistency(const struct partition *p, int partition)
4641 uint pbc, pbh, pbs; /* physical beginning c, h, s */
4642 uint pec, peh, pes; /* physical ending c, h, s */
4643 uint lbc, lbh, lbs; /* logical beginning c, h, s */
4644 uint lec, leh, les; /* logical ending c, h, s */
4646 if (!heads || !sectors || (partition >= 4))
4647 return; /* do not check extended partitions */
4649 /* physical beginning c, h, s */
4650 pbc = (p->cyl & 0xff) | ((p->sector << 2) & 0x300);
4652 pbs = p->sector & 0x3f;
4654 /* physical ending c, h, s */
4655 pec = (p->end_cyl & 0xff) | ((p->end_sector << 2) & 0x300);
4657 pes = p->end_sector & 0x3f;
4659 /* compute logical beginning (c, h, s) */
4660 long2chs(get_start_sect(p), &lbc, &lbh, &lbs);
4662 /* compute logical ending (c, h, s) */
4663 long2chs(get_start_sect(p) + get_nr_sects(p) - 1, &lec, &leh, &les);
4665 /* Same physical / logical beginning? */
4666 if (cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) {
4667 printf(_("Partition %d has different physical/logical "
4668 "beginnings (non-Linux?):\n"), partition + 1);
4669 printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs);
4670 printf(_("logical=(%d, %d, %d)\n"),lbc, lbh, lbs);
4673 /* Same physical / logical ending? */
4674 if (cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) {
4675 printf(_("Partition %d has different physical/logical "
4676 "endings:\n"), partition + 1);
4677 printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
4678 printf(_("logical=(%d, %d, %d)\n"),lec, leh, les);
4682 /* Beginning on cylinder boundary? */
4683 if (pbh != !pbc || pbs != 1) {
4684 printf(_("Partition %i does not start on cylinder "
4685 "boundary:\n"), partition + 1);
4686 printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs);
4687 printf(_("should be (%d, %d, 1)\n"), pbc, !pbc);
4691 /* Ending on cylinder boundary? */
4692 if (peh != (heads - 1) || pes != sectors) {
4693 printf(_("Partition %i does not end on cylinder boundary.\n"),
4696 printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
4697 printf(_("should be (%d, %d, %d)\n"),
4698 pec, heads - 1, sectors);
4704 list_disk_geometry(void)
4706 long long bytes = (total_number_of_sectors << 9);
4707 long megabytes = bytes/1000000;
4709 if (megabytes < 10000)
4710 printf(_("\nDisk %s: %ld MB, %lld bytes\n"),
4711 disk_device, megabytes, bytes);
4713 printf(_("\nDisk %s: %ld.%ld GB, %lld bytes\n"),
4714 disk_device, megabytes/1000, (megabytes/100)%10, bytes);
4715 printf(_("%d heads, %d sectors/track, %d cylinders"),
4716 heads, sectors, cylinders);
4717 if (units_per_sector == 1)
4718 printf(_(", total %llu sectors"),
4719 total_number_of_sectors / (sector_size/512));
4720 printf(_("\nUnits = %s of %d * %d = %d bytes\n\n"),
4722 units_per_sector, sector_size, units_per_sector * sector_size);
4726 * Check whether partition entries are ordered by their starting positions.
4727 * Return 0 if OK. Return i if partition i should have been earlier.
4728 * Two separate checks: primary and logical partitions.
4731 wrong_p_order(int *prev)
4733 const struct pte *pe;
4734 const struct partition *p;
4735 off_t last_p_start_pos = 0, p_start_pos;
4738 for (i = 0 ; i < partitions; i++) {
4741 last_p_start_pos = 0;
4744 if ((p = pe->part_table)->sys_ind) {
4745 p_start_pos = get_partition_start(pe);
4747 if (last_p_start_pos > p_start_pos) {
4753 last_p_start_pos = p_start_pos;
4760 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
4762 * Fix the chain of logicals.
4763 * extended_offset is unchanged, the set of sectors used is unchanged
4764 * The chain is sorted so that sectors increase, and so that
4765 * starting sectors increase.
4767 * After this it may still be that cfdisk doesnt like the table.
4768 * (This is because cfdisk considers expanded parts, from link to
4769 * end of partition, and these may still overlap.)
4771 * sfdisk /dev/hda > ohda; sfdisk /dev/hda < ohda
4775 fix_chain_of_logicals(void)
4777 int j, oj, ojj, sj, sjj;
4778 struct partition *pj,*pjj,tmp;
4780 /* Stage 1: sort sectors but leave sector of part 4 */
4781 /* (Its sector is the global extended_offset.) */
4783 for (j = 5; j < partitions-1; j++) {
4784 oj = ptes[j].offset;
4785 ojj = ptes[j+1].offset;
4787 ptes[j].offset = ojj;
4788 ptes[j+1].offset = oj;
4789 pj = ptes[j].part_table;
4790 set_start_sect(pj, get_start_sect(pj)+oj-ojj);
4791 pjj = ptes[j+1].part_table;
4792 set_start_sect(pjj, get_start_sect(pjj)+ojj-oj);
4793 set_start_sect(ptes[j-1].ext_pointer,
4794 ojj-extended_offset);
4795 set_start_sect(ptes[j].ext_pointer,
4796 oj-extended_offset);
4801 /* Stage 2: sort starting sectors */
4803 for (j = 4; j < partitions-1; j++) {
4804 pj = ptes[j].part_table;
4805 pjj = ptes[j+1].part_table;
4806 sj = get_start_sect(pj);
4807 sjj = get_start_sect(pjj);
4808 oj = ptes[j].offset;
4809 ojj = ptes[j+1].offset;
4810 if (oj+sj > ojj+sjj) {
4814 set_start_sect(pj, ojj+sjj-oj);
4815 set_start_sect(pjj, oj+sj-ojj);
4820 /* Probably something was changed */
4821 for (j = 4; j < partitions; j++)
4822 ptes[j].changed = 1;
4827 fix_partition_table_order(void)
4829 struct pte *pei, *pek;
4832 if (!wrong_p_order(NULL)) {
4833 printf(_("Nothing to do. Ordering is correct already.\n\n"));
4837 while ((i = wrong_p_order(&k)) != 0 && i < 4) {
4838 /* partition i should have come earlier, move it */
4839 /* We have to move data in the MBR */
4840 struct partition *pi, *pk, *pe, pbuf;
4844 pe = pei->ext_pointer;
4845 pei->ext_pointer = pek->ext_pointer;
4846 pek->ext_pointer = pe;
4848 pi = pei->part_table;
4849 pk = pek->part_table;
4851 memmove(&pbuf, pi, sizeof(struct partition));
4852 memmove(pi, pk, sizeof(struct partition));
4853 memmove(pk, &pbuf, sizeof(struct partition));
4855 pei->changed = pek->changed = 1;
4859 fix_chain_of_logicals();
4867 list_table(int xtra)
4869 const struct partition *p;
4872 #ifdef CONFIG_FEATURE_SUN_LABEL
4874 sun_list_table(xtra);
4879 #ifdef CONFIG_FEATURE_SGI_LABEL
4881 sgi_list_table(xtra);
4886 list_disk_geometry();
4888 #ifdef CONFIG_FEATURE_OSF_LABEL
4890 xbsd_print_disklabel(xtra);
4895 /* Heuristic: we list partition 3 of /dev/foo as /dev/foo3,
4896 but if the device name ends in a digit, say /dev/foo1,
4897 then the partition is called /dev/foo1p3. */
4898 w = strlen(disk_device);
4899 if (w && isdigit(disk_device[w-1]))
4904 printf(_("%*s Boot Start End Blocks Id System\n"),
4907 for (i = 0; i < partitions; i++) {
4908 const struct pte *pe = &ptes[i];
4911 if (p && !is_cleared_partition(p)) {
4912 off_t psects = get_nr_sects(p);
4913 off_t pblocks = psects;
4914 unsigned int podd = 0;
4916 if (sector_size < 1024) {
4917 pblocks /= (1024 / sector_size);
4918 podd = psects % (1024 / sector_size);
4920 if (sector_size > 1024)
4921 pblocks *= (sector_size / 1024);
4923 "%s %c %11llu %11llu %11llu%c %2x %s\n",
4924 partname(disk_device, i+1, w+2),
4925 /* boot flag */ !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG
4927 /* start */ (unsigned long long) cround(get_partition_start(pe)),
4928 /* end */ (unsigned long long) cround(get_partition_start(pe) + psects
4929 - (psects ? 1 : 0)),
4930 /* odd flag on end */ (unsigned long long) pblocks, podd ? '+' : ' ',
4931 /* type id */ p->sys_ind,
4932 /* type name */ partition_type(p->sys_ind));
4933 check_consistency(p, i);
4937 /* Is partition table in disk order? It need not be, but... */
4938 /* partition table entries are not checked for correct order if this
4939 is a sgi, sun or aix labeled disk... */
4940 if (dos_label && wrong_p_order(NULL)) {
4941 printf(_("\nPartition table entries are not in disk order\n"));
4945 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
4947 x_list_table(int extend)
4949 const struct pte *pe;
4950 const struct partition *p;
4953 printf(_("\nDisk %s: %d heads, %d sectors, %d cylinders\n\n"),
4954 disk_device, heads, sectors, cylinders);
4955 printf(_("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n"));
4956 for (i = 0 ; i < partitions; i++) {
4958 p = (extend ? pe->ext_pointer : pe->part_table);
4960 printf("%2d %02x%4d%4d%5d%4d%4d%5d%11u%11u %02x\n",
4961 i + 1, p->boot_ind, p->head,
4963 cylinder(p->sector, p->cyl), p->end_head,
4964 sector(p->end_sector),
4965 cylinder(p->end_sector, p->end_cyl),
4966 get_start_sect(p), get_nr_sects(p), p->sys_ind);
4968 check_consistency(p, i);
4974 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4976 fill_bounds(off_t *first, off_t *last)
4979 const struct pte *pe = &ptes[0];
4980 const struct partition *p;
4982 for (i = 0; i < partitions; pe++,i++) {
4984 if (!p->sys_ind || IS_EXTENDED(p->sys_ind)) {
4985 first[i] = 0xffffffff;
4988 first[i] = get_partition_start(pe);
4989 last[i] = first[i] + get_nr_sects(p) - 1;
4995 check(int n, uint h, uint s, uint c, off_t start)
4997 off_t total, real_s, real_c;
4999 real_s = sector(s) - 1;
5000 real_c = cylinder(s, c);
5001 total = (real_c * sectors + real_s) * heads + h;
5003 fprintf(stderr, _("Warning: partition %d contains sector 0\n"), n);
5006 _("Partition %d: head %d greater than maximum %d\n"),
5008 if (real_s >= sectors)
5009 fprintf(stderr, _("Partition %d: sector %d greater than "
5010 "maximum %d\n"), n, s, sectors);
5011 if (real_c >= cylinders)
5012 fprintf(stderr, _("Partitions %d: cylinder %llu greater than "
5013 "maximum %d\n"), n, (unsigned long long)real_c + 1, cylinders);
5014 if (cylinders <= 1024 && start != total)
5016 _("Partition %d: previous sectors %llu disagrees with "
5017 "total %llu\n"), n, (unsigned long long)start, (unsigned long long)total);
5025 off_t first[partitions], last[partitions];
5026 struct partition *p;
5028 if (warn_geometry())
5031 #ifdef CONFIG_FEATURE_SUN_LABEL
5037 #ifdef CONFIG_FEATURE_SGI_LABEL
5044 fill_bounds(first, last);
5045 for (i = 0; i < partitions; i++) {
5046 struct pte *pe = &ptes[i];
5049 if (p->sys_ind && !IS_EXTENDED(p->sys_ind)) {
5050 check_consistency(p, i);
5051 if (get_partition_start(pe) < first[i])
5052 printf(_("Warning: bad start-of-data in "
5053 "partition %d\n"), i + 1);
5054 check(i + 1, p->end_head, p->end_sector, p->end_cyl,
5056 total += last[i] + 1 - first[i];
5057 for (j = 0; j < i; j++)
5058 if ((first[i] >= first[j] && first[i] <= last[j])
5059 || ((last[i] <= last[j] && last[i] >= first[j]))) {
5060 printf(_("Warning: partition %d overlaps "
5061 "partition %d.\n"), j + 1, i + 1);
5062 total += first[i] >= first[j] ?
5063 first[i] : first[j];
5064 total -= last[i] <= last[j] ?
5070 if (extended_offset) {
5071 struct pte *pex = &ptes[ext_index];
5072 off_t e_last = get_start_sect(pex->part_table) +
5073 get_nr_sects(pex->part_table) - 1;
5075 for (i = 4; i < partitions; i++) {
5077 p = ptes[i].part_table;
5079 if (i != 4 || i + 1 < partitions)
5080 printf(_("Warning: partition %d "
5081 "is empty\n"), i + 1);
5083 else if (first[i] < extended_offset ||
5085 printf(_("Logical partition %d not entirely in "
5086 "partition %d\n"), i + 1, ext_index + 1);
5090 if (total > heads * sectors * cylinders)
5091 printf(_("Total allocated sectors %d greater than the maximum "
5092 "%d\n"), total, heads * sectors * cylinders);
5093 else if ((total = heads * sectors * cylinders - total) != 0)
5094 printf(_("%d unallocated sectors\n"), total);
5098 add_partition(int n, int sys)
5100 char mesg[256]; /* 48 does not suffice in Japanese */
5102 struct partition *p = ptes[n].part_table;
5103 struct partition *q = ptes[ext_index].part_table;
5105 off_t start, stop = 0, limit, temp,
5106 first[partitions], last[partitions];
5108 if (p && p->sys_ind) {
5109 printf(_("Partition %d is already defined. Delete "
5110 "it before re-adding it.\n"), n + 1);
5113 fill_bounds(first, last);
5115 start = sector_offset;
5116 if (display_in_cyl_units || !total_number_of_sectors)
5117 llimit = heads * sectors * cylinders - 1;
5119 llimit = total_number_of_sectors - 1;
5121 if (limit != llimit)
5123 if (extended_offset) {
5124 first[ext_index] = extended_offset;
5125 last[ext_index] = get_start_sect(q) +
5126 get_nr_sects(q) - 1;
5129 start = extended_offset + sector_offset;
5130 limit = get_start_sect(q) + get_nr_sects(q) - 1;
5132 if (display_in_cyl_units)
5133 for (i = 0; i < partitions; i++)
5134 first[i] = (cround(first[i]) - 1) * units_per_sector;
5136 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
5139 for (i = 0; i < partitions; i++) {
5142 if (start == ptes[i].offset)
5143 start += sector_offset;
5144 lastplusoff = last[i] + ((n < 4) ? 0 : sector_offset);
5145 if (start >= first[i] && start <= lastplusoff)
5146 start = lastplusoff + 1;
5150 if (start >= temp+units_per_sector && readed) {
5151 printf(_("Sector %llu is already allocated\n"), (unsigned long long)temp);
5155 if (!readed && start == temp) {
5158 saved_start = start;
5159 start = read_int(cround(saved_start), cround(saved_start), cround(limit),
5161 if (display_in_cyl_units) {
5162 start = (start - 1) * units_per_sector;
5163 if (start < saved_start) start = saved_start;
5167 } while (start != temp || !readed);
5168 if (n > 4) { /* NOT for fifth partition */
5169 struct pte *pe = &ptes[n];
5171 pe->offset = start - sector_offset;
5172 if (pe->offset == extended_offset) { /* must be corrected */
5174 if (sector_offset == 1)
5179 for (i = 0; i < partitions; i++) {
5180 struct pte *pe = &ptes[i];
5182 if (start < pe->offset && limit >= pe->offset)
5183 limit = pe->offset - 1;
5184 if (start < first[i] && limit >= first[i])
5185 limit = first[i] - 1;
5187 if (start > limit) {
5188 printf(_("No free sectors available\n"));
5193 if (cround(start) == cround(limit)) {
5196 snprintf(mesg, sizeof(mesg),
5197 _("Last %s or +size or +sizeM or +sizeK"),
5198 str_units(SINGULAR));
5199 stop = read_int(cround(start), cround(limit), cround(limit),
5200 cround(start), mesg);
5201 if (display_in_cyl_units) {
5202 stop = stop * units_per_sector - 1;
5208 set_partition(n, 0, start, stop, sys);
5210 set_partition(n - 1, 1, ptes[n].offset, stop, EXTENDED);
5212 if (IS_EXTENDED(sys)) {
5213 struct pte *pe4 = &ptes[4];
5214 struct pte *pen = &ptes[n];
5217 pen->ext_pointer = p;
5218 pe4->offset = extended_offset = start;
5219 pe4->sectorbuffer = xcalloc(1, sector_size);
5220 pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
5221 pe4->ext_pointer = pe4->part_table + 1;
5230 if (partitions > 5 || ptes[4].part_table->sys_ind) {
5231 struct pte *pe = &ptes[partitions];
5233 pe->sectorbuffer = xcalloc(1, sector_size);
5234 pe->part_table = pt_offset(pe->sectorbuffer, 0);
5235 pe->ext_pointer = pe->part_table + 1;
5240 add_partition(partitions - 1, LINUX_NATIVE);
5246 int i, free_primary = 0;
5248 if (warn_geometry())
5251 #ifdef CONFIG_FEATURE_SUN_LABEL
5253 add_sun_partition(get_partition(0, partitions), LINUX_NATIVE);
5257 #ifdef CONFIG_FEATURE_SGI_LABEL
5259 sgi_add_partition(get_partition(0, partitions), LINUX_NATIVE);
5263 #ifdef CONFIG_FEATURE_AIX_LABEL
5265 printf(_("\tSorry - this fdisk cannot handle AIX disk labels."
5266 "\n\tIf you want to add DOS-type partitions, create"
5267 "\n\ta new empty DOS partition table first. (Use o.)"
5269 "This will destroy the present disk contents.\n"));
5274 for (i = 0; i < 4; i++)
5275 free_primary += !ptes[i].part_table->sys_ind;
5277 if (!free_primary && partitions >= MAXIMUM_PARTS) {
5278 printf(_("The maximum number of partitions has been created\n"));
5282 if (!free_primary) {
5283 if (extended_offset)
5286 printf(_("You must delete some partition and add "
5287 "an extended partition first\n"));
5289 char c, line[LINE_LENGTH];
5290 snprintf(line, sizeof(line), "%s\n %s\n p primary "
5291 "partition (1-4)\n",
5292 "Command action", (extended_offset ?
5293 "l logical (5 or over)" : "e extended"));
5295 if ((c = read_char(line)) == 'p' || c == 'P') {
5296 i = get_nonexisting_partition(0, 4);
5298 add_partition(i, LINUX_NATIVE);
5301 else if (c == 'l' && extended_offset) {
5305 else if (c == 'e' && !extended_offset) {
5306 i = get_nonexisting_partition(0, 4);
5308 add_partition(i, EXTENDED);
5312 printf(_("Invalid partition number "
5313 "for type `%c'\n"), c);
5324 for (i = 0; i < 3; i++)
5325 if (ptes[i].changed)
5326 ptes[3].changed = 1;
5327 for (i = 3; i < partitions; i++) {
5328 struct pte *pe = &ptes[i];
5331 write_part_table_flag(pe->sectorbuffer);
5332 write_sector(pe->offset, pe->sectorbuffer);
5336 #ifdef CONFIG_FEATURE_SGI_LABEL
5337 else if (sgi_label) {
5338 /* no test on change? the printf below might be mistaken */
5342 #ifdef CONFIG_FEATURE_SUN_LABEL
5343 else if (sun_label) {
5346 for (i = 0; i < 8; i++)
5347 if (ptes[i].changed)
5354 printf(_("The partition table has been altered!\n\n"));
5355 reread_partition_table(1);
5359 reread_partition_table(int leave)
5364 printf(_("Calling ioctl() to re-read partition table.\n"));
5367 if ((i = ioctl(fd, BLKRRPART)) != 0) {
5370 /* some kernel versions (1.2.x) seem to have trouble
5371 rereading the partition table, but if asked to do it
5372 twice, the second time works. - biro@yggdrasil.com */
5375 if ((i = ioctl(fd, BLKRRPART)) != 0)
5380 printf(_("\nWARNING: Re-reading the partition table "
5381 "failed with error %d: %s.\n"
5382 "The kernel still uses the old table.\n"
5383 "The new table will be used "
5384 "at the next reboot.\n"),
5385 error, strerror(error));
5390 _("\nWARNING: If you have created or modified any DOS 6.x\n"
5391 "partitions, please see the fdisk manual page for additional\n"
5397 printf(_("Syncing disks.\n"));
5399 sleep(4); /* for sync() */
5403 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
5405 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
5406 #define MAX_PER_LINE 16
5408 print_buffer(char *pbuffer)
5412 for (i = 0, l = 0; i < sector_size; i++, l++) {
5414 printf("0x%03X:", i);
5415 printf(" %02X", (unsigned char) pbuffer[i]);
5416 if (l == MAX_PER_LINE - 1) {
5432 printf(_("Device: %s\n"), disk_device);
5433 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
5434 if (sun_label || sgi_label)
5435 print_buffer(MBRbuffer);
5438 for (i = 3; i < partitions; i++)
5439 print_buffer(ptes[i].sectorbuffer);
5445 struct pte *pe = &ptes[i];
5446 struct partition *p = pe->part_table;
5449 if (warn_geometry())
5451 if (!p->sys_ind || !get_nr_sects(p) || IS_EXTENDED(p->sys_ind)) {
5452 printf(_("Partition %d has no data area\n"), i + 1);
5455 first = get_partition_start(pe);
5456 new = read_int(first, first, first + get_nr_sects(p) - 1, first,
5457 _("New beginning of data")) - pe->offset;
5459 if (new != get_nr_sects(p)) {
5460 first = get_nr_sects(p) + get_start_sect(p) - new;
5461 set_nr_sects(p, first);
5462 set_start_sect(p, new);
5474 c = tolower(read_char(_("Expert command (m for help): ")));
5477 #ifdef CONFIG_FEATURE_SUN_LABEL
5484 move_begin(get_partition(0, partitions));
5487 user_cylinders = cylinders =
5488 read_int(1, cylinders, 1048576, 0,
5489 _("Number of cylinders"));
5490 #ifdef CONFIG_FEATURE_SUN_LABEL
5492 sun_set_ncyl(cylinders);
5501 #ifdef CONFIG_FEATURE_SGI_LABEL
5506 #ifdef CONFIG_FEATURE_SUN_LABEL
5516 fix_partition_table_order();
5519 #ifdef CONFIG_FEATURE_SGI_LABEL
5524 user_heads = heads = read_int(1, heads, 256, 0,
5525 _("Number of heads"));
5529 #ifdef CONFIG_FEATURE_SUN_LABEL
5535 #ifdef CONFIG_FEATURE_SUN_LABEL
5541 #ifdef CONFIG_FEATURE_SUN_LABEL
5555 user_sectors = sectors = read_int(1, sectors, 63, 0,
5556 _("Number of sectors"));
5557 if (dos_compatible_flag) {
5558 sector_offset = sectors;
5559 fprintf(stderr, _("Warning: setting "
5560 "sector offset for DOS "
5569 write_table(); /* does not return */
5572 #ifdef CONFIG_FEATURE_SUN_LABEL
5574 sun_set_pcylcount();
5582 #endif /* ADVANCED mode */
5585 is_ide_cdrom_or_tape(const char *device)
5589 struct stat statbuf;
5592 /* No device was given explicitly, and we are trying some
5593 likely things. But opening /dev/hdc may produce errors like
5594 "hdc: tray open or drive not ready"
5595 if it happens to be a CD-ROM drive. It even happens that
5596 the process hangs on the attempt to read a music CD.
5597 So try to be careful. This only works since 2.1.73. */
5599 if (strncmp("/dev/hd", device, 7))
5602 snprintf(buf, sizeof(buf), "/proc/ide/%s/media", device+5);
5603 procf = fopen(buf, "r");
5604 if (procf != NULL && fgets(buf, sizeof(buf), procf))
5605 is_ide = (!strncmp(buf, "cdrom", 5) ||
5606 !strncmp(buf, "tape", 4));
5608 /* Now when this proc file does not exist, skip the
5609 device when it is read-only. */
5610 if (stat(device, &statbuf) == 0)
5611 is_ide = ((statbuf.st_mode & 0222) == 0);
5619 try(const char *device, int user_specified)
5623 disk_device = device;
5624 if (setjmp(listingbuf))
5626 if (!user_specified)
5627 if (is_ide_cdrom_or_tape(device))
5629 if ((fd = open(disk_device, type_open)) >= 0) {
5630 gb = get_boot(try_only);
5631 if (gb > 0) { /* I/O error */
5633 } else if (gb < 0) { /* no DOS signature */
5634 list_disk_geometry();
5637 #ifdef CONFIG_FEATURE_OSF_LABEL
5638 if (btrydev(device) < 0)
5641 _("Disk %s doesn't contain a valid "
5642 "partition table\n"), device);
5647 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5648 if (!sun_label && partitions > 4)
5649 delete_partition(ext_index);
5653 /* Ignore other errors, since we try IDE
5654 and SCSI hard disks which may not be
5655 installed on the system. */
5656 if (errno == EACCES) {
5657 fprintf(stderr, _("Cannot open %s\n"), device);
5663 /* for fdisk -l: try all things in /proc/partitions
5664 that look like a partition name (do not end in a digit) */
5669 char line[100], ptname[100], devname[120], *s;
5672 procpt = bb_wfopen(PROC_PARTITIONS, "r");
5674 while (fgets(line, sizeof(line), procpt)) {
5675 if (sscanf(line, " %d %d %d %[^\n ]",
5676 &ma, &mi, &sz, ptname) != 4)
5678 for (s = ptname; *s; s++);
5681 sprintf(devname, "/dev/%s", ptname);
5684 #ifdef CONFIG_FEATURE_CLEAN_UP
5689 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5691 unknown_command(int c)
5693 printf(_("%c: unknown command\n"), c);
5697 int fdisk_main(int argc, char **argv)
5700 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5703 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5709 * fdisk -l [-b sectorsize] [-u] device ...
5710 * fdisk -s [partition] ...
5711 * fdisk [-b sectorsize] [-u] device
5713 * Options -C, -H, -S set the geometry.
5716 while ((c = getopt(argc, argv, "b:C:H:lS:uvV"
5717 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5723 /* Ugly: this sector size is really per device,
5724 so cannot be combined with multiple disks,
5725 and te same goes for the C/H/S options.
5727 sector_size = atoi(optarg);
5728 if (sector_size != 512 && sector_size != 1024 &&
5729 sector_size != 2048)
5732 user_set_sector_size = 1;
5735 user_cylinders = atoi(optarg);
5738 user_heads = atoi(optarg);
5739 if (user_heads <= 0 || user_heads >= 256)
5743 user_sectors = atoi(optarg);
5744 if (user_sectors <= 0 || user_sectors >= 64)
5748 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5752 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5758 display_in_cyl_units = 0;
5762 printf("fdisk v" UTIL_LINUX_VERSION "\n");
5770 printf(_("This kernel finds the sector size itself - "
5771 "-b option ignored\n"));
5773 if (user_set_sector_size && argc-optind != 1)
5774 printf(_("Warning: the -b (set sector size) option should"
5775 " be used with one specified device\n"));
5778 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5782 type_open = O_RDONLY;
5783 if (argc > optind) {
5786 /* avoid gcc warning:
5787 variable `k' might be clobbered by `longjmp' */
5791 for (k = optind; k < argc; k++)
5794 /* we no longer have default device names */
5795 /* but, we can use /proc/partitions instead */
5799 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5803 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5809 type_open = O_RDONLY;
5811 opts = argc - optind;
5815 for (j = optind; j < argc; j++) {
5816 disk_device = argv[j];
5817 if ((fd = open(disk_device, type_open)) < 0)
5818 fdisk_fatal(unable_to_open);
5819 if (ioctl(fd, BLKGETSIZE, &size))
5820 fdisk_fatal(ioctl_error);
5823 printf("%ld\n", size/2);
5825 printf("%s: %ld\n", argv[j], size/2);
5831 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5832 if (argc-optind == 1)
5833 disk_device = argv[optind];
5839 #ifdef CONFIG_FEATURE_OSF_LABEL
5841 /* OSF label, and no DOS label */
5842 printf(_("Detected an OSF/1 disklabel on %s, entering "
5843 "disklabel mode.\n"),
5847 /* If we return we may want to make an empty DOS label? */
5853 c = tolower(read_char(_("Command (m for help): ")));
5857 toggle_active(get_partition(1, partitions));
5858 #ifdef CONFIG_FEATURE_SUN_LABEL
5860 toggle_sunflags(get_partition(1, partitions),
5863 #ifdef CONFIG_FEATURE_SGI_LABEL
5865 sgi_set_bootpartition(
5866 get_partition(1, partitions));
5872 #ifdef CONFIG_FEATURE_SGI_LABEL
5874 printf(_("\nThe current boot file is: %s\n"),
5875 sgi_get_bootfile());
5876 if (read_chars(_("Please enter the name of the "
5877 "new boot file: ")) == '\n')
5878 printf(_("Boot file unchanged\n"));
5880 sgi_set_bootfile(line_ptr);
5883 #ifdef CONFIG_FEATURE_OSF_LABEL
5889 toggle_dos_compatibility_flag();
5890 #ifdef CONFIG_FEATURE_SUN_LABEL
5892 toggle_sunflags(get_partition(1, partitions),
5895 #ifdef CONFIG_FEATURE_SGI_LABEL
5897 sgi_set_swappartition(
5898 get_partition(1, partitions));
5906 #ifdef CONFIG_FEATURE_SGI_LABEL
5907 /* If sgi_label then don't use get_existing_partition,
5908 let the user select a partition, since
5909 get_existing_partition() only works for Linux-like
5912 j = get_existing_partition(1, partitions);
5914 j = get_partition(1, partitions);
5917 j = get_existing_partition(1, partitions);
5920 delete_partition(j);
5924 #ifdef CONFIG_FEATURE_SGI_LABEL
5931 list_types(get_sys_types());
5950 #ifdef CONFIG_FEATURE_SUN_LABEL
5964 write_table(); /* does not return */
5966 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
5968 #ifdef CONFIG_FEATURE_SGI_LABEL
5971 _("\n\tSorry, no experts menu for SGI "
5972 "partition tables available.\n\n"));
5985 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */