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 */
30 #include <sys/ioctl.h>
31 #include <sys/param.h>
32 #include <sys/sysmacros.h> /* major */
34 #include <stdint.h> /* for uint32_t, uint16_t, uint8_t, int16_t, etc */
36 /* Copied from linux/major.h */
37 #define FLOPPY_MAJOR 2
39 #include <sys/utsname.h>
43 #define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r))
49 #define BLKRRPART _IO(0x12,95) /* re-read partition table */
50 #define BLKGETSIZE _IO(0x12,96) /* return device size */
51 #define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */
52 #define BLKSSZGET _IO(0x12,104) /* get block device sector size */
54 /* Avoid conflicts with the 2.6 kernel headers, which define
55 * _IOR rather differently */
57 #define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size))
58 #define BLKGETSIZE64 _IOR(0x12,114,uint64_t)
64 #define DEFAULT_SECTOR_SIZE 512
65 #define MAX_SECTOR_SIZE 2048
66 #define SECTOR_SIZE 512 /* still used in BSD code */
67 #define MAXIMUM_PARTS 60
69 #define ACTIVE_FLAG 0x80
72 #define WIN98_EXTENDED 0x0f
73 #define LINUX_PARTITION 0x81
74 #define LINUX_SWAP 0x82
75 #define LINUX_NATIVE 0x83
76 #define LINUX_EXTENDED 0x85
77 #define LINUX_LVM 0x8e
78 #define LINUX_RAID 0xfd
83 #define IS_EXTENDED(i) \
84 ((i) == EXTENDED || (i) == WIN98_EXTENDED || (i) == LINUX_EXTENDED)
86 #define SIZE(a) (sizeof(a)/sizeof((a)[0]))
88 #define cround(n) (display_in_cyl_units ? ((n)/units_per_sector)+1 : (n))
89 #define scround(x) (((x)+units_per_sector-1)/units_per_sector)
91 #ifdef CONFIG_FEATURE_SUN_LABEL
92 #define SCSI_IOCTL_GET_IDLUN 0x5382
96 #if defined(CONFIG_LFS) || defined(FDISK_SUPPORT_LARGE_DISKS) || defined(__alpha__) || defined(__ia64__) || defined(__s390x__)
97 typedef long long fdisk_loff_t;
99 typedef long fdisk_loff_t;
103 /* including <linux/hdreg.h> also fails */
106 unsigned char sectors;
107 unsigned short cylinders;
111 #define HDIO_GETGEO 0x0301 /* get device geometry */
115 const unsigned char *name;
118 static uint sector_size = DEFAULT_SECTOR_SIZE,
119 user_set_sector_size,
123 * Raw disk label. For DOS-type partition tables the MBR,
124 * with descriptions of the primary partitions.
126 static char MBRbuffer[MAX_SECTOR_SIZE];
128 #ifdef CONFIG_FEATURE_SUN_LABEL
129 static int sun_label; /* looking at sun disklabel */
133 #ifdef CONFIG_FEATURE_SGI_LABEL
134 static int sgi_label; /* looking at sgi disklabel */
138 #ifdef CONFIG_FEATURE_AIX_LABEL
139 static int aix_label; /* looking at aix disklabel */
143 #ifdef CONFIG_FEATURE_OSF_LABEL
144 static int osf_label; /* looking at OSF/1 disklabel */
145 static int possibly_osf_label;
150 #define dos_label (!sun_label && !sgi_label && !aix_label && !osf_label)
152 static uint heads, sectors, cylinders;
153 static void update_units(void);
157 * return partition name - uses static storage unless buf is supplied
160 partname(const char *dev, int pno, int lth) {
161 static char buffer[80];
168 bufsiz = sizeof(buffer);
173 if (isdigit(dev[w-1]))
176 /* devfs kludge - note: fdisk partition names are not supposed
177 to equal kernel names, so there is no reason to do this */
178 if (strcmp (dev + w - 4, "disc") == 0) {
186 snprintf(bufp, bufsiz, "%*.*s%s%-2u",
187 lth-wp-2, w, dev, p, pno);
189 snprintf(bufp, bufsiz, "%.*s%s%-2u", w, dev, p, pno);
195 unsigned char boot_ind; /* 0x80 - active */
196 unsigned char head; /* starting head */
197 unsigned char sector; /* starting sector */
198 unsigned char cyl; /* starting cylinder */
199 unsigned char sys_ind; /* What partition type */
200 unsigned char end_head; /* end head */
201 unsigned char end_sector; /* end sector */
202 unsigned char end_cyl; /* end cylinder */
203 unsigned char start4[4]; /* starting sector counting from 0 */
204 unsigned char size4[4]; /* nr of sectors in partition */
205 } __attribute__((__packed__));
208 ioctl_error, unable_to_open, unable_to_read, unable_to_seek,
212 enum action {fdisk, require, try_only, create_empty_dos, create_empty_sun};
214 static const char *disk_device;
215 static int fd; /* the disk */
216 static int partitions = 4; /* maximum partition + 1 */
217 static uint display_in_cyl_units = 1;
218 static uint units_per_sector = 1;
219 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
220 static char *line_ptr;
221 static void change_units(void);
222 static void reread_partition_table(int leave);
223 static void delete_partition(int i);
224 static int get_partition(int warn, int max);
225 static void list_types(const struct systypes *sys);
226 static uint read_int(uint low, uint dflt, uint high, uint base, char *mesg);
228 static const char *partition_type(unsigned char type);
229 static void fdisk_fatal(enum failure why) __attribute__ ((noreturn));
230 static void get_geometry(void);
231 static int get_boot(enum action what);
236 #define hex_val(c) ({ \
238 isdigit(_c) ? _c - '0' : \
239 tolower(_c) + 10 - 'a'; \
243 #define LINE_LENGTH 800
244 #define pt_offset(b, n) ((struct partition *)((b) + 0x1be + \
245 (n) * sizeof(struct partition)))
246 #define sector(s) ((s) & 0x3f)
247 #define cylinder(s, c) ((c) | (((s) & 0xc0) << 2))
249 #define hsc2sector(h,s,c) (sector(s) - 1 + sectors * \
250 ((h) + heads * cylinder(s,c)))
251 #define set_hsc(h,s,c,sector) { \
252 s = sector % sectors + 1; \
254 h = sector % heads; \
257 s |= (sector >> 2) & 0xc0; \
261 static unsigned int get_start_sect(const struct partition *p);
262 static unsigned int get_nr_sects(const struct partition *p);
265 * per partition table entry data
267 * The four primary partitions have the same sectorbuffer (MBRbuffer)
268 * and have NULL ext_pointer.
269 * Each logical partition table entry has two pointers, one for the
270 * partition and one link to the next one.
273 struct partition *part_table; /* points into sectorbuffer */
274 struct partition *ext_pointer; /* points into sectorbuffer */
275 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
276 char changed; /* boolean */
278 uint offset; /* disk sector number */
279 char *sectorbuffer; /* disk sector contents */
280 } ptes[MAXIMUM_PARTS];
283 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
285 set_all_unchanged(void) {
288 for (i = 0; i < MAXIMUM_PARTS; i++)
296 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
298 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_OSF_LABEL)
299 static struct partition *
300 get_part_table(int i) {
301 return ptes[i].part_table;
306 str_units(int n) { /* n==1: use singular */
308 return display_in_cyl_units ? _("cylinder") : _("sector");
310 return display_in_cyl_units ? _("cylinders") : _("sectors");
314 valid_part_table_flag(const unsigned char *b) {
315 return (b[510] == 0x55 && b[511] == 0xaa);
318 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
319 static char line_buffer[LINE_LENGTH];
321 /* read line; return 0 or first char */
325 static int got_eof = 0;
327 fflush (stdout); /* requested by niles@scyld.com */
328 line_ptr = line_buffer;
329 if (!fgets(line_buffer, LINE_LENGTH, stdin)) {
331 got_eof++; /* user typed ^D ? */
333 fprintf(stderr, _("\ngot EOF thrice - exiting..\n"));
338 while (*line_ptr && !isgraph(*line_ptr))
344 read_char(const char *mesg)
348 } while (!read_line());
353 read_chars(const char *mesg)
364 read_hex(const struct systypes *sys)
370 read_char(_("Hex code (type L to list codes): "));
371 if (*line_ptr == 'l' || *line_ptr == 'L')
373 else if (isxdigit (*line_ptr))
377 hex = hex << 4 | hex_val(*line_ptr++);
378 while (isxdigit(*line_ptr));
383 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
385 #ifdef CONFIG_FEATURE_AIX_LABEL
387 * Copyright (C) Andreas Neuper, Sep 1998.
388 * This file may be redistributed under
389 * the terms of the GNU Public License.
393 unsigned int magic; /* expect AIX_LABEL_MAGIC */
394 unsigned int fillbytes1[124];
395 unsigned int physical_volume_id;
396 unsigned int fillbytes2[124];
399 #define AIX_LABEL_MAGIC 0xc9c2d4c1
400 #define AIX_LABEL_MAGIC_SWAPPED 0xc1d4c2c9
401 #define AIX_INFO_MAGIC 0x00072959
402 #define AIX_INFO_MAGIC_SWAPPED 0x59290700
404 #define aixlabel ((aix_partition *)MBRbuffer)
409 * 1999-03-20 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
410 * Internationalization
412 * 2003-03-20 Phillip Kesling <pkesling@sgi.com>
416 static int aix_other_endian;
417 static short aix_volumes=1;
420 * only dealing with free blocks here
426 _("\n\tThere is a valid AIX label on this disk.\n"
427 "\tUnfortunately Linux cannot handle these\n"
428 "\tdisks at the moment. Nevertheless some\n"
430 "\t1. fdisk will destroy its contents on write.\n"
431 "\t2. Be sure that this disk is NOT a still vital\n"
432 "\t part of a volume group. (Otherwise you may\n"
433 "\t erase the other disks as well, if unmirrored.)\n"
434 "\t3. Before deleting this physical volume be sure\n"
435 "\t to remove the disk logically from your AIX\n"
436 "\t machine. (Otherwise you become an AIXpert).")
446 memset( MBRbuffer, 0, sizeof(MBRbuffer) ); /* avoid fdisk cores */
451 check_aix_label( void )
453 if (aixlabel->magic != AIX_LABEL_MAGIC &&
454 aixlabel->magic != AIX_LABEL_MAGIC_SWAPPED) {
456 aix_other_endian = 0;
459 aix_other_endian = (aixlabel->magic == AIX_LABEL_MAGIC_SWAPPED);
465 aix_nolabel(); /* %% */
466 aix_label = 1; /* %% */
469 #endif /* AIX_LABEL */
471 #ifdef CONFIG_FEATURE_OSF_LABEL
473 * Copyright (c) 1987, 1988 Regents of the University of California.
474 * All rights reserved.
476 * Redistribution and use in source and binary forms, with or without
477 * modification, are permitted provided that the following conditions
479 * 1. Redistributions of source code must retain the above copyright
480 * notice, this list of conditions and the following disclaimer.
481 * 2. Redistributions in binary form must reproduce the above copyright
482 * notice, this list of conditions and the following disclaimer in the
483 * documentation and/or other materials provided with the distribution.
484 * 3. All advertising materials mentioning features or use of this software
485 * must display the following acknowledgement:
486 * This product includes software developed by the University of
487 * California, Berkeley and its contributors.
488 * 4. Neither the name of the University nor the names of its contributors
489 * may be used to endorse or promote products derived from this software
490 * without specific prior written permission.
492 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
493 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
494 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
495 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
496 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
497 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
498 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
499 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
500 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
501 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
506 #ifndef BSD_DISKMAGIC
507 #define BSD_DISKMAGIC ((uint32_t) 0x82564557)
510 #ifndef BSD_MAXPARTITIONS
511 #define BSD_MAXPARTITIONS 16
514 #define BSD_LINUX_BOOTDIR "/usr/ucb/mdec"
516 #if defined (i386) || defined (__sparc__) || defined (__arm__) || defined (__mips__) || defined (__s390__) || defined (__sh__) || defined(__x86_64__)
517 #define BSD_LABELSECTOR 1
518 #define BSD_LABELOFFSET 0
519 #elif defined (__alpha__) || defined (__powerpc__) || defined (__ia64__) || defined (__hppa__)
520 #define BSD_LABELSECTOR 0
521 #define BSD_LABELOFFSET 64
522 #elif defined (__s390__) || defined (__s390x__)
523 #define BSD_LABELSECTOR 1
524 #define BSD_LABELOFFSET 0
526 #error unknown architecture
529 #define BSD_BBSIZE 8192 /* size of boot area, with label */
530 #define BSD_SBSIZE 8192 /* max size of fs superblock */
532 struct xbsd_disklabel {
533 uint32_t d_magic; /* the magic number */
534 int16_t d_type; /* drive type */
535 int16_t d_subtype; /* controller/d_type specific */
536 char d_typename[16]; /* type name, e.g. "eagle" */
537 char d_packname[16]; /* pack identifier */
539 uint32_t d_secsize; /* # of bytes per sector */
540 uint32_t d_nsectors; /* # of data sectors per track */
541 uint32_t d_ntracks; /* # of tracks per cylinder */
542 uint32_t d_ncylinders; /* # of data cylinders per unit */
543 uint32_t d_secpercyl; /* # of data sectors per cylinder */
544 uint32_t d_secperunit; /* # of data sectors per unit */
546 * Spares (bad sector replacements) below
547 * are not counted in d_nsectors or d_secpercyl.
548 * Spare sectors are assumed to be physical sectors
549 * which occupy space at the end of each track and/or cylinder.
551 uint16_t d_sparespertrack; /* # of spare sectors per track */
552 uint16_t d_sparespercyl; /* # of spare sectors per cylinder */
554 * Alternate cylinders include maintenance, replacement,
555 * configuration description areas, etc.
557 uint32_t d_acylinders; /* # of alt. cylinders per unit */
559 /* hardware characteristics: */
561 * d_interleave, d_trackskew and d_cylskew describe perturbations
562 * in the media format used to compensate for a slow controller.
563 * Interleave is physical sector interleave, set up by the formatter
564 * or controller when formatting. When interleaving is in use,
565 * logically adjacent sectors are not physically contiguous,
566 * but instead are separated by some number of sectors.
567 * It is specified as the ratio of physical sectors traversed
568 * per logical sector. Thus an interleave of 1:1 implies contiguous
569 * layout, while 2:1 implies that logical sector 0 is separated
570 * by one sector from logical sector 1.
571 * d_trackskew is the offset of sector 0 on track N
572 * relative to sector 0 on track N-1 on the same cylinder.
573 * Finally, d_cylskew is the offset of sector 0 on cylinder N
574 * relative to sector 0 on cylinder N-1.
576 uint16_t d_rpm; /* rotational speed */
577 uint16_t d_interleave; /* hardware sector interleave */
578 uint16_t d_trackskew; /* sector 0 skew, per track */
579 uint16_t d_cylskew; /* sector 0 skew, per cylinder */
580 uint32_t d_headswitch; /* head switch time, usec */
581 uint32_t d_trkseek; /* track-to-track seek, usec */
582 uint32_t d_flags; /* generic flags */
584 uint32_t d_drivedata[NDDATA]; /* drive-type specific information */
586 uint32_t d_spare[NSPARE]; /* reserved for future use */
587 uint32_t d_magic2; /* the magic number (again) */
588 uint16_t d_checksum; /* xor of data incl. partitions */
589 /* filesystem and partition information: */
590 uint16_t d_npartitions; /* number of partitions in following */
591 uint32_t d_bbsize; /* size of boot area at sn0, bytes */
592 uint32_t d_sbsize; /* max size of fs superblock, bytes */
593 struct xbsd_partition { /* the partition table */
594 uint32_t p_size; /* number of sectors in partition */
595 uint32_t p_offset; /* starting sector */
596 uint32_t p_fsize; /* filesystem basic fragment size */
597 uint8_t p_fstype; /* filesystem type, see below */
598 uint8_t p_frag; /* filesystem fragments per block */
599 uint16_t p_cpg; /* filesystem cylinders per group */
600 } d_partitions[BSD_MAXPARTITIONS]; /* actually may be more */
604 #define BSD_DTYPE_SMD 1 /* SMD, XSMD; VAX hp/up */
605 #define BSD_DTYPE_MSCP 2 /* MSCP */
606 #define BSD_DTYPE_DEC 3 /* other DEC (rk, rl) */
607 #define BSD_DTYPE_SCSI 4 /* SCSI */
608 #define BSD_DTYPE_ESDI 5 /* ESDI interface */
609 #define BSD_DTYPE_ST506 6 /* ST506 etc. */
610 #define BSD_DTYPE_HPIB 7 /* CS/80 on HP-IB */
611 #define BSD_DTYPE_HPFL 8 /* HP Fiber-link */
612 #define BSD_DTYPE_FLOPPY 10 /* floppy */
614 /* d_subtype values: */
615 #define BSD_DSTYPE_INDOSPART 0x8 /* is inside dos partition */
616 #define BSD_DSTYPE_DOSPART(s) ((s) & 3) /* dos partition number */
617 #define BSD_DSTYPE_GEOMETRY 0x10 /* drive params in label */
620 static const char * const xbsd_dktypenames[] = {
634 #define BSD_DKMAXTYPES (sizeof(xbsd_dktypenames) / sizeof(xbsd_dktypenames[0]) - 1)
638 * Filesystem type and version.
639 * Used to interpret other filesystem-specific
640 * per-partition information.
642 #define BSD_FS_UNUSED 0 /* unused */
643 #define BSD_FS_SWAP 1 /* swap */
644 #define BSD_FS_V6 2 /* Sixth Edition */
645 #define BSD_FS_V7 3 /* Seventh Edition */
646 #define BSD_FS_SYSV 4 /* System V */
647 #define BSD_FS_V71K 5 /* V7 with 1K blocks (4.1, 2.9) */
648 #define BSD_FS_V8 6 /* Eighth Edition, 4K blocks */
649 #define BSD_FS_BSDFFS 7 /* 4.2BSD fast file system */
650 #define BSD_FS_BSDLFS 9 /* 4.4BSD log-structured file system */
651 #define BSD_FS_OTHER 10 /* in use, but unknown/unsupported */
652 #define BSD_FS_HPFS 11 /* OS/2 high-performance file system */
653 #define BSD_FS_ISO9660 12 /* ISO-9660 filesystem (cdrom) */
654 #define BSD_FS_ISOFS BSD_FS_ISO9660
655 #define BSD_FS_BOOT 13 /* partition contains bootstrap */
656 #define BSD_FS_ADOS 14 /* AmigaDOS fast file system */
657 #define BSD_FS_HFS 15 /* Macintosh HFS */
658 #define BSD_FS_ADVFS 16 /* Digital Unix AdvFS */
660 /* this is annoying, but it's also the way it is :-( */
662 #define BSD_FS_EXT2 8 /* ext2 file system */
664 #define BSD_FS_MSDOS 8 /* MS-DOS file system */
668 static const struct systypes xbsd_fstypes[] = {
669 /* BSD_FS_UNUSED */ {"\x00" "unused"},
670 /* BSD_FS_SWAP */ {"\x01" "swap"},
671 /* BSD_FS_V6 */ {"\x02" "Version 6"},
672 /* BSD_FS_V7 */ {"\x03" "Version 7"},
673 /* BSD_FS_SYSV */ {"\x04" "System V"},
674 /* BSD_FS_V71K */ {"\x05" "4.1BSD"},
675 /* BSD_FS_V8 */ {"\x06" "Eighth Edition"},
676 /* BSD_FS_BSDFFS */ {"\x07" "4.2BSD"},
678 /* BSD_FS_EXT2 */ {"\x08" "ext2"},
680 /* BSD_FS_MSDOS */ {"\x08" "MS-DOS"},
682 /* BSD_FS_BSDLFS */ {"\x09" "4.4LFS"},
683 /* BSD_FS_OTHER */ {"\x0a" "unknown"},
684 /* BSD_FS_HPFS */ {"\x0b" "HPFS"},
685 /* BSD_FS_ISO9660 */ {"\x0c" "ISO-9660"},
686 /* BSD_FS_BOOT */ {"\x0d" "boot"},
687 /* BSD_FS_ADOS */ {"\x0e" "ADOS"},
688 /* BSD_FS_HFS */ {"\x0f" "HFS"},
689 /* BSD_FS_ADVFS */ {"\x10" "AdvFS"},
692 #define BSD_FSMAXTYPES (SIZE(xbsd_fstypes)-1)
697 * flags shared by various drives:
699 #define BSD_D_REMOVABLE 0x01 /* removable media */
700 #define BSD_D_ECC 0x02 /* supports ECC */
701 #define BSD_D_BADSECT 0x04 /* supports bad sector forw. */
702 #define BSD_D_RAMDISK 0x08 /* disk emulator */
703 #define BSD_D_CHAIN 0x10 /* can do back-back transfers */
704 #define BSD_D_DOSPART 0x20 /* within MSDOS partition */
706 #endif /* OSF_LABEL */
709 * Copyright (C) Andreas Neuper, Sep 1998.
710 * This file may be modified and redistributed under
711 * the terms of the GNU Public License.
714 struct device_parameter { /* 48 bytes */
718 unsigned char sparecyl;
719 unsigned short pcylcount;
720 unsigned short head_vol0;
721 unsigned short ntrks; /* tracks in cyl 0 or vol 0 */
722 unsigned char cmd_tag_queue_depth;
723 unsigned char unused0;
724 unsigned short unused1;
725 unsigned short nsect; /* sectors/tracks in cyl 0 or vol 0 */
726 unsigned short bytes;
727 unsigned short ilfact;
728 unsigned int flags; /* controller flags */
729 unsigned int datarate;
730 unsigned int retries_on_error;
731 unsigned int ms_per_word;
732 unsigned short xylogics_gap1;
733 unsigned short xylogics_syncdelay;
734 unsigned short xylogics_readdelay;
735 unsigned short xylogics_gap2;
736 unsigned short xylogics_readgate;
737 unsigned short xylogics_writecont;
740 #define SGI_VOLHDR 0x00
741 /* 1 and 2 were used for drive types no longer supported by SGI */
742 #define SGI_SWAP 0x03
743 /* 4 and 5 were for filesystem types SGI haven't ever supported on MIPS CPUs */
744 #define SGI_VOLUME 0x06
746 #define SGI_LVOL 0x08
747 #define SGI_RLVOL 0x09
749 #define SGI_XFSLOG 0x0b
752 #define ENTIRE_DISK SGI_VOLUME
756 #define SECTOR_SLIP 0x01
757 #define SECTOR_FWD 0x02
758 #define TRACK_FWD 0x04
759 #define TRACK_MULTIVOL 0x08
760 #define IGNORE_ERRORS 0x10
762 #define ENABLE_CMDTAGQ 0x40
765 unsigned int magic; /* expect SGI_LABEL_MAGIC */
766 unsigned short boot_part; /* active boot partition */
767 unsigned short swap_part; /* active swap partition */
768 unsigned char boot_file[16]; /* name of the bootfile */
769 struct device_parameter devparam; /* 1 * 48 bytes */
770 struct volume_directory { /* 15 * 16 bytes */
771 unsigned char vol_file_name[8]; /* a character array */
772 unsigned int vol_file_start; /* number of logical block */
773 unsigned int vol_file_size; /* number of bytes */
775 struct sgi_partition { /* 16 * 12 bytes */
776 unsigned int num_sectors; /* number of blocks */
777 unsigned int start_sector; /* must be cylinder aligned */
781 unsigned int fillbytes;
785 unsigned int magic; /* looks like a magic number */
794 unsigned char scsi_string[50];
795 unsigned char serial[137];
796 unsigned short check1816;
797 unsigned char installer[225];
800 #define SGI_LABEL_MAGIC 0x0be5a941
801 #define SGI_LABEL_MAGIC_SWAPPED 0x41a9e50b
802 #define SGI_INFO_MAGIC 0x00072959
803 #define SGI_INFO_MAGIC_SWAPPED 0x59290700
804 #define SGI_SSWAP16(x) (sgi_other_endian ? __swap16(x) \
806 #define SGI_SSWAP32(x) (sgi_other_endian ? __swap32(x) \
809 #define sgilabel ((sgi_partition *)MBRbuffer)
810 #define sgiparam (sgilabel->devparam)
813 unsigned char info[128]; /* Informative text string */
814 unsigned char spare0[14];
816 unsigned char spare1;
818 unsigned char spare2;
821 unsigned char spare1[246]; /* Boot information etc. */
822 unsigned short rspeed; /* Disk rotational speed */
823 unsigned short pcylcount; /* Physical cylinder count */
824 unsigned short sparecyl; /* extra sects per cylinder */
825 unsigned char spare2[4]; /* More magic... */
826 unsigned short ilfact; /* Interleave factor */
827 unsigned short ncyl; /* Data cylinder count */
828 unsigned short nacyl; /* Alt. cylinder count */
829 unsigned short ntrks; /* Tracks per cylinder */
830 unsigned short nsect; /* Sectors per track */
831 unsigned char spare3[4]; /* Even more magic... */
832 struct sun_partition {
833 uint32_t start_cylinder;
834 uint32_t num_sectors;
836 unsigned short magic; /* Magic number */
837 unsigned short csum; /* Label xor'd checksum */
841 #define SUN_LABEL_MAGIC 0xDABE
842 #define SUN_LABEL_MAGIC_SWAPPED 0xBEDA
843 #define sunlabel ((sun_partition *)MBRbuffer)
844 #define SUN_SSWAP16(x) (sun_other_endian ? __swap16(x) \
846 #define SUN_SSWAP32(x) (sun_other_endian ? __swap32(x) \
849 #if defined(CONFIG_LFS) || defined(FDISK_SUPPORT_LARGE_DISKS)
851 * llseek.c -- stub calling the llseek system call
853 * Copyright (C) 1994 Remy Card. This file may be redistributed
854 * under the terms of the GNU Public License.
858 #if defined(__alpha__) || defined(__ia64__) || defined(__s390x__)
860 #define my_llseek lseek
866 static fdisk_loff_t my_llseek (unsigned int f_d, fdisk_loff_t offset,
872 retval = syscall(__NR__llseek, f_d, (unsigned long)(((unsigned long long) offset) >> 32),
873 (unsigned long)(((unsigned long long) offset) & 0xffffffff),
875 return (retval == -1 ? (fdisk_loff_t) retval : result);
878 #endif /* __alpha__ */
881 static fdisk_loff_t fdisk_llseek (unsigned int f_d, fdisk_loff_t offset,
885 static int do_compat = 0;
888 result = my_llseek (f_d, offset, origin);
889 if (!(result == -1 && errno == ENOSYS))
893 * Just in case this code runs on top of an old kernel
894 * which does not support the llseek system call
898 * Now try ordinary lseek.
902 if ((sizeof(off_t) >= sizeof(fdisk_loff_t)) ||
903 (offset < ((fdisk_loff_t) 1 << ((sizeof(off_t)*8) -1))))
904 return lseek(f_d, (off_t) offset, origin);
910 # define fdisk_llseek lseek
911 #endif /* FDISK_SUPPORT_LARGE_DISKS */
915 #ifdef CONFIG_FEATURE_OSF_LABEL
918 19990319 - Arnaldo Carvalho de Melo <acme@conectiva.com.br> - i18n/nls
920 20000101 - David Huggins-Daines <dhuggins@linuxcare.com> - Better
921 support for OSF/1 disklabels on Alpha.
922 Also fixed unaligned accesses in alpha_bootblock_checksum()
925 #define FREEBSD_PARTITION 0xa5
926 #define NETBSD_PARTITION 0xa9
928 static void xbsd_delete_part (void);
929 static void xbsd_new_part (void);
930 static void xbsd_write_disklabel (void);
931 static int xbsd_create_disklabel (void);
932 static void xbsd_edit_disklabel (void);
933 static void xbsd_write_bootstrap (void);
934 static void xbsd_change_fstype (void);
935 static int xbsd_get_part_index (int max);
936 static int xbsd_check_new_partition (int *i);
937 static void xbsd_list_types (void);
938 static u_short xbsd_dkcksum (struct xbsd_disklabel *lp);
939 static int xbsd_initlabel (struct partition *p, struct xbsd_disklabel *d,
941 static int xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d);
942 static int xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d);
944 #if defined (__alpha__)
945 static void alpha_bootblock_checksum (char *boot);
948 #if !defined (__alpha__)
949 static int xbsd_translate_fstype (int linux_type);
950 static void xbsd_link_part (void);
951 static struct partition *xbsd_part;
952 static int xbsd_part_index;
955 #if defined (__alpha__)
956 /* We access this through a uint64_t * when checksumming */
957 static char disklabelbuffer[BSD_BBSIZE] __attribute__((aligned(8)));
959 static char disklabelbuffer[BSD_BBSIZE];
962 static struct xbsd_disklabel xbsd_dlabel;
964 #define bsd_cround(n) \
965 (display_in_cyl_units ? ((n)/xbsd_dlabel.d_secpercyl) + 1 : (n))
968 * Test whether the whole disk has BSD disk label magic.
970 * Note: often reformatting with DOS-type label leaves the BSD magic,
971 * so this does not mean that there is a BSD disk label.
974 check_osf_label(void) {
975 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
980 static void xbsd_print_disklabel(int);
983 btrydev (const char * dev) {
984 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
986 printf(_("\nBSD label for device: %s\n"), dev);
987 xbsd_print_disklabel (0);
993 puts (_("Command action"));
994 puts (_("\td\tdelete a BSD partition"));
995 puts (_("\te\tedit drive data"));
996 puts (_("\ti\tinstall bootstrap"));
997 puts (_("\tl\tlist known filesystem types"));
998 puts (_("\tm\tprint this menu"));
999 puts (_("\tn\tadd a new BSD partition"));
1000 puts (_("\tp\tprint BSD partition table"));
1001 puts (_("\tq\tquit without saving changes"));
1002 puts (_("\tr\treturn to main menu"));
1003 puts (_("\ts\tshow complete disklabel"));
1004 puts (_("\tt\tchange a partition's filesystem id"));
1005 puts (_("\tu\tchange units (cylinders/sectors)"));
1006 puts (_("\tw\twrite disklabel to disk"));
1007 #if !defined (__alpha__)
1008 puts (_("\tx\tlink BSD partition to non-BSD partition"));
1012 #if !defined (__alpha__)
1019 is_bsd_partition_type(int type) {
1020 return (type == FREEBSD_PARTITION ||
1021 type == hidden(FREEBSD_PARTITION) ||
1022 type == NETBSD_PARTITION ||
1023 type == hidden(NETBSD_PARTITION));
1029 #if !defined (__alpha__)
1031 struct partition *p;
1033 for (t=0; t<4; t++) {
1034 p = get_part_table(t);
1035 if (p && is_bsd_partition_type(p->sys_ind)) {
1037 xbsd_part_index = t;
1038 ss = get_start_sect(xbsd_part);
1040 fprintf (stderr, _("Partition %s has invalid starting sector 0.\n"),
1041 partname(disk_device, t+1, 0));
1044 printf (_("Reading disklabel of %s at sector %d.\n"),
1045 partname(disk_device, t+1, 0), ss + BSD_LABELSECTOR);
1046 if (xbsd_readlabel (xbsd_part, &xbsd_dlabel) == 0)
1047 if (xbsd_create_disklabel () == 0)
1054 printf (_("There is no *BSD partition on %s.\n"), disk_device);
1058 #elif defined (__alpha__)
1060 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
1061 if (xbsd_create_disklabel () == 0)
1062 exit ( EXIT_SUCCESS );
1068 switch (tolower (read_char (_("BSD disklabel command (m for help): ")))) {
1070 xbsd_delete_part ();
1073 xbsd_edit_disklabel ();
1076 xbsd_write_bootstrap ();
1085 xbsd_print_disklabel (0);
1089 exit ( EXIT_SUCCESS );
1093 xbsd_print_disklabel (1);
1096 xbsd_change_fstype ();
1102 xbsd_write_disklabel ();
1104 #if !defined (__alpha__)
1117 xbsd_delete_part (void)
1121 i = xbsd_get_part_index (xbsd_dlabel.d_npartitions);
1122 xbsd_dlabel.d_partitions[i].p_size = 0;
1123 xbsd_dlabel.d_partitions[i].p_offset = 0;
1124 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
1125 if (xbsd_dlabel.d_npartitions == i + 1)
1126 while (xbsd_dlabel.d_partitions[xbsd_dlabel.d_npartitions-1].p_size == 0)
1127 xbsd_dlabel.d_npartitions--;
1131 xbsd_new_part (void)
1137 if (!xbsd_check_new_partition (&i))
1140 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
1141 begin = get_start_sect(xbsd_part);
1142 end = begin + get_nr_sects(xbsd_part) - 1;
1145 end = xbsd_dlabel.d_secperunit - 1;
1148 snprintf (mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
1149 begin = read_int (bsd_cround (begin), bsd_cround (begin), bsd_cround (end),
1152 if (display_in_cyl_units)
1153 begin = (begin - 1) * xbsd_dlabel.d_secpercyl;
1155 snprintf (mesg, sizeof(mesg), _("Last %s or +size or +sizeM or +sizeK"),
1156 str_units(SINGULAR));
1157 end = read_int (bsd_cround (begin), bsd_cround (end), bsd_cround (end),
1158 bsd_cround (begin), mesg);
1160 if (display_in_cyl_units)
1161 end = end * xbsd_dlabel.d_secpercyl - 1;
1163 xbsd_dlabel.d_partitions[i].p_size = end - begin + 1;
1164 xbsd_dlabel.d_partitions[i].p_offset = begin;
1165 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
1169 xbsd_print_disklabel (int show_all) {
1170 struct xbsd_disklabel *lp = &xbsd_dlabel;
1171 struct xbsd_partition *pp;
1175 #if defined (__alpha__)
1176 printf("# %s:\n", disk_device);
1178 printf("# %s:\n", partname(disk_device, xbsd_part_index+1, 0));
1180 if ((unsigned) lp->d_type < BSD_DKMAXTYPES)
1181 printf(_("type: %s\n"), xbsd_dktypenames[lp->d_type]);
1183 printf(_("type: %d\n"), lp->d_type);
1184 printf(_("disk: %.*s\n"), (int) sizeof(lp->d_typename), lp->d_typename);
1185 printf(_("label: %.*s\n"), (int) sizeof(lp->d_packname), lp->d_packname);
1186 printf(_("flags:"));
1187 if (lp->d_flags & BSD_D_REMOVABLE)
1188 printf(_(" removable"));
1189 if (lp->d_flags & BSD_D_ECC)
1191 if (lp->d_flags & BSD_D_BADSECT)
1192 printf(_(" badsect"));
1194 /* On various machines the fields of *lp are short/int/long */
1195 /* In order to avoid problems, we cast them all to long. */
1196 printf(_("bytes/sector: %ld\n"), (long) lp->d_secsize);
1197 printf(_("sectors/track: %ld\n"), (long) lp->d_nsectors);
1198 printf(_("tracks/cylinder: %ld\n"), (long) lp->d_ntracks);
1199 printf(_("sectors/cylinder: %ld\n"), (long) lp->d_secpercyl);
1200 printf(_("cylinders: %ld\n"), (long) lp->d_ncylinders);
1201 printf(_("rpm: %d\n"), lp->d_rpm);
1202 printf(_("interleave: %d\n"), lp->d_interleave);
1203 printf(_("trackskew: %d\n"), lp->d_trackskew);
1204 printf(_("cylinderskew: %d\n"), lp->d_cylskew);
1205 printf(_("headswitch: %ld\t\t# milliseconds\n"),
1206 (long) lp->d_headswitch);
1207 printf(_("track-to-track seek: %ld\t# milliseconds\n"),
1208 (long) lp->d_trkseek);
1209 printf(_("drivedata: "));
1210 for (i = NDDATA - 1; i >= 0; i--)
1211 if (lp->d_drivedata[i])
1215 for (j = 0; j <= i; j++)
1216 printf("%ld ", (long) lp->d_drivedata[j]);
1218 printf(_("\n%d partitions:\n"), lp->d_npartitions);
1219 printf(_("# start end size fstype [fsize bsize cpg]\n"));
1220 pp = lp->d_partitions;
1221 for (i = 0; i < lp->d_npartitions; i++, pp++) {
1223 if (display_in_cyl_units && lp->d_secpercyl) {
1224 printf(" %c: %8ld%c %8ld%c %8ld%c ",
1226 (long) pp->p_offset / lp->d_secpercyl + 1,
1227 (pp->p_offset % lp->d_secpercyl) ? '*' : ' ',
1228 (long) (pp->p_offset + pp->p_size + lp->d_secpercyl - 1)
1230 ((pp->p_offset + pp->p_size) % lp->d_secpercyl) ? '*' : ' ',
1231 (long) pp->p_size / lp->d_secpercyl,
1232 (pp->p_size % lp->d_secpercyl) ? '*' : ' ');
1234 printf(" %c: %8ld %8ld %8ld ",
1236 (long) pp->p_offset,
1237 (long) pp->p_offset + pp->p_size - 1,
1240 if ((unsigned) pp->p_fstype < BSD_FSMAXTYPES)
1241 printf("%8.8s", xbsd_fstypes[pp->p_fstype].name);
1243 printf("%8x", pp->p_fstype);
1244 switch (pp->p_fstype) {
1246 printf(" %5ld %5ld %5.5s ",
1247 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, "");
1251 printf(" %5ld %5ld %5d ",
1252 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag,
1257 printf("%22.22s", "");
1266 xbsd_write_disklabel (void) {
1267 #if defined (__alpha__)
1268 printf (_("Writing disklabel to %s.\n"), disk_device);
1269 xbsd_writelabel (NULL, &xbsd_dlabel);
1271 printf (_("Writing disklabel to %s.\n"),
1272 partname(disk_device, xbsd_part_index+1, 0));
1273 xbsd_writelabel (xbsd_part, &xbsd_dlabel);
1275 reread_partition_table(0); /* no exit yet */
1279 xbsd_create_disklabel (void) {
1282 #if defined (__alpha__)
1283 fprintf (stderr, _("%s contains no disklabel.\n"), disk_device);
1285 fprintf (stderr, _("%s contains no disklabel.\n"),
1286 partname(disk_device, xbsd_part_index+1, 0));
1290 c = read_char (_("Do you want to create a disklabel? (y/n) "));
1291 if (c == 'y' || c == 'Y') {
1292 if (xbsd_initlabel (
1293 #if defined (__alpha__) || defined (__powerpc__) || defined (__hppa__) || \
1294 defined (__s390__) || defined (__s390x__)
1295 NULL, &xbsd_dlabel, 0
1297 xbsd_part, &xbsd_dlabel, xbsd_part_index
1300 xbsd_print_disklabel (1);
1304 } else if (c == 'n')
1310 edit_int (int def, char *mesg)
1313 fputs (mesg, stdout);
1314 printf (" (%d): ", def);
1318 while (!isdigit (*line_ptr));
1319 return atoi (line_ptr);
1323 xbsd_edit_disklabel (void)
1325 struct xbsd_disklabel *d;
1329 #if defined (__alpha__) || defined (__ia64__)
1330 d -> d_secsize = (u_long) edit_int ((u_long) d -> d_secsize ,_("bytes/sector"));
1331 d -> d_nsectors = (u_long) edit_int ((u_long) d -> d_nsectors ,_("sectors/track"));
1332 d -> d_ntracks = (u_long) edit_int ((u_long) d -> d_ntracks ,_("tracks/cylinder"));
1333 d -> d_ncylinders = (u_long) edit_int ((u_long) d -> d_ncylinders ,_("cylinders"));
1336 /* d -> d_secpercyl can be != d -> d_nsectors * d -> d_ntracks */
1339 d -> d_secpercyl = (u_long) edit_int ((u_long) d -> d_nsectors * d -> d_ntracks,
1340 _("sectors/cylinder"));
1341 if (d -> d_secpercyl <= d -> d_nsectors * d -> d_ntracks)
1344 printf (_("Must be <= sectors/track * tracks/cylinder (default).\n"));
1346 d -> d_rpm = (u_short) edit_int ((u_short) d -> d_rpm ,_("rpm"));
1347 d -> d_interleave = (u_short) edit_int ((u_short) d -> d_interleave,_("interleave"));
1348 d -> d_trackskew = (u_short) edit_int ((u_short) d -> d_trackskew ,_("trackskew"));
1349 d -> d_cylskew = (u_short) edit_int ((u_short) d -> d_cylskew ,_("cylinderskew"));
1350 d -> d_headswitch = (u_long) edit_int ((u_long) d -> d_headswitch ,_("headswitch"));
1351 d -> d_trkseek = (u_long) edit_int ((u_long) d -> d_trkseek ,_("track-to-track seek"));
1353 d -> d_secperunit = d -> d_secpercyl * d -> d_ncylinders;
1357 xbsd_get_bootstrap (char *path, void *ptr, int size)
1361 if ((fdb = open (path, O_RDONLY)) < 0)
1366 if (read (fdb, ptr, size) < 0)
1372 printf (" ... %s\n", path);
1380 printf (_("\nSyncing disks.\n"));
1386 xbsd_write_bootstrap (void)
1388 char *bootdir = BSD_LINUX_BOOTDIR;
1389 char path[MAXPATHLEN];
1391 struct xbsd_disklabel dl;
1395 if (xbsd_dlabel.d_type == BSD_DTYPE_SCSI)
1400 printf (_("Bootstrap: %sboot -> boot%s (%s): "),
1401 dkbasename, dkbasename, dkbasename);
1403 line_ptr[strlen (line_ptr)-1] = '\0';
1404 dkbasename = line_ptr;
1406 snprintf (path, sizeof(path), "%s/%sboot", bootdir, dkbasename);
1407 if (!xbsd_get_bootstrap (path, disklabelbuffer, (int) xbsd_dlabel.d_secsize))
1410 /* We need a backup of the disklabel (xbsd_dlabel might have changed). */
1411 d = &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE];
1412 bcopy (d, &dl, sizeof (struct xbsd_disklabel));
1414 /* The disklabel will be overwritten by 0's from bootxx anyway */
1415 bzero (d, sizeof (struct xbsd_disklabel));
1417 snprintf (path, sizeof(path), "%s/boot%s", bootdir, dkbasename);
1418 if (!xbsd_get_bootstrap (path, &disklabelbuffer[xbsd_dlabel.d_secsize],
1419 (int) xbsd_dlabel.d_bbsize - xbsd_dlabel.d_secsize))
1422 e = d + sizeof (struct xbsd_disklabel);
1423 for (p=d; p < e; p++)
1425 fprintf (stderr, _("Bootstrap overlaps with disk label!\n"));
1426 exit ( EXIT_FAILURE );
1429 bcopy (&dl, d, sizeof (struct xbsd_disklabel));
1431 #if defined (__powerpc__) || defined (__hppa__)
1433 #elif defined (__alpha__)
1435 alpha_bootblock_checksum (disklabelbuffer);
1437 sector = get_start_sect(xbsd_part);
1440 if (fdisk_llseek (fd, (fdisk_loff_t) sector * SECTOR_SIZE, SEEK_SET) == -1)
1441 fdisk_fatal (unable_to_seek);
1442 if (BSD_BBSIZE != write (fd, disklabelbuffer, BSD_BBSIZE))
1443 fdisk_fatal (unable_to_write);
1445 #if defined (__alpha__)
1446 printf (_("Bootstrap installed on %s.\n"), disk_device);
1448 printf (_("Bootstrap installed on %s.\n"),
1449 partname (disk_device, xbsd_part_index+1, 0));
1456 xbsd_change_fstype (void)
1460 i = xbsd_get_part_index (xbsd_dlabel.d_npartitions);
1461 xbsd_dlabel.d_partitions[i].p_fstype = read_hex (xbsd_fstypes);
1465 xbsd_get_part_index (int max)
1470 snprintf (prompt, sizeof(prompt), _("Partition (a-%c): "), 'a' + max - 1);
1472 l = tolower (read_char (prompt));
1473 while (l < 'a' || l > 'a' + max - 1);
1478 xbsd_check_new_partition (int *i) {
1480 /* room for more? various BSD flavours have different maxima */
1481 if (xbsd_dlabel.d_npartitions == BSD_MAXPARTITIONS) {
1484 for (t = 0; t < BSD_MAXPARTITIONS; t++)
1485 if (xbsd_dlabel.d_partitions[t].p_size == 0)
1488 if (t == BSD_MAXPARTITIONS) {
1489 fprintf (stderr, _("The maximum number of partitions "
1490 "has been created\n"));
1495 *i = xbsd_get_part_index (BSD_MAXPARTITIONS);
1497 if (*i >= xbsd_dlabel.d_npartitions)
1498 xbsd_dlabel.d_npartitions = (*i) + 1;
1500 if (xbsd_dlabel.d_partitions[*i].p_size != 0) {
1501 fprintf (stderr, _("This partition already exists.\n"));
1509 xbsd_list_types (void) {
1510 list_types (xbsd_fstypes);
1514 xbsd_dkcksum (struct xbsd_disklabel *lp) {
1515 u_short *start, *end;
1518 start = (u_short *) lp;
1519 end = (u_short *) &lp->d_partitions[lp->d_npartitions];
1526 xbsd_initlabel (struct partition *p, struct xbsd_disklabel *d, int pindex) {
1527 struct xbsd_partition *pp;
1530 bzero (d, sizeof (struct xbsd_disklabel));
1532 d -> d_magic = BSD_DISKMAGIC;
1534 if (strncmp (disk_device, "/dev/sd", 7) == 0)
1535 d -> d_type = BSD_DTYPE_SCSI;
1537 d -> d_type = BSD_DTYPE_ST506;
1539 #if 0 /* not used (at least not written to disk) by NetBSD/i386 1.0 */
1540 d -> d_subtype = BSD_DSTYPE_INDOSPART & pindex;
1543 #if !defined (__alpha__)
1544 d -> d_flags = BSD_D_DOSPART;
1548 d -> d_secsize = SECTOR_SIZE; /* bytes/sector */
1549 d -> d_nsectors = sectors; /* sectors/track */
1550 d -> d_ntracks = heads; /* tracks/cylinder (heads) */
1551 d -> d_ncylinders = cylinders;
1552 d -> d_secpercyl = sectors * heads;/* sectors/cylinder */
1553 if (d -> d_secpercyl == 0)
1554 d -> d_secpercyl = 1; /* avoid segfaults */
1555 d -> d_secperunit = d -> d_secpercyl * d -> d_ncylinders;
1558 d -> d_interleave = 1;
1559 d -> d_trackskew = 0;
1561 d -> d_headswitch = 0;
1564 d -> d_magic2 = BSD_DISKMAGIC;
1565 d -> d_bbsize = BSD_BBSIZE;
1566 d -> d_sbsize = BSD_SBSIZE;
1568 #if !defined (__alpha__)
1569 d -> d_npartitions = 4;
1570 pp = &d -> d_partitions[2]; /* Partition C should be
1571 the NetBSD partition */
1572 pp -> p_offset = get_start_sect(p);
1573 pp -> p_size = get_nr_sects(p);
1574 pp -> p_fstype = BSD_FS_UNUSED;
1575 pp = &d -> d_partitions[3]; /* Partition D should be
1578 pp -> p_size = d -> d_secperunit;
1579 pp -> p_fstype = BSD_FS_UNUSED;
1580 #elif defined (__alpha__)
1581 d -> d_npartitions = 3;
1582 pp = &d -> d_partitions[2]; /* Partition C should be
1585 pp -> p_size = d -> d_secperunit;
1586 pp -> p_fstype = BSD_FS_UNUSED;
1593 * Read a xbsd_disklabel from sector 0 or from the starting sector of p.
1594 * If it has the right magic, return 1.
1597 xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d)
1601 /* p is used only to get the starting sector */
1602 #if !defined (__alpha__)
1603 sector = (p ? get_start_sect(p) : 0);
1604 #elif defined (__alpha__)
1608 if (fdisk_llseek (fd, (fdisk_loff_t) sector * SECTOR_SIZE, SEEK_SET) == -1)
1609 fdisk_fatal (unable_to_seek);
1610 if (BSD_BBSIZE != read (fd, disklabelbuffer, BSD_BBSIZE))
1611 fdisk_fatal (unable_to_read);
1613 bcopy (&disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
1614 d, sizeof (struct xbsd_disklabel));
1616 if (d -> d_magic != BSD_DISKMAGIC || d -> d_magic2 != BSD_DISKMAGIC)
1619 for (t = d -> d_npartitions; t < BSD_MAXPARTITIONS; t++) {
1620 d -> d_partitions[t].p_size = 0;
1621 d -> d_partitions[t].p_offset = 0;
1622 d -> d_partitions[t].p_fstype = BSD_FS_UNUSED;
1625 if (d -> d_npartitions > BSD_MAXPARTITIONS)
1626 fprintf (stderr, _("Warning: too many partitions "
1627 "(%d, maximum is %d).\n"),
1628 d -> d_npartitions, BSD_MAXPARTITIONS);
1633 xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d)
1635 unsigned int sector;
1637 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
1638 sector = get_start_sect(p) + BSD_LABELSECTOR;
1640 sector = BSD_LABELSECTOR;
1643 d -> d_checksum = 0;
1644 d -> d_checksum = xbsd_dkcksum (d);
1646 /* This is necessary if we want to write the bootstrap later,
1647 otherwise we'd write the old disklabel with the bootstrap.
1649 bcopy (d, &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
1650 sizeof (struct xbsd_disklabel));
1652 #if defined (__alpha__) && BSD_LABELSECTOR == 0
1653 alpha_bootblock_checksum (disklabelbuffer);
1654 if (fdisk_llseek (fd, (fdisk_loff_t) 0, SEEK_SET) == -1)
1655 fdisk_fatal (unable_to_seek);
1656 if (BSD_BBSIZE != write (fd, disklabelbuffer, BSD_BBSIZE))
1657 fdisk_fatal (unable_to_write);
1659 if (fdisk_llseek (fd, (fdisk_loff_t) sector * SECTOR_SIZE + BSD_LABELOFFSET,
1661 fdisk_fatal (unable_to_seek);
1662 if (sizeof (struct xbsd_disklabel) != write (fd, d, sizeof (struct xbsd_disklabel)))
1663 fdisk_fatal (unable_to_write);
1672 #if !defined (__alpha__)
1674 xbsd_translate_fstype (int linux_type)
1678 case 0x01: /* DOS 12-bit FAT */
1679 case 0x04: /* DOS 16-bit <32M */
1680 case 0x06: /* DOS 16-bit >=32M */
1681 case 0xe1: /* DOS access */
1682 case 0xe3: /* DOS R/O */
1683 case 0xf2: /* DOS secondary */
1684 return BSD_FS_MSDOS;
1685 case 0x07: /* OS/2 HPFS */
1688 return BSD_FS_OTHER;
1693 xbsd_link_part (void)
1696 struct partition *p;
1698 k = get_partition (1, partitions);
1700 if (!xbsd_check_new_partition (&i))
1703 p = get_part_table(k);
1705 xbsd_dlabel.d_partitions[i].p_size = get_nr_sects(p);
1706 xbsd_dlabel.d_partitions[i].p_offset = get_start_sect(p);
1707 xbsd_dlabel.d_partitions[i].p_fstype = xbsd_translate_fstype(p->sys_ind);
1711 #if defined (__alpha__)
1713 #if !defined(__GLIBC__)
1714 typedef unsigned long long uint64_t;
1718 alpha_bootblock_checksum (char *boot)
1723 dp = (uint64_t *)boot;
1725 for (i = 0; i < 63; i++)
1729 #endif /* __alpha__ */
1731 #endif /* OSF_LABEL */
1733 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
1734 static inline unsigned short
1735 __swap16(unsigned short x) {
1736 return (((uint16_t)(x) & 0xFF) << 8) | (((uint16_t)(x) & 0xFF00) >> 8);
1739 static inline uint32_t
1740 __swap32(uint32_t x) {
1741 return (((x & 0xFF) << 24) |
1742 ((x & 0xFF00) << 8) |
1743 ((x & 0xFF0000) >> 8) |
1744 ((x & 0xFF000000) >> 24));
1748 #ifdef CONFIG_FEATURE_SGI_LABEL
1753 * Copyright (C) Andreas Neuper, Sep 1998.
1754 * This file may be modified and redistributed under
1755 * the terms of the GNU Public License.
1757 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
1758 * Internationalization
1762 static int sgi_other_endian;
1764 static short sgi_volumes=1;
1767 * only dealing with free blocks here
1770 typedef struct { unsigned int first; unsigned int last; } freeblocks;
1771 static freeblocks freelist[17]; /* 16 partitions can produce 17 vacant slots */
1774 setfreelist(int i, unsigned int f, unsigned int l) {
1775 freelist[i].first = f;
1776 freelist[i].last = l;
1780 add2freelist(unsigned int f, unsigned int l) {
1782 for ( ; i < 17 ; i++)
1783 if (freelist[i].last == 0)
1785 setfreelist(i, f, l);
1789 clearfreelist(void) {
1792 for (i = 0; i < 17 ; i++)
1793 setfreelist(i, 0, 0);
1797 isinfreelist(unsigned int b) {
1800 for (i = 0; i < 17 ; i++)
1801 if (freelist[i].first <= b && freelist[i].last >= b)
1802 return freelist[i].last;
1805 /* return last vacant block of this stride (never 0). */
1806 /* the '>=' is not quite correct, but simplifies the code */
1808 * end of free blocks section
1811 static const struct systypes sgi_sys_types[] = {
1812 /* SGI_VOLHDR */ {"\x00" "SGI volhdr" },
1813 /* 0x01 */ {"\x01" "SGI trkrepl" },
1814 /* 0x02 */ {"\x02" "SGI secrepl" },
1815 /* SGI_SWAP */ {"\x03" "SGI raw" },
1816 /* 0x04 */ {"\x04" "SGI bsd" },
1817 /* 0x05 */ {"\x05" "SGI sysv" },
1818 /* ENTIRE_DISK */ {"\x06" "SGI volume" },
1819 /* SGI_EFS */ {"\x07" "SGI efs" },
1820 /* 0x08 */ {"\x08" "SGI lvol" },
1821 /* 0x09 */ {"\x09" "SGI rlvol" },
1822 /* SGI_XFS */ {"\x0a" "SGI xfs" },
1823 /* SGI_XFSLOG */ {"\x0b" "SGI xfslog" },
1824 /* SGI_XLV */ {"\x0c" "SGI xlv" },
1825 /* SGI_XVM */ {"\x0d" "SGI xvm" },
1826 /* LINUX_SWAP */ {"\x82" "Linux swap" },
1827 /* LINUX_NATIVE */ {"\x83" "Linux native" },
1828 /* LINUX_LVM */ {"\x8d" "Linux LVM" },
1829 /* LINUX_RAID */ {"\xfd" "Linux RAID" },
1835 sgi_get_nsect(void) {
1836 return SGI_SSWAP16(sgilabel->devparam.nsect);
1840 sgi_get_ntrks(void) {
1841 return SGI_SSWAP16(sgilabel->devparam.ntrks);
1846 sgilabel->magic = 0;
1852 two_s_complement_32bit_sum(unsigned int* base, int size /* in bytes */) {
1856 size /= sizeof(unsigned int);
1857 for (i = 0; i < size; i++)
1858 sum -= SGI_SSWAP32(base[i]);
1863 check_sgi_label(void) {
1864 if (sizeof(sgilabel) > 512) {
1866 _("According to MIPS Computer Systems, Inc the "
1867 "Label must not contain more than 512 bytes\n"));
1871 if (sgilabel->magic != SGI_LABEL_MAGIC &&
1872 sgilabel->magic != SGI_LABEL_MAGIC_SWAPPED) {
1874 sgi_other_endian = 0;
1878 sgi_other_endian = (sgilabel->magic == SGI_LABEL_MAGIC_SWAPPED);
1880 * test for correct checksum
1882 if (two_s_complement_32bit_sum((unsigned int*)sgilabel,
1883 sizeof(*sgilabel))) {
1885 _("Detected sgi disklabel with wrong checksum.\n"));
1895 sgi_get_start_sector(int i) {
1896 return SGI_SSWAP32(sgilabel->partitions[i].start_sector);
1900 sgi_get_num_sectors(int i) {
1901 return SGI_SSWAP32(sgilabel->partitions[i].num_sectors);
1905 sgi_get_sysid(int i)
1907 return SGI_SSWAP32(sgilabel->partitions[i].id);
1911 sgi_get_bootpartition(void)
1913 return SGI_SSWAP16(sgilabel->boot_part);
1917 sgi_get_swappartition(void)
1919 return SGI_SSWAP16(sgilabel->swap_part);
1923 sgi_list_table(int xtra) {
1925 int kpi = 0; /* kernel partition ID */
1928 printf(_("\nDisk %s (SGI disk label): %d heads, %d sectors\n"
1929 "%d cylinders, %d physical cylinders\n"
1930 "%d extra sects/cyl, interleave %d:1\n"
1932 "Units = %s of %d * 512 bytes\n\n"),
1933 disk_device, heads, sectors, cylinders,
1934 SGI_SSWAP16(sgiparam.pcylcount),
1935 SGI_SSWAP16(sgiparam.sparecyl),
1936 SGI_SSWAP16(sgiparam.ilfact),
1938 str_units(PLURAL), units_per_sector);
1940 printf( _("\nDisk %s (SGI disk label): "
1941 "%d heads, %d sectors, %d cylinders\n"
1942 "Units = %s of %d * 512 bytes\n\n"),
1943 disk_device, heads, sectors, cylinders,
1944 str_units(PLURAL), units_per_sector );
1947 w = strlen(disk_device);
1948 wd = strlen(_("Device"));
1952 printf(_("----- partitions -----\n"
1953 "Pt# %*s Info Start End Sectors Id System\n"),
1954 w + 2, _("Device"));
1955 for (i = 0 ; i < partitions; i++) {
1956 if( sgi_get_num_sectors(i) || debug ) {
1957 uint32_t start = sgi_get_start_sector(i);
1958 uint32_t len = sgi_get_num_sectors(i);
1959 kpi++; /* only count nonempty partitions */
1961 "%2d: %s %4s %9ld %9ld %9ld %2x %s\n",
1962 /* fdisk part number */ i+1,
1963 /* device */ partname(disk_device, kpi, w+3),
1964 /* flags */ (sgi_get_swappartition() == i) ? "swap" :
1965 /* flags */ (sgi_get_bootpartition() == i) ? "boot" : " ",
1966 /* start */ (long) scround(start),
1967 /* end */ (long) scround(start+len)-1,
1968 /* no odd flag on end */ (long) len,
1969 /* type id */ sgi_get_sysid(i),
1970 /* type name */ partition_type(sgi_get_sysid(i)));
1973 printf(_("----- Bootinfo -----\nBootfile: %s\n"
1974 "----- Directory Entries -----\n"),
1975 sgilabel->boot_file);
1976 for (i = 0 ; i < sgi_volumes; i++) {
1977 if (sgilabel->directory[i].vol_file_size) {
1978 uint32_t start = SGI_SSWAP32(sgilabel->directory[i].vol_file_start);
1979 uint32_t len = SGI_SSWAP32(sgilabel->directory[i].vol_file_size);
1980 char*name = sgilabel->directory[i].vol_file_name;
1982 printf(_("%2d: %-10s sector%5u size%8u\n"),
1983 i, name, (unsigned int) start, (unsigned int) len);
1989 sgi_set_bootpartition( int i )
1991 sgilabel->boot_part = SGI_SSWAP16(((short)i));
1995 sgi_get_lastblock(void) {
1996 return heads * sectors * cylinders;
2000 sgi_set_swappartition( int i ) {
2001 sgilabel->swap_part = SGI_SSWAP16(((short)i));
2005 sgi_check_bootfile(const char* aFile) {
2007 if (strlen(aFile) < 3) /* "/a\n" is minimum */ {
2008 printf(_("\nInvalid Bootfile!\n"
2009 "\tThe bootfile must be an absolute non-zero pathname,\n"
2010 "\te.g. \"/unix\" or \"/unix.save\".\n"));
2013 if (strlen(aFile) > 16) {
2014 printf(_("\n\tName of Bootfile too long: "
2015 "16 bytes maximum.\n"));
2018 if (aFile[0] != '/') {
2019 printf(_("\n\tBootfile must have a "
2020 "fully qualified pathname.\n"));
2025 if (strncmp(aFile, sgilabel->boot_file, 16)) {
2026 printf(_("\n\tBe aware, that the bootfile is not checked for existence.\n\t"
2027 "SGI's default is \"/unix\" and for backup \"/unix.save\".\n"));
2028 /* filename is correct and did change */
2031 return 0; /* filename did not change */
2035 sgi_get_bootfile(void) {
2036 return sgilabel->boot_file;
2040 sgi_set_bootfile(const char* aFile) {
2043 if (sgi_check_bootfile(aFile)) {
2045 if ((aFile[i] != '\n') /* in principle caught again by next line */
2046 && (strlen(aFile) > i))
2047 sgilabel->boot_file[i] = aFile[i];
2049 sgilabel->boot_file[i] = 0;
2052 printf(_("\n\tBootfile is changed to \"%s\".\n"), sgilabel->boot_file);
2057 create_sgiinfo(void)
2059 /* I keep SGI's habit to write the sgilabel to the second block */
2060 sgilabel->directory[0].vol_file_start = SGI_SSWAP32(2);
2061 sgilabel->directory[0].vol_file_size = SGI_SSWAP32(sizeof(sgiinfo));
2062 strncpy(sgilabel->directory[0].vol_file_name, "sgilabel", 8);
2065 static sgiinfo *fill_sgiinfo(void);
2068 sgi_write_table(void) {
2070 sgilabel->csum = SGI_SSWAP32(two_s_complement_32bit_sum(
2071 (unsigned int*)sgilabel,
2072 sizeof(*sgilabel)));
2073 assert(two_s_complement_32bit_sum(
2074 (unsigned int*)sgilabel, sizeof(*sgilabel)) == 0);
2075 if (lseek(fd, 0, SEEK_SET) < 0)
2076 fdisk_fatal(unable_to_seek);
2077 if (write(fd, sgilabel, SECTOR_SIZE) != SECTOR_SIZE)
2078 fdisk_fatal(unable_to_write);
2079 if (! strncmp(sgilabel->directory[0].vol_file_name, "sgilabel", 8)) {
2081 * keep this habit of first writing the "sgilabel".
2082 * I never tested whether it works without (AN 981002).
2084 sgiinfo *info = fill_sgiinfo();
2085 int infostartblock = SGI_SSWAP32(sgilabel->directory[0].vol_file_start);
2086 if (fdisk_llseek(fd, (long long)infostartblock*
2087 SECTOR_SIZE, SEEK_SET) < 0)
2088 fdisk_fatal(unable_to_seek);
2089 if (write(fd, info, SECTOR_SIZE) != SECTOR_SIZE)
2090 fdisk_fatal(unable_to_write);
2096 compare_start(int *x, int *y) {
2098 * sort according to start sectors
2099 * and prefers largest partition:
2100 * entry zero is entire disk entry
2102 unsigned int i = *x;
2103 unsigned int j = *y;
2104 unsigned int a = sgi_get_start_sector(i);
2105 unsigned int b = sgi_get_start_sector(j);
2106 unsigned int c = sgi_get_num_sectors(i);
2107 unsigned int d = sgi_get_num_sectors(j);
2110 return (d > c) ? 1 : (d == c) ? 0 : -1;
2111 return (a > b) ? 1 : -1;
2116 verify_sgi(int verbose)
2118 int Index[16]; /* list of valid partitions */
2119 int sortcount = 0; /* number of used partitions, i.e. non-zero lengths */
2120 int entire = 0, i = 0;
2121 unsigned int start = 0;
2122 long long gap = 0; /* count unused blocks */
2123 unsigned int lastblock = sgi_get_lastblock();
2126 for (i=0; i<16; i++) {
2127 if (sgi_get_num_sectors(i) != 0) {
2128 Index[sortcount++]=i;
2129 if (sgi_get_sysid(i) == ENTIRE_DISK) {
2130 if (entire++ == 1) {
2132 printf(_("More than one entire disk entry present.\n"));
2137 if (sortcount == 0) {
2139 printf(_("No partitions defined\n"));
2140 return (lastblock > 0) ? 1 : (lastblock == 0) ? 0 : -1;
2142 qsort(Index, sortcount, sizeof(Index[0]), (void*)compare_start);
2143 if (sgi_get_sysid(Index[0]) == ENTIRE_DISK) {
2144 if ((Index[0] != 10) && verbose)
2145 printf(_("IRIX likes when Partition 11 covers the entire disk.\n"));
2146 if ((sgi_get_start_sector(Index[0]) != 0) && verbose)
2147 printf(_("The entire disk partition should start "
2149 "not at diskblock %d.\n"),
2150 sgi_get_start_sector(Index[0]));
2151 if (debug) /* I do not understand how some disks fulfil it */
2152 if ((sgi_get_num_sectors(Index[0]) != lastblock) && verbose)
2153 printf(_("The entire disk partition is only %d diskblock large,\n"
2154 "but the disk is %d diskblocks long.\n"),
2155 sgi_get_num_sectors(Index[0]), lastblock);
2156 lastblock = sgi_get_num_sectors(Index[0]);
2159 printf(_("One Partition (#11) should cover the entire disk.\n"));
2161 printf("sysid=%d\tpartition=%d\n",
2162 sgi_get_sysid(Index[0]), Index[0]+1);
2164 for (i=1, start=0; i<sortcount; i++) {
2165 int cylsize = sgi_get_nsect() * sgi_get_ntrks();
2167 if ((sgi_get_start_sector(Index[i]) % cylsize) != 0) {
2168 if (debug) /* I do not understand how some disks fulfil it */
2170 printf(_("Partition %d does not start on cylinder boundary.\n"),
2173 if (sgi_get_num_sectors(Index[i]) % cylsize != 0) {
2174 if (debug) /* I do not understand how some disks fulfil it */
2176 printf(_("Partition %d does not end on cylinder boundary.\n"),
2179 /* We cannot handle several "entire disk" entries. */
2180 if (sgi_get_sysid(Index[i]) == ENTIRE_DISK) continue;
2181 if (start > sgi_get_start_sector(Index[i])) {
2183 printf(_("The Partition %d and %d overlap by %d sectors.\n"),
2184 Index[i-1]+1, Index[i]+1,
2185 start - sgi_get_start_sector(Index[i]));
2186 if (gap > 0) gap = -gap;
2187 if (gap == 0) gap = -1;
2189 if (start < sgi_get_start_sector(Index[i])) {
2191 printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"),
2192 sgi_get_start_sector(Index[i]) - start,
2193 start, sgi_get_start_sector(Index[i])-1);
2194 gap += sgi_get_start_sector(Index[i]) - start;
2195 add2freelist(start, sgi_get_start_sector(Index[i]));
2197 start = sgi_get_start_sector(Index[i])
2198 + sgi_get_num_sectors(Index[i]);
2201 printf("%2d:%12d\t%12d\t%12d\n", Index[i],
2202 sgi_get_start_sector(Index[i]),
2203 sgi_get_num_sectors(Index[i]),
2204 sgi_get_sysid(Index[i]));
2207 if (start < lastblock) {
2209 printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"),
2210 lastblock - start, start, lastblock-1);
2211 gap += lastblock - start;
2212 add2freelist(start, lastblock);
2215 * Done with arithmetics
2216 * Go for details now
2219 if (!sgi_get_num_sectors(sgi_get_bootpartition())) {
2220 printf(_("\nThe boot partition does not exist.\n"));
2222 if (!sgi_get_num_sectors(sgi_get_swappartition())) {
2223 printf(_("\nThe swap partition does not exist.\n"));
2225 if ((sgi_get_sysid(sgi_get_swappartition()) != SGI_SWAP)
2226 && (sgi_get_sysid(sgi_get_swappartition()) != LINUX_SWAP))
2227 printf(_("\nThe swap partition has no swap type.\n"));
2229 if (sgi_check_bootfile("/unix"))
2230 printf(_("\tYou have chosen an unusual boot file name.\n"));
2232 return (gap > 0) ? 1 : (gap == 0) ? 0 : -1;
2238 * returned value is:
2239 * = 0 : disk is properly filled to the rim
2240 * < 0 : there is an overlap
2241 * > 0 : there is still some vacant space
2243 return verify_sgi(0);
2247 sgi_change_sysid( int i, int sys )
2249 if( sgi_get_num_sectors(i) == 0 ) /* caught already before, ... */
2251 printf(_("Sorry You may change the Tag of non-empty partitions.\n"));
2254 if( ((sys != ENTIRE_DISK ) && (sys != SGI_VOLHDR))
2255 && (sgi_get_start_sector(i)<1) )
2258 _("It is highly recommended that the partition at offset 0\n"
2259 "is of type \"SGI volhdr\", the IRIX system will rely on it to\n"
2260 "retrieve from its directory standalone tools like sash and fx.\n"
2261 "Only the \"SGI volume\" entire disk section may violate this.\n"
2262 "Type YES if you are sure about tagging this partition differently.\n"));
2263 if (strcmp (line_ptr, _("YES\n")))
2266 sgilabel->partitions[i].id = SGI_SSWAP32(sys);
2269 /* returns partition index of first entry marked as entire disk */
2275 if(sgi_get_sysid(i) == SGI_VOLUME)
2281 sgi_set_partition(int i, unsigned int start, unsigned int length, int sys) {
2283 sgilabel->partitions[i].id = SGI_SSWAP32(sys);
2284 sgilabel->partitions[i].num_sectors = SGI_SSWAP32(length);
2285 sgilabel->partitions[i].start_sector = SGI_SSWAP32(start);
2287 if (sgi_gaps() < 0) /* rebuild freelist */
2288 printf(_("Do You know, You got a partition overlap on the disk?\n"));
2292 sgi_set_entire(void) {
2295 for(n=10; n < partitions; n++) {
2296 if(!sgi_get_num_sectors(n) ) {
2297 sgi_set_partition(n, 0, sgi_get_lastblock(), SGI_VOLUME);
2304 sgi_set_volhdr(void)
2307 for( n=8; n<partitions; n++ )
2309 if(!sgi_get_num_sectors( n ) )
2312 * 5 cylinders is an arbitrary value I like
2313 * IRIX 5.3 stored files in the volume header
2314 * (like sash, symmon, fx, ide) with ca. 3200
2317 if( heads * sectors * 5 < sgi_get_lastblock() )
2318 sgi_set_partition( n, 0, heads * sectors * 5, SGI_VOLHDR );
2325 sgi_delete_partition( int i )
2327 sgi_set_partition( i, 0, 0, 0 );
2331 sgi_add_partition( int n, int sys )
2334 unsigned int first=0, last=0;
2338 } else if ( n == 8 ) {
2341 if(sgi_get_num_sectors(n)) {
2342 printf(_("Partition %d is already defined. Delete "
2343 "it before re-adding it.\n"), n + 1);
2346 if( (sgi_entire() == -1) && (sys != SGI_VOLUME) ) {
2347 printf(_("Attempting to generate entire disk entry automatically.\n"));
2351 if( (sgi_gaps() == 0) && (sys != SGI_VOLUME) ) {
2352 printf(_("The entire disk is already covered with partitions.\n"));
2355 if(sgi_gaps() < 0) {
2356 printf(_("You got a partition overlap on the disk. Fix it first!\n"));
2359 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
2361 if(sys == SGI_VOLUME) {
2362 last = sgi_get_lastblock();
2363 first = read_int(0, 0, last-1, 0, mesg);
2365 printf(_("It is highly recommended that eleventh partition\n"
2366 "covers the entire disk and is of type `SGI volume'\n"));
2369 first = freelist[0].first;
2370 last = freelist[0].last;
2371 first = read_int(scround(first), scround(first), scround(last)-1,
2374 if (display_in_cyl_units)
2375 first *= units_per_sector;
2377 first = first; /* align to cylinder if you know how ... */
2379 last = isinfreelist(first);
2381 printf(_("You will get a partition overlap on the disk. "
2382 "Fix it first!\n"));
2386 snprintf(mesg, sizeof(mesg), _(" Last %s"), str_units(SINGULAR));
2387 last = read_int(scround(first), scround(last)-1, scround(last)-1,
2388 scround(first), mesg)+1;
2389 if (display_in_cyl_units)
2390 last *= units_per_sector;
2392 last = last; /* align to cylinder if You know how ... */
2393 if( (sys == SGI_VOLUME) && ( first != 0 || last != sgi_get_lastblock() ) )
2394 printf(_("It is highly recommended that eleventh partition\n"
2395 "covers the entire disk and is of type `SGI volume'\n"));
2396 sgi_set_partition( n, first, last-first, sys );
2399 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
2401 create_sgilabel(void)
2403 struct hd_geometry geometry;
2410 long longsectors; /* the number of sectors on the device */
2411 int res; /* the result from the ioctl */
2412 int sec_fac; /* the sector factor */
2414 sec_fac = sector_size / 512; /* determine the sector factor */
2417 _("Building a new SGI disklabel. Changes will remain in memory only,\n"
2418 "until you decide to write them. After that, of course, the previous\n"
2419 "content will be unrecoverably lost.\n\n"));
2421 sgi_other_endian = (BYTE_ORDER == LITTLE_ENDIAN);
2422 res = ioctl(fd, BLKGETSIZE, &longsectors);
2423 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
2424 heads = geometry.heads;
2425 sectors = geometry.sectors;
2427 /* the get device size ioctl was successful */
2428 cylinders = longsectors / (heads * sectors);
2429 cylinders /= sec_fac;
2431 /* otherwise print error and use truncated version */
2432 cylinders = geometry.cylinders;
2434 _("Warning: BLKGETSIZE ioctl failed on %s. "
2435 "Using geometry cylinder value of %d.\n"
2436 "This value may be truncated for devices"
2437 " > 33.8 GB.\n"), disk_device, cylinders);
2440 for (i = 0; i < 4; i++) {
2442 if(valid_part_table_flag(MBRbuffer)) {
2443 if(get_part_table(i)->sys_ind) {
2444 old[i].sysid = get_part_table(i)->sys_ind;
2445 old[i].start = get_start_sect(get_part_table(i));
2446 old[i].nsect = get_nr_sects(get_part_table(i));
2447 printf(_("Trying to keep parameters of partition %d.\n"), i);
2449 printf(_("ID=%02x\tSTART=%d\tLENGTH=%d\n"),
2450 old[i].sysid, old[i].start, old[i].nsect);
2455 memset(MBRbuffer, 0, sizeof(MBRbuffer));
2456 sgilabel->magic = SGI_SSWAP32(SGI_LABEL_MAGIC);
2457 sgilabel->boot_part = SGI_SSWAP16(0);
2458 sgilabel->swap_part = SGI_SSWAP16(1);
2460 /* sizeof(sgilabel->boot_file) = 16 > 6 */
2461 memset(sgilabel->boot_file, 0, 16);
2462 strcpy(sgilabel->boot_file, "/unix");
2464 sgilabel->devparam.skew = (0);
2465 sgilabel->devparam.gap1 = (0);
2466 sgilabel->devparam.gap2 = (0);
2467 sgilabel->devparam.sparecyl = (0);
2468 sgilabel->devparam.pcylcount = SGI_SSWAP16(geometry.cylinders);
2469 sgilabel->devparam.head_vol0 = SGI_SSWAP16(0);
2470 sgilabel->devparam.ntrks = SGI_SSWAP16(geometry.heads);
2471 /* tracks/cylinder (heads) */
2472 sgilabel->devparam.cmd_tag_queue_depth = (0);
2473 sgilabel->devparam.unused0 = (0);
2474 sgilabel->devparam.unused1 = SGI_SSWAP16(0);
2475 sgilabel->devparam.nsect = SGI_SSWAP16(geometry.sectors);
2477 sgilabel->devparam.bytes = SGI_SSWAP16(512);
2478 sgilabel->devparam.ilfact = SGI_SSWAP16(1);
2479 sgilabel->devparam.flags = SGI_SSWAP32(TRACK_FWD|
2480 IGNORE_ERRORS|RESEEK);
2481 sgilabel->devparam.datarate = SGI_SSWAP32(0);
2482 sgilabel->devparam.retries_on_error = SGI_SSWAP32(1);
2483 sgilabel->devparam.ms_per_word = SGI_SSWAP32(0);
2484 sgilabel->devparam.xylogics_gap1 = SGI_SSWAP16(0);
2485 sgilabel->devparam.xylogics_syncdelay = SGI_SSWAP16(0);
2486 sgilabel->devparam.xylogics_readdelay = SGI_SSWAP16(0);
2487 sgilabel->devparam.xylogics_gap2 = SGI_SSWAP16(0);
2488 sgilabel->devparam.xylogics_readgate = SGI_SSWAP16(0);
2489 sgilabel->devparam.xylogics_writecont = SGI_SSWAP16(0);
2490 memset( &(sgilabel->directory), 0, sizeof(struct volume_directory)*15 );
2491 memset( &(sgilabel->partitions), 0, sizeof(struct sgi_partition)*16 );
2497 for (i = 0; i < 4; i++) {
2499 sgi_set_partition(i, old[i].start, old[i].nsect, old[i].sysid);
2507 /* do nothing in the beginning */
2509 #endif /* CONFIG_FEATURE_FDISK_ADVANCED */
2511 /* _____________________________________________________________
2517 sgiinfo *info = calloc(1, sizeof(sgiinfo));
2519 info->magic=SGI_SSWAP32(SGI_INFO_MAGIC);
2520 info->b1=SGI_SSWAP32(-1);
2521 info->b2=SGI_SSWAP16(-1);
2522 info->b3=SGI_SSWAP16(1);
2523 /* You may want to replace this string !!!!!!! */
2524 strcpy( info->scsi_string, "IBM OEM 0662S12 3 30" );
2525 strcpy( info->serial, "0000" );
2526 info->check1816 = SGI_SSWAP16(18*256 +16 );
2527 strcpy( info->installer, "Sfx version 5.3, Oct 18, 1994" );
2530 #endif /* SGI_LABEL */
2533 #ifdef CONFIG_FEATURE_SUN_LABEL
2537 * I think this is mostly, or entirely, due to
2538 * Jakub Jelinek (jj@sunsite.mff.cuni.cz), July 1996
2540 * Merged with fdisk for other architectures, aeb, June 1998.
2542 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
2543 * Internationalization
2547 static int sun_other_endian;
2548 static int scsi_disk;
2552 #define IDE0_MAJOR 3
2555 #define IDE1_MAJOR 22
2558 static void guess_device_type(void) {
2559 struct stat bootstat;
2561 if (fstat (fd, &bootstat) < 0) {
2564 } else if (S_ISBLK(bootstat.st_mode)
2565 && (major(bootstat.st_rdev) == IDE0_MAJOR ||
2566 major(bootstat.st_rdev) == IDE1_MAJOR)) {
2569 } else if (S_ISBLK(bootstat.st_mode)
2570 && major(bootstat.st_rdev) == FLOPPY_MAJOR) {
2579 static const struct systypes sun_sys_types[] = {
2580 /* 0 */ {"\x00" "Empty" },
2581 /* 1 */ {"\x01" "Boot" },
2582 /* 2 */ {"\x02" "SunOS root" },
2583 /* SUNOS_SWAP */ {"\x03" "SunOS swap" },
2584 /* 4 */ {"\x04" "SunOS usr" },
2585 /* WHOLE_DISK */ {"\x05" "Whole disk" },
2586 /* 6 */ {"\x06" "SunOS stand" },
2587 /* 7 */ {"\x07" "SunOS var" },
2588 /* 8 */ {"\x08" "SunOS home" },
2589 /* LINUX_SWAP */ {"\x82" "Linux swap" },
2590 /* LINUX_NATIVE */ {"\x83" "Linux native" },
2591 /* 0x8e */ {"\x8e" "Linux LVM" },
2592 /* New (2.2.x) raid partition with autodetect using persistent superblock */
2593 /* 0xfd */ {"\xfd" "Linux raid autodetect" },
2599 set_sun_partition(int i, uint start, uint stop, int sysid) {
2600 sunlabel->infos[i].id = sysid;
2601 sunlabel->partitions[i].start_cylinder =
2602 SUN_SSWAP32(start / (heads * sectors));
2603 sunlabel->partitions[i].num_sectors =
2604 SUN_SSWAP32(stop - start);
2611 sunlabel->magic = 0;
2616 check_sun_label(void) {
2617 unsigned short *ush;
2620 if (sunlabel->magic != SUN_LABEL_MAGIC &&
2621 sunlabel->magic != SUN_LABEL_MAGIC_SWAPPED) {
2623 sun_other_endian = 0;
2626 sun_other_endian = (sunlabel->magic == SUN_LABEL_MAGIC_SWAPPED);
2627 ush = ((unsigned short *) (sunlabel + 1)) - 1;
2628 for (csum = 0; ush >= (unsigned short *)sunlabel;) csum ^= *ush--;
2630 fprintf(stderr,_("Detected sun disklabel with wrong checksum.\n"
2631 "Probably you'll have to set all the values,\n"
2632 "e.g. heads, sectors, cylinders and partitions\n"
2633 "or force a fresh label (s command in main menu)\n"));
2635 heads = SUN_SSWAP16(sunlabel->ntrks);
2636 cylinders = SUN_SSWAP16(sunlabel->ncyl);
2637 sectors = SUN_SSWAP16(sunlabel->nsect);
2645 static const struct sun_predefined_drives {
2648 unsigned short sparecyl;
2649 unsigned short ncyl;
2650 unsigned short nacyl;
2651 unsigned short pcylcount;
2652 unsigned short ntrks;
2653 unsigned short nsect;
2654 unsigned short rspeed;
2656 {"Quantum","ProDrive 80S",1,832,2,834,6,34,3662},
2657 {"Quantum","ProDrive 105S",1,974,2,1019,6,35,3662},
2658 {"CDC","Wren IV 94171-344",3,1545,2,1549,9,46,3600},
2659 {"IBM","DPES-31080",0,4901,2,4903,4,108,5400},
2660 {"IBM","DORS-32160",0,1015,2,1017,67,62,5400},
2661 {"IBM","DNES-318350",0,11199,2,11474,10,320,7200},
2662 {"SEAGATE","ST34371",0,3880,2,3882,16,135,7228},
2663 {"","SUN0104",1,974,2,1019,6,35,3662},
2664 {"","SUN0207",4,1254,2,1272,9,36,3600},
2665 {"","SUN0327",3,1545,2,1549,9,46,3600},
2666 {"","SUN0340",0,1538,2,1544,6,72,4200},
2667 {"","SUN0424",2,1151,2,2500,9,80,4400},
2668 {"","SUN0535",0,1866,2,2500,7,80,5400},
2669 {"","SUN0669",5,1614,2,1632,15,54,3600},
2670 {"","SUN1.0G",5,1703,2,1931,15,80,3597},
2671 {"","SUN1.05",0,2036,2,2038,14,72,5400},
2672 {"","SUN1.3G",6,1965,2,3500,17,80,5400},
2673 {"","SUN2.1G",0,2733,2,3500,19,80,5400},
2674 {"IOMEGA","Jaz",0,1019,2,1021,64,32,5394},
2677 static const struct sun_predefined_drives *
2678 sun_autoconfigure_scsi(void) {
2679 const struct sun_predefined_drives *p = NULL;
2681 #ifdef SCSI_IOCTL_GET_IDLUN
2691 if (!ioctl(fd, SCSI_IOCTL_GET_IDLUN, &id)) {
2693 "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n",
2695 ((id[0]>>24)&0xff)-/*PROC_SCSI_SCSI+PROC_SCSI_FILE*/33,
2697 /* This is very wrong (works only if you have one HBA),
2698 but I haven't found a way how to get hostno
2699 from the current kernel */
2705 pfd = fopen("/proc/scsi/scsi","r");
2707 while (fgets(buffer2,2048,pfd)) {
2708 if (!strcmp(buffer, buffer2)) {
2709 if (fgets(buffer2,2048,pfd)) {
2710 q = strstr(buffer2,"Vendor: ");
2715 *q++ = 0; /* truncate vendor name */
2716 q = strstr(q,"Model: ");
2721 q = strstr(q," Rev: ");
2724 for (i = 0; i < SIZE(sun_drives); i++) {
2725 if (*sun_drives[i].vendor && strcasecmp(sun_drives[i].vendor, vendor))
2727 if (!strstr(model, sun_drives[i].model))
2729 printf(_("Autoconfigure found a %s%s%s\n"),sun_drives[i].vendor,(*sun_drives[i].vendor) ? " " : "",sun_drives[i].model);
2747 static void create_sunlabel(void)
2749 struct hd_geometry geometry;
2753 const struct sun_predefined_drives *p = NULL;
2756 _("Building a new sun disklabel. Changes will remain in memory only,\n"
2757 "until you decide to write them. After that, of course, the previous\n"
2758 "content won't be recoverable.\n\n"));
2759 #if BYTE_ORDER == LITTLE_ENDIAN
2760 sun_other_endian = 1;
2762 sun_other_endian = 0;
2764 memset(MBRbuffer, 0, sizeof(MBRbuffer));
2765 sunlabel->magic = SUN_SSWAP16(SUN_LABEL_MAGIC);
2767 puts(_("Drive type\n"
2768 " ? auto configure\n"
2769 " 0 custom (with hardware detected defaults)"));
2770 for (i = 0; i < SIZE(sun_drives); i++) {
2771 printf(" %c %s%s%s\n",
2772 i + 'a', sun_drives[i].vendor,
2773 (*sun_drives[i].vendor) ? " " : "",
2774 sun_drives[i].model);
2777 c = read_char(_("Select type (? for auto, 0 for custom): "));
2778 if (c >= 'a' && c < 'a' + SIZE(sun_drives)) {
2779 p = sun_drives + c - 'a';
2781 } else if (c >= 'A' && c < 'A' + SIZE(sun_drives)) {
2782 p = sun_drives + c - 'A';
2784 } else if (c == '0') {
2786 } else if (c == '?' && scsi_disk) {
2787 p = sun_autoconfigure_scsi();
2789 printf(_("Autoconfigure failed.\n"));
2796 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
2797 heads = geometry.heads;
2798 sectors = geometry.sectors;
2799 cylinders = geometry.cylinders;
2806 sunlabel->nacyl = 0;
2807 sunlabel->pcylcount = SUN_SSWAP16(cylinders);
2808 sunlabel->rspeed = SUN_SSWAP16(300);
2809 sunlabel->ilfact = SUN_SSWAP16(1);
2810 sunlabel->sparecyl = 0;
2812 heads = read_int(1,heads,1024,0,_("Heads"));
2813 sectors = read_int(1,sectors,1024,0,_("Sectors/track"));
2815 cylinders = read_int(1,cylinders-2,65535,0,_("Cylinders"));
2817 cylinders = read_int(1,0,65535,0,_("Cylinders"));
2819 SUN_SSWAP16(read_int(0,2,65535,0,
2820 _("Alternate cylinders")));
2821 sunlabel->pcylcount =
2822 SUN_SSWAP16(read_int(0,cylinders+SUN_SSWAP16(sunlabel->nacyl),
2823 65535,0,_("Physical cylinders")));
2825 SUN_SSWAP16(read_int(1,5400,100000,0,
2826 _("Rotation speed (rpm)")));
2828 SUN_SSWAP16(read_int(1,1,32,0,_("Interleave factor")));
2829 sunlabel->sparecyl =
2830 SUN_SSWAP16(read_int(0,0,sectors,0,
2831 _("Extra sectors per cylinder")));
2834 sunlabel->sparecyl = SUN_SSWAP16(p->sparecyl);
2835 sunlabel->ncyl = SUN_SSWAP16(p->ncyl);
2836 sunlabel->nacyl = SUN_SSWAP16(p->nacyl);
2837 sunlabel->pcylcount = SUN_SSWAP16(p->pcylcount);
2838 sunlabel->ntrks = SUN_SSWAP16(p->ntrks);
2839 sunlabel->nsect = SUN_SSWAP16(p->nsect);
2840 sunlabel->rspeed = SUN_SSWAP16(p->rspeed);
2841 sunlabel->ilfact = SUN_SSWAP16(1);
2842 cylinders = p->ncyl;
2845 puts(_("You may change all the disk params from the x menu"));
2848 snprintf(sunlabel->info, sizeof(sunlabel->info),
2849 "%s%s%s cyl %d alt %d hd %d sec %d",
2850 p ? p->vendor : "", (p && *p->vendor) ? " " : "",
2852 : (floppy ? _("3,5\" floppy") : _("Linux custom")),
2853 cylinders, SUN_SSWAP16(sunlabel->nacyl), heads, sectors);
2855 sunlabel->ntrks = SUN_SSWAP16(heads);
2856 sunlabel->nsect = SUN_SSWAP16(sectors);
2857 sunlabel->ncyl = SUN_SSWAP16(cylinders);
2859 set_sun_partition(0, 0, cylinders * heads * sectors, LINUX_NATIVE);
2861 if (cylinders * heads * sectors >= 150 * 2048) {
2862 ndiv = cylinders - (50 * 2048 / (heads * sectors)); /* 50M swap */
2864 ndiv = cylinders * 2 / 3;
2865 set_sun_partition(0, 0, ndiv * heads * sectors, LINUX_NATIVE);
2866 set_sun_partition(1, ndiv * heads * sectors, cylinders * heads * sectors, LINUX_SWAP);
2867 sunlabel->infos[1].flags |= 0x01; /* Not mountable */
2869 set_sun_partition(2, 0, cylinders * heads * sectors, WHOLE_DISK);
2871 unsigned short *ush = (unsigned short *)sunlabel;
2872 unsigned short csum = 0;
2873 while(ush < (unsigned short *)(&sunlabel->csum))
2875 sunlabel->csum = csum;
2878 set_all_unchanged();
2880 get_boot(create_empty_sun);
2884 toggle_sunflags(int i, unsigned char mask) {
2885 if (sunlabel->infos[i].flags & mask)
2886 sunlabel->infos[i].flags &= ~mask;
2887 else sunlabel->infos[i].flags |= mask;
2892 fetch_sun(uint *starts, uint *lens, uint *start, uint *stop) {
2893 int i, continuous = 1;
2894 *start = 0; *stop = cylinders * heads * sectors;
2895 for (i = 0; i < partitions; i++) {
2896 if (sunlabel->partitions[i].num_sectors
2897 && sunlabel->infos[i].id
2898 && sunlabel->infos[i].id != WHOLE_DISK) {
2899 starts[i] = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
2900 lens[i] = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
2902 if (starts[i] == *start)
2904 else if (starts[i] + lens[i] >= *stop)
2908 /* There will be probably more gaps
2909 than one, so lets check afterwards */
2918 static uint *verify_sun_starts;
2921 verify_sun_cmp(int *a, int *b) {
2922 if (*a == -1) return 1;
2923 if (*b == -1) return -1;
2924 if (verify_sun_starts[*a] > verify_sun_starts[*b]) return 1;
2930 uint starts[8], lens[8], start, stop;
2931 int i,j,k,starto,endo;
2934 verify_sun_starts = starts;
2935 fetch_sun(starts,lens,&start,&stop);
2936 for (k = 0; k < 7; k++) {
2937 for (i = 0; i < 8; i++) {
2938 if (k && (lens[i] % (heads * sectors))) {
2939 printf(_("Partition %d doesn't end on cylinder boundary\n"), i+1);
2942 for (j = 0; j < i; j++)
2944 if (starts[j] == starts[i]+lens[i]) {
2945 starts[j] = starts[i]; lens[j] += lens[i];
2947 } else if (starts[i] == starts[j]+lens[j]){
2951 if (starts[i] < starts[j]+lens[j] &&
2952 starts[j] < starts[i]+lens[i]) {
2954 if (starts[j] > starto)
2956 endo = starts[i]+lens[i];
2957 if (starts[j]+lens[j] < endo)
2958 endo = starts[j]+lens[j];
2959 printf(_("Partition %d overlaps with others in "
2960 "sectors %d-%d\n"), i+1, starto, endo);
2967 for (i = 0; i < 8; i++) {
2973 qsort(array,SIZE(array),sizeof(array[0]),
2974 (int (*)(const void *,const void *)) verify_sun_cmp);
2975 if (array[0] == -1) {
2976 printf(_("No partitions defined\n"));
2979 stop = cylinders * heads * sectors;
2980 if (starts[array[0]])
2981 printf(_("Unused gap - sectors 0-%d\n"),starts[array[0]]);
2982 for (i = 0; i < 7 && array[i+1] != -1; i++) {
2983 printf(_("Unused gap - sectors %d-%d\n"),starts[array[i]]+lens[array[i]],starts[array[i+1]]);
2985 start = starts[array[i]]+lens[array[i]];
2987 printf(_("Unused gap - sectors %d-%d\n"),start,stop);
2991 add_sun_partition(int n, int sys) {
2992 uint start, stop, stop2;
2993 uint starts[8], lens[8];
2999 if (sunlabel->partitions[n].num_sectors && sunlabel->infos[n].id) {
3000 printf(_("Partition %d is already defined. Delete "
3001 "it before re-adding it.\n"), n + 1);
3005 fetch_sun(starts,lens,&start,&stop);
3006 if (stop <= start) {
3010 printf(_("Other partitions already cover the whole disk.\nDelete "
3011 "some/shrink them before retry.\n"));
3015 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
3018 first = read_int(0, 0, 0, 0, mesg);
3020 first = read_int(scround(start), scround(stop)+1,
3021 scround(stop), 0, mesg);
3022 if (display_in_cyl_units)
3023 first *= units_per_sector;
3025 /* Starting sector has to be properly aligned */
3026 first = (first + heads * sectors - 1) / (heads * sectors);
3027 if (n == 2 && first != 0)
3029 It is highly recommended that the third partition covers the whole disk\n\
3030 and is of type `Whole disk'\n");
3031 /* ewt asks to add: "don't start a partition at cyl 0"
3032 However, edmundo@rano.demon.co.uk writes:
3033 "In addition to having a Sun partition table, to be able to
3034 boot from the disc, the first partition, /dev/sdX1, must
3035 start at cylinder 0. This means that /dev/sdX1 contains
3036 the partition table and the boot block, as these are the
3037 first two sectors of the disc. Therefore you must be
3038 careful what you use /dev/sdX1 for. In particular, you must
3039 not use a partition starting at cylinder 0 for Linux swap,
3040 as that would overwrite the partition table and the boot
3041 block. You may, however, use such a partition for a UFS
3042 or EXT2 file system, as these file systems leave the first
3043 1024 bytes undisturbed. */
3044 /* On the other hand, one should not use partitions
3045 starting at block 0 in an md, or the label will
3047 for (i = 0; i < partitions; i++)
3048 if (lens[i] && starts[i] <= first
3049 && starts[i] + lens[i] > first)
3051 if (i < partitions && !whole_disk) {
3052 if (n == 2 && !first) {
3056 printf(_("Sector %d is already allocated\n"), first);
3060 stop = cylinders * heads * sectors;
3062 for (i = 0; i < partitions; i++) {
3063 if (starts[i] > first && starts[i] < stop)
3066 snprintf(mesg, sizeof(mesg),
3067 _("Last %s or +size or +sizeM or +sizeK"),
3068 str_units(SINGULAR));
3070 last = read_int(scround(stop2), scround(stop2), scround(stop2),
3072 else if (n == 2 && !first)
3073 last = read_int(scround(first), scround(stop2), scround(stop2),
3074 scround(first), mesg);
3076 last = read_int(scround(first), scround(stop), scround(stop),
3077 scround(first), mesg);
3078 if (display_in_cyl_units)
3079 last *= units_per_sector;
3080 if (n == 2 && !first) {
3081 if (last >= stop2) {
3084 } else if (last > stop) {
3086 _("You haven't covered the whole disk with the 3rd partition, but your value\n"
3087 "%d %s covers some other partition. Your entry has been changed\n"
3089 scround(last), str_units(SINGULAR),
3090 scround(stop), str_units(SINGULAR));
3093 } else if (!whole_disk && last > stop)
3096 if (whole_disk) sys = WHOLE_DISK;
3097 set_sun_partition(n, first, last, sys);
3101 sun_delete_partition(int i) {
3104 if (i == 2 && sunlabel->infos[i].id == WHOLE_DISK &&
3105 !sunlabel->partitions[i].start_cylinder &&
3106 (nsec = SUN_SSWAP32(sunlabel->partitions[i].num_sectors))
3107 == heads * sectors * cylinders)
3108 printf(_("If you want to maintain SunOS/Solaris compatibility, "
3109 "consider leaving this\n"
3110 "partition as Whole disk (5), starting at 0, with %u "
3111 "sectors\n"), nsec);
3112 sunlabel->infos[i].id = 0;
3113 sunlabel->partitions[i].num_sectors = 0;
3117 sun_change_sysid(int i, int sys) {
3118 if (sys == LINUX_SWAP && !sunlabel->partitions[i].start_cylinder) {
3120 _("It is highly recommended that the partition at offset 0\n"
3121 "is UFS, EXT2FS filesystem or SunOS swap. Putting Linux swap\n"
3122 "there may destroy your partition table and bootblock.\n"
3123 "Type YES if you're very sure you would like that partition\n"
3124 "tagged with 82 (Linux swap): "));
3125 if (strcmp (line_ptr, _("YES\n")))
3131 /* swaps are not mountable by default */
3132 sunlabel->infos[i].flags |= 0x01;
3135 /* assume other types are mountable;
3136 user can change it anyway */
3137 sunlabel->infos[i].flags &= ~0x01;
3140 sunlabel->infos[i].id = sys;
3144 sun_list_table(int xtra) {
3147 w = strlen(disk_device);
3150 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d rpm\n"
3151 "%d cylinders, %d alternate cylinders, %d physical cylinders\n"
3152 "%d extra sects/cyl, interleave %d:1\n"
3154 "Units = %s of %d * 512 bytes\n\n"),
3155 disk_device, heads, sectors, SUN_SSWAP16(sunlabel->rspeed),
3156 cylinders, SUN_SSWAP16(sunlabel->nacyl),
3157 SUN_SSWAP16(sunlabel->pcylcount),
3158 SUN_SSWAP16(sunlabel->sparecyl),
3159 SUN_SSWAP16(sunlabel->ilfact),
3161 str_units(PLURAL), units_per_sector);
3164 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d cylinders\n"
3165 "Units = %s of %d * 512 bytes\n\n"),
3166 disk_device, heads, sectors, cylinders,
3167 str_units(PLURAL), units_per_sector);
3169 printf(_("%*s Flag Start End Blocks Id System\n"),
3170 w + 1, _("Device"));
3171 for (i = 0 ; i < partitions; i++) {
3172 if (sunlabel->partitions[i].num_sectors) {
3173 uint32_t start = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
3174 uint32_t len = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
3176 "%s %c%c %9ld %9ld %9ld%c %2x %s\n",
3177 /* device */ partname(disk_device, i+1, w),
3178 /* flags */ (sunlabel->infos[i].flags & 0x01) ? 'u' : ' ',
3179 (sunlabel->infos[i].flags & 0x10) ? 'r' : ' ',
3180 /* start */ (long) scround(start),
3181 /* end */ (long) scround(start+len),
3182 /* odd flag on end */ (long) len / 2, len & 1 ? '+' : ' ',
3183 /* type id */ sunlabel->infos[i].id,
3184 /* type name */ partition_type(sunlabel->infos[i].id));
3189 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3192 sun_set_alt_cyl(void) {
3194 SUN_SSWAP16(read_int(0,SUN_SSWAP16(sunlabel->nacyl), 65535, 0,
3195 _("Number of alternate cylinders")));
3199 sun_set_ncyl(int cyl) {
3200 sunlabel->ncyl = SUN_SSWAP16(cyl);
3204 sun_set_xcyl(void) {
3205 sunlabel->sparecyl =
3206 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->sparecyl), sectors, 0,
3207 _("Extra sectors per cylinder")));
3211 sun_set_ilfact(void) {
3213 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->ilfact), 32, 0,
3214 _("Interleave factor")));
3218 sun_set_rspeed(void) {
3220 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->rspeed), 100000, 0,
3221 _("Rotation speed (rpm)")));
3225 sun_set_pcylcount(void) {
3226 sunlabel->pcylcount =
3227 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->pcylcount), 65535, 0,
3228 _("Number of physical cylinders")));
3230 #endif /* CONFIG_FEATURE_FDISK_ADVANCED */
3233 sun_write_table(void) {
3234 unsigned short *ush = (unsigned short *)sunlabel;
3235 unsigned short csum = 0;
3237 while(ush < (unsigned short *)(&sunlabel->csum))
3239 sunlabel->csum = csum;
3240 if (lseek(fd, 0, SEEK_SET) < 0)
3241 fdisk_fatal(unable_to_seek);
3242 if (write(fd, sunlabel, SECTOR_SIZE) != SECTOR_SIZE)
3243 fdisk_fatal(unable_to_write);
3245 #endif /* SUN_LABEL */
3247 /* DOS partition types */
3249 static const struct systypes i386_sys_types[] = {
3252 {"\x04" "FAT16 <32M"},
3253 {"\x05" "Extended"}, /* DOS 3.3+ extended partition */
3254 {"\x06" "FAT16"}, /* DOS 16-bit >=32M */
3255 {"\x07" "HPFS/NTFS"}, /* OS/2 IFS, eg, HPFS or NTFS or QNX */
3256 {"\x0a" "OS/2 Boot Manager"},/* OS/2 Boot Manager */
3257 {"\x0b" "Win95 FAT32"},
3258 {"\x0c" "Win95 FAT32 (LBA)"},/* LBA really is `Extended Int 13h' */
3259 {"\x0e" "Win95 FAT16 (LBA)"},
3260 {"\x0f" "Win95 Ext'd (LBA)"},
3261 {"\x11" "Hidden FAT12"},
3262 {"\x12" "Compaq diagnostics"},
3263 {"\x14" "Hidden FAT16 <32M"},
3264 {"\x16" "Hidden FAT16"},
3265 {"\x17" "Hidden HPFS/NTFS"},
3266 {"\x1b" "Hidden Win95 FAT32"},
3267 {"\x1c" "Hidden Win95 FAT32 (LBA)"},
3268 {"\x1e" "Hidden Win95 FAT16 (LBA)"},
3269 {"\x3c" "PartitionMagic recovery"},
3270 {"\x41" "PPC PReP Boot"},
3272 {"\x63" "GNU HURD or SysV"}, /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */
3273 {"\x80" "Old Minix"}, /* Minix 1.4a and earlier */
3274 {"\x81" "Minix / old Linux"},/* Minix 1.4b and later */
3275 {"\x82" "Linux swap"}, /* also Solaris */
3277 {"\x84" "OS/2 hidden C: drive"},
3278 {"\x85" "Linux extended"},
3279 {"\x86" "NTFS volume set"},
3280 {"\x87" "NTFS volume set"},
3281 {"\x8e" "Linux LVM"},
3282 {"\x9f" "BSD/OS"}, /* BSDI */
3283 {"\xa0" "IBM Thinkpad hibernation"},
3284 {"\xa5" "FreeBSD"}, /* various BSD flavours */
3286 {"\xa8" "Darwin UFS"},
3288 {"\xab" "Darwin boot"},
3290 {"\xb8" "BSDI swap"},
3291 {"\xbe" "Solaris boot"},
3293 {"\xee" "EFI GPT"}, /* Intel EFI GUID Partition Table */
3294 {"\xef" "EFI (FAT-12/16/32)"},/* Intel EFI System Partition */
3295 {"\xf0" "Linux/PA-RISC boot"},/* Linux/PA-RISC boot loader */
3296 {"\xf2" "DOS secondary"}, /* DOS 3.3+ secondary */
3297 {"\xfd" "Linux raid autodetect"},/* New (2.2.x) raid partition with
3298 autodetect using persistent
3300 #ifdef CONFIG_WEIRD_PARTITION_TYPES
3301 {"\x02" "XENIX root"},
3302 {"\x03" "XENIX usr"},
3303 {"\x08" "AIX"}, /* AIX boot (AIX -- PS/2 port) or SplitDrive */
3304 {"\x09" "AIX bootable"}, /* AIX data or Coherent */
3306 {"\x18" "AST SmartSleep"},
3309 {"\x40" "Venix 80286"},
3311 {"\x4e" "QNX4.x 2nd part"},
3312 {"\x4f" "QNX4.x 3rd part"},
3313 {"\x50" "OnTrack DM"},
3314 {"\x51" "OnTrack DM6 Aux1"}, /* (or Novell) */
3315 {"\x52" "CP/M"}, /* CP/M or Microport SysV/AT */
3316 {"\x53" "OnTrack DM6 Aux3"},
3317 {"\x54" "OnTrackDM6"},
3318 {"\x55" "EZ-Drive"},
3319 {"\x56" "Golden Bow"},
3320 {"\x5c" "Priam Edisk"},
3321 {"\x61" "SpeedStor"},
3322 {"\x64" "Novell Netware 286"},
3323 {"\x65" "Novell Netware 386"},
3324 {"\x70" "DiskSecure Multi-Boot"},
3327 {"\x94" "Amoeba BBT"}, /* (bad block table) */
3328 {"\xa7" "NeXTSTEP"},
3329 {"\xbb" "Boot Wizard hidden"},
3330 {"\xc1" "DRDOS/sec (FAT-12)"},
3331 {"\xc4" "DRDOS/sec (FAT-16 < 32M)"},
3332 {"\xc6" "DRDOS/sec (FAT-16)"},
3334 {"\xda" "Non-FS data"},
3335 {"\xdb" "CP/M / CTOS / ..."},/* CP/M or Concurrent CP/M or
3336 Concurrent DOS or CTOS */
3337 {"\xde" "Dell Utility"}, /* Dell PowerEdge Server utilities */
3338 {"\xdf" "BootIt"}, /* BootIt EMBRM */
3339 {"\xe1" "DOS access"}, /* DOS access or SpeedStor 12-bit FAT
3340 extended partition */
3341 {"\xe3" "DOS R/O"}, /* DOS R/O or SpeedStor */
3342 {"\xe4" "SpeedStor"}, /* SpeedStor 16-bit FAT extended
3343 partition < 1024 cyl. */
3344 {"\xf1" "SpeedStor"},
3345 {"\xf4" "SpeedStor"}, /* SpeedStor large partition */
3346 {"\xfe" "LANstep"}, /* SpeedStor >1024 cyl. or LANstep */
3347 {"\xff" "BBT"}, /* Xenix Bad Block Table */
3354 /* A valid partition table sector ends in 0x55 0xaa */
3356 part_table_flag(const char *b) {
3357 return ((uint) b[510]) + (((uint) b[511]) << 8);
3361 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3363 write_part_table_flag(char *b) {
3368 /* start_sect and nr_sects are stored little endian on all machines */
3369 /* moreover, they are not aligned correctly */
3371 store4_little_endian(unsigned char *cp, unsigned int val) {
3372 cp[0] = (val & 0xff);
3373 cp[1] = ((val >> 8) & 0xff);
3374 cp[2] = ((val >> 16) & 0xff);
3375 cp[3] = ((val >> 24) & 0xff);
3377 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3380 read4_little_endian(const unsigned char *cp) {
3381 return (uint)(cp[0]) + ((uint)(cp[1]) << 8)
3382 + ((uint)(cp[2]) << 16) + ((uint)(cp[3]) << 24);
3385 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3387 set_start_sect(struct partition *p, unsigned int start_sect) {
3388 store4_little_endian(p->start4, start_sect);
3393 get_start_sect(const struct partition *p) {
3394 return read4_little_endian(p->start4);
3397 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3399 set_nr_sects(struct partition *p, unsigned int nr_sects) {
3400 store4_little_endian(p->size4, nr_sects);
3405 get_nr_sects(const struct partition *p) {
3406 return read4_little_endian(p->size4);
3409 /* normally O_RDWR, -l option gives O_RDONLY */
3410 static int type_open = O_RDWR;
3413 static int ext_index, /* the prime extended partition */
3414 listing, /* no aborts for fdisk -l */
3415 dos_compatible_flag = ~0;
3416 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3417 static int dos_changed;
3418 static int nowarn; /* no warnings for fdisk -l/-s */
3423 static uint user_cylinders, user_heads, user_sectors;
3424 static uint pt_heads, pt_sectors;
3425 static uint kern_heads, kern_sectors;
3427 static uint extended_offset; /* offset of link pointers */
3429 static unsigned long long total_number_of_sectors;
3432 static jmp_buf listingbuf;
3434 static void fdisk_fatal(enum failure why) {
3435 const char *message;
3439 longjmp(listingbuf, 1);
3443 case unable_to_open:
3444 message = "Unable to open %s\n";
3446 case unable_to_read:
3447 message = "Unable to read %s\n";
3449 case unable_to_seek:
3450 message = "Unable to seek on %s\n";
3452 case unable_to_write:
3453 message = "Unable to write %s\n";
3456 message = "BLKGETSIZE ioctl failed on %s\n";
3459 message = "Fatal error\n";
3462 fputc('\n', stderr);
3463 fprintf(stderr, message, disk_device);
3468 seek_sector(uint secno) {
3469 fdisk_loff_t offset = (fdisk_loff_t) secno * sector_size;
3470 if (fdisk_llseek(fd, offset, SEEK_SET) == (fdisk_loff_t) -1)
3471 fdisk_fatal(unable_to_seek);
3474 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3476 write_sector(uint secno, char *buf) {
3478 if (write(fd, buf, sector_size) != sector_size)
3479 fdisk_fatal(unable_to_write);
3483 /* Allocate a buffer and read a partition table sector */
3485 read_pte(struct pte *pe, uint offset) {
3487 pe->offset = offset;
3488 pe->sectorbuffer = (char *) xmalloc(sector_size);
3489 seek_sector(offset);
3490 if (read(fd, pe->sectorbuffer, sector_size) != sector_size)
3491 fdisk_fatal(unable_to_read);
3492 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3495 pe->part_table = pe->ext_pointer = NULL;
3499 get_partition_start(const struct pte *pe) {
3500 return pe->offset + get_start_sect(pe->part_table);
3503 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3505 * Avoid warning about DOS partitions when no DOS partition was changed.
3506 * Here a heuristic "is probably dos partition".
3507 * We might also do the opposite and warn in all cases except
3508 * for "is probably nondos partition".
3511 is_dos_partition(int t) {
3512 return (t == 1 || t == 4 || t == 6 ||
3513 t == 0x0b || t == 0x0c || t == 0x0e ||
3514 t == 0x11 || t == 0x12 || t == 0x14 || t == 0x16 ||
3515 t == 0x1b || t == 0x1c || t == 0x1e || t == 0x24 ||
3516 t == 0xc1 || t == 0xc4 || t == 0xc6);
3521 #ifdef CONFIG_FEATURE_SUN_LABEL
3523 puts(_("Command action"));
3524 puts(_("\ta\ttoggle a read only flag")); /* sun */
3525 puts(_("\tb\tedit bsd disklabel"));
3526 puts(_("\tc\ttoggle the mountable flag")); /* sun */
3527 puts(_("\td\tdelete a partition"));
3528 puts(_("\tl\tlist known partition types"));
3529 puts(_("\tm\tprint this menu"));
3530 puts(_("\tn\tadd a new partition"));
3531 puts(_("\to\tcreate a new empty DOS partition table"));
3532 puts(_("\tp\tprint the partition table"));
3533 puts(_("\tq\tquit without saving changes"));
3534 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3535 puts(_("\tt\tchange a partition's system id"));
3536 puts(_("\tu\tchange display/entry units"));
3537 puts(_("\tv\tverify the partition table"));
3538 puts(_("\tw\twrite table to disk and exit"));
3539 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3540 puts(_("\tx\textra functionality (experts only)"));
3544 #ifdef CONFIG_FEATURE_SGI_LABEL
3546 puts(_("Command action"));
3547 puts(_("\ta\tselect bootable partition")); /* sgi flavour */
3548 puts(_("\tb\tedit bootfile entry")); /* sgi */
3549 puts(_("\tc\tselect sgi swap partition")); /* sgi flavour */
3550 puts(_("\td\tdelete a partition"));
3551 puts(_("\tl\tlist known partition types"));
3552 puts(_("\tm\tprint this menu"));
3553 puts(_("\tn\tadd a new partition"));
3554 puts(_("\to\tcreate a new empty DOS partition table"));
3555 puts(_("\tp\tprint the partition table"));
3556 puts(_("\tq\tquit without saving changes"));
3557 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3558 puts(_("\tt\tchange a partition's system id"));
3559 puts(_("\tu\tchange display/entry units"));
3560 puts(_("\tv\tverify the partition table"));
3561 puts(_("\tw\twrite table to disk and exit"));
3564 #ifdef CONFIG_FEATURE_AIX_LABEL
3566 puts(_("Command action"));
3567 puts(_("\tm\tprint this menu"));
3568 puts(_("\to\tcreate a new empty DOS partition table"));
3569 puts(_("\tq\tquit without saving changes"));
3570 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3574 puts(_("Command action"));
3575 puts(_("\ta\ttoggle a bootable flag"));
3576 puts(_("\tb\tedit bsd disklabel"));
3577 puts(_("\tc\ttoggle the dos compatibility flag"));
3578 puts(_("\td\tdelete a partition"));
3579 puts(_("\tl\tlist known partition types"));
3580 puts(_("\tm\tprint this menu"));
3581 puts(_("\tn\tadd a new partition"));
3582 puts(_("\to\tcreate a new empty DOS partition table"));
3583 puts(_("\tp\tprint the partition table"));
3584 puts(_("\tq\tquit without saving changes"));
3585 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3586 puts(_("\tt\tchange a partition's system id"));
3587 puts(_("\tu\tchange display/entry units"));
3588 puts(_("\tv\tverify the partition table"));
3589 puts(_("\tw\twrite table to disk and exit"));
3590 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3591 puts(_("\tx\textra functionality (experts only)"));
3595 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3598 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3601 #ifdef CONFIG_FEATURE_SUN_LABEL
3603 puts(_("Command action"));
3604 puts(_("\ta\tchange number of alternate cylinders")); /*sun*/
3605 puts(_("\tc\tchange number of cylinders"));
3606 puts(_("\td\tprint the raw data in the partition table"));
3607 puts(_("\te\tchange number of extra sectors per cylinder"));/*sun*/
3608 puts(_("\th\tchange number of heads"));
3609 puts(_("\ti\tchange interleave factor")); /*sun*/
3610 puts(_("\to\tchange rotation speed (rpm)")); /*sun*/
3611 puts(_("\tm\tprint this menu"));
3612 puts(_("\tp\tprint the partition table"));
3613 puts(_("\tq\tquit without saving changes"));
3614 puts(_("\tr\treturn to main menu"));
3615 puts(_("\ts\tchange number of sectors/track"));
3616 puts(_("\tv\tverify the partition table"));
3617 puts(_("\tw\twrite table to disk and exit"));
3618 puts(_("\ty\tchange number of physical cylinders")); /*sun*/
3621 #ifdef CONFIG_FEATURE_SGI_LABEL
3623 puts(_("Command action"));
3624 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3625 puts(_("\tc\tchange number of cylinders"));
3626 puts(_("\td\tprint the raw data in the partition table"));
3627 puts(_("\te\tlist extended partitions")); /* !sun */
3628 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3629 puts(_("\th\tchange number of heads"));
3630 puts(_("\tm\tprint this menu"));
3631 puts(_("\tp\tprint the partition table"));
3632 puts(_("\tq\tquit without saving changes"));
3633 puts(_("\tr\treturn to main menu"));
3634 puts(_("\ts\tchange number of sectors/track"));
3635 puts(_("\tv\tverify the partition table"));
3636 puts(_("\tw\twrite table to disk and exit"));
3639 #ifdef CONFIG_FEATURE_AIX_LABEL
3641 puts(_("Command action"));
3642 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3643 puts(_("\tc\tchange number of cylinders"));
3644 puts(_("\td\tprint the raw data in the partition table"));
3645 puts(_("\te\tlist extended partitions")); /* !sun */
3646 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3647 puts(_("\th\tchange number of heads"));
3648 puts(_("\tm\tprint this menu"));
3649 puts(_("\tp\tprint the partition table"));
3650 puts(_("\tq\tquit without saving changes"));
3651 puts(_("\tr\treturn to main menu"));
3652 puts(_("\ts\tchange number of sectors/track"));
3653 puts(_("\tv\tverify the partition table"));
3654 puts(_("\tw\twrite table to disk and exit"));
3658 puts(_("Command action"));
3659 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3660 puts(_("\tc\tchange number of cylinders"));
3661 puts(_("\td\tprint the raw data in the partition table"));
3662 puts(_("\te\tlist extended partitions")); /* !sun */
3663 puts(_("\tf\tfix partition order")); /* !sun, !aix, !sgi */
3664 #ifdef CONFIG_FEATURE_SGI_LABEL
3665 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3667 puts(_("\th\tchange number of heads"));
3668 puts(_("\tm\tprint this menu"));
3669 puts(_("\tp\tprint the partition table"));
3670 puts(_("\tq\tquit without saving changes"));
3671 puts(_("\tr\treturn to main menu"));
3672 puts(_("\ts\tchange number of sectors/track"));
3673 puts(_("\tv\tverify the partition table"));
3674 puts(_("\tw\twrite table to disk and exit"));
3677 #endif /* ADVANCED mode */
3679 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3680 static const struct systypes *
3681 get_sys_types(void) {
3683 #ifdef CONFIG_FEATURE_SUN_LABEL
3684 sun_label ? sun_sys_types :
3686 #ifdef CONFIG_FEATURE_SGI_LABEL
3687 sgi_label ? sgi_sys_types :
3692 #define get_sys_types() i386_sys_types
3693 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3695 static const char *partition_type(unsigned char type)
3698 const struct systypes *types = get_sys_types();
3700 for (i=0; types[i].name; i++)
3701 if (types[i].name[0] == type)
3702 return types[i].name + 1;
3704 return _("Unknown");
3708 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3712 #ifdef CONFIG_FEATURE_SUN_LABEL
3713 sun_label ? sunlabel->infos[i].id :
3715 #ifdef CONFIG_FEATURE_SGI_LABEL
3716 sgi_label ? sgi_get_sysid(i) :
3718 ptes[i].part_table->sys_ind);
3721 void list_types(const struct systypes *sys)
3723 uint last[4], done = 0, next = 0, size;
3726 for (i = 0; sys[i].name; i++);
3729 for (i = 3; i >= 0; i--)
3730 last[3 - i] = done += (size + i - done) / (i + 1);
3734 printf("%c%2x %-15.15s", i ? ' ' : '\n',
3735 sys[next].name[0], partition_type(sys[next].name[0]));
3736 next = last[i++] + done;
3737 if (i > 3 || next >= last[i]) {
3741 } while (done < last[0]);
3744 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3747 is_cleared_partition(const struct partition *p) {
3748 return !(!p || p->boot_ind || p->head || p->sector || p->cyl ||
3749 p->sys_ind || p->end_head || p->end_sector || p->end_cyl ||
3750 get_start_sect(p) || get_nr_sects(p));
3754 clear_partition(struct partition *p) {
3757 memset(p, 0, sizeof(struct partition));
3760 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3762 set_partition(int i, int doext, uint start, uint stop, int sysid) {
3763 struct partition *p;
3767 p = ptes[i].ext_pointer;
3768 offset = extended_offset;
3770 p = ptes[i].part_table;
3771 offset = ptes[i].offset;
3775 set_start_sect(p, start - offset);
3776 set_nr_sects(p, stop - start + 1);
3777 if (dos_compatible_flag && (start/(sectors*heads) > 1023))
3778 start = heads*sectors*1024 - 1;
3779 set_hsc(p->head, p->sector, p->cyl, start);
3780 if (dos_compatible_flag && (stop/(sectors*heads) > 1023))
3781 stop = heads*sectors*1024 - 1;
3782 set_hsc(p->end_head, p->end_sector, p->end_cyl, stop);
3783 ptes[i].changed = 1;
3788 test_c(const char **m, const char *mesg) {
3791 fprintf(stderr, _("You must set"));
3793 fprintf(stderr, " %s", *m);
3801 warn_geometry(void) {
3802 const char *m = NULL;
3806 prev = test_c(&m, _("heads"));
3808 prev = test_c(&m, _("sectors"));
3810 prev = test_c(&m, _("cylinders"));
3814 fprintf(stderr, "%s%s.\n"
3815 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3816 "You can do this from the extra functions menu.\n"
3818 , prev ? _(" and ") : " ", m);
3823 static void update_units(void)
3825 int cyl_units = heads * sectors;
3827 if (display_in_cyl_units && cyl_units)
3828 units_per_sector = cyl_units;
3830 units_per_sector = 1; /* in sectors */
3833 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3835 warn_cylinders(void) {
3836 if (dos_label && cylinders > 1024 && !nowarn)
3837 fprintf(stderr, _("\n"
3838 "The number of cylinders for this disk is set to %d.\n"
3839 "There is nothing wrong with that, but this is larger than 1024,\n"
3840 "and could in certain setups cause problems with:\n"
3841 "1) software that runs at boot time (e.g., old versions of LILO)\n"
3842 "2) booting and partitioning software from other OSs\n"
3843 " (e.g., DOS FDISK, OS/2 FDISK)\n"),
3849 read_extended(int ext) {
3852 struct partition *p, *q;
3856 pex->ext_pointer = pex->part_table;
3858 p = pex->part_table;
3859 if (!get_start_sect(p)) {
3861 _("Bad offset in primary extended partition\n"));
3865 while (IS_EXTENDED (p->sys_ind)) {
3866 struct pte *pe = &ptes[partitions];
3868 if (partitions >= MAXIMUM_PARTS) {
3869 /* This is not a Linux restriction, but
3870 this program uses arrays of size MAXIMUM_PARTS.
3871 Do not try to `improve' this test. */
3872 struct pte *pre = &ptes[partitions-1];
3873 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3875 _("Warning: deleting partitions after %d\n"),
3879 clear_partition(pre->ext_pointer);
3883 read_pte(pe, extended_offset + get_start_sect(p));
3885 if (!extended_offset)
3886 extended_offset = get_start_sect(p);
3888 q = p = pt_offset(pe->sectorbuffer, 0);
3889 for (i = 0; i < 4; i++, p++) if (get_nr_sects(p)) {
3890 if (IS_EXTENDED (p->sys_ind)) {
3891 if (pe->ext_pointer)
3893 _("Warning: extra link "
3894 "pointer in partition table"
3895 " %d\n"), partitions + 1);
3897 pe->ext_pointer = p;
3898 } else if (p->sys_ind) {
3901 _("Warning: ignoring extra "
3902 "data in partition table"
3903 " %d\n"), partitions + 1);
3909 /* very strange code here... */
3910 if (!pe->part_table) {
3911 if (q != pe->ext_pointer)
3914 pe->part_table = q + 1;
3916 if (!pe->ext_pointer) {
3917 if (q != pe->part_table)
3918 pe->ext_pointer = q;
3920 pe->ext_pointer = q + 1;
3923 p = pe->ext_pointer;
3927 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3928 /* remove empty links */
3930 for (i = 4; i < partitions; i++) {
3931 struct pte *pe = &ptes[i];
3933 if (!get_nr_sects(pe->part_table) &&
3934 (partitions > 5 || ptes[4].part_table->sys_ind)) {
3935 printf("omitting empty partition (%d)\n", i+1);
3936 delete_partition(i);
3937 goto remove; /* numbering changed */
3943 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3945 create_doslabel(void) {
3949 _("Building a new DOS disklabel. Changes will remain in memory only,\n"
3950 "until you decide to write them. After that, of course, the previous\n"
3951 "content won't be recoverable.\n\n"));
3952 #ifdef CONFIG_FEATURE_SUN_LABEL
3953 sun_nolabel(); /* otherwise always recognised as sun */
3955 #ifdef CONFIG_FEATURE_SGI_LABEL
3956 sgi_nolabel(); /* otherwise always recognised as sgi */
3958 #ifdef CONFIG_FEATURE_AIX_LABEL
3961 #ifdef CONFIG_FEATURE_OSF_LABEL
3963 possibly_osf_label = 0;
3967 for (i = 510-64; i < 510; i++)
3969 write_part_table_flag(MBRbuffer);
3970 extended_offset = 0;
3971 set_all_unchanged();
3973 get_boot(create_empty_dos);
3975 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3978 get_sectorsize(void) {
3979 if (!user_set_sector_size &&
3980 get_kernel_revision() >= MAKE_VERSION(2,3,3)) {
3982 if (ioctl(fd, BLKSSZGET, &arg) == 0)
3984 if (sector_size != DEFAULT_SECTOR_SIZE)
3985 printf(_("Note: sector size is %d (not %d)\n"),
3986 sector_size, DEFAULT_SECTOR_SIZE);
3991 get_kernel_geometry(void) {
3992 struct hd_geometry geometry;
3994 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
3995 kern_heads = geometry.heads;
3996 kern_sectors = geometry.sectors;
3997 /* never use geometry.cylinders - it is truncated */
4002 get_partition_table_geometry(void) {
4003 const unsigned char *bufp = MBRbuffer;
4004 struct partition *p;
4005 int i, h, s, hh, ss;
4009 if (!(valid_part_table_flag(bufp)))
4013 for (i=0; i<4; i++) {
4014 p = pt_offset(bufp, i);
4015 if (p->sys_ind != 0) {
4016 h = p->end_head + 1;
4017 s = (p->end_sector & 077);
4022 } else if (hh != h || ss != s)
4027 if (!first && !bad) {
4034 get_geometry(void) {
4036 unsigned long long bytes; /* really u64 */
4039 sec_fac = sector_size / 512;
4040 #ifdef CONFIG_FEATURE_SUN_LABEL
4041 guess_device_type();
4043 heads = cylinders = sectors = 0;
4044 kern_heads = kern_sectors = 0;
4045 pt_heads = pt_sectors = 0;
4047 get_kernel_geometry();
4048 get_partition_table_geometry();
4050 heads = user_heads ? user_heads :
4051 pt_heads ? pt_heads :
4052 kern_heads ? kern_heads : 255;
4053 sectors = user_sectors ? user_sectors :
4054 pt_sectors ? pt_sectors :
4055 kern_sectors ? kern_sectors : 63;
4056 if (ioctl(fd, BLKGETSIZE64, &bytes) == 0) {
4059 unsigned long longsectors;
4061 if (ioctl(fd, BLKGETSIZE, &longsectors))
4063 bytes = ((unsigned long long) longsectors) << 9;
4066 total_number_of_sectors = (bytes >> 9);
4069 if (dos_compatible_flag)
4070 sector_offset = sectors;
4072 cylinders = total_number_of_sectors / (heads * sectors * sec_fac);
4074 cylinders = user_cylinders;
4078 * Read MBR. Returns:
4079 * -1: no 0xaa55 flag present (possibly entire disk BSD)
4080 * 0: found or created label
4084 get_boot(enum action what) {
4089 for (i = 0; i < 4; i++) {
4090 struct pte *pe = &ptes[i];
4092 pe->part_table = pt_offset(MBRbuffer, i);
4093 pe->ext_pointer = NULL;
4095 pe->sectorbuffer = MBRbuffer;
4096 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4097 pe->changed = (what == create_empty_dos);
4101 #ifdef CONFIG_FEATURE_SUN_LABEL
4102 if (what == create_empty_sun && check_sun_label())
4106 memset(MBRbuffer, 0, 512);
4108 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4109 if (what == create_empty_dos)
4110 goto got_dos_table; /* skip reading disk */
4112 if ((fd = open(disk_device, type_open)) < 0) {
4113 if ((fd = open(disk_device, O_RDONLY)) < 0) {
4114 if (what == try_only)
4116 fdisk_fatal(unable_to_open);
4118 printf(_("You will not be able to write "
4119 "the partition table.\n"));
4122 if (512 != read(fd, MBRbuffer, 512)) {
4123 if (what == try_only)
4125 fdisk_fatal(unable_to_read);
4128 if ((fd = open(disk_device, O_RDONLY)) < 0)
4130 if (512 != read(fd, MBRbuffer, 512))
4138 #ifdef CONFIG_FEATURE_SUN_LABEL
4139 if (check_sun_label())
4143 #ifdef CONFIG_FEATURE_SGI_LABEL
4144 if (check_sgi_label())
4148 #ifdef CONFIG_FEATURE_AIX_LABEL
4149 if (check_aix_label())
4153 #ifdef CONFIG_FEATURE_OSF_LABEL
4154 if (check_osf_label()) {
4155 possibly_osf_label = 1;
4156 if (!valid_part_table_flag(MBRbuffer)) {
4160 printf(_("This disk has both DOS and BSD magic.\n"
4161 "Give the 'b' command to go to BSD mode.\n"));
4165 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4169 if (!valid_part_table_flag(MBRbuffer)) {
4170 #ifndef CONFIG_FEATURE_FDISK_WRITABLE
4176 _("Device contains neither a valid DOS "
4177 "partition table, nor Sun, SGI or OSF "
4180 #ifdef CONFIG_FEATURE_SUN_LABEL
4189 case create_empty_dos:
4190 #ifdef CONFIG_FEATURE_SUN_LABEL
4191 case create_empty_sun:
4195 fprintf(stderr, _("Internal error\n"));
4198 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
4201 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4206 for (i = 0; i < 4; i++) {
4207 struct pte *pe = &ptes[i];
4209 if (IS_EXTENDED (pe->part_table->sys_ind)) {
4210 if (partitions != 4)
4211 fprintf(stderr, _("Ignoring extra extended "
4212 "partition %d\n"), i + 1);
4218 for (i = 3; i < partitions; i++) {
4219 struct pte *pe = &ptes[i];
4221 if (!valid_part_table_flag(pe->sectorbuffer)) {
4223 _("Warning: invalid flag 0x%04x of partition "
4224 "table %d will be corrected by w(rite)\n"),
4225 part_table_flag(pe->sectorbuffer), i + 1);
4226 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4235 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4237 * Print the message MESG, then read an integer between LOW and HIGH (inclusive).
4238 * If the user hits Enter, DFLT is returned.
4239 * Answers like +10 are interpreted as offsets from BASE.
4241 * There is no default if DFLT is not between LOW and HIGH.
4244 read_int(uint low, uint dflt, uint high, uint base, char *mesg)
4248 static char *ms = NULL;
4249 static int mslen = 0;
4251 if (!ms || strlen(mesg)+100 > mslen) {
4252 mslen = strlen(mesg)+200;
4253 ms = xrealloc(ms,mslen);
4256 if (dflt < low || dflt > high)
4260 snprintf(ms, mslen, _("%s (%u-%u, default %u): "),
4261 mesg, low, high, dflt);
4263 snprintf(ms, mslen, "%s (%u-%u): ",
4267 int use_default = default_ok;
4269 /* ask question and read answer */
4270 while (read_chars(ms) != '\n' && !isdigit(*line_ptr)
4271 && *line_ptr != '-' && *line_ptr != '+')
4274 if (*line_ptr == '+' || *line_ptr == '-') {
4275 int minus = (*line_ptr == '-');
4278 i = atoi(line_ptr+1);
4280 while (isdigit(*++line_ptr))
4283 switch (*line_ptr) {
4286 if (!display_in_cyl_units)
4287 i *= heads * sectors;
4301 absolute = 1000000000;
4307 unsigned long long bytes;
4310 bytes = (unsigned long long) i * absolute;
4311 unit = sector_size * units_per_sector;
4312 bytes += unit/2; /* round */
4321 while (isdigit(*line_ptr)) {
4327 printf(_("Using default value %u\n"), i = dflt);
4328 if (i >= low && i <= high)
4331 printf(_("Value out of range.\n"));
4337 get_partition(int warn, int max) {
4341 i = read_int(1, 0, max, 0, _("Partition number")) - 1;
4345 if ((!sun_label && !sgi_label && !pe->part_table->sys_ind)
4346 #ifdef CONFIG_FEATURE_SUN_LABEL
4348 (!sunlabel->partitions[i].num_sectors ||
4349 !sunlabel->infos[i].id))
4351 #ifdef CONFIG_FEATURE_SGI_LABEL
4352 || (sgi_label && (!sgi_get_num_sectors(i)))
4356 _("Warning: partition %d has empty type\n"),
4363 get_existing_partition(int warn, int max) {
4367 for (i = 0; i < max; i++) {
4368 struct pte *pe = &ptes[i];
4369 struct partition *p = pe->part_table;
4371 if (p && !is_cleared_partition(p)) {
4378 printf(_("Selected partition %d\n"), pno+1);
4381 printf(_("No partition is defined yet!\n"));
4385 return get_partition(warn, max);
4389 get_nonexisting_partition(int warn, int max) {
4393 for (i = 0; i < max; i++) {
4394 struct pte *pe = &ptes[i];
4395 struct partition *p = pe->part_table;
4397 if (p && is_cleared_partition(p)) {
4404 printf(_("Selected partition %d\n"), pno+1);
4407 printf(_("All primary partitions have been defined already!\n"));
4411 return get_partition(warn, max);
4415 void change_units(void)
4417 display_in_cyl_units = !display_in_cyl_units;
4419 printf(_("Changing display/entry units to %s\n"),
4424 toggle_active(int i) {
4425 struct pte *pe = &ptes[i];
4426 struct partition *p = pe->part_table;
4428 if (IS_EXTENDED (p->sys_ind) && !p->boot_ind)
4430 _("WARNING: Partition %d is an extended partition\n"),
4432 p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG);
4437 toggle_dos_compatibility_flag(void) {
4438 dos_compatible_flag = ~dos_compatible_flag;
4439 if (dos_compatible_flag) {
4440 sector_offset = sectors;
4441 printf(_("DOS Compatibility flag is set\n"));
4445 printf(_("DOS Compatibility flag is not set\n"));
4450 delete_partition(int i) {
4451 struct pte *pe = &ptes[i];
4452 struct partition *p = pe->part_table;
4453 struct partition *q = pe->ext_pointer;
4455 /* Note that for the fifth partition (i == 4) we don't actually
4456 * decrement partitions.
4459 if (warn_geometry())
4460 return; /* C/H/S not set */
4463 #ifdef CONFIG_FEATURE_SUN_LABEL
4465 sun_delete_partition(i);
4469 #ifdef CONFIG_FEATURE_SGI_LABEL
4471 sgi_delete_partition(i);
4477 if (IS_EXTENDED (p->sys_ind) && i == ext_index) {
4479 ptes[ext_index].ext_pointer = NULL;
4480 extended_offset = 0;
4486 if (!q->sys_ind && i > 4) {
4487 /* the last one in the chain - just delete */
4490 clear_partition(ptes[i].ext_pointer);
4491 ptes[i].changed = 1;
4493 /* not the last one - further ones will be moved down */
4495 /* delete this link in the chain */
4496 p = ptes[i-1].ext_pointer;
4498 set_start_sect(p, get_start_sect(q));
4499 set_nr_sects(p, get_nr_sects(q));
4500 ptes[i-1].changed = 1;
4501 } else if (partitions > 5) { /* 5 will be moved to 4 */
4502 /* the first logical in a longer chain */
4505 if (pe->part_table) /* prevent SEGFAULT */
4506 set_start_sect(pe->part_table,
4507 get_partition_start(pe) -
4509 pe->offset = extended_offset;
4513 if (partitions > 5) {
4515 while (i < partitions) {
4516 ptes[i] = ptes[i+1];
4520 /* the only logical: clear only */
4521 clear_partition(ptes[i].part_table);
4526 change_sysid(void) {
4527 int i, sys, origsys;
4528 struct partition *p;
4530 #ifdef CONFIG_FEATURE_SGI_LABEL
4531 /* If sgi_label then don't use get_existing_partition,
4532 let the user select a partition, since get_existing_partition()
4533 only works for Linux like partition tables. */
4535 i = get_existing_partition(0, partitions);
4537 i = get_partition(0, partitions);
4540 i = get_existing_partition(0, partitions);
4544 p = ptes[i].part_table;
4545 origsys = sys = get_sysid(i);
4547 /* if changing types T to 0 is allowed, then
4548 the reverse change must be allowed, too */
4549 if (!sys && !sgi_label && !sun_label && !get_nr_sects(p))
4550 printf(_("Partition %d does not exist yet!\n"), i + 1);
4552 sys = read_hex (get_sys_types());
4554 if (!sys && !sgi_label && !sun_label) {
4555 printf(_("Type 0 means free space to many systems\n"
4556 "(but not to Linux). Having partitions of\n"
4557 "type 0 is probably unwise. You can delete\n"
4558 "a partition using the `d' command.\n"));
4562 if (!sun_label && !sgi_label) {
4563 if (IS_EXTENDED (sys) != IS_EXTENDED (p->sys_ind)) {
4564 printf(_("You cannot change a partition into"
4565 " an extended one or vice versa\n"
4566 "Delete it first.\n"));
4572 #ifdef CONFIG_FEATURE_SUN_LABEL
4573 if (sun_label && i == 2 && sys != WHOLE_DISK)
4574 printf(_("Consider leaving partition 3 "
4575 "as Whole disk (5),\n"
4576 "as SunOS/Solaris expects it and "
4577 "even Linux likes it.\n\n"));
4579 #ifdef CONFIG_FEATURE_SGI_LABEL
4580 if (sgi_label && ((i == 10 && sys != ENTIRE_DISK)
4581 || (i == 8 && sys != 0)))
4582 printf(_("Consider leaving partition 9 "
4583 "as volume header (0),\nand "
4584 "partition 11 as entire volume (6)"
4585 "as IRIX expects it.\n\n"));
4589 #ifdef CONFIG_FEATURE_SUN_LABEL
4591 sun_change_sysid(i, sys);
4594 #ifdef CONFIG_FEATURE_SGI_LABEL
4596 sgi_change_sysid(i, sys);
4600 printf (_("Changed system type of partition %d "
4601 "to %x (%s)\n"), i + 1, sys,
4602 partition_type(sys));
4603 ptes[i].changed = 1;
4604 if (is_dos_partition(origsys) ||
4605 is_dos_partition(sys))
4611 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
4614 /* check_consistency() and long2chs() added Sat Mar 6 12:28:16 1993,
4615 * faith@cs.unc.edu, based on code fragments from pfdisk by Gordon W. Ross,
4616 * Jan. 1990 (version 1.2.1 by Gordon W. Ross Aug. 1990; Modified by S.
4617 * Lubkin Oct. 1991). */
4619 static void long2chs(ulong ls, uint *c, uint *h, uint *s) {
4620 int spc = heads * sectors;
4625 *s = ls % sectors + 1; /* sectors count from 1 */
4628 static void check_consistency(const struct partition *p, int partition) {
4629 uint pbc, pbh, pbs; /* physical beginning c, h, s */
4630 uint pec, peh, pes; /* physical ending c, h, s */
4631 uint lbc, lbh, lbs; /* logical beginning c, h, s */
4632 uint lec, leh, les; /* logical ending c, h, s */
4634 if (!heads || !sectors || (partition >= 4))
4635 return; /* do not check extended partitions */
4637 /* physical beginning c, h, s */
4638 pbc = (p->cyl & 0xff) | ((p->sector << 2) & 0x300);
4640 pbs = p->sector & 0x3f;
4642 /* physical ending c, h, s */
4643 pec = (p->end_cyl & 0xff) | ((p->end_sector << 2) & 0x300);
4645 pes = p->end_sector & 0x3f;
4647 /* compute logical beginning (c, h, s) */
4648 long2chs(get_start_sect(p), &lbc, &lbh, &lbs);
4650 /* compute logical ending (c, h, s) */
4651 long2chs(get_start_sect(p) + get_nr_sects(p) - 1, &lec, &leh, &les);
4653 /* Same physical / logical beginning? */
4654 if (cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) {
4655 printf(_("Partition %d has different physical/logical "
4656 "beginnings (non-Linux?):\n"), partition + 1);
4657 printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs);
4658 printf(_("logical=(%d, %d, %d)\n"),lbc, lbh, lbs);
4661 /* Same physical / logical ending? */
4662 if (cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) {
4663 printf(_("Partition %d has different physical/logical "
4664 "endings:\n"), partition + 1);
4665 printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
4666 printf(_("logical=(%d, %d, %d)\n"),lec, leh, les);
4670 /* Beginning on cylinder boundary? */
4671 if (pbh != !pbc || pbs != 1) {
4672 printf(_("Partition %i does not start on cylinder "
4673 "boundary:\n"), partition + 1);
4674 printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs);
4675 printf(_("should be (%d, %d, 1)\n"), pbc, !pbc);
4679 /* Ending on cylinder boundary? */
4680 if (peh != (heads - 1) || pes != sectors) {
4681 printf(_("Partition %i does not end on cylinder boundary.\n"),
4684 printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
4685 printf(_("should be (%d, %d, %d)\n"),
4686 pec, heads - 1, sectors);
4692 list_disk_geometry(void) {
4693 long long bytes = (total_number_of_sectors << 9);
4694 long megabytes = bytes/1000000;
4696 if (megabytes < 10000)
4697 printf(_("\nDisk %s: %ld MB, %lld bytes\n"),
4698 disk_device, megabytes, bytes);
4700 printf(_("\nDisk %s: %ld.%ld GB, %lld bytes\n"),
4701 disk_device, megabytes/1000, (megabytes/100)%10, bytes);
4702 printf(_("%d heads, %d sectors/track, %d cylinders"),
4703 heads, sectors, cylinders);
4704 if (units_per_sector == 1)
4705 printf(_(", total %llu sectors"),
4706 total_number_of_sectors / (sector_size/512));
4707 printf(_("\nUnits = %s of %d * %d = %d bytes\n\n"),
4709 units_per_sector, sector_size, units_per_sector * sector_size);
4713 * Check whether partition entries are ordered by their starting positions.
4714 * Return 0 if OK. Return i if partition i should have been earlier.
4715 * Two separate checks: primary and logical partitions.
4718 wrong_p_order(int *prev) {
4719 const struct pte *pe;
4720 const struct partition *p;
4721 uint last_p_start_pos = 0, p_start_pos;
4724 for (i = 0 ; i < partitions; i++) {
4727 last_p_start_pos = 0;
4730 if ((p = pe->part_table)->sys_ind) {
4731 p_start_pos = get_partition_start(pe);
4733 if (last_p_start_pos > p_start_pos) {
4739 last_p_start_pos = p_start_pos;
4746 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
4748 * Fix the chain of logicals.
4749 * extended_offset is unchanged, the set of sectors used is unchanged
4750 * The chain is sorted so that sectors increase, and so that
4751 * starting sectors increase.
4753 * After this it may still be that cfdisk doesnt like the table.
4754 * (This is because cfdisk considers expanded parts, from link to
4755 * end of partition, and these may still overlap.)
4757 * sfdisk /dev/hda > ohda; sfdisk /dev/hda < ohda
4761 fix_chain_of_logicals(void) {
4762 int j, oj, ojj, sj, sjj;
4763 struct partition *pj,*pjj,tmp;
4765 /* Stage 1: sort sectors but leave sector of part 4 */
4766 /* (Its sector is the global extended_offset.) */
4768 for (j = 5; j < partitions-1; j++) {
4769 oj = ptes[j].offset;
4770 ojj = ptes[j+1].offset;
4772 ptes[j].offset = ojj;
4773 ptes[j+1].offset = oj;
4774 pj = ptes[j].part_table;
4775 set_start_sect(pj, get_start_sect(pj)+oj-ojj);
4776 pjj = ptes[j+1].part_table;
4777 set_start_sect(pjj, get_start_sect(pjj)+ojj-oj);
4778 set_start_sect(ptes[j-1].ext_pointer,
4779 ojj-extended_offset);
4780 set_start_sect(ptes[j].ext_pointer,
4781 oj-extended_offset);
4786 /* Stage 2: sort starting sectors */
4788 for (j = 4; j < partitions-1; j++) {
4789 pj = ptes[j].part_table;
4790 pjj = ptes[j+1].part_table;
4791 sj = get_start_sect(pj);
4792 sjj = get_start_sect(pjj);
4793 oj = ptes[j].offset;
4794 ojj = ptes[j+1].offset;
4795 if (oj+sj > ojj+sjj) {
4799 set_start_sect(pj, ojj+sjj-oj);
4800 set_start_sect(pjj, oj+sj-ojj);
4805 /* Probably something was changed */
4806 for (j = 4; j < partitions; j++)
4807 ptes[j].changed = 1;
4812 fix_partition_table_order(void) {
4813 struct pte *pei, *pek;
4816 if (!wrong_p_order(NULL)) {
4817 printf(_("Nothing to do. Ordering is correct already.\n\n"));
4821 while ((i = wrong_p_order(&k)) != 0 && i < 4) {
4822 /* partition i should have come earlier, move it */
4823 /* We have to move data in the MBR */
4824 struct partition *pi, *pk, *pe, pbuf;
4828 pe = pei->ext_pointer;
4829 pei->ext_pointer = pek->ext_pointer;
4830 pek->ext_pointer = pe;
4832 pi = pei->part_table;
4833 pk = pek->part_table;
4835 memmove(&pbuf, pi, sizeof(struct partition));
4836 memmove(pi, pk, sizeof(struct partition));
4837 memmove(pk, &pbuf, sizeof(struct partition));
4839 pei->changed = pek->changed = 1;
4843 fix_chain_of_logicals();
4851 list_table(int xtra) {
4852 const struct partition *p;
4855 #ifdef CONFIG_FEATURE_SUN_LABEL
4857 sun_list_table(xtra);
4862 #ifdef CONFIG_FEATURE_SGI_LABEL
4864 sgi_list_table(xtra);
4869 list_disk_geometry();
4871 #ifdef CONFIG_FEATURE_OSF_LABEL
4873 xbsd_print_disklabel(xtra);
4878 /* Heuristic: we list partition 3 of /dev/foo as /dev/foo3,
4879 but if the device name ends in a digit, say /dev/foo1,
4880 then the partition is called /dev/foo1p3. */
4881 w = strlen(disk_device);
4882 if (w && isdigit(disk_device[w-1]))
4887 printf(_("%*s Boot Start End Blocks Id System\n"),
4890 for (i = 0; i < partitions; i++) {
4891 const struct pte *pe = &ptes[i];
4894 if (p && !is_cleared_partition(p)) {
4895 unsigned int psects = get_nr_sects(p);
4896 unsigned int pblocks = psects;
4897 unsigned int podd = 0;
4899 if (sector_size < 1024) {
4900 pblocks /= (1024 / sector_size);
4901 podd = psects % (1024 / sector_size);
4903 if (sector_size > 1024)
4904 pblocks *= (sector_size / 1024);
4906 "%s %c %11lu %11lu %11lu%c %2x %s\n",
4907 partname(disk_device, i+1, w+2),
4908 /* boot flag */ !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG
4910 /* start */ (unsigned long) cround(get_partition_start(pe)),
4911 /* end */ (unsigned long) cround(get_partition_start(pe) + psects
4912 - (psects ? 1 : 0)),
4913 /* odd flag on end */ (unsigned long) pblocks, podd ? '+' : ' ',
4914 /* type id */ p->sys_ind,
4915 /* type name */ partition_type(p->sys_ind));
4916 check_consistency(p, i);
4920 /* Is partition table in disk order? It need not be, but... */
4921 /* partition table entries are not checked for correct order if this
4922 is a sgi, sun or aix labeled disk... */
4923 if (dos_label && wrong_p_order(NULL)) {
4924 printf(_("\nPartition table entries are not in disk order\n"));
4928 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
4930 x_list_table(int extend) {
4931 const struct pte *pe;
4932 const struct partition *p;
4935 printf(_("\nDisk %s: %d heads, %d sectors, %d cylinders\n\n"),
4936 disk_device, heads, sectors, cylinders);
4937 printf(_("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n"));
4938 for (i = 0 ; i < partitions; i++) {
4940 p = (extend ? pe->ext_pointer : pe->part_table);
4942 printf("%2d %02x%4d%4d%5d%4d%4d%5d%11u%11u %02x\n",
4943 i + 1, p->boot_ind, p->head,
4945 cylinder(p->sector, p->cyl), p->end_head,
4946 sector(p->end_sector),
4947 cylinder(p->end_sector, p->end_cyl),
4948 get_start_sect(p), get_nr_sects(p), p->sys_ind);
4950 check_consistency(p, i);
4956 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4958 fill_bounds(uint *first, uint *last) {
4960 const struct pte *pe = &ptes[0];
4961 const struct partition *p;
4963 for (i = 0; i < partitions; pe++,i++) {
4965 if (!p->sys_ind || IS_EXTENDED (p->sys_ind)) {
4966 first[i] = 0xffffffff;
4969 first[i] = get_partition_start(pe);
4970 last[i] = first[i] + get_nr_sects(p) - 1;
4976 check(int n, uint h, uint s, uint c, uint start) {
4977 uint total, real_s, real_c;
4979 real_s = sector(s) - 1;
4980 real_c = cylinder(s, c);
4981 total = (real_c * sectors + real_s) * heads + h;
4983 fprintf(stderr, _("Warning: partition %d contains sector 0\n"), n);
4986 _("Partition %d: head %d greater than maximum %d\n"),
4988 if (real_s >= sectors)
4989 fprintf(stderr, _("Partition %d: sector %d greater than "
4990 "maximum %d\n"), n, s, sectors);
4991 if (real_c >= cylinders)
4992 fprintf(stderr, _("Partitions %d: cylinder %d greater than "
4993 "maximum %d\n"), n, real_c + 1, cylinders);
4994 if (cylinders <= 1024 && start != total)
4996 _("Partition %d: previous sectors %d disagrees with "
4997 "total %d\n"), n, start, total);
5004 uint first[partitions], last[partitions];
5005 struct partition *p;
5007 if (warn_geometry())
5010 #ifdef CONFIG_FEATURE_SUN_LABEL
5016 #ifdef CONFIG_FEATURE_SGI_LABEL
5023 fill_bounds(first, last);
5024 for (i = 0; i < partitions; i++) {
5025 struct pte *pe = &ptes[i];
5028 if (p->sys_ind && !IS_EXTENDED (p->sys_ind)) {
5029 check_consistency(p, i);
5030 if (get_partition_start(pe) < first[i])
5031 printf(_("Warning: bad start-of-data in "
5032 "partition %d\n"), i + 1);
5033 check(i + 1, p->end_head, p->end_sector, p->end_cyl,
5035 total += last[i] + 1 - first[i];
5036 for (j = 0; j < i; j++)
5037 if ((first[i] >= first[j] && first[i] <= last[j])
5038 || ((last[i] <= last[j] && last[i] >= first[j]))) {
5039 printf(_("Warning: partition %d overlaps "
5040 "partition %d.\n"), j + 1, i + 1);
5041 total += first[i] >= first[j] ?
5042 first[i] : first[j];
5043 total -= last[i] <= last[j] ?
5049 if (extended_offset) {
5050 struct pte *pex = &ptes[ext_index];
5051 uint e_last = get_start_sect(pex->part_table) +
5052 get_nr_sects(pex->part_table) - 1;
5054 for (i = 4; i < partitions; i++) {
5056 p = ptes[i].part_table;
5058 if (i != 4 || i + 1 < partitions)
5059 printf(_("Warning: partition %d "
5060 "is empty\n"), i + 1);
5062 else if (first[i] < extended_offset ||
5064 printf(_("Logical partition %d not entirely in "
5065 "partition %d\n"), i + 1, ext_index + 1);
5069 if (total > heads * sectors * cylinders)
5070 printf(_("Total allocated sectors %d greater than the maximum "
5071 "%d\n"), total, heads * sectors * cylinders);
5072 else if ((total = heads * sectors * cylinders - total) != 0)
5073 printf(_("%d unallocated sectors\n"), total);
5077 add_partition(int n, int sys) {
5078 char mesg[256]; /* 48 does not suffice in Japanese */
5080 struct partition *p = ptes[n].part_table;
5081 struct partition *q = ptes[ext_index].part_table;
5083 uint start, stop = 0, limit, temp,
5084 first[partitions], last[partitions];
5086 if (p && p->sys_ind) {
5087 printf(_("Partition %d is already defined. Delete "
5088 "it before re-adding it.\n"), n + 1);
5091 fill_bounds(first, last);
5093 start = sector_offset;
5094 if (display_in_cyl_units || !total_number_of_sectors)
5095 llimit = heads * sectors * cylinders - 1;
5097 llimit = total_number_of_sectors - 1;
5099 if (limit != llimit)
5101 if (extended_offset) {
5102 first[ext_index] = extended_offset;
5103 last[ext_index] = get_start_sect(q) +
5104 get_nr_sects(q) - 1;
5107 start = extended_offset + sector_offset;
5108 limit = get_start_sect(q) + get_nr_sects(q) - 1;
5110 if (display_in_cyl_units)
5111 for (i = 0; i < partitions; i++)
5112 first[i] = (cround(first[i]) - 1) * units_per_sector;
5114 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
5117 for (i = 0; i < partitions; i++) {
5120 if (start == ptes[i].offset)
5121 start += sector_offset;
5122 lastplusoff = last[i] + ((n<4) ? 0 : sector_offset);
5123 if (start >= first[i] && start <= lastplusoff)
5124 start = lastplusoff + 1;
5128 if (start >= temp+units_per_sector && readed) {
5129 printf(_("Sector %d is already allocated\n"), temp);
5133 if (!readed && start == temp) {
5136 saved_start = start;
5137 start = read_int(cround(saved_start), cround(saved_start), cround(limit),
5139 if (display_in_cyl_units) {
5140 start = (start - 1) * units_per_sector;
5141 if (start < saved_start) start = saved_start;
5145 } while (start != temp || !readed);
5146 if (n > 4) { /* NOT for fifth partition */
5147 struct pte *pe = &ptes[n];
5149 pe->offset = start - sector_offset;
5150 if (pe->offset == extended_offset) { /* must be corrected */
5152 if (sector_offset == 1)
5157 for (i = 0; i < partitions; i++) {
5158 struct pte *pe = &ptes[i];
5160 if (start < pe->offset && limit >= pe->offset)
5161 limit = pe->offset - 1;
5162 if (start < first[i] && limit >= first[i])
5163 limit = first[i] - 1;
5165 if (start > limit) {
5166 printf(_("No free sectors available\n"));
5171 if (cround(start) == cround(limit)) {
5174 snprintf(mesg, sizeof(mesg),
5175 _("Last %s or +size or +sizeM or +sizeK"),
5176 str_units(SINGULAR));
5177 stop = read_int(cround(start), cround(limit), cround(limit),
5178 cround(start), mesg);
5179 if (display_in_cyl_units) {
5180 stop = stop * units_per_sector - 1;
5186 set_partition(n, 0, start, stop, sys);
5188 set_partition(n - 1, 1, ptes[n].offset, stop, EXTENDED);
5190 if (IS_EXTENDED (sys)) {
5191 struct pte *pe4 = &ptes[4];
5192 struct pte *pen = &ptes[n];
5195 pen->ext_pointer = p;
5196 pe4->offset = extended_offset = start;
5197 pe4->sectorbuffer = xcalloc(1, sector_size);
5198 pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
5199 pe4->ext_pointer = pe4->part_table + 1;
5207 if (partitions > 5 || ptes[4].part_table->sys_ind) {
5208 struct pte *pe = &ptes[partitions];
5210 pe->sectorbuffer = xcalloc(1, sector_size);
5211 pe->part_table = pt_offset(pe->sectorbuffer, 0);
5212 pe->ext_pointer = pe->part_table + 1;
5217 add_partition(partitions - 1, LINUX_NATIVE);
5221 new_partition(void) {
5222 int i, free_primary = 0;
5224 if (warn_geometry())
5227 #ifdef CONFIG_FEATURE_SUN_LABEL
5229 add_sun_partition(get_partition(0, partitions), LINUX_NATIVE);
5233 #ifdef CONFIG_FEATURE_SGI_LABEL
5235 sgi_add_partition(get_partition(0, partitions), LINUX_NATIVE);
5239 #ifdef CONFIG_FEATURE_AIX_LABEL
5241 printf(_("\tSorry - this fdisk cannot handle AIX disk labels."
5242 "\n\tIf you want to add DOS-type partitions, create"
5243 "\n\ta new empty DOS partition table first. (Use o.)"
5245 "This will destroy the present disk contents.\n"));
5250 for (i = 0; i < 4; i++)
5251 free_primary += !ptes[i].part_table->sys_ind;
5253 if (!free_primary && partitions >= MAXIMUM_PARTS) {
5254 printf(_("The maximum number of partitions has been created\n"));
5258 if (!free_primary) {
5259 if (extended_offset)
5262 printf(_("You must delete some partition and add "
5263 "an extended partition first\n"));
5265 char c, line[LINE_LENGTH];
5266 snprintf(line, sizeof(line), "%s\n %s\n p primary "
5267 "partition (1-4)\n",
5268 "Command action", (extended_offset ?
5269 "l logical (5 or over)" : "e extended"));
5271 if ((c = read_char(line)) == 'p' || c == 'P') {
5272 i = get_nonexisting_partition(0, 4);
5274 add_partition(i, LINUX_NATIVE);
5277 else if (c == 'l' && extended_offset) {
5281 else if (c == 'e' && !extended_offset) {
5282 i = get_nonexisting_partition(0, 4);
5284 add_partition(i, EXTENDED);
5288 printf(_("Invalid partition number "
5289 "for type `%c'\n"), c);
5300 if (ptes[i].changed)
5301 ptes[3].changed = 1;
5302 for (i = 3; i < partitions; i++) {
5303 struct pte *pe = &ptes[i];
5306 write_part_table_flag(pe->sectorbuffer);
5307 write_sector(pe->offset, pe->sectorbuffer);
5311 #ifdef CONFIG_FEATURE_SGI_LABEL
5312 else if (sgi_label) {
5313 /* no test on change? the printf below might be mistaken */
5317 #ifdef CONFIG_FEATURE_SUN_LABEL
5318 else if (sun_label) {
5322 if (ptes[i].changed)
5329 printf(_("The partition table has been altered!\n\n"));
5330 reread_partition_table(1);
5334 reread_partition_table(int leave) {
5338 printf(_("Calling ioctl() to re-read partition table.\n"));
5341 if ((i = ioctl(fd, BLKRRPART)) != 0) {
5344 /* some kernel versions (1.2.x) seem to have trouble
5345 rereading the partition table, but if asked to do it
5346 twice, the second time works. - biro@yggdrasil.com */
5349 if ((i = ioctl(fd, BLKRRPART)) != 0)
5354 printf(_("\nWARNING: Re-reading the partition table "
5355 "failed with error %d: %s.\n"
5356 "The kernel still uses the old table.\n"
5357 "The new table will be used "
5358 "at the next reboot.\n"),
5359 error, strerror(error));
5364 _("\nWARNING: If you have created or modified any DOS 6.x\n"
5365 "partitions, please see the fdisk manual page for additional\n"
5371 printf(_("Syncing disks.\n"));
5373 sleep(4); /* for sync() */
5377 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
5379 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
5380 #define MAX_PER_LINE 16
5382 print_buffer(char pbuffer[]) {
5386 for (i = 0, l = 0; i < sector_size; i++, l++) {
5388 printf("0x%03X:", i);
5389 printf(" %02X", (unsigned char) pbuffer[i]);
5390 if (l == MAX_PER_LINE - 1) {
5405 printf(_("Device: %s\n"), disk_device);
5406 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
5407 if (sun_label || sgi_label)
5408 print_buffer(MBRbuffer);
5411 for (i = 3; i < partitions; i++)
5412 print_buffer(ptes[i].sectorbuffer);
5417 struct pte *pe = &ptes[i];
5418 struct partition *p = pe->part_table;
5421 if (warn_geometry())
5423 if (!p->sys_ind || !get_nr_sects(p) || IS_EXTENDED (p->sys_ind)) {
5424 printf(_("Partition %d has no data area\n"), i + 1);
5427 first = get_partition_start(pe);
5428 new = read_int(first, first, first + get_nr_sects(p) - 1, first,
5429 _("New beginning of data")) - pe->offset;
5431 if (new != get_nr_sects(p)) {
5432 first = get_nr_sects(p) + get_start_sect(p) - new;
5433 set_nr_sects(p, first);
5434 set_start_sect(p, new);
5445 c = tolower(read_char(_("Expert command (m for help): ")));
5448 #ifdef CONFIG_FEATURE_SUN_LABEL
5455 move_begin(get_partition(0, partitions));
5458 user_cylinders = cylinders =
5459 read_int(1, cylinders, 1048576, 0,
5460 _("Number of cylinders"));
5461 #ifdef CONFIG_FEATURE_SUN_LABEL
5463 sun_set_ncyl(cylinders);
5472 #ifdef CONFIG_FEATURE_SGI_LABEL
5477 #ifdef CONFIG_FEATURE_SUN_LABEL
5487 fix_partition_table_order();
5490 #ifdef CONFIG_FEATURE_SGI_LABEL
5495 user_heads = heads = read_int(1, heads, 256, 0,
5496 _("Number of heads"));
5500 #ifdef CONFIG_FEATURE_SUN_LABEL
5506 #ifdef CONFIG_FEATURE_SUN_LABEL
5512 #ifdef CONFIG_FEATURE_SUN_LABEL
5526 user_sectors = sectors = read_int(1, sectors, 63, 0,
5527 _("Number of sectors"));
5528 if (dos_compatible_flag) {
5529 sector_offset = sectors;
5530 fprintf(stderr, _("Warning: setting "
5531 "sector offset for DOS "
5540 write_table(); /* does not return */
5543 #ifdef CONFIG_FEATURE_SUN_LABEL
5545 sun_set_pcylcount();
5553 #endif /* ADVANCED mode */
5556 is_ide_cdrom_or_tape(const char *device) {
5559 struct stat statbuf;
5562 /* No device was given explicitly, and we are trying some
5563 likely things. But opening /dev/hdc may produce errors like
5564 "hdc: tray open or drive not ready"
5565 if it happens to be a CD-ROM drive. It even happens that
5566 the process hangs on the attempt to read a music CD.
5567 So try to be careful. This only works since 2.1.73. */
5569 if (strncmp("/dev/hd", device, 7))
5572 snprintf(buf, sizeof(buf), "/proc/ide/%s/media", device+5);
5573 procf = fopen(buf, "r");
5574 if (procf != NULL && fgets(buf, sizeof(buf), procf))
5575 is_ide = (!strncmp(buf, "cdrom", 5) ||
5576 !strncmp(buf, "tape", 4));
5578 /* Now when this proc file does not exist, skip the
5579 device when it is read-only. */
5580 if (stat(device, &statbuf) == 0)
5581 is_ide = ((statbuf.st_mode & 0222) == 0);
5589 try(const char *device, int user_specified) {
5592 disk_device = device;
5593 if (setjmp(listingbuf))
5595 if (!user_specified)
5596 if (is_ide_cdrom_or_tape(device))
5598 if ((fd = open(disk_device, type_open)) >= 0) {
5599 gb = get_boot(try_only);
5600 if (gb > 0) { /* I/O error */
5602 } else if (gb < 0) { /* no DOS signature */
5603 list_disk_geometry();
5606 #ifdef CONFIG_FEATURE_OSF_LABEL
5607 if (btrydev(device) < 0)
5610 _("Disk %s doesn't contain a valid "
5611 "partition table\n"), device);
5616 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5617 if (!sun_label && partitions > 4)
5618 delete_partition(ext_index);
5622 /* Ignore other errors, since we try IDE
5623 and SCSI hard disks which may not be
5624 installed on the system. */
5625 if (errno == EACCES) {
5626 fprintf(stderr, _("Cannot open %s\n"), device);
5632 /* for fdisk -l: try all things in /proc/partitions
5633 that look like a partition name (do not end in a digit) */
5637 char line[100], ptname[100], devname[120], *s;
5640 procpt = bb_wfopen(PROC_PARTITIONS, "r");
5642 while (fgets(line, sizeof(line), procpt)) {
5643 if (sscanf (line, " %d %d %d %[^\n ]",
5644 &ma, &mi, &sz, ptname) != 4)
5646 for (s = ptname; *s; s++);
5649 sprintf(devname, "/dev/%s", ptname);
5652 #ifdef CONFIG_FEATURE_CLEAN_UP
5657 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5659 unknown_command(int c) {
5660 printf(_("%c: unknown command\n"), c);
5664 int fdisk_main(int argc, char **argv) {
5666 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5669 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5675 * fdisk -l [-b sectorsize] [-u] device ...
5676 * fdisk -s [partition] ...
5677 * fdisk [-b sectorsize] [-u] device
5679 * Options -C, -H, -S set the geometry.
5682 while ((c = getopt(argc, argv, "b:C:H:lS:uvV"
5683 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5689 /* Ugly: this sector size is really per device,
5690 so cannot be combined with multiple disks,
5691 and te same goes for the C/H/S options.
5693 sector_size = atoi(optarg);
5694 if (sector_size != 512 && sector_size != 1024 &&
5695 sector_size != 2048)
5698 user_set_sector_size = 1;
5701 user_cylinders = atoi(optarg);
5704 user_heads = atoi(optarg);
5705 if (user_heads <= 0 || user_heads >= 256)
5709 user_sectors = atoi(optarg);
5710 if (user_sectors <= 0 || user_sectors >= 64)
5714 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5718 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5724 display_in_cyl_units = 0;
5728 printf("fdisk v" UTIL_LINUX_VERSION "\n");
5736 printf(_("This kernel finds the sector size itself - "
5737 "-b option ignored\n"));
5739 if (user_set_sector_size && argc-optind != 1)
5740 printf(_("Warning: the -b (set sector size) option should"
5741 " be used with one specified device\n"));
5744 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5748 type_open = O_RDONLY;
5749 if (argc > optind) {
5752 /* avoid gcc warning:
5753 variable `k' might be clobbered by `longjmp' */
5757 for (k=optind; k<argc; k++)
5760 /* we no longer have default device names */
5761 /* but, we can use /proc/partitions instead */
5765 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5769 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5775 type_open = O_RDONLY;
5777 opts = argc - optind;
5781 for (j = optind; j < argc; j++) {
5782 disk_device = argv[j];
5783 if ((fd = open(disk_device, type_open)) < 0)
5784 fdisk_fatal(unable_to_open);
5785 if (ioctl(fd, BLKGETSIZE, &size))
5786 fdisk_fatal(ioctl_error);
5789 printf("%ld\n", size/2);
5791 printf("%s: %ld\n", argv[j], size/2);
5797 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5798 if (argc-optind == 1)
5799 disk_device = argv[optind];
5805 #ifdef CONFIG_FEATURE_OSF_LABEL
5807 /* OSF label, and no DOS label */
5808 printf(_("Detected an OSF/1 disklabel on %s, entering "
5809 "disklabel mode.\n"),
5813 /* If we return we may want to make an empty DOS label? */
5819 c = tolower(read_char(_("Command (m for help): ")));
5823 toggle_active(get_partition(1, partitions));
5824 #ifdef CONFIG_FEATURE_SUN_LABEL
5826 toggle_sunflags(get_partition(1, partitions),
5829 #ifdef CONFIG_FEATURE_SGI_LABEL
5831 sgi_set_bootpartition(
5832 get_partition(1, partitions));
5838 #ifdef CONFIG_FEATURE_SGI_LABEL
5840 printf(_("\nThe current boot file is: %s\n"),
5841 sgi_get_bootfile());
5842 if (read_chars(_("Please enter the name of the "
5843 "new boot file: ")) == '\n')
5844 printf(_("Boot file unchanged\n"));
5846 sgi_set_bootfile(line_ptr);
5849 #ifdef CONFIG_FEATURE_OSF_LABEL
5855 toggle_dos_compatibility_flag();
5856 #ifdef CONFIG_FEATURE_SUN_LABEL
5858 toggle_sunflags(get_partition(1, partitions),
5861 #ifdef CONFIG_FEATURE_SGI_LABEL
5863 sgi_set_swappartition(
5864 get_partition(1, partitions));
5872 #ifdef CONFIG_FEATURE_SGI_LABEL
5873 /* If sgi_label then don't use get_existing_partition,
5874 let the user select a partition, since
5875 get_existing_partition() only works for Linux-like
5878 j = get_existing_partition(1, partitions);
5880 j = get_partition(1, partitions);
5883 j = get_existing_partition(1, partitions);
5886 delete_partition(j);
5890 #ifdef CONFIG_FEATURE_SGI_LABEL
5897 list_types(get_sys_types());
5916 #ifdef CONFIG_FEATURE_SUN_LABEL
5930 write_table(); /* does not return */
5932 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
5934 #ifdef CONFIG_FEATURE_SGI_LABEL
5937 _("\n\tSorry, no experts menu for SGI "
5938 "partition tables available.\n\n"));
5951 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */