1 /* fdisk.c -- Partition table manipulator for Linux.
3 * Copyright (C) 1992 A. V. Le Blanc (LeBlanc@mcc.ac.uk)
5 * This program is free software. You can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation: either version 1 or
8 * (at your option) any later version.
10 * Vladimir Oleynik <dzo@simtreas.ru> 2001,2002 Busybox port
13 #define UTIL_LINUX_VERSION "2.12"
15 #define PROC_PARTITIONS "/proc/partitions"
17 #include <sys/types.h>
18 #include <sys/stat.h> /* stat */
27 #include <assert.h> /* assert */
31 #define u_char unsigned char
32 #include <scsi/scsi.h> /* SCSI_IOCTL_GET_IDLUN */
35 #include <sys/ioctl.h>
36 #include <sys/param.h>
37 #include <sys/sysmacros.h> /* major */
39 #include <stdint.h> /* for uint32_t, uint16_t, uint8_t, int16_t, etc */
41 /* Copied from linux/major.h */
42 #define FLOPPY_MAJOR 2
44 #include <sys/utsname.h>
48 #define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r))
54 #define BLKRRPART _IO(0x12,95) /* re-read partition table */
55 #define BLKGETSIZE _IO(0x12,96) /* return device size */
56 #define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */
57 #define BLKSSZGET _IO(0x12,104) /* get block device sector size */
59 /* Avoid conflicts with the 2.6 kernel headers, which define
60 * _IOR rather differently */
62 #define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size))
63 #define BLKGETSIZE64 _IOR(0x12,114,8) /* 8 = sizeof(u64) */
69 #define DEFAULT_SECTOR_SIZE 512
70 #define MAX_SECTOR_SIZE 2048
71 #define SECTOR_SIZE 512 /* still used in BSD code */
72 #define MAXIMUM_PARTS 60
74 #define ACTIVE_FLAG 0x80
77 #define WIN98_EXTENDED 0x0f
78 #define LINUX_PARTITION 0x81
79 #define LINUX_SWAP 0x82
80 #define LINUX_NATIVE 0x83
81 #define LINUX_EXTENDED 0x85
82 #define LINUX_LVM 0x8e
83 #define LINUX_RAID 0xfd
88 #define IS_EXTENDED(i) \
89 ((i) == EXTENDED || (i) == WIN98_EXTENDED || (i) == LINUX_EXTENDED)
91 #define SIZE(a) (sizeof(a)/sizeof((a)[0]))
93 #define cround(n) (display_in_cyl_units ? ((n)/units_per_sector)+1 : (n))
94 #define scround(x) (((x)+units_per_sector-1)/units_per_sector)
97 #if defined(CONFIG_LFS) || defined(FDISK_SUPPORT_LARGE_DISKS) || defined(__alpha__) || defined(__ia64__) || defined(__s390x__)
98 typedef long long fdisk_loff_t;
100 typedef long fdisk_loff_t;
104 /* including <linux/hdreg.h> also fails */
107 unsigned char sectors;
108 unsigned short cylinders;
112 #define HDIO_GETGEO 0x0301 /* get device geometry */
116 const unsigned char *name;
119 static uint sector_size = DEFAULT_SECTOR_SIZE,
120 user_set_sector_size,
124 * Raw disk label. For DOS-type partition tables the MBR,
125 * with descriptions of the primary partitions.
127 static char MBRbuffer[MAX_SECTOR_SIZE];
129 #ifdef CONFIG_FEATURE_SUN_LABEL
130 static int sun_label; /* looking at sun disklabel */
134 #ifdef CONFIG_FEATURE_SGI_LABEL
135 static int sgi_label; /* looking at sgi disklabel */
139 #ifdef CONFIG_FEATURE_AIX_LABEL
140 static int aix_label; /* looking at aix disklabel */
144 #ifdef CONFIG_FEATURE_OSF_LABEL
145 static int osf_label; /* looking at OSF/1 disklabel */
146 static int possibly_osf_label;
151 #define dos_label (!sun_label && !sgi_label && !aix_label && !osf_label)
153 static uint heads, sectors, cylinders;
154 static void update_units(void);
158 * return partition name - uses static storage unless buf is supplied
161 partname(const char *dev, int pno, int lth) {
162 static char buffer[80];
169 bufsiz = sizeof(buffer);
174 if (isdigit(dev[w-1]))
177 /* devfs kludge - note: fdisk partition names are not supposed
178 to equal kernel names, so there is no reason to do this */
179 if (strcmp (dev + w - 4, "disc") == 0) {
187 snprintf(bufp, bufsiz, "%*.*s%s%-2u",
188 lth-wp-2, w, dev, p, pno);
190 snprintf(bufp, bufsiz, "%.*s%s%-2u", w, dev, p, pno);
196 unsigned char boot_ind; /* 0x80 - active */
197 unsigned char head; /* starting head */
198 unsigned char sector; /* starting sector */
199 unsigned char cyl; /* starting cylinder */
200 unsigned char sys_ind; /* What partition type */
201 unsigned char end_head; /* end head */
202 unsigned char end_sector; /* end sector */
203 unsigned char end_cyl; /* end cylinder */
204 unsigned char start4[4]; /* starting sector counting from 0 */
205 unsigned char size4[4]; /* nr of sectors in partition */
209 ioctl_error, unable_to_open, unable_to_read, unable_to_seek,
213 enum action {fdisk, require, try_only, create_empty_dos, create_empty_sun};
215 static const char *disk_device;
216 static int fd; /* the disk */
217 static int partitions = 4; /* maximum partition + 1 */
218 static uint display_in_cyl_units = 1;
219 static uint units_per_sector = 1;
220 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
221 static char *line_ptr;
222 static void change_units(void);
223 static void reread_partition_table(int leave);
224 static void delete_partition(int i);
225 static int get_partition(int warn, int max);
226 static void list_types(const struct systypes *sys);
227 static uint read_int(uint low, uint dflt, uint high, uint base, char *mesg);
229 static const char *partition_type(unsigned char type);
230 static void fdisk_fatal(enum failure why) __attribute__ ((noreturn));
231 static void get_geometry(void);
232 static int get_boot(enum action what);
237 #define hex_val(c) ({ \
239 isdigit(_c) ? _c - '0' : \
240 tolower(_c) + 10 - 'a'; \
244 #define LINE_LENGTH 800
245 #define pt_offset(b, n) ((struct partition *)((b) + 0x1be + \
246 (n) * sizeof(struct partition)))
247 #define sector(s) ((s) & 0x3f)
248 #define cylinder(s, c) ((c) | (((s) & 0xc0) << 2))
250 #define hsc2sector(h,s,c) (sector(s) - 1 + sectors * \
251 ((h) + heads * cylinder(s,c)))
252 #define set_hsc(h,s,c,sector) { \
253 s = sector % sectors + 1; \
255 h = sector % heads; \
258 s |= (sector >> 2) & 0xc0; \
262 static unsigned int get_start_sect(const struct partition *p);
263 static unsigned int get_nr_sects(const struct partition *p);
266 * per partition table entry data
268 * The four primary partitions have the same sectorbuffer (MBRbuffer)
269 * and have NULL ext_pointer.
270 * Each logical partition table entry has two pointers, one for the
271 * partition and one link to the next one.
274 struct partition *part_table; /* points into sectorbuffer */
275 struct partition *ext_pointer; /* points into sectorbuffer */
276 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
277 char changed; /* boolean */
279 uint offset; /* disk sector number */
280 char *sectorbuffer; /* disk sector contents */
281 } ptes[MAXIMUM_PARTS];
284 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
286 set_all_unchanged(void) {
289 for (i = 0; i < MAXIMUM_PARTS; i++)
297 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
299 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_OSF_LABEL)
300 static struct partition *
301 get_part_table(int i) {
302 return ptes[i].part_table;
307 str_units(int n) { /* n==1: use singular */
309 return display_in_cyl_units ? _("cylinder") : _("sector");
311 return display_in_cyl_units ? _("cylinders") : _("sectors");
315 valid_part_table_flag(const unsigned char *b) {
316 return (b[510] == 0x55 && b[511] == 0xaa);
319 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
320 static char line_buffer[LINE_LENGTH];
322 /* read line; return 0 or first char */
326 static int got_eof = 0;
328 fflush (stdout); /* requested by niles@scyld.com */
329 line_ptr = line_buffer;
330 if (!fgets(line_buffer, LINE_LENGTH, stdin)) {
332 got_eof++; /* user typed ^D ? */
334 fprintf(stderr, _("\ngot EOF thrice - exiting..\n"));
339 while (*line_ptr && !isgraph(*line_ptr))
345 read_char(const char *mesg)
349 } while (!read_line());
354 read_chars(const char *mesg)
365 read_hex(const struct systypes *sys)
371 read_char(_("Hex code (type L to list codes): "));
372 if (*line_ptr == 'l' || *line_ptr == 'L')
374 else if (isxdigit (*line_ptr))
378 hex = hex << 4 | hex_val(*line_ptr++);
379 while (isxdigit(*line_ptr));
384 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
386 #ifdef CONFIG_FEATURE_AIX_LABEL
388 * Copyright (C) Andreas Neuper, Sep 1998.
389 * This file may be redistributed under
390 * the terms of the GNU Public License.
394 unsigned int magic; /* expect AIX_LABEL_MAGIC */
395 unsigned int fillbytes1[124];
396 unsigned int physical_volume_id;
397 unsigned int fillbytes2[124];
400 #define AIX_LABEL_MAGIC 0xc9c2d4c1
401 #define AIX_LABEL_MAGIC_SWAPPED 0xc1d4c2c9
402 #define AIX_INFO_MAGIC 0x00072959
403 #define AIX_INFO_MAGIC_SWAPPED 0x59290700
405 #define aixlabel ((aix_partition *)MBRbuffer)
410 * 1999-03-20 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
411 * Internationalization
413 * 2003-03-20 Phillip Kesling <pkesling@sgi.com>
417 static int aix_other_endian;
418 static short aix_volumes=1;
421 * only dealing with free blocks here
427 _("\n\tThere is a valid AIX label on this disk.\n"
428 "\tUnfortunately Linux cannot handle these\n"
429 "\tdisks at the moment. Nevertheless some\n"
431 "\t1. fdisk will destroy its contents on write.\n"
432 "\t2. Be sure that this disk is NOT a still vital\n"
433 "\t part of a volume group. (Otherwise you may\n"
434 "\t erase the other disks as well, if unmirrored.)\n"
435 "\t3. Before deleting this physical volume be sure\n"
436 "\t to remove the disk logically from your AIX\n"
437 "\t machine. (Otherwise you become an AIXpert).")
447 memset( MBRbuffer, 0, sizeof(MBRbuffer) ); /* avoid fdisk cores */
452 check_aix_label( void )
454 if (aixlabel->magic != AIX_LABEL_MAGIC &&
455 aixlabel->magic != AIX_LABEL_MAGIC_SWAPPED) {
457 aix_other_endian = 0;
460 aix_other_endian = (aixlabel->magic == AIX_LABEL_MAGIC_SWAPPED);
466 aix_nolabel(); /* %% */
467 aix_label = 1; /* %% */
470 #endif /* AIX_LABEL */
472 #ifdef CONFIG_FEATURE_OSF_LABEL
474 * Copyright (c) 1987, 1988 Regents of the University of California.
475 * All rights reserved.
477 * Redistribution and use in source and binary forms, with or without
478 * modification, are permitted provided that the following conditions
480 * 1. Redistributions of source code must retain the above copyright
481 * notice, this list of conditions and the following disclaimer.
482 * 2. Redistributions in binary form must reproduce the above copyright
483 * notice, this list of conditions and the following disclaimer in the
484 * documentation and/or other materials provided with the distribution.
485 * 3. All advertising materials mentioning features or use of this software
486 * must display the following acknowledgement:
487 * This product includes software developed by the University of
488 * California, Berkeley and its contributors.
489 * 4. Neither the name of the University nor the names of its contributors
490 * may be used to endorse or promote products derived from this software
491 * without specific prior written permission.
493 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
494 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
495 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
496 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
497 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
498 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
499 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
500 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
501 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
502 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
507 #ifndef BSD_DISKMAGIC
508 #define BSD_DISKMAGIC ((uint32_t) 0x82564557)
511 #ifndef BSD_MAXPARTITIONS
512 #define BSD_MAXPARTITIONS 16
515 #define BSD_LINUX_BOOTDIR "/usr/ucb/mdec"
517 #if defined (i386) || defined (__sparc__) || defined (__arm__) || defined (__mips__) || defined (__s390__) || defined (__sh__) || defined(__x86_64__)
518 #define BSD_LABELSECTOR 1
519 #define BSD_LABELOFFSET 0
520 #elif defined (__alpha__) || defined (__powerpc__) || defined (__ia64__) || defined (__hppa__)
521 #define BSD_LABELSECTOR 0
522 #define BSD_LABELOFFSET 64
523 #elif defined (__s390__) || defined (__s390x__)
524 #define BSD_LABELSECTOR 1
525 #define BSD_LABELOFFSET 0
527 #error unknown architecture
530 #define BSD_BBSIZE 8192 /* size of boot area, with label */
531 #define BSD_SBSIZE 8192 /* max size of fs superblock */
533 struct xbsd_disklabel {
534 uint32_t d_magic; /* the magic number */
535 int16_t d_type; /* drive type */
536 int16_t d_subtype; /* controller/d_type specific */
537 char d_typename[16]; /* type name, e.g. "eagle" */
538 char d_packname[16]; /* pack identifier */
540 uint32_t d_secsize; /* # of bytes per sector */
541 uint32_t d_nsectors; /* # of data sectors per track */
542 uint32_t d_ntracks; /* # of tracks per cylinder */
543 uint32_t d_ncylinders; /* # of data cylinders per unit */
544 uint32_t d_secpercyl; /* # of data sectors per cylinder */
545 uint32_t d_secperunit; /* # of data sectors per unit */
547 * Spares (bad sector replacements) below
548 * are not counted in d_nsectors or d_secpercyl.
549 * Spare sectors are assumed to be physical sectors
550 * which occupy space at the end of each track and/or cylinder.
552 uint16_t d_sparespertrack; /* # of spare sectors per track */
553 uint16_t d_sparespercyl; /* # of spare sectors per cylinder */
555 * Alternate cylinders include maintenance, replacement,
556 * configuration description areas, etc.
558 uint32_t d_acylinders; /* # of alt. cylinders per unit */
560 /* hardware characteristics: */
562 * d_interleave, d_trackskew and d_cylskew describe perturbations
563 * in the media format used to compensate for a slow controller.
564 * Interleave is physical sector interleave, set up by the formatter
565 * or controller when formatting. When interleaving is in use,
566 * logically adjacent sectors are not physically contiguous,
567 * but instead are separated by some number of sectors.
568 * It is specified as the ratio of physical sectors traversed
569 * per logical sector. Thus an interleave of 1:1 implies contiguous
570 * layout, while 2:1 implies that logical sector 0 is separated
571 * by one sector from logical sector 1.
572 * d_trackskew is the offset of sector 0 on track N
573 * relative to sector 0 on track N-1 on the same cylinder.
574 * Finally, d_cylskew is the offset of sector 0 on cylinder N
575 * relative to sector 0 on cylinder N-1.
577 uint16_t d_rpm; /* rotational speed */
578 uint16_t d_interleave; /* hardware sector interleave */
579 uint16_t d_trackskew; /* sector 0 skew, per track */
580 uint16_t d_cylskew; /* sector 0 skew, per cylinder */
581 uint32_t d_headswitch; /* head switch time, usec */
582 uint32_t d_trkseek; /* track-to-track seek, usec */
583 uint32_t d_flags; /* generic flags */
585 uint32_t d_drivedata[NDDATA]; /* drive-type specific information */
587 uint32_t d_spare[NSPARE]; /* reserved for future use */
588 uint32_t d_magic2; /* the magic number (again) */
589 uint16_t d_checksum; /* xor of data incl. partitions */
590 /* filesystem and partition information: */
591 uint16_t d_npartitions; /* number of partitions in following */
592 uint32_t d_bbsize; /* size of boot area at sn0, bytes */
593 uint32_t d_sbsize; /* max size of fs superblock, bytes */
594 struct xbsd_partition { /* the partition table */
595 uint32_t p_size; /* number of sectors in partition */
596 uint32_t p_offset; /* starting sector */
597 uint32_t p_fsize; /* filesystem basic fragment size */
598 uint8_t p_fstype; /* filesystem type, see below */
599 uint8_t p_frag; /* filesystem fragments per block */
600 uint16_t p_cpg; /* filesystem cylinders per group */
601 } d_partitions[BSD_MAXPARTITIONS]; /* actually may be more */
605 #define BSD_DTYPE_SMD 1 /* SMD, XSMD; VAX hp/up */
606 #define BSD_DTYPE_MSCP 2 /* MSCP */
607 #define BSD_DTYPE_DEC 3 /* other DEC (rk, rl) */
608 #define BSD_DTYPE_SCSI 4 /* SCSI */
609 #define BSD_DTYPE_ESDI 5 /* ESDI interface */
610 #define BSD_DTYPE_ST506 6 /* ST506 etc. */
611 #define BSD_DTYPE_HPIB 7 /* CS/80 on HP-IB */
612 #define BSD_DTYPE_HPFL 8 /* HP Fiber-link */
613 #define BSD_DTYPE_FLOPPY 10 /* floppy */
615 /* d_subtype values: */
616 #define BSD_DSTYPE_INDOSPART 0x8 /* is inside dos partition */
617 #define BSD_DSTYPE_DOSPART(s) ((s) & 3) /* dos partition number */
618 #define BSD_DSTYPE_GEOMETRY 0x10 /* drive params in label */
621 static const char * const xbsd_dktypenames[] = {
635 #define BSD_DKMAXTYPES (sizeof(xbsd_dktypenames) / sizeof(xbsd_dktypenames[0]) - 1)
639 * Filesystem type and version.
640 * Used to interpret other filesystem-specific
641 * per-partition information.
643 #define BSD_FS_UNUSED 0 /* unused */
644 #define BSD_FS_SWAP 1 /* swap */
645 #define BSD_FS_V6 2 /* Sixth Edition */
646 #define BSD_FS_V7 3 /* Seventh Edition */
647 #define BSD_FS_SYSV 4 /* System V */
648 #define BSD_FS_V71K 5 /* V7 with 1K blocks (4.1, 2.9) */
649 #define BSD_FS_V8 6 /* Eighth Edition, 4K blocks */
650 #define BSD_FS_BSDFFS 7 /* 4.2BSD fast file system */
651 #define BSD_FS_BSDLFS 9 /* 4.4BSD log-structured file system */
652 #define BSD_FS_OTHER 10 /* in use, but unknown/unsupported */
653 #define BSD_FS_HPFS 11 /* OS/2 high-performance file system */
654 #define BSD_FS_ISO9660 12 /* ISO-9660 filesystem (cdrom) */
655 #define BSD_FS_ISOFS BSD_FS_ISO9660
656 #define BSD_FS_BOOT 13 /* partition contains bootstrap */
657 #define BSD_FS_ADOS 14 /* AmigaDOS fast file system */
658 #define BSD_FS_HFS 15 /* Macintosh HFS */
659 #define BSD_FS_ADVFS 16 /* Digital Unix AdvFS */
661 /* this is annoying, but it's also the way it is :-( */
663 #define BSD_FS_EXT2 8 /* ext2 file system */
665 #define BSD_FS_MSDOS 8 /* MS-DOS file system */
669 static const struct systypes xbsd_fstypes[] = {
670 /* BSD_FS_UNUSED */ {"\x00" "unused"},
671 /* BSD_FS_SWAP */ {"\x01" "swap"},
672 /* BSD_FS_V6 */ {"\x02" "Version 6"},
673 /* BSD_FS_V7 */ {"\x03" "Version 7"},
674 /* BSD_FS_SYSV */ {"\x04" "System V"},
675 /* BSD_FS_V71K */ {"\x05" "4.1BSD"},
676 /* BSD_FS_V8 */ {"\x06" "Eighth Edition"},
677 /* BSD_FS_BSDFFS */ {"\x07" "4.2BSD"},
679 /* BSD_FS_EXT2 */ {"\x08" "ext2"},
681 /* BSD_FS_MSDOS */ {"\x08" "MS-DOS"},
683 /* BSD_FS_BSDLFS */ {"\x09" "4.4LFS"},
684 /* BSD_FS_OTHER */ {"\x0a" "unknown"},
685 /* BSD_FS_HPFS */ {"\x0b" "HPFS"},
686 /* BSD_FS_ISO9660 */ {"\x0c" "ISO-9660"},
687 /* BSD_FS_BOOT */ {"\x0d" "boot"},
688 /* BSD_FS_ADOS */ {"\x0e" "ADOS"},
689 /* BSD_FS_HFS */ {"\x0f" "HFS"},
690 /* BSD_FS_ADVFS */ {"\x10" "AdvFS"},
693 #define BSD_FSMAXTYPES (SIZE(xbsd_fstypes)-1)
698 * flags shared by various drives:
700 #define BSD_D_REMOVABLE 0x01 /* removable media */
701 #define BSD_D_ECC 0x02 /* supports ECC */
702 #define BSD_D_BADSECT 0x04 /* supports bad sector forw. */
703 #define BSD_D_RAMDISK 0x08 /* disk emulator */
704 #define BSD_D_CHAIN 0x10 /* can do back-back transfers */
705 #define BSD_D_DOSPART 0x20 /* within MSDOS partition */
707 #endif /* OSF_LABEL */
710 * Copyright (C) Andreas Neuper, Sep 1998.
711 * This file may be modified and redistributed under
712 * the terms of the GNU Public License.
715 struct device_parameter { /* 48 bytes */
719 unsigned char sparecyl;
720 unsigned short pcylcount;
721 unsigned short head_vol0;
722 unsigned short ntrks; /* tracks in cyl 0 or vol 0 */
723 unsigned char cmd_tag_queue_depth;
724 unsigned char unused0;
725 unsigned short unused1;
726 unsigned short nsect; /* sectors/tracks in cyl 0 or vol 0 */
727 unsigned short bytes;
728 unsigned short ilfact;
729 unsigned int flags; /* controller flags */
730 unsigned int datarate;
731 unsigned int retries_on_error;
732 unsigned int ms_per_word;
733 unsigned short xylogics_gap1;
734 unsigned short xylogics_syncdelay;
735 unsigned short xylogics_readdelay;
736 unsigned short xylogics_gap2;
737 unsigned short xylogics_readgate;
738 unsigned short xylogics_writecont;
741 #define SGI_VOLHDR 0x00
742 /* 1 and 2 were used for drive types no longer supported by SGI */
743 #define SGI_SWAP 0x03
744 /* 4 and 5 were for filesystem types SGI haven't ever supported on MIPS CPUs */
745 #define SGI_VOLUME 0x06
747 #define SGI_LVOL 0x08
748 #define SGI_RLVOL 0x09
750 #define SGI_XFSLOG 0x0b
753 #define ENTIRE_DISK SGI_VOLUME
757 #define SECTOR_SLIP 0x01
758 #define SECTOR_FWD 0x02
759 #define TRACK_FWD 0x04
760 #define TRACK_MULTIVOL 0x08
761 #define IGNORE_ERRORS 0x10
763 #define ENABLE_CMDTAGQ 0x40
766 unsigned int magic; /* expect SGI_LABEL_MAGIC */
767 unsigned short boot_part; /* active boot partition */
768 unsigned short swap_part; /* active swap partition */
769 unsigned char boot_file[16]; /* name of the bootfile */
770 struct device_parameter devparam; /* 1 * 48 bytes */
771 struct volume_directory { /* 15 * 16 bytes */
772 unsigned char vol_file_name[8]; /* a character array */
773 unsigned int vol_file_start; /* number of logical block */
774 unsigned int vol_file_size; /* number of bytes */
776 struct sgi_partition { /* 16 * 12 bytes */
777 unsigned int num_sectors; /* number of blocks */
778 unsigned int start_sector; /* must be cylinder aligned */
782 unsigned int fillbytes;
786 unsigned int magic; /* looks like a magic number */
795 unsigned char scsi_string[50];
796 unsigned char serial[137];
797 unsigned short check1816;
798 unsigned char installer[225];
801 #define SGI_LABEL_MAGIC 0x0be5a941
802 #define SGI_LABEL_MAGIC_SWAPPED 0x41a9e50b
803 #define SGI_INFO_MAGIC 0x00072959
804 #define SGI_INFO_MAGIC_SWAPPED 0x59290700
805 #define SGI_SSWAP16(x) (sgi_other_endian ? __swap16(x) \
807 #define SGI_SSWAP32(x) (sgi_other_endian ? __swap32(x) \
810 #define sgilabel ((sgi_partition *)MBRbuffer)
811 #define sgiparam (sgilabel->devparam)
814 unsigned char info[128]; /* Informative text string */
815 unsigned char spare0[14];
817 unsigned char spare1;
819 unsigned char spare2;
822 unsigned char spare1[246]; /* Boot information etc. */
823 unsigned short rspeed; /* Disk rotational speed */
824 unsigned short pcylcount; /* Physical cylinder count */
825 unsigned short sparecyl; /* extra sects per cylinder */
826 unsigned char spare2[4]; /* More magic... */
827 unsigned short ilfact; /* Interleave factor */
828 unsigned short ncyl; /* Data cylinder count */
829 unsigned short nacyl; /* Alt. cylinder count */
830 unsigned short ntrks; /* Tracks per cylinder */
831 unsigned short nsect; /* Sectors per track */
832 unsigned char spare3[4]; /* Even more magic... */
833 struct sun_partition {
834 uint32_t start_cylinder;
835 uint32_t num_sectors;
837 unsigned short magic; /* Magic number */
838 unsigned short csum; /* Label xor'd checksum */
842 #define SUN_LABEL_MAGIC 0xDABE
843 #define SUN_LABEL_MAGIC_SWAPPED 0xBEDA
844 #define sunlabel ((sun_partition *)MBRbuffer)
845 #define SUN_SSWAP16(x) (sun_other_endian ? __swap16(x) \
847 #define SUN_SSWAP32(x) (sun_other_endian ? __swap32(x) \
850 #if defined(CONFIG_LFS) || defined(FDISK_SUPPORT_LARGE_DISKS)
852 * llseek.c -- stub calling the llseek system call
854 * Copyright (C) 1994 Remy Card. This file may be redistributed
855 * under the terms of the GNU Public License.
859 #if defined(__alpha__) || defined(__ia64__) || defined(__s390x__)
861 #define my_llseek lseek
867 static fdisk_loff_t my_llseek (unsigned int f_d, fdisk_loff_t offset,
873 retval = syscall(__NR__llseek, f_d, ((unsigned long long) offset) >> 32,
874 ((unsigned long long) offset) & 0xffffffff,
876 return (retval == -1 ? (fdisk_loff_t) retval : result);
879 #endif /* __alpha__ */
882 static fdisk_loff_t fdisk_llseek (unsigned int f_d, fdisk_loff_t offset,
886 static int do_compat = 0;
889 result = my_llseek (f_d, offset, origin);
890 if (!(result == -1 && errno == ENOSYS))
894 * Just in case this code runs on top of an old kernel
895 * which does not support the llseek system call
899 * Now try ordinary lseek.
903 if ((sizeof(off_t) >= sizeof(fdisk_loff_t)) ||
904 (offset < ((fdisk_loff_t) 1 << ((sizeof(off_t)*8) -1))))
905 return lseek(f_d, (off_t) offset, origin);
911 # define fdisk_llseek lseek
912 #endif /* FDISK_SUPPORT_LARGE_DISKS */
916 #ifdef CONFIG_FEATURE_OSF_LABEL
919 19990319 - Arnaldo Carvalho de Melo <acme@conectiva.com.br> - i18n/nls
921 20000101 - David Huggins-Daines <dhuggins@linuxcare.com> - Better
922 support for OSF/1 disklabels on Alpha.
923 Also fixed unaligned accesses in alpha_bootblock_checksum()
926 #define FREEBSD_PARTITION 0xa5
927 #define NETBSD_PARTITION 0xa9
929 static void xbsd_delete_part (void);
930 static void xbsd_new_part (void);
931 static void xbsd_write_disklabel (void);
932 static int xbsd_create_disklabel (void);
933 static void xbsd_edit_disklabel (void);
934 static void xbsd_write_bootstrap (void);
935 static void xbsd_change_fstype (void);
936 static int xbsd_get_part_index (int max);
937 static int xbsd_check_new_partition (int *i);
938 static void xbsd_list_types (void);
939 static u_short xbsd_dkcksum (struct xbsd_disklabel *lp);
940 static int xbsd_initlabel (struct partition *p, struct xbsd_disklabel *d,
942 static int xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d);
943 static int xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d);
945 #if defined (__alpha__)
946 static void alpha_bootblock_checksum (char *boot);
949 #if !defined (__alpha__)
950 static int xbsd_translate_fstype (int linux_type);
951 static void xbsd_link_part (void);
952 static struct partition *xbsd_part;
953 static int xbsd_part_index;
956 #if defined (__alpha__)
957 /* We access this through a u_int64_t * when checksumming */
958 static char disklabelbuffer[BSD_BBSIZE] __attribute__((aligned(8)));
960 static char disklabelbuffer[BSD_BBSIZE];
963 static struct xbsd_disklabel xbsd_dlabel;
965 #define bsd_cround(n) \
966 (display_in_cyl_units ? ((n)/xbsd_dlabel.d_secpercyl) + 1 : (n))
969 * Test whether the whole disk has BSD disk label magic.
971 * Note: often reformatting with DOS-type label leaves the BSD magic,
972 * so this does not mean that there is a BSD disk label.
975 check_osf_label(void) {
976 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
981 static void xbsd_print_disklabel(int);
984 btrydev (const char * dev) {
985 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
987 printf(_("\nBSD label for device: %s\n"), dev);
988 xbsd_print_disklabel (0);
994 puts (_("Command action"));
995 puts (_("\td\tdelete a BSD partition"));
996 puts (_("\te\tedit drive data"));
997 puts (_("\ti\tinstall bootstrap"));
998 puts (_("\tl\tlist known filesystem types"));
999 puts (_("\tm\tprint this menu"));
1000 puts (_("\tn\tadd a new BSD partition"));
1001 puts (_("\tp\tprint BSD partition table"));
1002 puts (_("\tq\tquit without saving changes"));
1003 puts (_("\tr\treturn to main menu"));
1004 puts (_("\ts\tshow complete disklabel"));
1005 puts (_("\tt\tchange a partition's filesystem id"));
1006 puts (_("\tu\tchange units (cylinders/sectors)"));
1007 puts (_("\tw\twrite disklabel to disk"));
1008 #if !defined (__alpha__)
1009 puts (_("\tx\tlink BSD partition to non-BSD partition"));
1013 #if !defined (__alpha__)
1020 is_bsd_partition_type(int type) {
1021 return (type == FREEBSD_PARTITION ||
1022 type == hidden(FREEBSD_PARTITION) ||
1023 type == NETBSD_PARTITION ||
1024 type == hidden(NETBSD_PARTITION));
1030 #if !defined (__alpha__)
1032 struct partition *p;
1034 for (t=0; t<4; t++) {
1035 p = get_part_table(t);
1036 if (p && is_bsd_partition_type(p->sys_ind)) {
1038 xbsd_part_index = t;
1039 ss = get_start_sect(xbsd_part);
1041 fprintf (stderr, _("Partition %s has invalid starting sector 0.\n"),
1042 partname(disk_device, t+1, 0));
1045 printf (_("Reading disklabel of %s at sector %d.\n"),
1046 partname(disk_device, t+1, 0), ss + BSD_LABELSECTOR);
1047 if (xbsd_readlabel (xbsd_part, &xbsd_dlabel) == 0)
1048 if (xbsd_create_disklabel () == 0)
1055 printf (_("There is no *BSD partition on %s.\n"), disk_device);
1059 #elif defined (__alpha__)
1061 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
1062 if (xbsd_create_disklabel () == 0)
1063 exit ( EXIT_SUCCESS );
1069 switch (tolower (read_char (_("BSD disklabel command (m for help): ")))) {
1071 xbsd_delete_part ();
1074 xbsd_edit_disklabel ();
1077 xbsd_write_bootstrap ();
1086 xbsd_print_disklabel (0);
1090 exit ( EXIT_SUCCESS );
1094 xbsd_print_disklabel (1);
1097 xbsd_change_fstype ();
1103 xbsd_write_disklabel ();
1105 #if !defined (__alpha__)
1118 xbsd_delete_part (void)
1122 i = xbsd_get_part_index (xbsd_dlabel.d_npartitions);
1123 xbsd_dlabel.d_partitions[i].p_size = 0;
1124 xbsd_dlabel.d_partitions[i].p_offset = 0;
1125 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
1126 if (xbsd_dlabel.d_npartitions == i + 1)
1127 while (xbsd_dlabel.d_partitions[xbsd_dlabel.d_npartitions-1].p_size == 0)
1128 xbsd_dlabel.d_npartitions--;
1132 xbsd_new_part (void)
1138 if (!xbsd_check_new_partition (&i))
1141 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
1142 begin = get_start_sect(xbsd_part);
1143 end = begin + get_nr_sects(xbsd_part) - 1;
1146 end = xbsd_dlabel.d_secperunit - 1;
1149 snprintf (mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
1150 begin = read_int (bsd_cround (begin), bsd_cround (begin), bsd_cround (end),
1153 if (display_in_cyl_units)
1154 begin = (begin - 1) * xbsd_dlabel.d_secpercyl;
1156 snprintf (mesg, sizeof(mesg), _("Last %s or +size or +sizeM or +sizeK"),
1157 str_units(SINGULAR));
1158 end = read_int (bsd_cround (begin), bsd_cround (end), bsd_cround (end),
1159 bsd_cround (begin), mesg);
1161 if (display_in_cyl_units)
1162 end = end * xbsd_dlabel.d_secpercyl - 1;
1164 xbsd_dlabel.d_partitions[i].p_size = end - begin + 1;
1165 xbsd_dlabel.d_partitions[i].p_offset = begin;
1166 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
1170 xbsd_print_disklabel (int show_all) {
1171 struct xbsd_disklabel *lp = &xbsd_dlabel;
1172 struct xbsd_partition *pp;
1176 #if defined (__alpha__)
1177 printf("# %s:\n", disk_device);
1179 printf("# %s:\n", partname(disk_device, xbsd_part_index+1, 0));
1181 if ((unsigned) lp->d_type < BSD_DKMAXTYPES)
1182 printf(_("type: %s\n"), xbsd_dktypenames[lp->d_type]);
1184 printf(_("type: %d\n"), lp->d_type);
1185 printf(_("disk: %.*s\n"), (int) sizeof(lp->d_typename), lp->d_typename);
1186 printf(_("label: %.*s\n"), (int) sizeof(lp->d_packname), lp->d_packname);
1187 printf(_("flags:"));
1188 if (lp->d_flags & BSD_D_REMOVABLE)
1189 printf(_(" removable"));
1190 if (lp->d_flags & BSD_D_ECC)
1192 if (lp->d_flags & BSD_D_BADSECT)
1193 printf(_(" badsect"));
1195 /* On various machines the fields of *lp are short/int/long */
1196 /* In order to avoid problems, we cast them all to long. */
1197 printf(_("bytes/sector: %ld\n"), (long) lp->d_secsize);
1198 printf(_("sectors/track: %ld\n"), (long) lp->d_nsectors);
1199 printf(_("tracks/cylinder: %ld\n"), (long) lp->d_ntracks);
1200 printf(_("sectors/cylinder: %ld\n"), (long) lp->d_secpercyl);
1201 printf(_("cylinders: %ld\n"), (long) lp->d_ncylinders);
1202 printf(_("rpm: %d\n"), lp->d_rpm);
1203 printf(_("interleave: %d\n"), lp->d_interleave);
1204 printf(_("trackskew: %d\n"), lp->d_trackskew);
1205 printf(_("cylinderskew: %d\n"), lp->d_cylskew);
1206 printf(_("headswitch: %ld\t\t# milliseconds\n"),
1207 (long) lp->d_headswitch);
1208 printf(_("track-to-track seek: %ld\t# milliseconds\n"),
1209 (long) lp->d_trkseek);
1210 printf(_("drivedata: "));
1211 for (i = NDDATA - 1; i >= 0; i--)
1212 if (lp->d_drivedata[i])
1216 for (j = 0; j <= i; j++)
1217 printf("%ld ", (long) lp->d_drivedata[j]);
1219 printf(_("\n%d partitions:\n"), lp->d_npartitions);
1220 printf(_("# start end size fstype [fsize bsize cpg]\n"));
1221 pp = lp->d_partitions;
1222 for (i = 0; i < lp->d_npartitions; i++, pp++) {
1224 if (display_in_cyl_units && lp->d_secpercyl) {
1225 printf(" %c: %8ld%c %8ld%c %8ld%c ",
1227 (long) pp->p_offset / lp->d_secpercyl + 1,
1228 (pp->p_offset % lp->d_secpercyl) ? '*' : ' ',
1229 (long) (pp->p_offset + pp->p_size + lp->d_secpercyl - 1)
1231 ((pp->p_offset + pp->p_size) % lp->d_secpercyl) ? '*' : ' ',
1232 (long) pp->p_size / lp->d_secpercyl,
1233 (pp->p_size % lp->d_secpercyl) ? '*' : ' ');
1235 printf(" %c: %8ld %8ld %8ld ",
1237 (long) pp->p_offset,
1238 (long) pp->p_offset + pp->p_size - 1,
1241 if ((unsigned) pp->p_fstype < BSD_FSMAXTYPES)
1242 printf("%8.8s", xbsd_fstypes[pp->p_fstype].name);
1244 printf("%8x", pp->p_fstype);
1245 switch (pp->p_fstype) {
1247 printf(" %5ld %5ld %5.5s ",
1248 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, "");
1252 printf(" %5ld %5ld %5d ",
1253 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag,
1258 printf("%22.22s", "");
1267 xbsd_write_disklabel (void) {
1268 #if defined (__alpha__)
1269 printf (_("Writing disklabel to %s.\n"), disk_device);
1270 xbsd_writelabel (NULL, &xbsd_dlabel);
1272 printf (_("Writing disklabel to %s.\n"),
1273 partname(disk_device, xbsd_part_index+1, 0));
1274 xbsd_writelabel (xbsd_part, &xbsd_dlabel);
1276 reread_partition_table(0); /* no exit yet */
1280 xbsd_create_disklabel (void) {
1283 #if defined (__alpha__)
1284 fprintf (stderr, _("%s contains no disklabel.\n"), disk_device);
1286 fprintf (stderr, _("%s contains no disklabel.\n"),
1287 partname(disk_device, xbsd_part_index+1, 0));
1291 c = read_char (_("Do you want to create a disklabel? (y/n) "));
1292 if (c == 'y' || c == 'Y') {
1293 if (xbsd_initlabel (
1294 #if defined (__alpha__) || defined (__powerpc__) || defined (__hppa__) || \
1295 defined (__s390__) || defined (__s390x__)
1296 NULL, &xbsd_dlabel, 0
1298 xbsd_part, &xbsd_dlabel, xbsd_part_index
1301 xbsd_print_disklabel (1);
1305 } else if (c == 'n')
1311 edit_int (int def, char *mesg)
1314 fputs (mesg, stdout);
1315 printf (" (%d): ", def);
1319 while (!isdigit (*line_ptr));
1320 return atoi (line_ptr);
1324 xbsd_edit_disklabel (void)
1326 struct xbsd_disklabel *d;
1330 #if defined (__alpha__) || defined (__ia64__)
1331 d -> d_secsize = (u_long) edit_int ((u_long) d -> d_secsize ,_("bytes/sector"));
1332 d -> d_nsectors = (u_long) edit_int ((u_long) d -> d_nsectors ,_("sectors/track"));
1333 d -> d_ntracks = (u_long) edit_int ((u_long) d -> d_ntracks ,_("tracks/cylinder"));
1334 d -> d_ncylinders = (u_long) edit_int ((u_long) d -> d_ncylinders ,_("cylinders"));
1337 /* d -> d_secpercyl can be != d -> d_nsectors * d -> d_ntracks */
1340 d -> d_secpercyl = (u_long) edit_int ((u_long) d -> d_nsectors * d -> d_ntracks,
1341 _("sectors/cylinder"));
1342 if (d -> d_secpercyl <= d -> d_nsectors * d -> d_ntracks)
1345 printf (_("Must be <= sectors/track * tracks/cylinder (default).\n"));
1347 d -> d_rpm = (u_short) edit_int ((u_short) d -> d_rpm ,_("rpm"));
1348 d -> d_interleave = (u_short) edit_int ((u_short) d -> d_interleave,_("interleave"));
1349 d -> d_trackskew = (u_short) edit_int ((u_short) d -> d_trackskew ,_("trackskew"));
1350 d -> d_cylskew = (u_short) edit_int ((u_short) d -> d_cylskew ,_("cylinderskew"));
1351 d -> d_headswitch = (u_long) edit_int ((u_long) d -> d_headswitch ,_("headswitch"));
1352 d -> d_trkseek = (u_long) edit_int ((u_long) d -> d_trkseek ,_("track-to-track seek"));
1354 d -> d_secperunit = d -> d_secpercyl * d -> d_ncylinders;
1358 xbsd_get_bootstrap (char *path, void *ptr, int size)
1362 if ((fdb = open (path, O_RDONLY)) < 0)
1367 if (read (fdb, ptr, size) < 0)
1373 printf (" ... %s\n", path);
1381 printf (_("\nSyncing disks.\n"));
1387 xbsd_write_bootstrap (void)
1389 char *bootdir = BSD_LINUX_BOOTDIR;
1390 char path[MAXPATHLEN];
1392 struct xbsd_disklabel dl;
1396 if (xbsd_dlabel.d_type == BSD_DTYPE_SCSI)
1401 printf (_("Bootstrap: %sboot -> boot%s (%s): "),
1402 dkbasename, dkbasename, dkbasename);
1404 line_ptr[strlen (line_ptr)-1] = '\0';
1405 dkbasename = line_ptr;
1407 snprintf (path, sizeof(path), "%s/%sboot", bootdir, dkbasename);
1408 if (!xbsd_get_bootstrap (path, disklabelbuffer, (int) xbsd_dlabel.d_secsize))
1411 /* We need a backup of the disklabel (xbsd_dlabel might have changed). */
1412 d = &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE];
1413 bcopy (d, &dl, sizeof (struct xbsd_disklabel));
1415 /* The disklabel will be overwritten by 0's from bootxx anyway */
1416 bzero (d, sizeof (struct xbsd_disklabel));
1418 snprintf (path, sizeof(path), "%s/boot%s", bootdir, dkbasename);
1419 if (!xbsd_get_bootstrap (path, &disklabelbuffer[xbsd_dlabel.d_secsize],
1420 (int) xbsd_dlabel.d_bbsize - xbsd_dlabel.d_secsize))
1423 e = d + sizeof (struct xbsd_disklabel);
1424 for (p=d; p < e; p++)
1426 fprintf (stderr, _("Bootstrap overlaps with disk label!\n"));
1427 exit ( EXIT_FAILURE );
1430 bcopy (&dl, d, sizeof (struct xbsd_disklabel));
1432 #if defined (__powerpc__) || defined (__hppa__)
1434 #elif defined (__alpha__)
1436 alpha_bootblock_checksum (disklabelbuffer);
1438 sector = get_start_sect(xbsd_part);
1441 if (fdisk_llseek (fd, (fdisk_loff_t) sector * SECTOR_SIZE, SEEK_SET) == -1)
1442 fdisk_fatal (unable_to_seek);
1443 if (BSD_BBSIZE != write (fd, disklabelbuffer, BSD_BBSIZE))
1444 fdisk_fatal (unable_to_write);
1446 #if defined (__alpha__)
1447 printf (_("Bootstrap installed on %s.\n"), disk_device);
1449 printf (_("Bootstrap installed on %s.\n"),
1450 partname (disk_device, xbsd_part_index+1, 0));
1457 xbsd_change_fstype (void)
1461 i = xbsd_get_part_index (xbsd_dlabel.d_npartitions);
1462 xbsd_dlabel.d_partitions[i].p_fstype = read_hex (xbsd_fstypes);
1466 xbsd_get_part_index (int max)
1471 snprintf (prompt, sizeof(prompt), _("Partition (a-%c): "), 'a' + max - 1);
1473 l = tolower (read_char (prompt));
1474 while (l < 'a' || l > 'a' + max - 1);
1479 xbsd_check_new_partition (int *i) {
1481 /* room for more? various BSD flavours have different maxima */
1482 if (xbsd_dlabel.d_npartitions == BSD_MAXPARTITIONS) {
1485 for (t = 0; t < BSD_MAXPARTITIONS; t++)
1486 if (xbsd_dlabel.d_partitions[t].p_size == 0)
1489 if (t == BSD_MAXPARTITIONS) {
1490 fprintf (stderr, _("The maximum number of partitions "
1491 "has been created\n"));
1496 *i = xbsd_get_part_index (BSD_MAXPARTITIONS);
1498 if (*i >= xbsd_dlabel.d_npartitions)
1499 xbsd_dlabel.d_npartitions = (*i) + 1;
1501 if (xbsd_dlabel.d_partitions[*i].p_size != 0) {
1502 fprintf (stderr, _("This partition already exists.\n"));
1510 xbsd_list_types (void) {
1511 list_types (xbsd_fstypes);
1515 xbsd_dkcksum (struct xbsd_disklabel *lp) {
1516 u_short *start, *end;
1519 start = (u_short *) lp;
1520 end = (u_short *) &lp->d_partitions[lp->d_npartitions];
1527 xbsd_initlabel (struct partition *p, struct xbsd_disklabel *d, int pindex) {
1528 struct xbsd_partition *pp;
1531 bzero (d, sizeof (struct xbsd_disklabel));
1533 d -> d_magic = BSD_DISKMAGIC;
1535 if (strncmp (disk_device, "/dev/sd", 7) == 0)
1536 d -> d_type = BSD_DTYPE_SCSI;
1538 d -> d_type = BSD_DTYPE_ST506;
1540 #if 0 /* not used (at least not written to disk) by NetBSD/i386 1.0 */
1541 d -> d_subtype = BSD_DSTYPE_INDOSPART & pindex;
1544 #if !defined (__alpha__)
1545 d -> d_flags = BSD_D_DOSPART;
1549 d -> d_secsize = SECTOR_SIZE; /* bytes/sector */
1550 d -> d_nsectors = sectors; /* sectors/track */
1551 d -> d_ntracks = heads; /* tracks/cylinder (heads) */
1552 d -> d_ncylinders = cylinders;
1553 d -> d_secpercyl = sectors * heads;/* sectors/cylinder */
1554 if (d -> d_secpercyl == 0)
1555 d -> d_secpercyl = 1; /* avoid segfaults */
1556 d -> d_secperunit = d -> d_secpercyl * d -> d_ncylinders;
1559 d -> d_interleave = 1;
1560 d -> d_trackskew = 0;
1562 d -> d_headswitch = 0;
1565 d -> d_magic2 = BSD_DISKMAGIC;
1566 d -> d_bbsize = BSD_BBSIZE;
1567 d -> d_sbsize = BSD_SBSIZE;
1569 #if !defined (__alpha__)
1570 d -> d_npartitions = 4;
1571 pp = &d -> d_partitions[2]; /* Partition C should be
1572 the NetBSD partition */
1573 pp -> p_offset = get_start_sect(p);
1574 pp -> p_size = get_nr_sects(p);
1575 pp -> p_fstype = BSD_FS_UNUSED;
1576 pp = &d -> d_partitions[3]; /* Partition D should be
1579 pp -> p_size = d -> d_secperunit;
1580 pp -> p_fstype = BSD_FS_UNUSED;
1581 #elif defined (__alpha__)
1582 d -> d_npartitions = 3;
1583 pp = &d -> d_partitions[2]; /* Partition C should be
1586 pp -> p_size = d -> d_secperunit;
1587 pp -> p_fstype = BSD_FS_UNUSED;
1594 * Read a xbsd_disklabel from sector 0 or from the starting sector of p.
1595 * If it has the right magic, return 1.
1598 xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d)
1602 /* p is used only to get the starting sector */
1603 #if !defined (__alpha__)
1604 sector = (p ? get_start_sect(p) : 0);
1605 #elif defined (__alpha__)
1609 if (fdisk_llseek (fd, (fdisk_loff_t) sector * SECTOR_SIZE, SEEK_SET) == -1)
1610 fdisk_fatal (unable_to_seek);
1611 if (BSD_BBSIZE != read (fd, disklabelbuffer, BSD_BBSIZE))
1612 fdisk_fatal (unable_to_read);
1614 bcopy (&disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
1615 d, sizeof (struct xbsd_disklabel));
1617 if (d -> d_magic != BSD_DISKMAGIC || d -> d_magic2 != BSD_DISKMAGIC)
1620 for (t = d -> d_npartitions; t < BSD_MAXPARTITIONS; t++) {
1621 d -> d_partitions[t].p_size = 0;
1622 d -> d_partitions[t].p_offset = 0;
1623 d -> d_partitions[t].p_fstype = BSD_FS_UNUSED;
1626 if (d -> d_npartitions > BSD_MAXPARTITIONS)
1627 fprintf (stderr, _("Warning: too many partitions "
1628 "(%d, maximum is %d).\n"),
1629 d -> d_npartitions, BSD_MAXPARTITIONS);
1634 xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d)
1636 unsigned int sector;
1638 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
1639 sector = get_start_sect(p) + BSD_LABELSECTOR;
1641 sector = BSD_LABELSECTOR;
1644 d -> d_checksum = 0;
1645 d -> d_checksum = xbsd_dkcksum (d);
1647 /* This is necessary if we want to write the bootstrap later,
1648 otherwise we'd write the old disklabel with the bootstrap.
1650 bcopy (d, &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
1651 sizeof (struct xbsd_disklabel));
1653 #if defined (__alpha__) && BSD_LABELSECTOR == 0
1654 alpha_bootblock_checksum (disklabelbuffer);
1655 if (fdisk_llseek (fd, (fdisk_loff_t) 0, SEEK_SET) == -1)
1656 fdisk_fatal (unable_to_seek);
1657 if (BSD_BBSIZE != write (fd, disklabelbuffer, BSD_BBSIZE))
1658 fdisk_fatal (unable_to_write);
1660 if (fdisk_llseek (fd, (fdisk_loff_t) sector * SECTOR_SIZE + BSD_LABELOFFSET,
1662 fdisk_fatal (unable_to_seek);
1663 if (sizeof (struct xbsd_disklabel) != write (fd, d, sizeof (struct xbsd_disklabel)))
1664 fdisk_fatal (unable_to_write);
1673 #if !defined (__alpha__)
1675 xbsd_translate_fstype (int linux_type)
1679 case 0x01: /* DOS 12-bit FAT */
1680 case 0x04: /* DOS 16-bit <32M */
1681 case 0x06: /* DOS 16-bit >=32M */
1682 case 0xe1: /* DOS access */
1683 case 0xe3: /* DOS R/O */
1684 case 0xf2: /* DOS secondary */
1685 return BSD_FS_MSDOS;
1686 case 0x07: /* OS/2 HPFS */
1689 return BSD_FS_OTHER;
1694 xbsd_link_part (void)
1697 struct partition *p;
1699 k = get_partition (1, partitions);
1701 if (!xbsd_check_new_partition (&i))
1704 p = get_part_table(k);
1706 xbsd_dlabel.d_partitions[i].p_size = get_nr_sects(p);
1707 xbsd_dlabel.d_partitions[i].p_offset = get_start_sect(p);
1708 xbsd_dlabel.d_partitions[i].p_fstype = xbsd_translate_fstype(p->sys_ind);
1712 #if defined (__alpha__)
1714 #if !defined(__GLIBC__)
1715 typedef unsigned long long u_int64_t;
1719 alpha_bootblock_checksum (char *boot)
1724 dp = (u_int64_t *)boot;
1726 for (i = 0; i < 63; i++)
1730 #endif /* __alpha__ */
1732 #endif /* OSF_LABEL */
1734 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
1735 static inline unsigned short
1736 __swap16(unsigned short x) {
1737 return (((uint16_t)(x) & 0xFF) << 8) | (((uint16_t)(x) & 0xFF00) >> 8);
1740 static inline uint32_t
1741 __swap32(uint32_t x) {
1742 return (((x & 0xFF) << 24) |
1743 ((x & 0xFF00) << 8) |
1744 ((x & 0xFF0000) >> 8) |
1745 ((x & 0xFF000000) >> 24));
1749 #ifdef CONFIG_FEATURE_SGI_LABEL
1754 * Copyright (C) Andreas Neuper, Sep 1998.
1755 * This file may be modified and redistributed under
1756 * the terms of the GNU Public License.
1758 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
1759 * Internationalization
1763 static int sgi_other_endian;
1765 static short sgi_volumes=1;
1768 * only dealing with free blocks here
1771 typedef struct { unsigned int first; unsigned int last; } freeblocks;
1772 static freeblocks freelist[17]; /* 16 partitions can produce 17 vacant slots */
1775 setfreelist(int i, unsigned int f, unsigned int l) {
1776 freelist[i].first = f;
1777 freelist[i].last = l;
1781 add2freelist(unsigned int f, unsigned int l) {
1783 for ( ; i < 17 ; i++)
1784 if (freelist[i].last == 0)
1786 setfreelist(i, f, l);
1790 clearfreelist(void) {
1793 for (i = 0; i < 17 ; i++)
1794 setfreelist(i, 0, 0);
1798 isinfreelist(unsigned int b) {
1801 for (i = 0; i < 17 ; i++)
1802 if (freelist[i].first <= b && freelist[i].last >= b)
1803 return freelist[i].last;
1806 /* return last vacant block of this stride (never 0). */
1807 /* the '>=' is not quite correct, but simplifies the code */
1809 * end of free blocks section
1812 static const struct systypes sgi_sys_types[] = {
1813 /* SGI_VOLHDR */ {"\x00" "SGI volhdr" },
1814 /* 0x01 */ {"\x01" "SGI trkrepl" },
1815 /* 0x02 */ {"\x02" "SGI secrepl" },
1816 /* SGI_SWAP */ {"\x03" "SGI raw" },
1817 /* 0x04 */ {"\x04" "SGI bsd" },
1818 /* 0x05 */ {"\x05" "SGI sysv" },
1819 /* ENTIRE_DISK */ {"\x06" "SGI volume" },
1820 /* SGI_EFS */ {"\x07" "SGI efs" },
1821 /* 0x08 */ {"\x08" "SGI lvol" },
1822 /* 0x09 */ {"\x09" "SGI rlvol" },
1823 /* SGI_XFS */ {"\x0a" "SGI xfs" },
1824 /* SGI_XFSLOG */ {"\x0b" "SGI xfslog" },
1825 /* SGI_XLV */ {"\x0c" "SGI xlv" },
1826 /* SGI_XVM */ {"\x0d" "SGI xvm" },
1827 /* LINUX_SWAP */ {"\x82" "Linux swap" },
1828 /* LINUX_NATIVE */ {"\x83" "Linux native" },
1829 /* LINUX_LVM */ {"\x8d" "Linux LVM" },
1830 /* LINUX_RAID */ {"\xfd" "Linux RAID" },
1836 sgi_get_nsect(void) {
1837 return SGI_SSWAP16(sgilabel->devparam.nsect);
1841 sgi_get_ntrks(void) {
1842 return SGI_SSWAP16(sgilabel->devparam.ntrks);
1847 sgilabel->magic = 0;
1853 two_s_complement_32bit_sum(unsigned int* base, int size /* in bytes */) {
1857 size /= sizeof(unsigned int);
1858 for (i = 0; i < size; i++)
1859 sum -= SGI_SSWAP32(base[i]);
1864 check_sgi_label(void) {
1865 if (sizeof(sgilabel) > 512) {
1867 _("According to MIPS Computer Systems, Inc the "
1868 "Label must not contain more than 512 bytes\n"));
1872 if (sgilabel->magic != SGI_LABEL_MAGIC &&
1873 sgilabel->magic != SGI_LABEL_MAGIC_SWAPPED) {
1875 sgi_other_endian = 0;
1879 sgi_other_endian = (sgilabel->magic == SGI_LABEL_MAGIC_SWAPPED);
1881 * test for correct checksum
1883 if (two_s_complement_32bit_sum((unsigned int*)sgilabel,
1884 sizeof(*sgilabel))) {
1886 _("Detected sgi disklabel with wrong checksum.\n"));
1896 sgi_get_start_sector(int i) {
1897 return SGI_SSWAP32(sgilabel->partitions[i].start_sector);
1901 sgi_get_num_sectors(int i) {
1902 return SGI_SSWAP32(sgilabel->partitions[i].num_sectors);
1906 sgi_get_sysid(int i)
1908 return SGI_SSWAP32(sgilabel->partitions[i].id);
1912 sgi_get_bootpartition(void)
1914 return SGI_SSWAP16(sgilabel->boot_part);
1918 sgi_get_swappartition(void)
1920 return SGI_SSWAP16(sgilabel->swap_part);
1924 sgi_list_table(int xtra) {
1926 int kpi = 0; /* kernel partition ID */
1929 printf(_("\nDisk %s (SGI disk label): %d heads, %d sectors\n"
1930 "%d cylinders, %d physical cylinders\n"
1931 "%d extra sects/cyl, interleave %d:1\n"
1933 "Units = %s of %d * 512 bytes\n\n"),
1934 disk_device, heads, sectors, cylinders,
1935 SGI_SSWAP16(sgiparam.pcylcount),
1936 SGI_SSWAP16(sgiparam.sparecyl),
1937 SGI_SSWAP16(sgiparam.ilfact),
1939 str_units(PLURAL), units_per_sector);
1941 printf( _("\nDisk %s (SGI disk label): "
1942 "%d heads, %d sectors, %d cylinders\n"
1943 "Units = %s of %d * 512 bytes\n\n"),
1944 disk_device, heads, sectors, cylinders,
1945 str_units(PLURAL), units_per_sector );
1948 w = strlen(disk_device);
1949 wd = strlen(_("Device"));
1953 printf(_("----- partitions -----\n"
1954 "Pt# %*s Info Start End Sectors Id System\n"),
1955 w + 2, _("Device"));
1956 for (i = 0 ; i < partitions; i++) {
1957 if( sgi_get_num_sectors(i) || debug ) {
1958 uint32_t start = sgi_get_start_sector(i);
1959 uint32_t len = sgi_get_num_sectors(i);
1960 kpi++; /* only count nonempty partitions */
1962 "%2d: %s %4s %9ld %9ld %9ld %2x %s\n",
1963 /* fdisk part number */ i+1,
1964 /* device */ partname(disk_device, kpi, w+3),
1965 /* flags */ (sgi_get_swappartition() == i) ? "swap" :
1966 /* flags */ (sgi_get_bootpartition() == i) ? "boot" : " ",
1967 /* start */ (long) scround(start),
1968 /* end */ (long) scround(start+len)-1,
1969 /* no odd flag on end */ (long) len,
1970 /* type id */ sgi_get_sysid(i),
1971 /* type name */ partition_type(sgi_get_sysid(i)));
1974 printf(_("----- Bootinfo -----\nBootfile: %s\n"
1975 "----- Directory Entries -----\n"),
1976 sgilabel->boot_file);
1977 for (i = 0 ; i < sgi_volumes; i++) {
1978 if (sgilabel->directory[i].vol_file_size) {
1979 uint32_t start = SGI_SSWAP32(sgilabel->directory[i].vol_file_start);
1980 uint32_t len = SGI_SSWAP32(sgilabel->directory[i].vol_file_size);
1981 char*name = sgilabel->directory[i].vol_file_name;
1983 printf(_("%2d: %-10s sector%5u size%8u\n"),
1984 i, name, (unsigned int) start, (unsigned int) len);
1990 sgi_set_bootpartition( int i )
1992 sgilabel->boot_part = SGI_SSWAP16(((short)i));
1996 sgi_get_lastblock(void) {
1997 return heads * sectors * cylinders;
2001 sgi_set_swappartition( int i ) {
2002 sgilabel->swap_part = SGI_SSWAP16(((short)i));
2006 sgi_check_bootfile(const char* aFile) {
2008 if (strlen(aFile) < 3) /* "/a\n" is minimum */ {
2009 printf(_("\nInvalid Bootfile!\n"
2010 "\tThe bootfile must be an absolute non-zero pathname,\n"
2011 "\te.g. \"/unix\" or \"/unix.save\".\n"));
2014 if (strlen(aFile) > 16) {
2015 printf(_("\n\tName of Bootfile too long: "
2016 "16 bytes maximum.\n"));
2019 if (aFile[0] != '/') {
2020 printf(_("\n\tBootfile must have a "
2021 "fully qualified pathname.\n"));
2026 if (strncmp(aFile, sgilabel->boot_file, 16)) {
2027 printf(_("\n\tBe aware, that the bootfile is not checked for existence.\n\t"
2028 "SGI's default is \"/unix\" and for backup \"/unix.save\".\n"));
2029 /* filename is correct and did change */
2032 return 0; /* filename did not change */
2036 sgi_get_bootfile(void) {
2037 return sgilabel->boot_file;
2041 sgi_set_bootfile(const char* aFile) {
2044 if (sgi_check_bootfile(aFile)) {
2046 if ((aFile[i] != '\n') /* in principle caught again by next line */
2047 && (strlen(aFile) > i))
2048 sgilabel->boot_file[i] = aFile[i];
2050 sgilabel->boot_file[i] = 0;
2053 printf(_("\n\tBootfile is changed to \"%s\".\n"), sgilabel->boot_file);
2058 create_sgiinfo(void)
2060 /* I keep SGI's habit to write the sgilabel to the second block */
2061 sgilabel->directory[0].vol_file_start = SGI_SSWAP32(2);
2062 sgilabel->directory[0].vol_file_size = SGI_SSWAP32(sizeof(sgiinfo));
2063 strncpy(sgilabel->directory[0].vol_file_name, "sgilabel", 8);
2066 static sgiinfo *fill_sgiinfo(void);
2069 sgi_write_table(void) {
2071 sgilabel->csum = SGI_SSWAP32(two_s_complement_32bit_sum(
2072 (unsigned int*)sgilabel,
2073 sizeof(*sgilabel)));
2074 assert(two_s_complement_32bit_sum(
2075 (unsigned int*)sgilabel, sizeof(*sgilabel)) == 0);
2076 if (lseek(fd, 0, SEEK_SET) < 0)
2077 fdisk_fatal(unable_to_seek);
2078 if (write(fd, sgilabel, SECTOR_SIZE) != SECTOR_SIZE)
2079 fdisk_fatal(unable_to_write);
2080 if (! strncmp(sgilabel->directory[0].vol_file_name, "sgilabel", 8)) {
2082 * keep this habit of first writing the "sgilabel".
2083 * I never tested whether it works without (AN 981002).
2085 sgiinfo *info = fill_sgiinfo();
2086 int infostartblock = SGI_SSWAP32(sgilabel->directory[0].vol_file_start);
2087 if (fdisk_llseek(fd, (long long)infostartblock*
2088 SECTOR_SIZE, SEEK_SET) < 0)
2089 fdisk_fatal(unable_to_seek);
2090 if (write(fd, info, SECTOR_SIZE) != SECTOR_SIZE)
2091 fdisk_fatal(unable_to_write);
2097 compare_start(int *x, int *y) {
2099 * sort according to start sectors
2100 * and prefers largest partition:
2101 * entry zero is entire disk entry
2103 unsigned int i = *x;
2104 unsigned int j = *y;
2105 unsigned int a = sgi_get_start_sector(i);
2106 unsigned int b = sgi_get_start_sector(j);
2107 unsigned int c = sgi_get_num_sectors(i);
2108 unsigned int d = sgi_get_num_sectors(j);
2111 return (d > c) ? 1 : (d == c) ? 0 : -1;
2112 return (a > b) ? 1 : -1;
2117 verify_sgi(int verbose)
2119 int Index[16]; /* list of valid partitions */
2120 int sortcount = 0; /* number of used partitions, i.e. non-zero lengths */
2121 int entire = 0, i = 0;
2122 unsigned int start = 0;
2123 long long gap = 0; /* count unused blocks */
2124 unsigned int lastblock = sgi_get_lastblock();
2127 for (i=0; i<16; i++) {
2128 if (sgi_get_num_sectors(i) != 0) {
2129 Index[sortcount++]=i;
2130 if (sgi_get_sysid(i) == ENTIRE_DISK) {
2131 if (entire++ == 1) {
2133 printf(_("More than one entire disk entry present.\n"));
2138 if (sortcount == 0) {
2140 printf(_("No partitions defined\n"));
2141 return (lastblock > 0) ? 1 : (lastblock == 0) ? 0 : -1;
2143 qsort(Index, sortcount, sizeof(Index[0]), (void*)compare_start);
2144 if (sgi_get_sysid(Index[0]) == ENTIRE_DISK) {
2145 if ((Index[0] != 10) && verbose)
2146 printf(_("IRIX likes when Partition 11 covers the entire disk.\n"));
2147 if ((sgi_get_start_sector(Index[0]) != 0) && verbose)
2148 printf(_("The entire disk partition should start "
2150 "not at diskblock %d.\n"),
2151 sgi_get_start_sector(Index[0]));
2152 if (debug) /* I do not understand how some disks fulfil it */
2153 if ((sgi_get_num_sectors(Index[0]) != lastblock) && verbose)
2154 printf(_("The entire disk partition is only %d diskblock large,\n"
2155 "but the disk is %d diskblocks long.\n"),
2156 sgi_get_num_sectors(Index[0]), lastblock);
2157 lastblock = sgi_get_num_sectors(Index[0]);
2160 printf(_("One Partition (#11) should cover the entire disk.\n"));
2162 printf("sysid=%d\tpartition=%d\n",
2163 sgi_get_sysid(Index[0]), Index[0]+1);
2165 for (i=1, start=0; i<sortcount; i++) {
2166 int cylsize = sgi_get_nsect() * sgi_get_ntrks();
2168 if ((sgi_get_start_sector(Index[i]) % cylsize) != 0) {
2169 if (debug) /* I do not understand how some disks fulfil it */
2171 printf(_("Partition %d does not start on cylinder boundary.\n"),
2174 if (sgi_get_num_sectors(Index[i]) % cylsize != 0) {
2175 if (debug) /* I do not understand how some disks fulfil it */
2177 printf(_("Partition %d does not end on cylinder boundary.\n"),
2180 /* We cannot handle several "entire disk" entries. */
2181 if (sgi_get_sysid(Index[i]) == ENTIRE_DISK) continue;
2182 if (start > sgi_get_start_sector(Index[i])) {
2184 printf(_("The Partition %d and %d overlap by %d sectors.\n"),
2185 Index[i-1]+1, Index[i]+1,
2186 start - sgi_get_start_sector(Index[i]));
2187 if (gap > 0) gap = -gap;
2188 if (gap == 0) gap = -1;
2190 if (start < sgi_get_start_sector(Index[i])) {
2192 printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"),
2193 sgi_get_start_sector(Index[i]) - start,
2194 start, sgi_get_start_sector(Index[i])-1);
2195 gap += sgi_get_start_sector(Index[i]) - start;
2196 add2freelist(start, sgi_get_start_sector(Index[i]));
2198 start = sgi_get_start_sector(Index[i])
2199 + sgi_get_num_sectors(Index[i]);
2202 printf("%2d:%12d\t%12d\t%12d\n", Index[i],
2203 sgi_get_start_sector(Index[i]),
2204 sgi_get_num_sectors(Index[i]),
2205 sgi_get_sysid(Index[i]));
2208 if (start < lastblock) {
2210 printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"),
2211 lastblock - start, start, lastblock-1);
2212 gap += lastblock - start;
2213 add2freelist(start, lastblock);
2216 * Done with arithmetics
2217 * Go for details now
2220 if (!sgi_get_num_sectors(sgi_get_bootpartition())) {
2221 printf(_("\nThe boot partition does not exist.\n"));
2223 if (!sgi_get_num_sectors(sgi_get_swappartition())) {
2224 printf(_("\nThe swap partition does not exist.\n"));
2226 if ((sgi_get_sysid(sgi_get_swappartition()) != SGI_SWAP)
2227 && (sgi_get_sysid(sgi_get_swappartition()) != LINUX_SWAP))
2228 printf(_("\nThe swap partition has no swap type.\n"));
2230 if (sgi_check_bootfile("/unix"))
2231 printf(_("\tYou have chosen an unusual boot file name.\n"));
2233 return (gap > 0) ? 1 : (gap == 0) ? 0 : -1;
2239 * returned value is:
2240 * = 0 : disk is properly filled to the rim
2241 * < 0 : there is an overlap
2242 * > 0 : there is still some vacant space
2244 return verify_sgi(0);
2248 sgi_change_sysid( int i, int sys )
2250 if( sgi_get_num_sectors(i) == 0 ) /* caught already before, ... */
2252 printf(_("Sorry You may change the Tag of non-empty partitions.\n"));
2255 if( ((sys != ENTIRE_DISK ) && (sys != SGI_VOLHDR))
2256 && (sgi_get_start_sector(i)<1) )
2259 _("It is highly recommended that the partition at offset 0\n"
2260 "is of type \"SGI volhdr\", the IRIX system will rely on it to\n"
2261 "retrieve from its directory standalone tools like sash and fx.\n"
2262 "Only the \"SGI volume\" entire disk section may violate this.\n"
2263 "Type YES if you are sure about tagging this partition differently.\n"));
2264 if (strcmp (line_ptr, _("YES\n")))
2267 sgilabel->partitions[i].id = SGI_SSWAP32(sys);
2270 /* returns partition index of first entry marked as entire disk */
2276 if(sgi_get_sysid(i) == SGI_VOLUME)
2282 sgi_set_partition(int i, unsigned int start, unsigned int length, int sys) {
2284 sgilabel->partitions[i].id = SGI_SSWAP32(sys);
2285 sgilabel->partitions[i].num_sectors = SGI_SSWAP32(length);
2286 sgilabel->partitions[i].start_sector = SGI_SSWAP32(start);
2288 if (sgi_gaps() < 0) /* rebuild freelist */
2289 printf(_("Do You know, You got a partition overlap on the disk?\n"));
2293 sgi_set_entire(void) {
2296 for(n=10; n < partitions; n++) {
2297 if(!sgi_get_num_sectors(n) ) {
2298 sgi_set_partition(n, 0, sgi_get_lastblock(), SGI_VOLUME);
2305 sgi_set_volhdr(void)
2308 for( n=8; n<partitions; n++ )
2310 if(!sgi_get_num_sectors( n ) )
2313 * 5 cylinders is an arbitrary value I like
2314 * IRIX 5.3 stored files in the volume header
2315 * (like sash, symmon, fx, ide) with ca. 3200
2318 if( heads * sectors * 5 < sgi_get_lastblock() )
2319 sgi_set_partition( n, 0, heads * sectors * 5, SGI_VOLHDR );
2326 sgi_delete_partition( int i )
2328 sgi_set_partition( i, 0, 0, 0 );
2332 sgi_add_partition( int n, int sys )
2335 unsigned int first=0, last=0;
2339 } else if ( n == 8 ) {
2342 if(sgi_get_num_sectors(n)) {
2343 printf(_("Partition %d is already defined. Delete "
2344 "it before re-adding it.\n"), n + 1);
2347 if( (sgi_entire() == -1) && (sys != SGI_VOLUME) ) {
2348 printf(_("Attempting to generate entire disk entry automatically.\n"));
2352 if( (sgi_gaps() == 0) && (sys != SGI_VOLUME) ) {
2353 printf(_("The entire disk is already covered with partitions.\n"));
2356 if(sgi_gaps() < 0) {
2357 printf(_("You got a partition overlap on the disk. Fix it first!\n"));
2360 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
2362 if(sys == SGI_VOLUME) {
2363 last = sgi_get_lastblock();
2364 first = read_int(0, 0, last-1, 0, mesg);
2366 printf(_("It is highly recommended that eleventh partition\n"
2367 "covers the entire disk and is of type `SGI volume'\n"));
2370 first = freelist[0].first;
2371 last = freelist[0].last;
2372 first = read_int(scround(first), scround(first), scround(last)-1,
2375 if (display_in_cyl_units)
2376 first *= units_per_sector;
2378 first = first; /* align to cylinder if you know how ... */
2380 last = isinfreelist(first);
2382 printf(_("You will get a partition overlap on the disk. "
2383 "Fix it first!\n"));
2387 snprintf(mesg, sizeof(mesg), _(" Last %s"), str_units(SINGULAR));
2388 last = read_int(scround(first), scround(last)-1, scround(last)-1,
2389 scround(first), mesg)+1;
2390 if (display_in_cyl_units)
2391 last *= units_per_sector;
2393 last = last; /* align to cylinder if You know how ... */
2394 if( (sys == SGI_VOLUME) && ( first != 0 || last != sgi_get_lastblock() ) )
2395 printf(_("It is highly recommended that eleventh partition\n"
2396 "covers the entire disk and is of type `SGI volume'\n"));
2397 sgi_set_partition( n, first, last-first, sys );
2400 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
2402 create_sgilabel(void)
2404 struct hd_geometry geometry;
2411 long longsectors; /* the number of sectors on the device */
2412 int res; /* the result from the ioctl */
2413 int sec_fac; /* the sector factor */
2415 sec_fac = sector_size / 512; /* determine the sector factor */
2418 _("Building a new SGI disklabel. Changes will remain in memory only,\n"
2419 "until you decide to write them. After that, of course, the previous\n"
2420 "content will be unrecoverably lost.\n\n"));
2422 sgi_other_endian = (BYTE_ORDER == LITTLE_ENDIAN);
2423 res = ioctl(fd, BLKGETSIZE, &longsectors);
2424 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
2425 heads = geometry.heads;
2426 sectors = geometry.sectors;
2428 /* the get device size ioctl was successful */
2429 cylinders = longsectors / (heads * sectors);
2430 cylinders /= sec_fac;
2432 /* otherwise print error and use truncated version */
2433 cylinders = geometry.cylinders;
2435 _("Warning: BLKGETSIZE ioctl failed on %s. "
2436 "Using geometry cylinder value of %d.\n"
2437 "This value may be truncated for devices"
2438 " > 33.8 GB.\n"), disk_device, cylinders);
2441 for (i = 0; i < 4; i++) {
2443 if(valid_part_table_flag(MBRbuffer)) {
2444 if(get_part_table(i)->sys_ind) {
2445 old[i].sysid = get_part_table(i)->sys_ind;
2446 old[i].start = get_start_sect(get_part_table(i));
2447 old[i].nsect = get_nr_sects(get_part_table(i));
2448 printf(_("Trying to keep parameters of partition %d.\n"), i);
2450 printf(_("ID=%02x\tSTART=%d\tLENGTH=%d\n"),
2451 old[i].sysid, old[i].start, old[i].nsect);
2456 memset(MBRbuffer, 0, sizeof(MBRbuffer));
2457 sgilabel->magic = SGI_SSWAP32(SGI_LABEL_MAGIC);
2458 sgilabel->boot_part = SGI_SSWAP16(0);
2459 sgilabel->swap_part = SGI_SSWAP16(1);
2461 /* sizeof(sgilabel->boot_file) = 16 > 6 */
2462 memset(sgilabel->boot_file, 0, 16);
2463 strcpy(sgilabel->boot_file, "/unix");
2465 sgilabel->devparam.skew = (0);
2466 sgilabel->devparam.gap1 = (0);
2467 sgilabel->devparam.gap2 = (0);
2468 sgilabel->devparam.sparecyl = (0);
2469 sgilabel->devparam.pcylcount = SGI_SSWAP16(geometry.cylinders);
2470 sgilabel->devparam.head_vol0 = SGI_SSWAP16(0);
2471 sgilabel->devparam.ntrks = SGI_SSWAP16(geometry.heads);
2472 /* tracks/cylinder (heads) */
2473 sgilabel->devparam.cmd_tag_queue_depth = (0);
2474 sgilabel->devparam.unused0 = (0);
2475 sgilabel->devparam.unused1 = SGI_SSWAP16(0);
2476 sgilabel->devparam.nsect = SGI_SSWAP16(geometry.sectors);
2478 sgilabel->devparam.bytes = SGI_SSWAP16(512);
2479 sgilabel->devparam.ilfact = SGI_SSWAP16(1);
2480 sgilabel->devparam.flags = SGI_SSWAP32(TRACK_FWD|
2481 IGNORE_ERRORS|RESEEK);
2482 sgilabel->devparam.datarate = SGI_SSWAP32(0);
2483 sgilabel->devparam.retries_on_error = SGI_SSWAP32(1);
2484 sgilabel->devparam.ms_per_word = SGI_SSWAP32(0);
2485 sgilabel->devparam.xylogics_gap1 = SGI_SSWAP16(0);
2486 sgilabel->devparam.xylogics_syncdelay = SGI_SSWAP16(0);
2487 sgilabel->devparam.xylogics_readdelay = SGI_SSWAP16(0);
2488 sgilabel->devparam.xylogics_gap2 = SGI_SSWAP16(0);
2489 sgilabel->devparam.xylogics_readgate = SGI_SSWAP16(0);
2490 sgilabel->devparam.xylogics_writecont = SGI_SSWAP16(0);
2491 memset( &(sgilabel->directory), 0, sizeof(struct volume_directory)*15 );
2492 memset( &(sgilabel->partitions), 0, sizeof(struct sgi_partition)*16 );
2498 for (i = 0; i < 4; i++) {
2500 sgi_set_partition(i, old[i].start, old[i].nsect, old[i].sysid);
2508 /* do nothing in the beginning */
2510 #endif /* CONFIG_FEATURE_FDISK_ADVANCED */
2512 /* _____________________________________________________________
2518 sgiinfo *info = calloc(1, sizeof(sgiinfo));
2520 info->magic=SGI_SSWAP32(SGI_INFO_MAGIC);
2521 info->b1=SGI_SSWAP32(-1);
2522 info->b2=SGI_SSWAP16(-1);
2523 info->b3=SGI_SSWAP16(1);
2524 /* You may want to replace this string !!!!!!! */
2525 strcpy( info->scsi_string, "IBM OEM 0662S12 3 30" );
2526 strcpy( info->serial, "0000" );
2527 info->check1816 = SGI_SSWAP16(18*256 +16 );
2528 strcpy( info->installer, "Sfx version 5.3, Oct 18, 1994" );
2531 #endif /* SGI_LABEL */
2534 #ifdef CONFIG_FEATURE_SUN_LABEL
2538 * I think this is mostly, or entirely, due to
2539 * Jakub Jelinek (jj@sunsite.mff.cuni.cz), July 1996
2541 * Merged with fdisk for other architectures, aeb, June 1998.
2543 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
2544 * Internationalization
2548 static int sun_other_endian;
2549 static int scsi_disk;
2553 #define IDE0_MAJOR 3
2556 #define IDE1_MAJOR 22
2559 static void guess_device_type(void) {
2560 struct stat bootstat;
2562 if (fstat (fd, &bootstat) < 0) {
2565 } else if (S_ISBLK(bootstat.st_mode)
2566 && (major(bootstat.st_rdev) == IDE0_MAJOR ||
2567 major(bootstat.st_rdev) == IDE1_MAJOR)) {
2570 } else if (S_ISBLK(bootstat.st_mode)
2571 && major(bootstat.st_rdev) == FLOPPY_MAJOR) {
2580 static const struct systypes sun_sys_types[] = {
2581 /* 0 */ {"\x00" "Empty" },
2582 /* 1 */ {"\x01" "Boot" },
2583 /* 2 */ {"\x02" "SunOS root" },
2584 /* SUNOS_SWAP */ {"\x03" "SunOS swap" },
2585 /* 4 */ {"\x04" "SunOS usr" },
2586 /* WHOLE_DISK */ {"\x05" "Whole disk" },
2587 /* 6 */ {"\x06" "SunOS stand" },
2588 /* 7 */ {"\x07" "SunOS var" },
2589 /* 8 */ {"\x08" "SunOS home" },
2590 /* LINUX_SWAP */ {"\x82" "Linux swap" },
2591 /* LINUX_NATIVE */ {"\x83" "Linux native" },
2592 /* 0x8e */ {"\x8e" "Linux LVM" },
2593 /* New (2.2.x) raid partition with autodetect using persistent superblock */
2594 /* 0xfd */ {"\xfd" "Linux raid autodetect" },
2600 set_sun_partition(int i, uint start, uint stop, int sysid) {
2601 sunlabel->infos[i].id = sysid;
2602 sunlabel->partitions[i].start_cylinder =
2603 SUN_SSWAP32(start / (heads * sectors));
2604 sunlabel->partitions[i].num_sectors =
2605 SUN_SSWAP32(stop - start);
2612 sunlabel->magic = 0;
2617 check_sun_label(void) {
2618 unsigned short *ush;
2621 if (sunlabel->magic != SUN_LABEL_MAGIC &&
2622 sunlabel->magic != SUN_LABEL_MAGIC_SWAPPED) {
2624 sun_other_endian = 0;
2627 sun_other_endian = (sunlabel->magic == SUN_LABEL_MAGIC_SWAPPED);
2628 ush = ((unsigned short *) (sunlabel + 1)) - 1;
2629 for (csum = 0; ush >= (unsigned short *)sunlabel;) csum ^= *ush--;
2631 fprintf(stderr,_("Detected sun disklabel with wrong checksum.\n"
2632 "Probably you'll have to set all the values,\n"
2633 "e.g. heads, sectors, cylinders and partitions\n"
2634 "or force a fresh label (s command in main menu)\n"));
2636 heads = SUN_SSWAP16(sunlabel->ntrks);
2637 cylinders = SUN_SSWAP16(sunlabel->ncyl);
2638 sectors = SUN_SSWAP16(sunlabel->nsect);
2646 static const struct sun_predefined_drives {
2649 unsigned short sparecyl;
2650 unsigned short ncyl;
2651 unsigned short nacyl;
2652 unsigned short pcylcount;
2653 unsigned short ntrks;
2654 unsigned short nsect;
2655 unsigned short rspeed;
2657 {"Quantum","ProDrive 80S",1,832,2,834,6,34,3662},
2658 {"Quantum","ProDrive 105S",1,974,2,1019,6,35,3662},
2659 {"CDC","Wren IV 94171-344",3,1545,2,1549,9,46,3600},
2660 {"IBM","DPES-31080",0,4901,2,4903,4,108,5400},
2661 {"IBM","DORS-32160",0,1015,2,1017,67,62,5400},
2662 {"IBM","DNES-318350",0,11199,2,11474,10,320,7200},
2663 {"SEAGATE","ST34371",0,3880,2,3882,16,135,7228},
2664 {"","SUN0104",1,974,2,1019,6,35,3662},
2665 {"","SUN0207",4,1254,2,1272,9,36,3600},
2666 {"","SUN0327",3,1545,2,1549,9,46,3600},
2667 {"","SUN0340",0,1538,2,1544,6,72,4200},
2668 {"","SUN0424",2,1151,2,2500,9,80,4400},
2669 {"","SUN0535",0,1866,2,2500,7,80,5400},
2670 {"","SUN0669",5,1614,2,1632,15,54,3600},
2671 {"","SUN1.0G",5,1703,2,1931,15,80,3597},
2672 {"","SUN1.05",0,2036,2,2038,14,72,5400},
2673 {"","SUN1.3G",6,1965,2,3500,17,80,5400},
2674 {"","SUN2.1G",0,2733,2,3500,19,80,5400},
2675 {"IOMEGA","Jaz",0,1019,2,1021,64,32,5394},
2678 static const struct sun_predefined_drives *
2679 sun_autoconfigure_scsi(void) {
2680 const struct sun_predefined_drives *p = NULL;
2682 #ifdef SCSI_IOCTL_GET_IDLUN
2692 if (!ioctl(fd, SCSI_IOCTL_GET_IDLUN, &id)) {
2694 "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n",
2696 ((id[0]>>24)&0xff)-/*PROC_SCSI_SCSI+PROC_SCSI_FILE*/33,
2698 /* This is very wrong (works only if you have one HBA),
2699 but I haven't found a way how to get hostno
2700 from the current kernel */
2706 pfd = fopen("/proc/scsi/scsi","r");
2708 while (fgets(buffer2,2048,pfd)) {
2709 if (!strcmp(buffer, buffer2)) {
2710 if (fgets(buffer2,2048,pfd)) {
2711 q = strstr(buffer2,"Vendor: ");
2716 *q++ = 0; /* truncate vendor name */
2717 q = strstr(q,"Model: ");
2722 q = strstr(q," Rev: ");
2725 for (i = 0; i < SIZE(sun_drives); i++) {
2726 if (*sun_drives[i].vendor && strcasecmp(sun_drives[i].vendor, vendor))
2728 if (!strstr(model, sun_drives[i].model))
2730 printf(_("Autoconfigure found a %s%s%s\n"),sun_drives[i].vendor,(*sun_drives[i].vendor) ? " " : "",sun_drives[i].model);
2748 static void create_sunlabel(void)
2750 struct hd_geometry geometry;
2754 const struct sun_predefined_drives *p = NULL;
2757 _("Building a new sun disklabel. Changes will remain in memory only,\n"
2758 "until you decide to write them. After that, of course, the previous\n"
2759 "content won't be recoverable.\n\n"));
2760 #if BYTE_ORDER == LITTLE_ENDIAN
2761 sun_other_endian = 1;
2763 sun_other_endian = 0;
2765 memset(MBRbuffer, 0, sizeof(MBRbuffer));
2766 sunlabel->magic = SUN_SSWAP16(SUN_LABEL_MAGIC);
2768 puts(_("Drive type\n"
2769 " ? auto configure\n"
2770 " 0 custom (with hardware detected defaults)"));
2771 for (i = 0; i < SIZE(sun_drives); i++) {
2772 printf(" %c %s%s%s\n",
2773 i + 'a', sun_drives[i].vendor,
2774 (*sun_drives[i].vendor) ? " " : "",
2775 sun_drives[i].model);
2778 c = read_char(_("Select type (? for auto, 0 for custom): "));
2779 if (c >= 'a' && c < 'a' + SIZE(sun_drives)) {
2780 p = sun_drives + c - 'a';
2782 } else if (c >= 'A' && c < 'A' + SIZE(sun_drives)) {
2783 p = sun_drives + c - 'A';
2785 } else if (c == '0') {
2787 } else if (c == '?' && scsi_disk) {
2788 p = sun_autoconfigure_scsi();
2790 printf(_("Autoconfigure failed.\n"));
2797 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
2798 heads = geometry.heads;
2799 sectors = geometry.sectors;
2800 cylinders = geometry.cylinders;
2807 sunlabel->nacyl = 0;
2808 sunlabel->pcylcount = SUN_SSWAP16(cylinders);
2809 sunlabel->rspeed = SUN_SSWAP16(300);
2810 sunlabel->ilfact = SUN_SSWAP16(1);
2811 sunlabel->sparecyl = 0;
2813 heads = read_int(1,heads,1024,0,_("Heads"));
2814 sectors = read_int(1,sectors,1024,0,_("Sectors/track"));
2816 cylinders = read_int(1,cylinders-2,65535,0,_("Cylinders"));
2818 cylinders = read_int(1,0,65535,0,_("Cylinders"));
2820 SUN_SSWAP16(read_int(0,2,65535,0,
2821 _("Alternate cylinders")));
2822 sunlabel->pcylcount =
2823 SUN_SSWAP16(read_int(0,cylinders+SUN_SSWAP16(sunlabel->nacyl),
2824 65535,0,_("Physical cylinders")));
2826 SUN_SSWAP16(read_int(1,5400,100000,0,
2827 _("Rotation speed (rpm)")));
2829 SUN_SSWAP16(read_int(1,1,32,0,_("Interleave factor")));
2830 sunlabel->sparecyl =
2831 SUN_SSWAP16(read_int(0,0,sectors,0,
2832 _("Extra sectors per cylinder")));
2835 sunlabel->sparecyl = SUN_SSWAP16(p->sparecyl);
2836 sunlabel->ncyl = SUN_SSWAP16(p->ncyl);
2837 sunlabel->nacyl = SUN_SSWAP16(p->nacyl);
2838 sunlabel->pcylcount = SUN_SSWAP16(p->pcylcount);
2839 sunlabel->ntrks = SUN_SSWAP16(p->ntrks);
2840 sunlabel->nsect = SUN_SSWAP16(p->nsect);
2841 sunlabel->rspeed = SUN_SSWAP16(p->rspeed);
2842 sunlabel->ilfact = SUN_SSWAP16(1);
2843 cylinders = p->ncyl;
2846 puts(_("You may change all the disk params from the x menu"));
2849 snprintf(sunlabel->info, sizeof(sunlabel->info),
2850 "%s%s%s cyl %d alt %d hd %d sec %d",
2851 p ? p->vendor : "", (p && *p->vendor) ? " " : "",
2853 : (floppy ? _("3,5\" floppy") : _("Linux custom")),
2854 cylinders, SUN_SSWAP16(sunlabel->nacyl), heads, sectors);
2856 sunlabel->ntrks = SUN_SSWAP16(heads);
2857 sunlabel->nsect = SUN_SSWAP16(sectors);
2858 sunlabel->ncyl = SUN_SSWAP16(cylinders);
2860 set_sun_partition(0, 0, cylinders * heads * sectors, LINUX_NATIVE);
2862 if (cylinders * heads * sectors >= 150 * 2048) {
2863 ndiv = cylinders - (50 * 2048 / (heads * sectors)); /* 50M swap */
2865 ndiv = cylinders * 2 / 3;
2866 set_sun_partition(0, 0, ndiv * heads * sectors, LINUX_NATIVE);
2867 set_sun_partition(1, ndiv * heads * sectors, cylinders * heads * sectors, LINUX_SWAP);
2868 sunlabel->infos[1].flags |= 0x01; /* Not mountable */
2870 set_sun_partition(2, 0, cylinders * heads * sectors, WHOLE_DISK);
2872 unsigned short *ush = (unsigned short *)sunlabel;
2873 unsigned short csum = 0;
2874 while(ush < (unsigned short *)(&sunlabel->csum))
2876 sunlabel->csum = csum;
2879 set_all_unchanged();
2881 get_boot(create_empty_sun);
2885 toggle_sunflags(int i, unsigned char mask) {
2886 if (sunlabel->infos[i].flags & mask)
2887 sunlabel->infos[i].flags &= ~mask;
2888 else sunlabel->infos[i].flags |= mask;
2893 fetch_sun(uint *starts, uint *lens, uint *start, uint *stop) {
2894 int i, continuous = 1;
2895 *start = 0; *stop = cylinders * heads * sectors;
2896 for (i = 0; i < partitions; i++) {
2897 if (sunlabel->partitions[i].num_sectors
2898 && sunlabel->infos[i].id
2899 && sunlabel->infos[i].id != WHOLE_DISK) {
2900 starts[i] = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
2901 lens[i] = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
2903 if (starts[i] == *start)
2905 else if (starts[i] + lens[i] >= *stop)
2909 /* There will be probably more gaps
2910 than one, so lets check afterwards */
2919 static uint *verify_sun_starts;
2922 verify_sun_cmp(int *a, int *b) {
2923 if (*a == -1) return 1;
2924 if (*b == -1) return -1;
2925 if (verify_sun_starts[*a] > verify_sun_starts[*b]) return 1;
2931 uint starts[8], lens[8], start, stop;
2932 int i,j,k,starto,endo;
2935 verify_sun_starts = starts;
2936 fetch_sun(starts,lens,&start,&stop);
2937 for (k = 0; k < 7; k++) {
2938 for (i = 0; i < 8; i++) {
2939 if (k && (lens[i] % (heads * sectors))) {
2940 printf(_("Partition %d doesn't end on cylinder boundary\n"), i+1);
2943 for (j = 0; j < i; j++)
2945 if (starts[j] == starts[i]+lens[i]) {
2946 starts[j] = starts[i]; lens[j] += lens[i];
2948 } else if (starts[i] == starts[j]+lens[j]){
2952 if (starts[i] < starts[j]+lens[j] &&
2953 starts[j] < starts[i]+lens[i]) {
2955 if (starts[j] > starto)
2957 endo = starts[i]+lens[i];
2958 if (starts[j]+lens[j] < endo)
2959 endo = starts[j]+lens[j];
2960 printf(_("Partition %d overlaps with others in "
2961 "sectors %d-%d\n"), i+1, starto, endo);
2968 for (i = 0; i < 8; i++) {
2974 qsort(array,SIZE(array),sizeof(array[0]),
2975 (int (*)(const void *,const void *)) verify_sun_cmp);
2976 if (array[0] == -1) {
2977 printf(_("No partitions defined\n"));
2980 stop = cylinders * heads * sectors;
2981 if (starts[array[0]])
2982 printf(_("Unused gap - sectors 0-%d\n"),starts[array[0]]);
2983 for (i = 0; i < 7 && array[i+1] != -1; i++) {
2984 printf(_("Unused gap - sectors %d-%d\n"),starts[array[i]]+lens[array[i]],starts[array[i+1]]);
2986 start = starts[array[i]]+lens[array[i]];
2988 printf(_("Unused gap - sectors %d-%d\n"),start,stop);
2992 add_sun_partition(int n, int sys) {
2993 uint start, stop, stop2;
2994 uint starts[8], lens[8];
3000 if (sunlabel->partitions[n].num_sectors && sunlabel->infos[n].id) {
3001 printf(_("Partition %d is already defined. Delete "
3002 "it before re-adding it.\n"), n + 1);
3006 fetch_sun(starts,lens,&start,&stop);
3007 if (stop <= start) {
3011 printf(_("Other partitions already cover the whole disk.\nDelete "
3012 "some/shrink them before retry.\n"));
3016 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
3019 first = read_int(0, 0, 0, 0, mesg);
3021 first = read_int(scround(start), scround(stop)+1,
3022 scround(stop), 0, mesg);
3023 if (display_in_cyl_units)
3024 first *= units_per_sector;
3026 /* Starting sector has to be properly aligned */
3027 first = (first + heads * sectors - 1) / (heads * sectors);
3028 if (n == 2 && first != 0)
3030 It is highly recommended that the third partition covers the whole disk\n\
3031 and is of type `Whole disk'\n");
3032 /* ewt asks to add: "don't start a partition at cyl 0"
3033 However, edmundo@rano.demon.co.uk writes:
3034 "In addition to having a Sun partition table, to be able to
3035 boot from the disc, the first partition, /dev/sdX1, must
3036 start at cylinder 0. This means that /dev/sdX1 contains
3037 the partition table and the boot block, as these are the
3038 first two sectors of the disc. Therefore you must be
3039 careful what you use /dev/sdX1 for. In particular, you must
3040 not use a partition starting at cylinder 0 for Linux swap,
3041 as that would overwrite the partition table and the boot
3042 block. You may, however, use such a partition for a UFS
3043 or EXT2 file system, as these file systems leave the first
3044 1024 bytes undisturbed. */
3045 /* On the other hand, one should not use partitions
3046 starting at block 0 in an md, or the label will
3048 for (i = 0; i < partitions; i++)
3049 if (lens[i] && starts[i] <= first
3050 && starts[i] + lens[i] > first)
3052 if (i < partitions && !whole_disk) {
3053 if (n == 2 && !first) {
3057 printf(_("Sector %d is already allocated\n"), first);
3061 stop = cylinders * heads * sectors;
3063 for (i = 0; i < partitions; i++) {
3064 if (starts[i] > first && starts[i] < stop)
3067 snprintf(mesg, sizeof(mesg),
3068 _("Last %s or +size or +sizeM or +sizeK"),
3069 str_units(SINGULAR));
3071 last = read_int(scround(stop2), scround(stop2), scround(stop2),
3073 else if (n == 2 && !first)
3074 last = read_int(scround(first), scround(stop2), scround(stop2),
3075 scround(first), mesg);
3077 last = read_int(scround(first), scround(stop), scround(stop),
3078 scround(first), mesg);
3079 if (display_in_cyl_units)
3080 last *= units_per_sector;
3081 if (n == 2 && !first) {
3082 if (last >= stop2) {
3085 } else if (last > stop) {
3087 _("You haven't covered the whole disk with the 3rd partition, but your value\n"
3088 "%d %s covers some other partition. Your entry has been changed\n"
3090 scround(last), str_units(SINGULAR),
3091 scround(stop), str_units(SINGULAR));
3094 } else if (!whole_disk && last > stop)
3097 if (whole_disk) sys = WHOLE_DISK;
3098 set_sun_partition(n, first, last, sys);
3102 sun_delete_partition(int i) {
3105 if (i == 2 && sunlabel->infos[i].id == WHOLE_DISK &&
3106 !sunlabel->partitions[i].start_cylinder &&
3107 (nsec = SUN_SSWAP32(sunlabel->partitions[i].num_sectors))
3108 == heads * sectors * cylinders)
3109 printf(_("If you want to maintain SunOS/Solaris compatibility, "
3110 "consider leaving this\n"
3111 "partition as Whole disk (5), starting at 0, with %u "
3112 "sectors\n"), nsec);
3113 sunlabel->infos[i].id = 0;
3114 sunlabel->partitions[i].num_sectors = 0;
3118 sun_change_sysid(int i, int sys) {
3119 if (sys == LINUX_SWAP && !sunlabel->partitions[i].start_cylinder) {
3121 _("It is highly recommended that the partition at offset 0\n"
3122 "is UFS, EXT2FS filesystem or SunOS swap. Putting Linux swap\n"
3123 "there may destroy your partition table and bootblock.\n"
3124 "Type YES if you're very sure you would like that partition\n"
3125 "tagged with 82 (Linux swap): "));
3126 if (strcmp (line_ptr, _("YES\n")))
3132 /* swaps are not mountable by default */
3133 sunlabel->infos[i].flags |= 0x01;
3136 /* assume other types are mountable;
3137 user can change it anyway */
3138 sunlabel->infos[i].flags &= ~0x01;
3141 sunlabel->infos[i].id = sys;
3145 sun_list_table(int xtra) {
3148 w = strlen(disk_device);
3151 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d rpm\n"
3152 "%d cylinders, %d alternate cylinders, %d physical cylinders\n"
3153 "%d extra sects/cyl, interleave %d:1\n"
3155 "Units = %s of %d * 512 bytes\n\n"),
3156 disk_device, heads, sectors, SUN_SSWAP16(sunlabel->rspeed),
3157 cylinders, SUN_SSWAP16(sunlabel->nacyl),
3158 SUN_SSWAP16(sunlabel->pcylcount),
3159 SUN_SSWAP16(sunlabel->sparecyl),
3160 SUN_SSWAP16(sunlabel->ilfact),
3162 str_units(PLURAL), units_per_sector);
3165 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d cylinders\n"
3166 "Units = %s of %d * 512 bytes\n\n"),
3167 disk_device, heads, sectors, cylinders,
3168 str_units(PLURAL), units_per_sector);
3170 printf(_("%*s Flag Start End Blocks Id System\n"),
3171 w + 1, _("Device"));
3172 for (i = 0 ; i < partitions; i++) {
3173 if (sunlabel->partitions[i].num_sectors) {
3174 uint32_t start = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
3175 uint32_t len = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
3177 "%s %c%c %9ld %9ld %9ld%c %2x %s\n",
3178 /* device */ partname(disk_device, i+1, w),
3179 /* flags */ (sunlabel->infos[i].flags & 0x01) ? 'u' : ' ',
3180 (sunlabel->infos[i].flags & 0x10) ? 'r' : ' ',
3181 /* start */ (long) scround(start),
3182 /* end */ (long) scround(start+len),
3183 /* odd flag on end */ (long) len / 2, len & 1 ? '+' : ' ',
3184 /* type id */ sunlabel->infos[i].id,
3185 /* type name */ partition_type(sunlabel->infos[i].id));
3190 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3193 sun_set_alt_cyl(void) {
3195 SUN_SSWAP16(read_int(0,SUN_SSWAP16(sunlabel->nacyl), 65535, 0,
3196 _("Number of alternate cylinders")));
3200 sun_set_ncyl(int cyl) {
3201 sunlabel->ncyl = SUN_SSWAP16(cyl);
3205 sun_set_xcyl(void) {
3206 sunlabel->sparecyl =
3207 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->sparecyl), sectors, 0,
3208 _("Extra sectors per cylinder")));
3212 sun_set_ilfact(void) {
3214 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->ilfact), 32, 0,
3215 _("Interleave factor")));
3219 sun_set_rspeed(void) {
3221 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->rspeed), 100000, 0,
3222 _("Rotation speed (rpm)")));
3226 sun_set_pcylcount(void) {
3227 sunlabel->pcylcount =
3228 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->pcylcount), 65535, 0,
3229 _("Number of physical cylinders")));
3231 #endif /* CONFIG_FEATURE_FDISK_ADVANCED */
3234 sun_write_table(void) {
3235 unsigned short *ush = (unsigned short *)sunlabel;
3236 unsigned short csum = 0;
3238 while(ush < (unsigned short *)(&sunlabel->csum))
3240 sunlabel->csum = csum;
3241 if (lseek(fd, 0, SEEK_SET) < 0)
3242 fdisk_fatal(unable_to_seek);
3243 if (write(fd, sunlabel, SECTOR_SIZE) != SECTOR_SIZE)
3244 fdisk_fatal(unable_to_write);
3246 #endif /* SUN_LABEL */
3248 /* DOS partition types */
3250 static const struct systypes i386_sys_types[] = {
3253 {"\x04" "FAT16 <32M"},
3254 {"\x05" "Extended"}, /* DOS 3.3+ extended partition */
3255 {"\x06" "FAT16"}, /* DOS 16-bit >=32M */
3256 {"\x07" "HPFS/NTFS"}, /* OS/2 IFS, eg, HPFS or NTFS or QNX */
3257 {"\x0a" "OS/2 Boot Manager"},/* OS/2 Boot Manager */
3258 {"\x0b" "Win95 FAT32"},
3259 {"\x0c" "Win95 FAT32 (LBA)"},/* LBA really is `Extended Int 13h' */
3260 {"\x0e" "Win95 FAT16 (LBA)"},
3261 {"\x0f" "Win95 Ext'd (LBA)"},
3262 {"\x11" "Hidden FAT12"},
3263 {"\x12" "Compaq diagnostics"},
3264 {"\x14" "Hidden FAT16 <32M"},
3265 {"\x16" "Hidden FAT16"},
3266 {"\x17" "Hidden HPFS/NTFS"},
3267 {"\x1b" "Hidden Win95 FAT32"},
3268 {"\x1c" "Hidden Win95 FAT32 (LBA)"},
3269 {"\x1e" "Hidden Win95 FAT16 (LBA)"},
3270 {"\x3c" "PartitionMagic recovery"},
3271 {"\x41" "PPC PReP Boot"},
3273 {"\x63" "GNU HURD or SysV"}, /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */
3274 {"\x80" "Old Minix"}, /* Minix 1.4a and earlier */
3275 {"\x81" "Minix / old Linux"},/* Minix 1.4b and later */
3276 {"\x82" "Linux swap"}, /* also Solaris */
3278 {"\x84" "OS/2 hidden C: drive"},
3279 {"\x85" "Linux extended"},
3280 {"\x86" "NTFS volume set"},
3281 {"\x87" "NTFS volume set"},
3282 {"\x8e" "Linux LVM"},
3283 {"\x9f" "BSD/OS"}, /* BSDI */
3284 {"\xa0" "IBM Thinkpad hibernation"},
3285 {"\xa5" "FreeBSD"}, /* various BSD flavours */
3287 {"\xa8" "Darwin UFS"},
3289 {"\xab" "Darwin boot"},
3291 {"\xb8" "BSDI swap"},
3292 {"\xbe" "Solaris boot"},
3294 {"\xee" "EFI GPT"}, /* Intel EFI GUID Partition Table */
3295 {"\xef" "EFI (FAT-12/16/32)"},/* Intel EFI System Partition */
3296 {"\xf0" "Linux/PA-RISC boot"},/* Linux/PA-RISC boot loader */
3297 {"\xf2" "DOS secondary"}, /* DOS 3.3+ secondary */
3298 {"\xfd" "Linux raid autodetect"},/* New (2.2.x) raid partition with
3299 autodetect using persistent
3301 #ifdef CONFIG_WEIRD_PARTITION_TYPES
3302 {"\x02" "XENIX root"},
3303 {"\x03" "XENIX usr"},
3304 {"\x08" "AIX"}, /* AIX boot (AIX -- PS/2 port) or SplitDrive */
3305 {"\x09" "AIX bootable"}, /* AIX data or Coherent */
3307 {"\x18" "AST SmartSleep"},
3310 {"\x40" "Venix 80286"},
3312 {"\x4e" "QNX4.x 2nd part"},
3313 {"\x4f" "QNX4.x 3rd part"},
3314 {"\x50" "OnTrack DM"},
3315 {"\x51" "OnTrack DM6 Aux1"}, /* (or Novell) */
3316 {"\x52" "CP/M"}, /* CP/M or Microport SysV/AT */
3317 {"\x53" "OnTrack DM6 Aux3"},
3318 {"\x54" "OnTrackDM6"},
3319 {"\x55" "EZ-Drive"},
3320 {"\x56" "Golden Bow"},
3321 {"\x5c" "Priam Edisk"},
3322 {"\x61" "SpeedStor"},
3323 {"\x64" "Novell Netware 286"},
3324 {"\x65" "Novell Netware 386"},
3325 {"\x70" "DiskSecure Multi-Boot"},
3328 {"\x94" "Amoeba BBT"}, /* (bad block table) */
3329 {"\xa7" "NeXTSTEP"},
3330 {"\xbb" "Boot Wizard hidden"},
3331 {"\xc1" "DRDOS/sec (FAT-12)"},
3332 {"\xc4" "DRDOS/sec (FAT-16 < 32M)"},
3333 {"\xc6" "DRDOS/sec (FAT-16)"},
3335 {"\xda" "Non-FS data"},
3336 {"\xdb" "CP/M / CTOS / ..."},/* CP/M or Concurrent CP/M or
3337 Concurrent DOS or CTOS */
3338 {"\xde" "Dell Utility"}, /* Dell PowerEdge Server utilities */
3339 {"\xdf" "BootIt"}, /* BootIt EMBRM */
3340 {"\xe1" "DOS access"}, /* DOS access or SpeedStor 12-bit FAT
3341 extended partition */
3342 {"\xe3" "DOS R/O"}, /* DOS R/O or SpeedStor */
3343 {"\xe4" "SpeedStor"}, /* SpeedStor 16-bit FAT extended
3344 partition < 1024 cyl. */
3345 {"\xf1" "SpeedStor"},
3346 {"\xf4" "SpeedStor"}, /* SpeedStor large partition */
3347 {"\xfe" "LANstep"}, /* SpeedStor >1024 cyl. or LANstep */
3348 {"\xff" "BBT"}, /* Xenix Bad Block Table */
3355 /* A valid partition table sector ends in 0x55 0xaa */
3357 part_table_flag(const char *b) {
3358 return ((uint) b[510]) + (((uint) b[511]) << 8);
3362 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3364 write_part_table_flag(char *b) {
3369 /* start_sect and nr_sects are stored little endian on all machines */
3370 /* moreover, they are not aligned correctly */
3372 store4_little_endian(unsigned char *cp, unsigned int val) {
3373 cp[0] = (val & 0xff);
3374 cp[1] = ((val >> 8) & 0xff);
3375 cp[2] = ((val >> 16) & 0xff);
3376 cp[3] = ((val >> 24) & 0xff);
3378 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3381 read4_little_endian(const unsigned char *cp) {
3382 return (uint)(cp[0]) + ((uint)(cp[1]) << 8)
3383 + ((uint)(cp[2]) << 16) + ((uint)(cp[3]) << 24);
3386 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3388 set_start_sect(struct partition *p, unsigned int start_sect) {
3389 store4_little_endian(p->start4, start_sect);
3394 get_start_sect(const struct partition *p) {
3395 return read4_little_endian(p->start4);
3398 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3400 set_nr_sects(struct partition *p, unsigned int nr_sects) {
3401 store4_little_endian(p->size4, nr_sects);
3406 get_nr_sects(const struct partition *p) {
3407 return read4_little_endian(p->size4);
3410 /* normally O_RDWR, -l option gives O_RDONLY */
3411 static int type_open = O_RDWR;
3414 static int ext_index, /* the prime extended partition */
3415 listing, /* no aborts for fdisk -l */
3416 dos_compatible_flag = ~0;
3417 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3418 static int dos_changed;
3419 static int nowarn; /* no warnings for fdisk -l/-s */
3424 static uint user_cylinders, user_heads, user_sectors;
3425 static uint pt_heads, pt_sectors;
3426 static uint kern_heads, kern_sectors;
3428 static uint extended_offset; /* offset of link pointers */
3430 static unsigned long long total_number_of_sectors;
3433 static jmp_buf listingbuf;
3435 static void fdisk_fatal(enum failure why) {
3436 const char *message;
3440 longjmp(listingbuf, 1);
3444 case unable_to_open:
3445 message = "Unable to open %s\n";
3447 case unable_to_read:
3448 message = "Unable to read %s\n";
3450 case unable_to_seek:
3451 message = "Unable to seek on %s\n";
3453 case unable_to_write:
3454 message = "Unable to write %s\n";
3457 message = "BLKGETSIZE ioctl failed on %s\n";
3460 message = "Fatal error\n";
3463 fputc('\n', stderr);
3464 fprintf(stderr, message, disk_device);
3469 seek_sector(uint secno) {
3470 fdisk_loff_t offset = (fdisk_loff_t) secno * sector_size;
3471 if (fdisk_llseek(fd, offset, SEEK_SET) == (fdisk_loff_t) -1)
3472 fdisk_fatal(unable_to_seek);
3475 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3477 write_sector(uint secno, char *buf) {
3479 if (write(fd, buf, sector_size) != sector_size)
3480 fdisk_fatal(unable_to_write);
3484 /* Allocate a buffer and read a partition table sector */
3486 read_pte(struct pte *pe, uint offset) {
3488 pe->offset = offset;
3489 pe->sectorbuffer = (char *) xmalloc(sector_size);
3490 seek_sector(offset);
3491 if (read(fd, pe->sectorbuffer, sector_size) != sector_size)
3492 fdisk_fatal(unable_to_read);
3493 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3496 pe->part_table = pe->ext_pointer = NULL;
3500 get_partition_start(const struct pte *pe) {
3501 return pe->offset + get_start_sect(pe->part_table);
3504 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3506 * Avoid warning about DOS partitions when no DOS partition was changed.
3507 * Here a heuristic "is probably dos partition".
3508 * We might also do the opposite and warn in all cases except
3509 * for "is probably nondos partition".
3512 is_dos_partition(int t) {
3513 return (t == 1 || t == 4 || t == 6 ||
3514 t == 0x0b || t == 0x0c || t == 0x0e ||
3515 t == 0x11 || t == 0x12 || t == 0x14 || t == 0x16 ||
3516 t == 0x1b || t == 0x1c || t == 0x1e || t == 0x24 ||
3517 t == 0xc1 || t == 0xc4 || t == 0xc6);
3522 #ifdef CONFIG_FEATURE_SUN_LABEL
3524 puts(_("Command action"));
3525 puts(_("\ta\ttoggle a read only flag")); /* sun */
3526 puts(_("\tb\tedit bsd disklabel"));
3527 puts(_("\tc\ttoggle the mountable flag")); /* sun */
3528 puts(_("\td\tdelete a partition"));
3529 puts(_("\tl\tlist known partition types"));
3530 puts(_("\tm\tprint this menu"));
3531 puts(_("\tn\tadd a new partition"));
3532 puts(_("\to\tcreate a new empty DOS partition table"));
3533 puts(_("\tp\tprint the partition table"));
3534 puts(_("\tq\tquit without saving changes"));
3535 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3536 puts(_("\tt\tchange a partition's system id"));
3537 puts(_("\tu\tchange display/entry units"));
3538 puts(_("\tv\tverify the partition table"));
3539 puts(_("\tw\twrite table to disk and exit"));
3540 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3541 puts(_("\tx\textra functionality (experts only)"));
3545 #ifdef CONFIG_FEATURE_SGI_LABEL
3547 puts(_("Command action"));
3548 puts(_("\ta\tselect bootable partition")); /* sgi flavour */
3549 puts(_("\tb\tedit bootfile entry")); /* sgi */
3550 puts(_("\tc\tselect sgi swap partition")); /* sgi flavour */
3551 puts(_("\td\tdelete a partition"));
3552 puts(_("\tl\tlist known partition types"));
3553 puts(_("\tm\tprint this menu"));
3554 puts(_("\tn\tadd a new partition"));
3555 puts(_("\to\tcreate a new empty DOS partition table"));
3556 puts(_("\tp\tprint the partition table"));
3557 puts(_("\tq\tquit without saving changes"));
3558 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3559 puts(_("\tt\tchange a partition's system id"));
3560 puts(_("\tu\tchange display/entry units"));
3561 puts(_("\tv\tverify the partition table"));
3562 puts(_("\tw\twrite table to disk and exit"));
3565 #ifdef CONFIG_FEATURE_AIX_LABEL
3567 puts(_("Command action"));
3568 puts(_("\tm\tprint this menu"));
3569 puts(_("\to\tcreate a new empty DOS partition table"));
3570 puts(_("\tq\tquit without saving changes"));
3571 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3575 puts(_("Command action"));
3576 puts(_("\ta\ttoggle a bootable flag"));
3577 puts(_("\tb\tedit bsd disklabel"));
3578 puts(_("\tc\ttoggle the dos compatibility flag"));
3579 puts(_("\td\tdelete a partition"));
3580 puts(_("\tl\tlist known partition types"));
3581 puts(_("\tm\tprint this menu"));
3582 puts(_("\tn\tadd a new partition"));
3583 puts(_("\to\tcreate a new empty DOS partition table"));
3584 puts(_("\tp\tprint the partition table"));
3585 puts(_("\tq\tquit without saving changes"));
3586 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3587 puts(_("\tt\tchange a partition's system id"));
3588 puts(_("\tu\tchange display/entry units"));
3589 puts(_("\tv\tverify the partition table"));
3590 puts(_("\tw\twrite table to disk and exit"));
3591 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3592 puts(_("\tx\textra functionality (experts only)"));
3596 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3599 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3602 #ifdef CONFIG_FEATURE_SUN_LABEL
3604 puts(_("Command action"));
3605 puts(_("\ta\tchange number of alternate cylinders")); /*sun*/
3606 puts(_("\tc\tchange number of cylinders"));
3607 puts(_("\td\tprint the raw data in the partition table"));
3608 puts(_("\te\tchange number of extra sectors per cylinder"));/*sun*/
3609 puts(_("\th\tchange number of heads"));
3610 puts(_("\ti\tchange interleave factor")); /*sun*/
3611 puts(_("\to\tchange rotation speed (rpm)")); /*sun*/
3612 puts(_("\tm\tprint this menu"));
3613 puts(_("\tp\tprint the partition table"));
3614 puts(_("\tq\tquit without saving changes"));
3615 puts(_("\tr\treturn to main menu"));
3616 puts(_("\ts\tchange number of sectors/track"));
3617 puts(_("\tv\tverify the partition table"));
3618 puts(_("\tw\twrite table to disk and exit"));
3619 puts(_("\ty\tchange number of physical cylinders")); /*sun*/
3622 #ifdef CONFIG_FEATURE_SGI_LABEL
3624 puts(_("Command action"));
3625 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3626 puts(_("\tc\tchange number of cylinders"));
3627 puts(_("\td\tprint the raw data in the partition table"));
3628 puts(_("\te\tlist extended partitions")); /* !sun */
3629 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3630 puts(_("\th\tchange number of heads"));
3631 puts(_("\tm\tprint this menu"));
3632 puts(_("\tp\tprint the partition table"));
3633 puts(_("\tq\tquit without saving changes"));
3634 puts(_("\tr\treturn to main menu"));
3635 puts(_("\ts\tchange number of sectors/track"));
3636 puts(_("\tv\tverify the partition table"));
3637 puts(_("\tw\twrite table to disk and exit"));
3640 #ifdef CONFIG_FEATURE_AIX_LABEL
3642 puts(_("Command action"));
3643 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3644 puts(_("\tc\tchange number of cylinders"));
3645 puts(_("\td\tprint the raw data in the partition table"));
3646 puts(_("\te\tlist extended partitions")); /* !sun */
3647 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3648 puts(_("\th\tchange number of heads"));
3649 puts(_("\tm\tprint this menu"));
3650 puts(_("\tp\tprint the partition table"));
3651 puts(_("\tq\tquit without saving changes"));
3652 puts(_("\tr\treturn to main menu"));
3653 puts(_("\ts\tchange number of sectors/track"));
3654 puts(_("\tv\tverify the partition table"));
3655 puts(_("\tw\twrite table to disk and exit"));
3659 puts(_("Command action"));
3660 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3661 puts(_("\tc\tchange number of cylinders"));
3662 puts(_("\td\tprint the raw data in the partition table"));
3663 puts(_("\te\tlist extended partitions")); /* !sun */
3664 puts(_("\tf\tfix partition order")); /* !sun, !aix, !sgi */
3665 #ifdef CONFIG_FEATURE_SGI_LABEL
3666 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3668 puts(_("\th\tchange number of heads"));
3669 puts(_("\tm\tprint this menu"));
3670 puts(_("\tp\tprint the partition table"));
3671 puts(_("\tq\tquit without saving changes"));
3672 puts(_("\tr\treturn to main menu"));
3673 puts(_("\ts\tchange number of sectors/track"));
3674 puts(_("\tv\tverify the partition table"));
3675 puts(_("\tw\twrite table to disk and exit"));
3678 #endif /* ADVANCED mode */
3680 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3681 static const struct systypes *
3682 get_sys_types(void) {
3684 #ifdef CONFIG_FEATURE_SUN_LABEL
3685 sun_label ? sun_sys_types :
3687 #ifdef CONFIG_FEATURE_SGI_LABEL
3688 sgi_label ? sgi_sys_types :
3693 #define get_sys_types() i386_sys_types
3694 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3696 static const char *partition_type(unsigned char type)
3699 const struct systypes *types = get_sys_types();
3701 for (i=0; types[i].name; i++)
3702 if (types[i].name[0] == type)
3703 return types[i].name + 1;
3705 return _("Unknown");
3709 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3713 #ifdef CONFIG_FEATURE_SUN_LABEL
3714 sun_label ? sunlabel->infos[i].id :
3716 #ifdef CONFIG_FEATURE_SGI_LABEL
3717 sgi_label ? sgi_get_sysid(i) :
3719 ptes[i].part_table->sys_ind);
3722 void list_types(const struct systypes *sys)
3724 uint last[4], done = 0, next = 0, size;
3727 for (i = 0; sys[i].name; i++);
3730 for (i = 3; i >= 0; i--)
3731 last[3 - i] = done += (size + i - done) / (i + 1);
3735 printf("%c%2x %-15.15s", i ? ' ' : '\n',
3736 sys[next].name[0], partition_type(sys[next].name[0]));
3737 next = last[i++] + done;
3738 if (i > 3 || next >= last[i]) {
3742 } while (done < last[0]);
3745 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3748 is_cleared_partition(const struct partition *p) {
3749 return !(!p || p->boot_ind || p->head || p->sector || p->cyl ||
3750 p->sys_ind || p->end_head || p->end_sector || p->end_cyl ||
3751 get_start_sect(p) || get_nr_sects(p));
3755 clear_partition(struct partition *p) {
3758 memset(p, 0, sizeof(struct partition));
3761 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3763 set_partition(int i, int doext, uint start, uint stop, int sysid) {
3764 struct partition *p;
3768 p = ptes[i].ext_pointer;
3769 offset = extended_offset;
3771 p = ptes[i].part_table;
3772 offset = ptes[i].offset;
3776 set_start_sect(p, start - offset);
3777 set_nr_sects(p, stop - start + 1);
3778 if (dos_compatible_flag && (start/(sectors*heads) > 1023))
3779 start = heads*sectors*1024 - 1;
3780 set_hsc(p->head, p->sector, p->cyl, start);
3781 if (dos_compatible_flag && (stop/(sectors*heads) > 1023))
3782 stop = heads*sectors*1024 - 1;
3783 set_hsc(p->end_head, p->end_sector, p->end_cyl, stop);
3784 ptes[i].changed = 1;
3789 test_c(const char **m, const char *mesg) {
3792 fprintf(stderr, _("You must set"));
3794 fprintf(stderr, " %s", *m);
3802 warn_geometry(void) {
3803 const char *m = NULL;
3807 prev = test_c(&m, _("heads"));
3809 prev = test_c(&m, _("sectors"));
3811 prev = test_c(&m, _("cylinders"));
3815 fprintf(stderr, "%s%s.\n"
3816 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3817 "You can do this from the extra functions menu.\n"
3819 , prev ? _(" and ") : " ", m);
3824 static void update_units(void)
3826 int cyl_units = heads * sectors;
3828 if (display_in_cyl_units && cyl_units)
3829 units_per_sector = cyl_units;
3831 units_per_sector = 1; /* in sectors */
3834 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3836 warn_cylinders(void) {
3837 if (dos_label && cylinders > 1024 && !nowarn)
3838 fprintf(stderr, _("\n"
3839 "The number of cylinders for this disk is set to %d.\n"
3840 "There is nothing wrong with that, but this is larger than 1024,\n"
3841 "and could in certain setups cause problems with:\n"
3842 "1) software that runs at boot time (e.g., old versions of LILO)\n"
3843 "2) booting and partitioning software from other OSs\n"
3844 " (e.g., DOS FDISK, OS/2 FDISK)\n"),
3850 read_extended(int ext) {
3853 struct partition *p, *q;
3857 pex->ext_pointer = pex->part_table;
3859 p = pex->part_table;
3860 if (!get_start_sect(p)) {
3862 _("Bad offset in primary extended partition\n"));
3866 while (IS_EXTENDED (p->sys_ind)) {
3867 struct pte *pe = &ptes[partitions];
3869 if (partitions >= MAXIMUM_PARTS) {
3870 /* This is not a Linux restriction, but
3871 this program uses arrays of size MAXIMUM_PARTS.
3872 Do not try to `improve' this test. */
3873 struct pte *pre = &ptes[partitions-1];
3874 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3876 _("Warning: deleting partitions after %d\n"),
3880 clear_partition(pre->ext_pointer);
3884 read_pte(pe, extended_offset + get_start_sect(p));
3886 if (!extended_offset)
3887 extended_offset = get_start_sect(p);
3889 q = p = pt_offset(pe->sectorbuffer, 0);
3890 for (i = 0; i < 4; i++, p++) if (get_nr_sects(p)) {
3891 if (IS_EXTENDED (p->sys_ind)) {
3892 if (pe->ext_pointer)
3894 _("Warning: extra link "
3895 "pointer in partition table"
3896 " %d\n"), partitions + 1);
3898 pe->ext_pointer = p;
3899 } else if (p->sys_ind) {
3902 _("Warning: ignoring extra "
3903 "data in partition table"
3904 " %d\n"), partitions + 1);
3910 /* very strange code here... */
3911 if (!pe->part_table) {
3912 if (q != pe->ext_pointer)
3915 pe->part_table = q + 1;
3917 if (!pe->ext_pointer) {
3918 if (q != pe->part_table)
3919 pe->ext_pointer = q;
3921 pe->ext_pointer = q + 1;
3924 p = pe->ext_pointer;
3928 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3929 /* remove empty links */
3931 for (i = 4; i < partitions; i++) {
3932 struct pte *pe = &ptes[i];
3934 if (!get_nr_sects(pe->part_table) &&
3935 (partitions > 5 || ptes[4].part_table->sys_ind)) {
3936 printf("omitting empty partition (%d)\n", i+1);
3937 delete_partition(i);
3938 goto remove; /* numbering changed */
3944 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3946 create_doslabel(void) {
3950 _("Building a new DOS disklabel. Changes will remain in memory only,\n"
3951 "until you decide to write them. After that, of course, the previous\n"
3952 "content won't be recoverable.\n\n"));
3953 #ifdef CONFIG_FEATURE_SUN_LABEL
3954 sun_nolabel(); /* otherwise always recognised as sun */
3956 #ifdef CONFIG_FEATURE_SGI_LABEL
3957 sgi_nolabel(); /* otherwise always recognised as sgi */
3959 #ifdef CONFIG_FEATURE_AIX_LABEL
3962 #ifdef CONFIG_FEATURE_OSF_LABEL
3964 possibly_osf_label = 0;
3968 for (i = 510-64; i < 510; i++)
3970 write_part_table_flag(MBRbuffer);
3971 extended_offset = 0;
3972 set_all_unchanged();
3974 get_boot(create_empty_dos);
3976 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3979 get_sectorsize(void) {
3980 if (!user_set_sector_size &&
3981 get_kernel_revision() >= MAKE_VERSION(2,3,3)) {
3983 if (ioctl(fd, BLKSSZGET, &arg) == 0)
3985 if (sector_size != DEFAULT_SECTOR_SIZE)
3986 printf(_("Note: sector size is %d (not %d)\n"),
3987 sector_size, DEFAULT_SECTOR_SIZE);
3992 get_kernel_geometry(void) {
3993 struct hd_geometry geometry;
3995 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
3996 kern_heads = geometry.heads;
3997 kern_sectors = geometry.sectors;
3998 /* never use geometry.cylinders - it is truncated */
4003 get_partition_table_geometry(void) {
4004 const unsigned char *bufp = MBRbuffer;
4005 struct partition *p;
4006 int i, h, s, hh, ss;
4010 if (!(valid_part_table_flag(bufp)))
4014 for (i=0; i<4; i++) {
4015 p = pt_offset(bufp, i);
4016 if (p->sys_ind != 0) {
4017 h = p->end_head + 1;
4018 s = (p->end_sector & 077);
4023 } else if (hh != h || ss != s)
4028 if (!first && !bad) {
4035 get_geometry(void) {
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) {
4090 for (i = 0; i < 4; i++) {
4091 struct pte *pe = &ptes[i];
4093 pe->part_table = pt_offset(MBRbuffer, i);
4094 pe->ext_pointer = NULL;
4096 pe->sectorbuffer = MBRbuffer;
4097 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4098 pe->changed = (what == create_empty_dos);
4102 #ifdef CONFIG_FEATURE_SUN_LABEL
4103 if (what == create_empty_sun && check_sun_label())
4107 memset(MBRbuffer, 0, 512);
4109 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4110 if (what == create_empty_dos)
4111 goto got_dos_table; /* skip reading disk */
4113 if ((fd = open(disk_device, type_open)) < 0) {
4114 if ((fd = open(disk_device, O_RDONLY)) < 0) {
4115 if (what == try_only)
4117 fdisk_fatal(unable_to_open);
4119 printf(_("You will not be able to write "
4120 "the partition table.\n"));
4123 if (512 != read(fd, MBRbuffer, 512)) {
4124 if (what == try_only)
4126 fdisk_fatal(unable_to_read);
4129 if ((fd = open(disk_device, O_RDONLY)) < 0)
4131 if (512 != read(fd, MBRbuffer, 512))
4139 #ifdef CONFIG_FEATURE_SUN_LABEL
4140 if (check_sun_label())
4144 #ifdef CONFIG_FEATURE_SGI_LABEL
4145 if (check_sgi_label())
4149 #ifdef CONFIG_FEATURE_AIX_LABEL
4150 if (check_aix_label())
4154 #ifdef CONFIG_FEATURE_OSF_LABEL
4155 if (check_osf_label()) {
4156 possibly_osf_label = 1;
4157 if (!valid_part_table_flag(MBRbuffer)) {
4161 printf(_("This disk has both DOS and BSD magic.\n"
4162 "Give the 'b' command to go to BSD mode.\n"));
4166 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4170 if (!valid_part_table_flag(MBRbuffer)) {
4171 #ifndef CONFIG_FEATURE_FDISK_WRITABLE
4177 _("Device contains neither a valid DOS "
4178 "partition table, nor Sun, SGI or OSF "
4181 #ifdef CONFIG_FEATURE_SUN_LABEL
4190 case create_empty_dos:
4191 #ifdef CONFIG_FEATURE_SUN_LABEL
4192 case create_empty_sun:
4196 fprintf(stderr, _("Internal error\n"));
4199 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
4202 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4207 for (i = 0; i < 4; i++) {
4208 struct pte *pe = &ptes[i];
4210 if (IS_EXTENDED (pe->part_table->sys_ind)) {
4211 if (partitions != 4)
4212 fprintf(stderr, _("Ignoring extra extended "
4213 "partition %d\n"), i + 1);
4219 for (i = 3; i < partitions; i++) {
4220 struct pte *pe = &ptes[i];
4222 if (!valid_part_table_flag(pe->sectorbuffer)) {
4224 _("Warning: invalid flag 0x%04x of partition "
4225 "table %d will be corrected by w(rite)\n"),
4226 part_table_flag(pe->sectorbuffer), i + 1);
4227 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4236 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4238 * Print the message MESG, then read an integer between LOW and HIGH (inclusive).
4239 * If the user hits Enter, DFLT is returned.
4240 * Answers like +10 are interpreted as offsets from BASE.
4242 * There is no default if DFLT is not between LOW and HIGH.
4245 read_int(uint low, uint dflt, uint high, uint base, char *mesg)
4249 static char *ms = NULL;
4250 static int mslen = 0;
4252 if (!ms || strlen(mesg)+100 > mslen) {
4253 mslen = strlen(mesg)+200;
4254 ms = xrealloc(ms,mslen);
4257 if (dflt < low || dflt > high)
4261 snprintf(ms, mslen, _("%s (%u-%u, default %u): "),
4262 mesg, low, high, dflt);
4264 snprintf(ms, mslen, "%s (%u-%u): ",
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) {
4342 i = read_int(1, 0, max, 0, _("Partition number")) - 1;
4346 if ((!sun_label && !sgi_label && !pe->part_table->sys_ind)
4347 #ifdef CONFIG_FEATURE_SUN_LABEL
4349 (!sunlabel->partitions[i].num_sectors ||
4350 !sunlabel->infos[i].id))
4352 #ifdef CONFIG_FEATURE_SGI_LABEL
4353 || (sgi_label && (!sgi_get_num_sectors(i)))
4357 _("Warning: partition %d has empty type\n"),
4364 get_existing_partition(int warn, int max) {
4368 for (i = 0; i < max; i++) {
4369 struct pte *pe = &ptes[i];
4370 struct partition *p = pe->part_table;
4372 if (p && !is_cleared_partition(p)) {
4379 printf(_("Selected partition %d\n"), pno+1);
4382 printf(_("No partition is defined yet!\n"));
4386 return get_partition(warn, max);
4390 get_nonexisting_partition(int warn, int max) {
4394 for (i = 0; i < max; i++) {
4395 struct pte *pe = &ptes[i];
4396 struct partition *p = pe->part_table;
4398 if (p && is_cleared_partition(p)) {
4405 printf(_("Selected partition %d\n"), pno+1);
4408 printf(_("All primary partitions have been defined already!\n"));
4412 return get_partition(warn, max);
4416 void change_units(void)
4418 display_in_cyl_units = !display_in_cyl_units;
4420 printf(_("Changing display/entry units to %s\n"),
4425 toggle_active(int i) {
4426 struct pte *pe = &ptes[i];
4427 struct partition *p = pe->part_table;
4429 if (IS_EXTENDED (p->sys_ind) && !p->boot_ind)
4431 _("WARNING: Partition %d is an extended partition\n"),
4433 p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG);
4438 toggle_dos_compatibility_flag(void) {
4439 dos_compatible_flag = ~dos_compatible_flag;
4440 if (dos_compatible_flag) {
4441 sector_offset = sectors;
4442 printf(_("DOS Compatibility flag is set\n"));
4446 printf(_("DOS Compatibility flag is not set\n"));
4451 delete_partition(int i) {
4452 struct pte *pe = &ptes[i];
4453 struct partition *p = pe->part_table;
4454 struct partition *q = pe->ext_pointer;
4456 /* Note that for the fifth partition (i == 4) we don't actually
4457 * decrement partitions.
4460 if (warn_geometry())
4461 return; /* C/H/S not set */
4464 #ifdef CONFIG_FEATURE_SUN_LABEL
4466 sun_delete_partition(i);
4470 #ifdef CONFIG_FEATURE_SGI_LABEL
4472 sgi_delete_partition(i);
4478 if (IS_EXTENDED (p->sys_ind) && i == ext_index) {
4480 ptes[ext_index].ext_pointer = NULL;
4481 extended_offset = 0;
4487 if (!q->sys_ind && i > 4) {
4488 /* the last one in the chain - just delete */
4491 clear_partition(ptes[i].ext_pointer);
4492 ptes[i].changed = 1;
4494 /* not the last one - further ones will be moved down */
4496 /* delete this link in the chain */
4497 p = ptes[i-1].ext_pointer;
4499 set_start_sect(p, get_start_sect(q));
4500 set_nr_sects(p, get_nr_sects(q));
4501 ptes[i-1].changed = 1;
4502 } else if (partitions > 5) { /* 5 will be moved to 4 */
4503 /* the first logical in a longer chain */
4506 if (pe->part_table) /* prevent SEGFAULT */
4507 set_start_sect(pe->part_table,
4508 get_partition_start(pe) -
4510 pe->offset = extended_offset;
4514 if (partitions > 5) {
4516 while (i < partitions) {
4517 ptes[i] = ptes[i+1];
4521 /* the only logical: clear only */
4522 clear_partition(ptes[i].part_table);
4527 change_sysid(void) {
4528 int i, sys, origsys;
4529 struct partition *p;
4531 #ifdef CONFIG_FEATURE_SGI_LABEL
4532 /* If sgi_label then don't use get_existing_partition,
4533 let the user select a partition, since get_existing_partition()
4534 only works for Linux like partition tables. */
4536 i = get_existing_partition(0, partitions);
4538 i = get_partition(0, partitions);
4541 i = get_existing_partition(0, partitions);
4545 p = ptes[i].part_table;
4546 origsys = sys = get_sysid(i);
4548 /* if changing types T to 0 is allowed, then
4549 the reverse change must be allowed, too */
4550 if (!sys && !sgi_label && !sun_label && !get_nr_sects(p))
4551 printf(_("Partition %d does not exist yet!\n"), i + 1);
4553 sys = read_hex (get_sys_types());
4555 if (!sys && !sgi_label && !sun_label) {
4556 printf(_("Type 0 means free space to many systems\n"
4557 "(but not to Linux). Having partitions of\n"
4558 "type 0 is probably unwise. You can delete\n"
4559 "a partition using the `d' command.\n"));
4563 if (!sun_label && !sgi_label) {
4564 if (IS_EXTENDED (sys) != IS_EXTENDED (p->sys_ind)) {
4565 printf(_("You cannot change a partition into"
4566 " an extended one or vice versa\n"
4567 "Delete it first.\n"));
4573 #ifdef CONFIG_FEATURE_SUN_LABEL
4574 if (sun_label && i == 2 && sys != WHOLE_DISK)
4575 printf(_("Consider leaving partition 3 "
4576 "as Whole disk (5),\n"
4577 "as SunOS/Solaris expects it and "
4578 "even Linux likes it.\n\n"));
4580 #ifdef CONFIG_FEATURE_SGI_LABEL
4581 if (sgi_label && ((i == 10 && sys != ENTIRE_DISK)
4582 || (i == 8 && sys != 0)))
4583 printf(_("Consider leaving partition 9 "
4584 "as volume header (0),\nand "
4585 "partition 11 as entire volume (6)"
4586 "as IRIX expects it.\n\n"));
4590 #ifdef CONFIG_FEATURE_SUN_LABEL
4592 sun_change_sysid(i, sys);
4595 #ifdef CONFIG_FEATURE_SGI_LABEL
4597 sgi_change_sysid(i, sys);
4601 printf (_("Changed system type of partition %d "
4602 "to %x (%s)\n"), i + 1, sys,
4603 partition_type(sys));
4604 ptes[i].changed = 1;
4605 if (is_dos_partition(origsys) ||
4606 is_dos_partition(sys))
4612 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
4615 /* check_consistency() and long2chs() added Sat Mar 6 12:28:16 1993,
4616 * faith@cs.unc.edu, based on code fragments from pfdisk by Gordon W. Ross,
4617 * Jan. 1990 (version 1.2.1 by Gordon W. Ross Aug. 1990; Modified by S.
4618 * Lubkin Oct. 1991). */
4620 static void long2chs(ulong ls, uint *c, uint *h, uint *s) {
4621 int spc = heads * sectors;
4626 *s = ls % sectors + 1; /* sectors count from 1 */
4629 static void check_consistency(const struct partition *p, int partition) {
4630 uint pbc, pbh, pbs; /* physical beginning c, h, s */
4631 uint pec, peh, pes; /* physical ending c, h, s */
4632 uint lbc, lbh, lbs; /* logical beginning c, h, s */
4633 uint lec, leh, les; /* logical ending c, h, s */
4635 if (!heads || !sectors || (partition >= 4))
4636 return; /* do not check extended partitions */
4638 /* physical beginning c, h, s */
4639 pbc = (p->cyl & 0xff) | ((p->sector << 2) & 0x300);
4641 pbs = p->sector & 0x3f;
4643 /* physical ending c, h, s */
4644 pec = (p->end_cyl & 0xff) | ((p->end_sector << 2) & 0x300);
4646 pes = p->end_sector & 0x3f;
4648 /* compute logical beginning (c, h, s) */
4649 long2chs(get_start_sect(p), &lbc, &lbh, &lbs);
4651 /* compute logical ending (c, h, s) */
4652 long2chs(get_start_sect(p) + get_nr_sects(p) - 1, &lec, &leh, &les);
4654 /* Same physical / logical beginning? */
4655 if (cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) {
4656 printf(_("Partition %d has different physical/logical "
4657 "beginnings (non-Linux?):\n"), partition + 1);
4658 printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs);
4659 printf(_("logical=(%d, %d, %d)\n"),lbc, lbh, lbs);
4662 /* Same physical / logical ending? */
4663 if (cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) {
4664 printf(_("Partition %d has different physical/logical "
4665 "endings:\n"), partition + 1);
4666 printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
4667 printf(_("logical=(%d, %d, %d)\n"),lec, leh, les);
4671 /* Beginning on cylinder boundary? */
4672 if (pbh != !pbc || pbs != 1) {
4673 printf(_("Partition %i does not start on cylinder "
4674 "boundary:\n"), partition + 1);
4675 printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs);
4676 printf(_("should be (%d, %d, 1)\n"), pbc, !pbc);
4680 /* Ending on cylinder boundary? */
4681 if (peh != (heads - 1) || pes != sectors) {
4682 printf(_("Partition %i does not end on cylinder boundary.\n"),
4685 printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
4686 printf(_("should be (%d, %d, %d)\n"),
4687 pec, heads - 1, sectors);
4693 list_disk_geometry(void) {
4694 long long bytes = (total_number_of_sectors << 9);
4695 long megabytes = bytes/1000000;
4697 if (megabytes < 10000)
4698 printf(_("\nDisk %s: %ld MB, %lld bytes\n"),
4699 disk_device, megabytes, bytes);
4701 printf(_("\nDisk %s: %ld.%ld GB, %lld bytes\n"),
4702 disk_device, megabytes/1000, (megabytes/100)%10, bytes);
4703 printf(_("%d heads, %d sectors/track, %d cylinders"),
4704 heads, sectors, cylinders);
4705 if (units_per_sector == 1)
4706 printf(_(", total %llu sectors"),
4707 total_number_of_sectors / (sector_size/512));
4708 printf(_("\nUnits = %s of %d * %d = %d bytes\n\n"),
4710 units_per_sector, sector_size, units_per_sector * sector_size);
4714 * Check whether partition entries are ordered by their starting positions.
4715 * Return 0 if OK. Return i if partition i should have been earlier.
4716 * Two separate checks: primary and logical partitions.
4719 wrong_p_order(int *prev) {
4720 const struct pte *pe;
4721 const struct partition *p;
4722 uint last_p_start_pos = 0, p_start_pos;
4725 for (i = 0 ; i < partitions; i++) {
4728 last_p_start_pos = 0;
4731 if ((p = pe->part_table)->sys_ind) {
4732 p_start_pos = get_partition_start(pe);
4734 if (last_p_start_pos > p_start_pos) {
4740 last_p_start_pos = p_start_pos;
4747 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
4749 * Fix the chain of logicals.
4750 * extended_offset is unchanged, the set of sectors used is unchanged
4751 * The chain is sorted so that sectors increase, and so that
4752 * starting sectors increase.
4754 * After this it may still be that cfdisk doesnt like the table.
4755 * (This is because cfdisk considers expanded parts, from link to
4756 * end of partition, and these may still overlap.)
4758 * sfdisk /dev/hda > ohda; sfdisk /dev/hda < ohda
4762 fix_chain_of_logicals(void) {
4763 int j, oj, ojj, sj, sjj;
4764 struct partition *pj,*pjj,tmp;
4766 /* Stage 1: sort sectors but leave sector of part 4 */
4767 /* (Its sector is the global extended_offset.) */
4769 for (j = 5; j < partitions-1; j++) {
4770 oj = ptes[j].offset;
4771 ojj = ptes[j+1].offset;
4773 ptes[j].offset = ojj;
4774 ptes[j+1].offset = oj;
4775 pj = ptes[j].part_table;
4776 set_start_sect(pj, get_start_sect(pj)+oj-ojj);
4777 pjj = ptes[j+1].part_table;
4778 set_start_sect(pjj, get_start_sect(pjj)+ojj-oj);
4779 set_start_sect(ptes[j-1].ext_pointer,
4780 ojj-extended_offset);
4781 set_start_sect(ptes[j].ext_pointer,
4782 oj-extended_offset);
4787 /* Stage 2: sort starting sectors */
4789 for (j = 4; j < partitions-1; j++) {
4790 pj = ptes[j].part_table;
4791 pjj = ptes[j+1].part_table;
4792 sj = get_start_sect(pj);
4793 sjj = get_start_sect(pjj);
4794 oj = ptes[j].offset;
4795 ojj = ptes[j+1].offset;
4796 if (oj+sj > ojj+sjj) {
4800 set_start_sect(pj, ojj+sjj-oj);
4801 set_start_sect(pjj, oj+sj-ojj);
4806 /* Probably something was changed */
4807 for (j = 4; j < partitions; j++)
4808 ptes[j].changed = 1;
4813 fix_partition_table_order(void) {
4814 struct pte *pei, *pek;
4817 if (!wrong_p_order(NULL)) {
4818 printf(_("Nothing to do. Ordering is correct already.\n\n"));
4822 while ((i = wrong_p_order(&k)) != 0 && i < 4) {
4823 /* partition i should have come earlier, move it */
4824 /* We have to move data in the MBR */
4825 struct partition *pi, *pk, *pe, pbuf;
4829 pe = pei->ext_pointer;
4830 pei->ext_pointer = pek->ext_pointer;
4831 pek->ext_pointer = pe;
4833 pi = pei->part_table;
4834 pk = pek->part_table;
4836 memmove(&pbuf, pi, sizeof(struct partition));
4837 memmove(pi, pk, sizeof(struct partition));
4838 memmove(pk, &pbuf, sizeof(struct partition));
4840 pei->changed = pek->changed = 1;
4844 fix_chain_of_logicals();
4852 list_table(int xtra) {
4853 const struct partition *p;
4856 #ifdef CONFIG_FEATURE_SUN_LABEL
4858 sun_list_table(xtra);
4863 #ifdef CONFIG_FEATURE_SGI_LABEL
4865 sgi_list_table(xtra);
4870 list_disk_geometry();
4872 #ifdef CONFIG_FEATURE_OSF_LABEL
4874 xbsd_print_disklabel(xtra);
4879 /* Heuristic: we list partition 3 of /dev/foo as /dev/foo3,
4880 but if the device name ends in a digit, say /dev/foo1,
4881 then the partition is called /dev/foo1p3. */
4882 w = strlen(disk_device);
4883 if (w && isdigit(disk_device[w-1]))
4888 printf(_("%*s Boot Start End Blocks Id System\n"),
4891 for (i = 0; i < partitions; i++) {
4892 const struct pte *pe = &ptes[i];
4895 if (p && !is_cleared_partition(p)) {
4896 unsigned int psects = get_nr_sects(p);
4897 unsigned int pblocks = psects;
4898 unsigned int podd = 0;
4900 if (sector_size < 1024) {
4901 pblocks /= (1024 / sector_size);
4902 podd = psects % (1024 / sector_size);
4904 if (sector_size > 1024)
4905 pblocks *= (sector_size / 1024);
4907 "%s %c %11lu %11lu %11lu%c %2x %s\n",
4908 partname(disk_device, i+1, w+2),
4909 /* boot flag */ !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG
4911 /* start */ (unsigned long) cround(get_partition_start(pe)),
4912 /* end */ (unsigned long) cround(get_partition_start(pe) + psects
4913 - (psects ? 1 : 0)),
4914 /* odd flag on end */ (unsigned long) pblocks, podd ? '+' : ' ',
4915 /* type id */ p->sys_ind,
4916 /* type name */ partition_type(p->sys_ind));
4917 check_consistency(p, i);
4921 /* Is partition table in disk order? It need not be, but... */
4922 /* partition table entries are not checked for correct order if this
4923 is a sgi, sun or aix labeled disk... */
4924 if (dos_label && wrong_p_order(NULL)) {
4925 printf(_("\nPartition table entries are not in disk order\n"));
4929 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
4931 x_list_table(int extend) {
4932 const struct pte *pe;
4933 const struct partition *p;
4936 printf(_("\nDisk %s: %d heads, %d sectors, %d cylinders\n\n"),
4937 disk_device, heads, sectors, cylinders);
4938 printf(_("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n"));
4939 for (i = 0 ; i < partitions; i++) {
4941 p = (extend ? pe->ext_pointer : pe->part_table);
4943 printf("%2d %02x%4d%4d%5d%4d%4d%5d%11u%11u %02x\n",
4944 i + 1, p->boot_ind, p->head,
4946 cylinder(p->sector, p->cyl), p->end_head,
4947 sector(p->end_sector),
4948 cylinder(p->end_sector, p->end_cyl),
4949 get_start_sect(p), get_nr_sects(p), p->sys_ind);
4951 check_consistency(p, i);
4957 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4959 fill_bounds(uint *first, uint *last) {
4961 const struct pte *pe = &ptes[0];
4962 const struct partition *p;
4964 for (i = 0; i < partitions; pe++,i++) {
4966 if (!p->sys_ind || IS_EXTENDED (p->sys_ind)) {
4967 first[i] = 0xffffffff;
4970 first[i] = get_partition_start(pe);
4971 last[i] = first[i] + get_nr_sects(p) - 1;
4977 check(int n, uint h, uint s, uint c, uint start) {
4978 uint total, real_s, real_c;
4980 real_s = sector(s) - 1;
4981 real_c = cylinder(s, c);
4982 total = (real_c * sectors + real_s) * heads + h;
4984 fprintf(stderr, _("Warning: partition %d contains sector 0\n"), n);
4987 _("Partition %d: head %d greater than maximum %d\n"),
4989 if (real_s >= sectors)
4990 fprintf(stderr, _("Partition %d: sector %d greater than "
4991 "maximum %d\n"), n, s, sectors);
4992 if (real_c >= cylinders)
4993 fprintf(stderr, _("Partitions %d: cylinder %d greater than "
4994 "maximum %d\n"), n, real_c + 1, cylinders);
4995 if (cylinders <= 1024 && start != total)
4997 _("Partition %d: previous sectors %d disagrees with "
4998 "total %d\n"), n, start, total);
5005 uint first[partitions], last[partitions];
5006 struct partition *p;
5008 if (warn_geometry())
5011 #ifdef CONFIG_FEATURE_SUN_LABEL
5017 #ifdef CONFIG_FEATURE_SGI_LABEL
5024 fill_bounds(first, last);
5025 for (i = 0; i < partitions; i++) {
5026 struct pte *pe = &ptes[i];
5029 if (p->sys_ind && !IS_EXTENDED (p->sys_ind)) {
5030 check_consistency(p, i);
5031 if (get_partition_start(pe) < first[i])
5032 printf(_("Warning: bad start-of-data in "
5033 "partition %d\n"), i + 1);
5034 check(i + 1, p->end_head, p->end_sector, p->end_cyl,
5036 total += last[i] + 1 - first[i];
5037 for (j = 0; j < i; j++)
5038 if ((first[i] >= first[j] && first[i] <= last[j])
5039 || ((last[i] <= last[j] && last[i] >= first[j]))) {
5040 printf(_("Warning: partition %d overlaps "
5041 "partition %d.\n"), j + 1, i + 1);
5042 total += first[i] >= first[j] ?
5043 first[i] : first[j];
5044 total -= last[i] <= last[j] ?
5050 if (extended_offset) {
5051 struct pte *pex = &ptes[ext_index];
5052 uint e_last = get_start_sect(pex->part_table) +
5053 get_nr_sects(pex->part_table) - 1;
5055 for (i = 4; i < partitions; i++) {
5057 p = ptes[i].part_table;
5059 if (i != 4 || i + 1 < partitions)
5060 printf(_("Warning: partition %d "
5061 "is empty\n"), i + 1);
5063 else if (first[i] < extended_offset ||
5065 printf(_("Logical partition %d not entirely in "
5066 "partition %d\n"), i + 1, ext_index + 1);
5070 if (total > heads * sectors * cylinders)
5071 printf(_("Total allocated sectors %d greater than the maximum "
5072 "%d\n"), total, heads * sectors * cylinders);
5073 else if ((total = heads * sectors * cylinders - total) != 0)
5074 printf(_("%d unallocated sectors\n"), total);
5078 add_partition(int n, int sys) {
5079 char mesg[256]; /* 48 does not suffice in Japanese */
5081 struct partition *p = ptes[n].part_table;
5082 struct partition *q = ptes[ext_index].part_table;
5084 uint start, stop = 0, limit, temp,
5085 first[partitions], last[partitions];
5087 if (p && p->sys_ind) {
5088 printf(_("Partition %d is already defined. Delete "
5089 "it before re-adding it.\n"), n + 1);
5092 fill_bounds(first, last);
5094 start = sector_offset;
5095 if (display_in_cyl_units || !total_number_of_sectors)
5096 llimit = heads * sectors * cylinders - 1;
5098 llimit = total_number_of_sectors - 1;
5100 if (limit != llimit)
5102 if (extended_offset) {
5103 first[ext_index] = extended_offset;
5104 last[ext_index] = get_start_sect(q) +
5105 get_nr_sects(q) - 1;
5108 start = extended_offset + sector_offset;
5109 limit = get_start_sect(q) + get_nr_sects(q) - 1;
5111 if (display_in_cyl_units)
5112 for (i = 0; i < partitions; i++)
5113 first[i] = (cround(first[i]) - 1) * units_per_sector;
5115 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
5118 for (i = 0; i < partitions; i++) {
5121 if (start == ptes[i].offset)
5122 start += sector_offset;
5123 lastplusoff = last[i] + ((n<4) ? 0 : sector_offset);
5124 if (start >= first[i] && start <= lastplusoff)
5125 start = lastplusoff + 1;
5129 if (start >= temp+units_per_sector && readed) {
5130 printf(_("Sector %d is already allocated\n"), temp);
5134 if (!readed && start == temp) {
5137 saved_start = start;
5138 start = read_int(cround(saved_start), cround(saved_start), cround(limit),
5140 if (display_in_cyl_units) {
5141 start = (start - 1) * units_per_sector;
5142 if (start < saved_start) start = saved_start;
5146 } while (start != temp || !readed);
5147 if (n > 4) { /* NOT for fifth partition */
5148 struct pte *pe = &ptes[n];
5150 pe->offset = start - sector_offset;
5151 if (pe->offset == extended_offset) { /* must be corrected */
5153 if (sector_offset == 1)
5158 for (i = 0; i < partitions; i++) {
5159 struct pte *pe = &ptes[i];
5161 if (start < pe->offset && limit >= pe->offset)
5162 limit = pe->offset - 1;
5163 if (start < first[i] && limit >= first[i])
5164 limit = first[i] - 1;
5166 if (start > limit) {
5167 printf(_("No free sectors available\n"));
5172 if (cround(start) == cround(limit)) {
5175 snprintf(mesg, sizeof(mesg),
5176 _("Last %s or +size or +sizeM or +sizeK"),
5177 str_units(SINGULAR));
5178 stop = read_int(cround(start), cround(limit), cround(limit),
5179 cround(start), mesg);
5180 if (display_in_cyl_units) {
5181 stop = stop * units_per_sector - 1;
5187 set_partition(n, 0, start, stop, sys);
5189 set_partition(n - 1, 1, ptes[n].offset, stop, EXTENDED);
5191 if (IS_EXTENDED (sys)) {
5192 struct pte *pe4 = &ptes[4];
5193 struct pte *pen = &ptes[n];
5196 pen->ext_pointer = p;
5197 pe4->offset = extended_offset = start;
5198 pe4->sectorbuffer = xcalloc(1, sector_size);
5199 pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
5200 pe4->ext_pointer = pe4->part_table + 1;
5208 if (partitions > 5 || ptes[4].part_table->sys_ind) {
5209 struct pte *pe = &ptes[partitions];
5211 pe->sectorbuffer = xcalloc(1, sector_size);
5212 pe->part_table = pt_offset(pe->sectorbuffer, 0);
5213 pe->ext_pointer = pe->part_table + 1;
5218 add_partition(partitions - 1, LINUX_NATIVE);
5222 new_partition(void) {
5223 int i, free_primary = 0;
5225 if (warn_geometry())
5228 #ifdef CONFIG_FEATURE_SUN_LABEL
5230 add_sun_partition(get_partition(0, partitions), LINUX_NATIVE);
5234 #ifdef CONFIG_FEATURE_SGI_LABEL
5236 sgi_add_partition(get_partition(0, partitions), LINUX_NATIVE);
5240 #ifdef CONFIG_FEATURE_AIX_LABEL
5242 printf(_("\tSorry - this fdisk cannot handle AIX disk labels."
5243 "\n\tIf you want to add DOS-type partitions, create"
5244 "\n\ta new empty DOS partition table first. (Use o.)"
5246 "This will destroy the present disk contents.\n"));
5251 for (i = 0; i < 4; i++)
5252 free_primary += !ptes[i].part_table->sys_ind;
5254 if (!free_primary && partitions >= MAXIMUM_PARTS) {
5255 printf(_("The maximum number of partitions has been created\n"));
5259 if (!free_primary) {
5260 if (extended_offset)
5263 printf(_("You must delete some partition and add "
5264 "an extended partition first\n"));
5266 char c, line[LINE_LENGTH];
5267 snprintf(line, sizeof(line), "%s\n %s\n p primary "
5268 "partition (1-4)\n",
5269 "Command action", (extended_offset ?
5270 "l logical (5 or over)" : "e extended"));
5272 if ((c = read_char(line)) == 'p' || c == 'P') {
5273 i = get_nonexisting_partition(0, 4);
5275 add_partition(i, LINUX_NATIVE);
5278 else if (c == 'l' && extended_offset) {
5282 else if (c == 'e' && !extended_offset) {
5283 i = get_nonexisting_partition(0, 4);
5285 add_partition(i, EXTENDED);
5289 printf(_("Invalid partition number "
5290 "for type `%c'\n"), c);
5301 if (ptes[i].changed)
5302 ptes[3].changed = 1;
5303 for (i = 3; i < partitions; i++) {
5304 struct pte *pe = &ptes[i];
5307 write_part_table_flag(pe->sectorbuffer);
5308 write_sector(pe->offset, pe->sectorbuffer);
5312 #ifdef CONFIG_FEATURE_SGI_LABEL
5313 else if (sgi_label) {
5314 /* no test on change? the printf below might be mistaken */
5318 #ifdef CONFIG_FEATURE_SUN_LABEL
5319 else if (sun_label) {
5323 if (ptes[i].changed)
5330 printf(_("The partition table has been altered!\n\n"));
5331 reread_partition_table(1);
5335 reread_partition_table(int leave) {
5339 printf(_("Calling ioctl() to re-read partition table.\n"));
5342 if ((i = ioctl(fd, BLKRRPART)) != 0) {
5345 /* some kernel versions (1.2.x) seem to have trouble
5346 rereading the partition table, but if asked to do it
5347 twice, the second time works. - biro@yggdrasil.com */
5350 if ((i = ioctl(fd, BLKRRPART)) != 0)
5355 printf(_("\nWARNING: Re-reading the partition table "
5356 "failed with error %d: %s.\n"
5357 "The kernel still uses the old table.\n"
5358 "The new table will be used "
5359 "at the next reboot.\n"),
5360 error, strerror(error));
5365 _("\nWARNING: If you have created or modified any DOS 6.x\n"
5366 "partitions, please see the fdisk manual page for additional\n"
5372 printf(_("Syncing disks.\n"));
5374 sleep(4); /* for sync() */
5378 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
5380 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
5381 #define MAX_PER_LINE 16
5383 print_buffer(char pbuffer[]) {
5387 for (i = 0, l = 0; i < sector_size; i++, l++) {
5389 printf("0x%03X:", i);
5390 printf(" %02X", (unsigned char) pbuffer[i]);
5391 if (l == MAX_PER_LINE - 1) {
5406 printf(_("Device: %s\n"), disk_device);
5407 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
5408 if (sun_label || sgi_label)
5409 print_buffer(MBRbuffer);
5412 for (i = 3; i < partitions; i++)
5413 print_buffer(ptes[i].sectorbuffer);
5418 struct pte *pe = &ptes[i];
5419 struct partition *p = pe->part_table;
5422 if (warn_geometry())
5424 if (!p->sys_ind || !get_nr_sects(p) || IS_EXTENDED (p->sys_ind)) {
5425 printf(_("Partition %d has no data area\n"), i + 1);
5428 first = get_partition_start(pe);
5429 new = read_int(first, first, first + get_nr_sects(p) - 1, first,
5430 _("New beginning of data")) - pe->offset;
5432 if (new != get_nr_sects(p)) {
5433 first = get_nr_sects(p) + get_start_sect(p) - new;
5434 set_nr_sects(p, first);
5435 set_start_sect(p, new);
5446 c = tolower(read_char(_("Expert command (m for help): ")));
5449 #ifdef CONFIG_FEATURE_SUN_LABEL
5456 move_begin(get_partition(0, partitions));
5459 user_cylinders = cylinders =
5460 read_int(1, cylinders, 1048576, 0,
5461 _("Number of cylinders"));
5462 #ifdef CONFIG_FEATURE_SUN_LABEL
5464 sun_set_ncyl(cylinders);
5473 #ifdef CONFIG_FEATURE_SGI_LABEL
5478 #ifdef CONFIG_FEATURE_SUN_LABEL
5488 fix_partition_table_order();
5491 #ifdef CONFIG_FEATURE_SGI_LABEL
5496 user_heads = heads = read_int(1, heads, 256, 0,
5497 _("Number of heads"));
5501 #ifdef CONFIG_FEATURE_SUN_LABEL
5507 #ifdef CONFIG_FEATURE_SUN_LABEL
5513 #ifdef CONFIG_FEATURE_SUN_LABEL
5527 user_sectors = sectors = read_int(1, sectors, 63, 0,
5528 _("Number of sectors"));
5529 if (dos_compatible_flag) {
5530 sector_offset = sectors;
5531 fprintf(stderr, _("Warning: setting "
5532 "sector offset for DOS "
5541 write_table(); /* does not return */
5544 #ifdef CONFIG_FEATURE_SUN_LABEL
5546 sun_set_pcylcount();
5554 #endif /* ADVANCED mode */
5557 is_ide_cdrom_or_tape(const char *device) {
5560 struct stat statbuf;
5563 /* No device was given explicitly, and we are trying some
5564 likely things. But opening /dev/hdc may produce errors like
5565 "hdc: tray open or drive not ready"
5566 if it happens to be a CD-ROM drive. It even happens that
5567 the process hangs on the attempt to read a music CD.
5568 So try to be careful. This only works since 2.1.73. */
5570 if (strncmp("/dev/hd", device, 7))
5573 snprintf(buf, sizeof(buf), "/proc/ide/%s/media", device+5);
5574 procf = fopen(buf, "r");
5575 if (procf != NULL && fgets(buf, sizeof(buf), procf))
5576 is_ide = (!strncmp(buf, "cdrom", 5) ||
5577 !strncmp(buf, "tape", 4));
5579 /* Now when this proc file does not exist, skip the
5580 device when it is read-only. */
5581 if (stat(device, &statbuf) == 0)
5582 is_ide = ((statbuf.st_mode & 0222) == 0);
5590 try(const char *device, int user_specified) {
5593 disk_device = device;
5594 if (setjmp(listingbuf))
5596 if (!user_specified)
5597 if (is_ide_cdrom_or_tape(device))
5599 if ((fd = open(disk_device, type_open)) >= 0) {
5600 gb = get_boot(try_only);
5601 if (gb > 0) { /* I/O error */
5603 } else if (gb < 0) { /* no DOS signature */
5604 list_disk_geometry();
5607 #ifdef CONFIG_FEATURE_OSF_LABEL
5608 if (btrydev(device) < 0)
5611 _("Disk %s doesn't contain a valid "
5612 "partition table\n"), device);
5617 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5618 if (!sun_label && partitions > 4)
5619 delete_partition(ext_index);
5623 /* Ignore other errors, since we try IDE
5624 and SCSI hard disks which may not be
5625 installed on the system. */
5626 if (errno == EACCES) {
5627 fprintf(stderr, _("Cannot open %s\n"), device);
5633 /* for fdisk -l: try all things in /proc/partitions
5634 that look like a partition name (do not end in a digit) */
5638 char line[100], ptname[100], devname[120], *s;
5641 procpt = bb_wfopen(PROC_PARTITIONS, "r");
5643 while (fgets(line, sizeof(line), procpt)) {
5644 if (sscanf (line, " %d %d %d %[^\n ]",
5645 &ma, &mi, &sz, ptname) != 4)
5647 for (s = ptname; *s; s++);
5650 sprintf(devname, "/dev/%s", ptname);
5653 #ifdef CONFIG_FEATURE_CLEAN_UP
5658 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5660 unknown_command(int c) {
5661 printf(_("%c: unknown command\n"), c);
5665 int fdisk_main(int argc, char **argv) {
5667 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5670 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5676 * fdisk -l [-b sectorsize] [-u] device ...
5677 * fdisk -s [partition] ...
5678 * fdisk [-b sectorsize] [-u] device
5680 * Options -C, -H, -S set the geometry.
5683 while ((c = getopt(argc, argv, "b:C:H:lS:uvV"
5684 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5690 /* Ugly: this sector size is really per device,
5691 so cannot be combined with multiple disks,
5692 and te same goes for the C/H/S options.
5694 sector_size = atoi(optarg);
5695 if (sector_size != 512 && sector_size != 1024 &&
5696 sector_size != 2048)
5699 user_set_sector_size = 1;
5702 user_cylinders = atoi(optarg);
5705 user_heads = atoi(optarg);
5706 if (user_heads <= 0 || user_heads >= 256)
5710 user_sectors = atoi(optarg);
5711 if (user_sectors <= 0 || user_sectors >= 64)
5715 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5719 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5725 display_in_cyl_units = 0;
5729 printf("fdisk v" UTIL_LINUX_VERSION "\n");
5737 printf(_("This kernel finds the sector size itself - "
5738 "-b option ignored\n"));
5740 if (user_set_sector_size && argc-optind != 1)
5741 printf(_("Warning: the -b (set sector size) option should"
5742 " be used with one specified device\n"));
5745 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5749 type_open = O_RDONLY;
5750 if (argc > optind) {
5753 /* avoid gcc warning:
5754 variable `k' might be clobbered by `longjmp' */
5758 for (k=optind; k<argc; k++)
5761 /* we no longer have default device names */
5762 /* but, we can use /proc/partitions instead */
5766 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5770 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5776 type_open = O_RDONLY;
5778 opts = argc - optind;
5782 for (j = optind; j < argc; j++) {
5783 disk_device = argv[j];
5784 if ((fd = open(disk_device, type_open)) < 0)
5785 fdisk_fatal(unable_to_open);
5786 if (ioctl(fd, BLKGETSIZE, &size))
5787 fdisk_fatal(ioctl_error);
5790 printf("%ld\n", size/2);
5792 printf("%s: %ld\n", argv[j], size/2);
5798 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5799 if (argc-optind == 1)
5800 disk_device = argv[optind];
5806 #ifdef CONFIG_FEATURE_OSF_LABEL
5808 /* OSF label, and no DOS label */
5809 printf(_("Detected an OSF/1 disklabel on %s, entering "
5810 "disklabel mode.\n"),
5814 /* If we return we may want to make an empty DOS label? */
5820 c = tolower(read_char(_("Command (m for help): ")));
5824 toggle_active(get_partition(1, partitions));
5825 #ifdef CONFIG_FEATURE_SUN_LABEL
5827 toggle_sunflags(get_partition(1, partitions),
5830 #ifdef CONFIG_FEATURE_SGI_LABEL
5832 sgi_set_bootpartition(
5833 get_partition(1, partitions));
5839 #ifdef CONFIG_FEATURE_SGI_LABEL
5841 printf(_("\nThe current boot file is: %s\n"),
5842 sgi_get_bootfile());
5843 if (read_chars(_("Please enter the name of the "
5844 "new boot file: ")) == '\n')
5845 printf(_("Boot file unchanged\n"));
5847 sgi_set_bootfile(line_ptr);
5850 #ifdef CONFIG_FEATURE_OSF_LABEL
5856 toggle_dos_compatibility_flag();
5857 #ifdef CONFIG_FEATURE_SUN_LABEL
5859 toggle_sunflags(get_partition(1, partitions),
5862 #ifdef CONFIG_FEATURE_SGI_LABEL
5864 sgi_set_swappartition(
5865 get_partition(1, partitions));
5873 #ifdef CONFIG_FEATURE_SGI_LABEL
5874 /* If sgi_label then don't use get_existing_partition,
5875 let the user select a partition, since
5876 get_existing_partition() only works for Linux-like
5879 j = get_existing_partition(1, partitions);
5881 j = get_partition(1, partitions);
5884 j = get_existing_partition(1, partitions);
5887 delete_partition(j);
5891 #ifdef CONFIG_FEATURE_SGI_LABEL
5898 list_types(get_sys_types());
5917 #ifdef CONFIG_FEATURE_SUN_LABEL
5931 write_table(); /* does not return */
5933 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
5935 #ifdef CONFIG_FEATURE_SGI_LABEL
5938 _("\n\tSorry, no experts menu for SGI "
5939 "partition tables available.\n\n"));
5952 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */