1 /* fdisk.c -- Partition table manipulator for Linux.
3 * Copyright (C) 1992 A. V. Le Blanc (LeBlanc@mcc.ac.uk)
5 * This program is free software. You can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation: either version 1 or
8 * (at your option) any later version.
10 * Vladimir Oleynik <dzo@simtreas.ru> 2001,2002 Busybox port
13 #define UTIL_LINUX_VERSION "2.12"
15 #define PROC_PARTITIONS "/proc/partitions"
17 #include <sys/types.h>
18 #include <sys/stat.h> /* stat */
27 #include <assert.h> /* assert */
31 #define u_char unsigned char
32 #include <scsi/scsi.h> /* SCSI_IOCTL_GET_IDLUN */
35 #include <sys/ioctl.h>
36 #include <sys/param.h>
37 #include <sys/sysmacros.h> /* major */
39 #include <stdint.h> /* for uint32_t, uint16_t, uint8_t, int16_t, etc */
41 /* Copied from linux/major.h */
42 #define FLOPPY_MAJOR 2
44 #include <sys/utsname.h>
48 #define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r))
54 #define BLKRRPART _IO(0x12,95) /* re-read partition table */
55 #define BLKGETSIZE _IO(0x12,96) /* return device size */
56 #define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */
57 #define BLKSSZGET _IO(0x12,104) /* get block device sector size */
58 #define BLKGETSIZE64 _IOR(0x12,114,8) /* 8 = sizeof(u64) */
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)
92 #if defined(CONFIG_LFS) || defined(FDISK_SUPPORT_LARGE_DISKS) || defined(__alpha__) || defined(__ia64__) || defined(__s390x__)
93 typedef long long fdisk_loff_t;
95 typedef long fdisk_loff_t;
99 /* including <linux/hdreg.h> also fails */
102 unsigned char sectors;
103 unsigned short cylinders;
107 #define HDIO_GETGEO 0x0301 /* get device geometry */
111 const unsigned char *name;
114 static uint sector_size = DEFAULT_SECTOR_SIZE,
115 user_set_sector_size,
119 * Raw disk label. For DOS-type partition tables the MBR,
120 * with descriptions of the primary partitions.
122 static char MBRbuffer[MAX_SECTOR_SIZE];
124 #ifdef CONFIG_FEATURE_SUN_LABEL
125 static int sun_label; /* looking at sun disklabel */
129 #ifdef CONFIG_FEATURE_SGI_LABEL
130 static int sgi_label; /* looking at sgi disklabel */
134 #ifdef CONFIG_FEATURE_AIX_LABEL
135 static int aix_label; /* looking at aix disklabel */
139 #ifdef CONFIG_FEATURE_OSF_LABEL
140 static int osf_label; /* looking at OSF/1 disklabel */
141 static int possibly_osf_label;
146 #define dos_label (!sun_label && !sgi_label && !aix_label && !osf_label)
148 static uint heads, sectors, cylinders;
149 static void update_units(void);
153 * return partition name - uses static storage unless buf is supplied
156 partname(const char *dev, int pno, int lth) {
157 static char buffer[80];
164 bufsiz = sizeof(buffer);
169 if (isdigit(dev[w-1]))
172 /* devfs kludge - note: fdisk partition names are not supposed
173 to equal kernel names, so there is no reason to do this */
174 if (strcmp (dev + w - 4, "disc") == 0) {
182 snprintf(bufp, bufsiz, "%*.*s%s%-2u",
183 lth-wp-2, w, dev, p, pno);
185 snprintf(bufp, bufsiz, "%.*s%s%-2u", w, dev, p, pno);
191 unsigned char boot_ind; /* 0x80 - active */
192 unsigned char head; /* starting head */
193 unsigned char sector; /* starting sector */
194 unsigned char cyl; /* starting cylinder */
195 unsigned char sys_ind; /* What partition type */
196 unsigned char end_head; /* end head */
197 unsigned char end_sector; /* end sector */
198 unsigned char end_cyl; /* end cylinder */
199 unsigned char start4[4]; /* starting sector counting from 0 */
200 unsigned char size4[4]; /* nr of sectors in partition */
204 ioctl_error, unable_to_open, unable_to_read, unable_to_seek,
208 enum action {fdisk, require, try_only, create_empty_dos, create_empty_sun};
210 static const char *disk_device;
211 static int fd; /* the disk */
212 static int partitions = 4; /* maximum partition + 1 */
213 static uint display_in_cyl_units = 1;
214 static uint units_per_sector = 1;
215 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
216 static char *line_ptr;
217 static void change_units(void);
218 static void reread_partition_table(int leave);
219 static void delete_partition(int i);
220 static int get_partition(int warn, int max);
221 static void list_types(const struct systypes *sys);
222 static uint read_int(uint low, uint dflt, uint high, uint base, char *mesg);
224 static const char *partition_type(unsigned char type);
225 static void fdisk_fatal(enum failure why) __attribute__ ((noreturn));
226 static void get_geometry(void);
227 static int get_boot(enum action what);
232 #define hex_val(c) ({ \
234 isdigit(_c) ? _c - '0' : \
235 tolower(_c) + 10 - 'a'; \
239 #define LINE_LENGTH 800
240 #define pt_offset(b, n) ((struct partition *)((b) + 0x1be + \
241 (n) * sizeof(struct partition)))
242 #define sector(s) ((s) & 0x3f)
243 #define cylinder(s, c) ((c) | (((s) & 0xc0) << 2))
245 #define hsc2sector(h,s,c) (sector(s) - 1 + sectors * \
246 ((h) + heads * cylinder(s,c)))
247 #define set_hsc(h,s,c,sector) { \
248 s = sector % sectors + 1; \
250 h = sector % heads; \
253 s |= (sector >> 2) & 0xc0; \
257 static unsigned int get_start_sect(const struct partition *p);
258 static unsigned int get_nr_sects(const struct partition *p);
261 * per partition table entry data
263 * The four primary partitions have the same sectorbuffer (MBRbuffer)
264 * and have NULL ext_pointer.
265 * Each logical partition table entry has two pointers, one for the
266 * partition and one link to the next one.
269 struct partition *part_table; /* points into sectorbuffer */
270 struct partition *ext_pointer; /* points into sectorbuffer */
271 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
272 char changed; /* boolean */
274 uint offset; /* disk sector number */
275 char *sectorbuffer; /* disk sector contents */
276 } ptes[MAXIMUM_PARTS];
279 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
281 set_all_unchanged(void) {
284 for (i = 0; i < MAXIMUM_PARTS; i++)
292 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
294 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_OSF_LABEL)
295 static struct partition *
296 get_part_table(int i) {
297 return ptes[i].part_table;
302 str_units(int n) { /* n==1: use singular */
304 return display_in_cyl_units ? _("cylinder") : _("sector");
306 return display_in_cyl_units ? _("cylinders") : _("sectors");
310 valid_part_table_flag(const unsigned char *b) {
311 return (b[510] == 0x55 && b[511] == 0xaa);
314 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
315 static char line_buffer[LINE_LENGTH];
317 /* read line; return 0 or first char */
321 static int got_eof = 0;
323 fflush (stdout); /* requested by niles@scyld.com */
324 line_ptr = line_buffer;
325 if (!fgets(line_buffer, LINE_LENGTH, stdin)) {
327 got_eof++; /* user typed ^D ? */
329 fprintf(stderr, _("\ngot EOF thrice - exiting..\n"));
334 while (*line_ptr && !isgraph(*line_ptr))
340 read_char(const char *mesg)
344 } while (!read_line());
349 read_chars(const char *mesg)
360 read_hex(const struct systypes *sys)
366 read_char(_("Hex code (type L to list codes): "));
367 if (*line_ptr == 'l' || *line_ptr == 'L')
369 else if (isxdigit (*line_ptr))
373 hex = hex << 4 | hex_val(*line_ptr++);
374 while (isxdigit(*line_ptr));
379 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
381 #ifdef CONFIG_FEATURE_AIX_LABEL
383 * Copyright (C) Andreas Neuper, Sep 1998.
384 * This file may be redistributed under
385 * the terms of the GNU Public License.
389 unsigned int magic; /* expect AIX_LABEL_MAGIC */
390 unsigned int fillbytes1[124];
391 unsigned int physical_volume_id;
392 unsigned int fillbytes2[124];
395 #define AIX_LABEL_MAGIC 0xc9c2d4c1
396 #define AIX_LABEL_MAGIC_SWAPPED 0xc1d4c2c9
397 #define AIX_INFO_MAGIC 0x00072959
398 #define AIX_INFO_MAGIC_SWAPPED 0x59290700
400 #define aixlabel ((aix_partition *)MBRbuffer)
405 * 1999-03-20 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
406 * Internationalization
408 * 2003-03-20 Phillip Kesling <pkesling@sgi.com>
412 static int aix_other_endian;
413 static short aix_volumes=1;
416 * only dealing with free blocks here
422 _("\n\tThere is a valid AIX label on this disk.\n"
423 "\tUnfortunately Linux cannot handle these\n"
424 "\tdisks at the moment. Nevertheless some\n"
426 "\t1. fdisk will destroy its contents on write.\n"
427 "\t2. Be sure that this disk is NOT a still vital\n"
428 "\t part of a volume group. (Otherwise you may\n"
429 "\t erase the other disks as well, if unmirrored.)\n"
430 "\t3. Before deleting this physical volume be sure\n"
431 "\t to remove the disk logically from your AIX\n"
432 "\t machine. (Otherwise you become an AIXpert).")
442 memset( MBRbuffer, 0, sizeof(MBRbuffer) ); /* avoid fdisk cores */
447 check_aix_label( void )
449 if (aixlabel->magic != AIX_LABEL_MAGIC &&
450 aixlabel->magic != AIX_LABEL_MAGIC_SWAPPED) {
452 aix_other_endian = 0;
455 aix_other_endian = (aixlabel->magic == AIX_LABEL_MAGIC_SWAPPED);
461 aix_nolabel(); /* %% */
462 aix_label = 1; /* %% */
465 #endif /* AIX_LABEL */
467 #ifdef CONFIG_FEATURE_OSF_LABEL
469 * Copyright (c) 1987, 1988 Regents of the University of California.
470 * All rights reserved.
472 * Redistribution and use in source and binary forms, with or without
473 * modification, are permitted provided that the following conditions
475 * 1. Redistributions of source code must retain the above copyright
476 * notice, this list of conditions and the following disclaimer.
477 * 2. Redistributions in binary form must reproduce the above copyright
478 * notice, this list of conditions and the following disclaimer in the
479 * documentation and/or other materials provided with the distribution.
480 * 3. All advertising materials mentioning features or use of this software
481 * must display the following acknowledgement:
482 * This product includes software developed by the University of
483 * California, Berkeley and its contributors.
484 * 4. Neither the name of the University nor the names of its contributors
485 * may be used to endorse or promote products derived from this software
486 * without specific prior written permission.
488 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
489 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
490 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
491 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
492 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
493 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
494 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
495 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
496 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
497 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
502 #ifndef BSD_DISKMAGIC
503 #define BSD_DISKMAGIC ((uint32_t) 0x82564557)
506 #ifndef BSD_MAXPARTITIONS
507 #define BSD_MAXPARTITIONS 16
510 #define BSD_LINUX_BOOTDIR "/usr/ucb/mdec"
512 #if defined (i386) || defined (__sparc__) || defined (__arm__) || defined (__mips__) || defined (__s390__) || defined (__sh__) || defined(__x86_64__)
513 #define BSD_LABELSECTOR 1
514 #define BSD_LABELOFFSET 0
515 #elif defined (__alpha__) || defined (__powerpc__) || defined (__ia64__) || defined (__hppa__)
516 #define BSD_LABELSECTOR 0
517 #define BSD_LABELOFFSET 64
518 #elif defined (__s390__) || defined (__s390x__)
519 #define BSD_LABELSECTOR 1
520 #define BSD_LABELOFFSET 0
522 #error unknown architecture
525 #define BSD_BBSIZE 8192 /* size of boot area, with label */
526 #define BSD_SBSIZE 8192 /* max size of fs superblock */
528 struct xbsd_disklabel {
529 uint32_t d_magic; /* the magic number */
530 int16_t d_type; /* drive type */
531 int16_t d_subtype; /* controller/d_type specific */
532 char d_typename[16]; /* type name, e.g. "eagle" */
533 char d_packname[16]; /* pack identifier */
535 uint32_t d_secsize; /* # of bytes per sector */
536 uint32_t d_nsectors; /* # of data sectors per track */
537 uint32_t d_ntracks; /* # of tracks per cylinder */
538 uint32_t d_ncylinders; /* # of data cylinders per unit */
539 uint32_t d_secpercyl; /* # of data sectors per cylinder */
540 uint32_t d_secperunit; /* # of data sectors per unit */
542 * Spares (bad sector replacements) below
543 * are not counted in d_nsectors or d_secpercyl.
544 * Spare sectors are assumed to be physical sectors
545 * which occupy space at the end of each track and/or cylinder.
547 uint16_t d_sparespertrack; /* # of spare sectors per track */
548 uint16_t d_sparespercyl; /* # of spare sectors per cylinder */
550 * Alternate cylinders include maintenance, replacement,
551 * configuration description areas, etc.
553 uint32_t d_acylinders; /* # of alt. cylinders per unit */
555 /* hardware characteristics: */
557 * d_interleave, d_trackskew and d_cylskew describe perturbations
558 * in the media format used to compensate for a slow controller.
559 * Interleave is physical sector interleave, set up by the formatter
560 * or controller when formatting. When interleaving is in use,
561 * logically adjacent sectors are not physically contiguous,
562 * but instead are separated by some number of sectors.
563 * It is specified as the ratio of physical sectors traversed
564 * per logical sector. Thus an interleave of 1:1 implies contiguous
565 * layout, while 2:1 implies that logical sector 0 is separated
566 * by one sector from logical sector 1.
567 * d_trackskew is the offset of sector 0 on track N
568 * relative to sector 0 on track N-1 on the same cylinder.
569 * Finally, d_cylskew is the offset of sector 0 on cylinder N
570 * relative to sector 0 on cylinder N-1.
572 uint16_t d_rpm; /* rotational speed */
573 uint16_t d_interleave; /* hardware sector interleave */
574 uint16_t d_trackskew; /* sector 0 skew, per track */
575 uint16_t d_cylskew; /* sector 0 skew, per cylinder */
576 uint32_t d_headswitch; /* head switch time, usec */
577 uint32_t d_trkseek; /* track-to-track seek, usec */
578 uint32_t d_flags; /* generic flags */
580 uint32_t d_drivedata[NDDATA]; /* drive-type specific information */
582 uint32_t d_spare[NSPARE]; /* reserved for future use */
583 uint32_t d_magic2; /* the magic number (again) */
584 uint16_t d_checksum; /* xor of data incl. partitions */
585 /* filesystem and partition information: */
586 uint16_t d_npartitions; /* number of partitions in following */
587 uint32_t d_bbsize; /* size of boot area at sn0, bytes */
588 uint32_t d_sbsize; /* max size of fs superblock, bytes */
589 struct xbsd_partition { /* the partition table */
590 uint32_t p_size; /* number of sectors in partition */
591 uint32_t p_offset; /* starting sector */
592 uint32_t p_fsize; /* filesystem basic fragment size */
593 uint8_t p_fstype; /* filesystem type, see below */
594 uint8_t p_frag; /* filesystem fragments per block */
595 uint16_t p_cpg; /* filesystem cylinders per group */
596 } d_partitions[BSD_MAXPARTITIONS]; /* actually may be more */
600 #define BSD_DTYPE_SMD 1 /* SMD, XSMD; VAX hp/up */
601 #define BSD_DTYPE_MSCP 2 /* MSCP */
602 #define BSD_DTYPE_DEC 3 /* other DEC (rk, rl) */
603 #define BSD_DTYPE_SCSI 4 /* SCSI */
604 #define BSD_DTYPE_ESDI 5 /* ESDI interface */
605 #define BSD_DTYPE_ST506 6 /* ST506 etc. */
606 #define BSD_DTYPE_HPIB 7 /* CS/80 on HP-IB */
607 #define BSD_DTYPE_HPFL 8 /* HP Fiber-link */
608 #define BSD_DTYPE_FLOPPY 10 /* floppy */
610 /* d_subtype values: */
611 #define BSD_DSTYPE_INDOSPART 0x8 /* is inside dos partition */
612 #define BSD_DSTYPE_DOSPART(s) ((s) & 3) /* dos partition number */
613 #define BSD_DSTYPE_GEOMETRY 0x10 /* drive params in label */
616 static const char * const xbsd_dktypenames[] = {
630 #define BSD_DKMAXTYPES (sizeof(xbsd_dktypenames) / sizeof(xbsd_dktypenames[0]) - 1)
634 * Filesystem type and version.
635 * Used to interpret other filesystem-specific
636 * per-partition information.
638 #define BSD_FS_UNUSED 0 /* unused */
639 #define BSD_FS_SWAP 1 /* swap */
640 #define BSD_FS_V6 2 /* Sixth Edition */
641 #define BSD_FS_V7 3 /* Seventh Edition */
642 #define BSD_FS_SYSV 4 /* System V */
643 #define BSD_FS_V71K 5 /* V7 with 1K blocks (4.1, 2.9) */
644 #define BSD_FS_V8 6 /* Eighth Edition, 4K blocks */
645 #define BSD_FS_BSDFFS 7 /* 4.2BSD fast file system */
646 #define BSD_FS_BSDLFS 9 /* 4.4BSD log-structured file system */
647 #define BSD_FS_OTHER 10 /* in use, but unknown/unsupported */
648 #define BSD_FS_HPFS 11 /* OS/2 high-performance file system */
649 #define BSD_FS_ISO9660 12 /* ISO-9660 filesystem (cdrom) */
650 #define BSD_FS_ISOFS BSD_FS_ISO9660
651 #define BSD_FS_BOOT 13 /* partition contains bootstrap */
652 #define BSD_FS_ADOS 14 /* AmigaDOS fast file system */
653 #define BSD_FS_HFS 15 /* Macintosh HFS */
654 #define BSD_FS_ADVFS 16 /* Digital Unix AdvFS */
656 /* this is annoying, but it's also the way it is :-( */
658 #define BSD_FS_EXT2 8 /* ext2 file system */
660 #define BSD_FS_MSDOS 8 /* MS-DOS file system */
664 static const struct systypes xbsd_fstypes[] = {
665 /* BSD_FS_UNUSED */ {"\x00" "unused"},
666 /* BSD_FS_SWAP */ {"\x01" "swap"},
667 /* BSD_FS_V6 */ {"\x02" "Version 6"},
668 /* BSD_FS_V7 */ {"\x03" "Version 7"},
669 /* BSD_FS_SYSV */ {"\x04" "System V"},
670 /* BSD_FS_V71K */ {"\x05" "4.1BSD"},
671 /* BSD_FS_V8 */ {"\x06" "Eighth Edition"},
672 /* BSD_FS_BSDFFS */ {"\x07" "4.2BSD"},
674 /* BSD_FS_EXT2 */ {"\x08" "ext2"},
676 /* BSD_FS_MSDOS */ {"\x08" "MS-DOS"},
678 /* BSD_FS_BSDLFS */ {"\x09" "4.4LFS"},
679 /* BSD_FS_OTHER */ {"\x0a" "unknown"},
680 /* BSD_FS_HPFS */ {"\x0b" "HPFS"},
681 /* BSD_FS_ISO9660 */ {"\x0c" "ISO-9660"},
682 /* BSD_FS_BOOT */ {"\x0d" "boot"},
683 /* BSD_FS_ADOS */ {"\x0e" "ADOS"},
684 /* BSD_FS_HFS */ {"\x0f" "HFS"},
685 /* BSD_FS_ADVFS */ {"\x10" "AdvFS"},
688 #define BSD_FSMAXTYPES (SIZE(xbsd_fstypes)-1)
693 * flags shared by various drives:
695 #define BSD_D_REMOVABLE 0x01 /* removable media */
696 #define BSD_D_ECC 0x02 /* supports ECC */
697 #define BSD_D_BADSECT 0x04 /* supports bad sector forw. */
698 #define BSD_D_RAMDISK 0x08 /* disk emulator */
699 #define BSD_D_CHAIN 0x10 /* can do back-back transfers */
700 #define BSD_D_DOSPART 0x20 /* within MSDOS partition */
702 #endif /* OSF_LABEL */
705 * Copyright (C) Andreas Neuper, Sep 1998.
706 * This file may be modified and redistributed under
707 * the terms of the GNU Public License.
710 struct device_parameter { /* 48 bytes */
714 unsigned char sparecyl;
715 unsigned short pcylcount;
716 unsigned short head_vol0;
717 unsigned short ntrks; /* tracks in cyl 0 or vol 0 */
718 unsigned char cmd_tag_queue_depth;
719 unsigned char unused0;
720 unsigned short unused1;
721 unsigned short nsect; /* sectors/tracks in cyl 0 or vol 0 */
722 unsigned short bytes;
723 unsigned short ilfact;
724 unsigned int flags; /* controller flags */
725 unsigned int datarate;
726 unsigned int retries_on_error;
727 unsigned int ms_per_word;
728 unsigned short xylogics_gap1;
729 unsigned short xylogics_syncdelay;
730 unsigned short xylogics_readdelay;
731 unsigned short xylogics_gap2;
732 unsigned short xylogics_readgate;
733 unsigned short xylogics_writecont;
736 #define SGI_VOLHDR 0x00
737 /* 1 and 2 were used for drive types no longer supported by SGI */
738 #define SGI_SWAP 0x03
739 /* 4 and 5 were for filesystem types SGI haven't ever supported on MIPS CPUs */
740 #define SGI_VOLUME 0x06
742 #define SGI_LVOL 0x08
743 #define SGI_RLVOL 0x09
745 #define SGI_XFSLOG 0x0b
748 #define ENTIRE_DISK SGI_VOLUME
752 #define SECTOR_SLIP 0x01
753 #define SECTOR_FWD 0x02
754 #define TRACK_FWD 0x04
755 #define TRACK_MULTIVOL 0x08
756 #define IGNORE_ERRORS 0x10
758 #define ENABLE_CMDTAGQ 0x40
761 unsigned int magic; /* expect SGI_LABEL_MAGIC */
762 unsigned short boot_part; /* active boot partition */
763 unsigned short swap_part; /* active swap partition */
764 unsigned char boot_file[16]; /* name of the bootfile */
765 struct device_parameter devparam; /* 1 * 48 bytes */
766 struct volume_directory { /* 15 * 16 bytes */
767 unsigned char vol_file_name[8]; /* a character array */
768 unsigned int vol_file_start; /* number of logical block */
769 unsigned int vol_file_size; /* number of bytes */
771 struct sgi_partition { /* 16 * 12 bytes */
772 unsigned int num_sectors; /* number of blocks */
773 unsigned int start_sector; /* must be cylinder aligned */
777 unsigned int fillbytes;
781 unsigned int magic; /* looks like a magic number */
790 unsigned char scsi_string[50];
791 unsigned char serial[137];
792 unsigned short check1816;
793 unsigned char installer[225];
796 #define SGI_LABEL_MAGIC 0x0be5a941
797 #define SGI_LABEL_MAGIC_SWAPPED 0x41a9e50b
798 #define SGI_INFO_MAGIC 0x00072959
799 #define SGI_INFO_MAGIC_SWAPPED 0x59290700
800 #define SGI_SSWAP16(x) (sgi_other_endian ? __swap16(x) \
802 #define SGI_SSWAP32(x) (sgi_other_endian ? __swap32(x) \
805 #define sgilabel ((sgi_partition *)MBRbuffer)
806 #define sgiparam (sgilabel->devparam)
809 unsigned char info[128]; /* Informative text string */
810 unsigned char spare0[14];
812 unsigned char spare1;
814 unsigned char spare2;
817 unsigned char spare1[246]; /* Boot information etc. */
818 unsigned short rspeed; /* Disk rotational speed */
819 unsigned short pcylcount; /* Physical cylinder count */
820 unsigned short sparecyl; /* extra sects per cylinder */
821 unsigned char spare2[4]; /* More magic... */
822 unsigned short ilfact; /* Interleave factor */
823 unsigned short ncyl; /* Data cylinder count */
824 unsigned short nacyl; /* Alt. cylinder count */
825 unsigned short ntrks; /* Tracks per cylinder */
826 unsigned short nsect; /* Sectors per track */
827 unsigned char spare3[4]; /* Even more magic... */
828 struct sun_partition {
829 uint32_t start_cylinder;
830 uint32_t num_sectors;
832 unsigned short magic; /* Magic number */
833 unsigned short csum; /* Label xor'd checksum */
837 #define SUN_LABEL_MAGIC 0xDABE
838 #define SUN_LABEL_MAGIC_SWAPPED 0xBEDA
839 #define sunlabel ((sun_partition *)MBRbuffer)
840 #define SUN_SSWAP16(x) (sun_other_endian ? __swap16(x) \
842 #define SUN_SSWAP32(x) (sun_other_endian ? __swap32(x) \
845 #if defined(FDISK_SUPPORT_LARGE_DISKS)
847 * llseek.c -- stub calling the llseek system call
849 * Copyright (C) 1994 Remy Card. This file may be redistributed
850 * under the terms of the GNU Public License.
857 #if defined(__alpha__) || defined(__ia64__) || defined(__s390x__)
859 #define my_llseek lseek
863 static int _llseek (unsigned int, unsigned long,
864 unsigned long, fdisk_loff_t *, unsigned int);
866 static _syscall5(int,_llseek,unsigned int,f_d,unsigned long,offset_high,
867 unsigned long, offset_low,fdisk_loff_t *,result,
868 unsigned int, origin)
870 static fdisk_loff_t my_llseek (unsigned int f_d, fdisk_loff_t offset,
876 retval = _llseek (f_d, ((unsigned long long) offset) >> 32,
877 ((unsigned long long) offset) & 0xffffffff,
879 return (retval == -1 ? (fdisk_loff_t) retval : result);
882 #endif /* __alpha__ */
885 static fdisk_loff_t fdisk_llseek (unsigned int f_d, fdisk_loff_t offset,
889 static int do_compat = 0;
892 result = my_llseek (f_d, offset, origin);
893 if (!(result == -1 && errno == ENOSYS))
897 * Just in case this code runs on top of an old kernel
898 * which does not support the llseek system call
902 * Now try ordinary lseek.
906 if ((sizeof(off_t) >= sizeof(fdisk_loff_t)) ||
907 (offset < ((fdisk_loff_t) 1 << ((sizeof(off_t)*8) -1))))
908 return lseek(f_d, (off_t) offset, origin);
914 # define fdisk_llseek lseek
915 #endif /* FDISK_SUPPORT_LARGE_DISKS */
919 #ifdef CONFIG_FEATURE_OSF_LABEL
922 19990319 - Arnaldo Carvalho de Melo <acme@conectiva.com.br> - i18n/nls
924 20000101 - David Huggins-Daines <dhuggins@linuxcare.com> - Better
925 support for OSF/1 disklabels on Alpha.
926 Also fixed unaligned accesses in alpha_bootblock_checksum()
929 #define FREEBSD_PARTITION 0xa5
930 #define NETBSD_PARTITION 0xa9
932 static void xbsd_delete_part (void);
933 static void xbsd_new_part (void);
934 static void xbsd_write_disklabel (void);
935 static int xbsd_create_disklabel (void);
936 static void xbsd_edit_disklabel (void);
937 static void xbsd_write_bootstrap (void);
938 static void xbsd_change_fstype (void);
939 static int xbsd_get_part_index (int max);
940 static int xbsd_check_new_partition (int *i);
941 static void xbsd_list_types (void);
942 static u_short xbsd_dkcksum (struct xbsd_disklabel *lp);
943 static int xbsd_initlabel (struct partition *p, struct xbsd_disklabel *d,
945 static int xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d);
946 static int xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d);
948 #if defined (__alpha__)
949 static void alpha_bootblock_checksum (char *boot);
952 #if !defined (__alpha__)
953 static int xbsd_translate_fstype (int linux_type);
954 static void xbsd_link_part (void);
955 static struct partition *xbsd_part;
956 static int xbsd_part_index;
959 #if defined (__alpha__)
960 /* We access this through a u_int64_t * when checksumming */
961 static char disklabelbuffer[BSD_BBSIZE] __attribute__((aligned(8)));
963 static char disklabelbuffer[BSD_BBSIZE];
966 static struct xbsd_disklabel xbsd_dlabel;
968 #define bsd_cround(n) \
969 (display_in_cyl_units ? ((n)/xbsd_dlabel.d_secpercyl) + 1 : (n))
972 * Test whether the whole disk has BSD disk label magic.
974 * Note: often reformatting with DOS-type label leaves the BSD magic,
975 * so this does not mean that there is a BSD disk label.
978 check_osf_label(void) {
979 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
984 static void xbsd_print_disklabel(int);
987 btrydev (const char * dev) {
988 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
990 printf(_("\nBSD label for device: %s\n"), dev);
991 xbsd_print_disklabel (0);
997 puts (_("Command action"));
998 puts (_("\td\tdelete a BSD partition"));
999 puts (_("\te\tedit drive data"));
1000 puts (_("\ti\tinstall bootstrap"));
1001 puts (_("\tl\tlist known filesystem types"));
1002 puts (_("\tm\tprint this menu"));
1003 puts (_("\tn\tadd a new BSD partition"));
1004 puts (_("\tp\tprint BSD partition table"));
1005 puts (_("\tq\tquit without saving changes"));
1006 puts (_("\tr\treturn to main menu"));
1007 puts (_("\ts\tshow complete disklabel"));
1008 puts (_("\tt\tchange a partition's filesystem id"));
1009 puts (_("\tu\tchange units (cylinders/sectors)"));
1010 puts (_("\tw\twrite disklabel to disk"));
1011 #if !defined (__alpha__)
1012 puts (_("\tx\tlink BSD partition to non-BSD partition"));
1016 #if !defined (__alpha__)
1023 is_bsd_partition_type(int type) {
1024 return (type == FREEBSD_PARTITION ||
1025 type == hidden(FREEBSD_PARTITION) ||
1026 type == NETBSD_PARTITION ||
1027 type == hidden(NETBSD_PARTITION));
1033 #if !defined (__alpha__)
1035 struct partition *p;
1037 for (t=0; t<4; t++) {
1038 p = get_part_table(t);
1039 if (p && is_bsd_partition_type(p->sys_ind)) {
1041 xbsd_part_index = t;
1042 ss = get_start_sect(xbsd_part);
1044 fprintf (stderr, _("Partition %s has invalid starting sector 0.\n"),
1045 partname(disk_device, t+1, 0));
1048 printf (_("Reading disklabel of %s at sector %d.\n"),
1049 partname(disk_device, t+1, 0), ss + BSD_LABELSECTOR);
1050 if (xbsd_readlabel (xbsd_part, &xbsd_dlabel) == 0)
1051 if (xbsd_create_disklabel () == 0)
1058 printf (_("There is no *BSD partition on %s.\n"), disk_device);
1062 #elif defined (__alpha__)
1064 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
1065 if (xbsd_create_disklabel () == 0)
1066 exit ( EXIT_SUCCESS );
1072 switch (tolower (read_char (_("BSD disklabel command (m for help): ")))) {
1074 xbsd_delete_part ();
1077 xbsd_edit_disklabel ();
1080 xbsd_write_bootstrap ();
1089 xbsd_print_disklabel (0);
1093 exit ( EXIT_SUCCESS );
1097 xbsd_print_disklabel (1);
1100 xbsd_change_fstype ();
1106 xbsd_write_disklabel ();
1108 #if !defined (__alpha__)
1121 xbsd_delete_part (void)
1125 i = xbsd_get_part_index (xbsd_dlabel.d_npartitions);
1126 xbsd_dlabel.d_partitions[i].p_size = 0;
1127 xbsd_dlabel.d_partitions[i].p_offset = 0;
1128 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
1129 if (xbsd_dlabel.d_npartitions == i + 1)
1130 while (xbsd_dlabel.d_partitions[xbsd_dlabel.d_npartitions-1].p_size == 0)
1131 xbsd_dlabel.d_npartitions--;
1135 xbsd_new_part (void)
1141 if (!xbsd_check_new_partition (&i))
1144 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
1145 begin = get_start_sect(xbsd_part);
1146 end = begin + get_nr_sects(xbsd_part) - 1;
1149 end = xbsd_dlabel.d_secperunit - 1;
1152 snprintf (mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
1153 begin = read_int (bsd_cround (begin), bsd_cround (begin), bsd_cround (end),
1156 if (display_in_cyl_units)
1157 begin = (begin - 1) * xbsd_dlabel.d_secpercyl;
1159 snprintf (mesg, sizeof(mesg), _("Last %s or +size or +sizeM or +sizeK"),
1160 str_units(SINGULAR));
1161 end = read_int (bsd_cround (begin), bsd_cround (end), bsd_cround (end),
1162 bsd_cround (begin), mesg);
1164 if (display_in_cyl_units)
1165 end = end * xbsd_dlabel.d_secpercyl - 1;
1167 xbsd_dlabel.d_partitions[i].p_size = end - begin + 1;
1168 xbsd_dlabel.d_partitions[i].p_offset = begin;
1169 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
1173 xbsd_print_disklabel (int show_all) {
1174 struct xbsd_disklabel *lp = &xbsd_dlabel;
1175 struct xbsd_partition *pp;
1179 #if defined (__alpha__)
1180 printf("# %s:\n", disk_device);
1182 printf("# %s:\n", partname(disk_device, xbsd_part_index+1, 0));
1184 if ((unsigned) lp->d_type < BSD_DKMAXTYPES)
1185 printf(_("type: %s\n"), xbsd_dktypenames[lp->d_type]);
1187 printf(_("type: %d\n"), lp->d_type);
1188 printf(_("disk: %.*s\n"), (int) sizeof(lp->d_typename), lp->d_typename);
1189 printf(_("label: %.*s\n"), (int) sizeof(lp->d_packname), lp->d_packname);
1190 printf(_("flags:"));
1191 if (lp->d_flags & BSD_D_REMOVABLE)
1192 printf(_(" removable"));
1193 if (lp->d_flags & BSD_D_ECC)
1195 if (lp->d_flags & BSD_D_BADSECT)
1196 printf(_(" badsect"));
1198 /* On various machines the fields of *lp are short/int/long */
1199 /* In order to avoid problems, we cast them all to long. */
1200 printf(_("bytes/sector: %ld\n"), (long) lp->d_secsize);
1201 printf(_("sectors/track: %ld\n"), (long) lp->d_nsectors);
1202 printf(_("tracks/cylinder: %ld\n"), (long) lp->d_ntracks);
1203 printf(_("sectors/cylinder: %ld\n"), (long) lp->d_secpercyl);
1204 printf(_("cylinders: %ld\n"), (long) lp->d_ncylinders);
1205 printf(_("rpm: %d\n"), lp->d_rpm);
1206 printf(_("interleave: %d\n"), lp->d_interleave);
1207 printf(_("trackskew: %d\n"), lp->d_trackskew);
1208 printf(_("cylinderskew: %d\n"), lp->d_cylskew);
1209 printf(_("headswitch: %ld\t\t# milliseconds\n"),
1210 (long) lp->d_headswitch);
1211 printf(_("track-to-track seek: %ld\t# milliseconds\n"),
1212 (long) lp->d_trkseek);
1213 printf(_("drivedata: "));
1214 for (i = NDDATA - 1; i >= 0; i--)
1215 if (lp->d_drivedata[i])
1219 for (j = 0; j <= i; j++)
1220 printf("%ld ", (long) lp->d_drivedata[j]);
1222 printf(_("\n%d partitions:\n"), lp->d_npartitions);
1223 printf(_("# start end size fstype [fsize bsize cpg]\n"));
1224 pp = lp->d_partitions;
1225 for (i = 0; i < lp->d_npartitions; i++, pp++) {
1227 if (display_in_cyl_units && lp->d_secpercyl) {
1228 printf(" %c: %8ld%c %8ld%c %8ld%c ",
1230 (long) pp->p_offset / lp->d_secpercyl + 1,
1231 (pp->p_offset % lp->d_secpercyl) ? '*' : ' ',
1232 (long) (pp->p_offset + pp->p_size + lp->d_secpercyl - 1)
1234 ((pp->p_offset + pp->p_size) % lp->d_secpercyl) ? '*' : ' ',
1235 (long) pp->p_size / lp->d_secpercyl,
1236 (pp->p_size % lp->d_secpercyl) ? '*' : ' ');
1238 printf(" %c: %8ld %8ld %8ld ",
1240 (long) pp->p_offset,
1241 (long) pp->p_offset + pp->p_size - 1,
1244 if ((unsigned) pp->p_fstype < BSD_FSMAXTYPES)
1245 printf("%8.8s", xbsd_fstypes[pp->p_fstype].name);
1247 printf("%8x", pp->p_fstype);
1248 switch (pp->p_fstype) {
1250 printf(" %5ld %5ld %5.5s ",
1251 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, "");
1255 printf(" %5ld %5ld %5d ",
1256 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag,
1261 printf("%22.22s", "");
1270 xbsd_write_disklabel (void) {
1271 #if defined (__alpha__)
1272 printf (_("Writing disklabel to %s.\n"), disk_device);
1273 xbsd_writelabel (NULL, &xbsd_dlabel);
1275 printf (_("Writing disklabel to %s.\n"),
1276 partname(disk_device, xbsd_part_index+1, 0));
1277 xbsd_writelabel (xbsd_part, &xbsd_dlabel);
1279 reread_partition_table(0); /* no exit yet */
1283 xbsd_create_disklabel (void) {
1286 #if defined (__alpha__)
1287 fprintf (stderr, _("%s contains no disklabel.\n"), disk_device);
1289 fprintf (stderr, _("%s contains no disklabel.\n"),
1290 partname(disk_device, xbsd_part_index+1, 0));
1294 c = read_char (_("Do you want to create a disklabel? (y/n) "));
1295 if (c == 'y' || c == 'Y') {
1296 if (xbsd_initlabel (
1297 #if defined (__alpha__) || defined (__powerpc__) || defined (__hppa__) || \
1298 defined (__s390__) || defined (__s390x__)
1299 NULL, &xbsd_dlabel, 0
1301 xbsd_part, &xbsd_dlabel, xbsd_part_index
1304 xbsd_print_disklabel (1);
1308 } else if (c == 'n')
1314 edit_int (int def, char *mesg)
1317 fputs (mesg, stdout);
1318 printf (" (%d): ", def);
1322 while (!isdigit (*line_ptr));
1323 return atoi (line_ptr);
1327 xbsd_edit_disklabel (void)
1329 struct xbsd_disklabel *d;
1333 #if defined (__alpha__) || defined (__ia64__)
1334 d -> d_secsize = (u_long) edit_int ((u_long) d -> d_secsize ,_("bytes/sector"));
1335 d -> d_nsectors = (u_long) edit_int ((u_long) d -> d_nsectors ,_("sectors/track"));
1336 d -> d_ntracks = (u_long) edit_int ((u_long) d -> d_ntracks ,_("tracks/cylinder"));
1337 d -> d_ncylinders = (u_long) edit_int ((u_long) d -> d_ncylinders ,_("cylinders"));
1340 /* d -> d_secpercyl can be != d -> d_nsectors * d -> d_ntracks */
1343 d -> d_secpercyl = (u_long) edit_int ((u_long) d -> d_nsectors * d -> d_ntracks,
1344 _("sectors/cylinder"));
1345 if (d -> d_secpercyl <= d -> d_nsectors * d -> d_ntracks)
1348 printf (_("Must be <= sectors/track * tracks/cylinder (default).\n"));
1350 d -> d_rpm = (u_short) edit_int ((u_short) d -> d_rpm ,_("rpm"));
1351 d -> d_interleave = (u_short) edit_int ((u_short) d -> d_interleave,_("interleave"));
1352 d -> d_trackskew = (u_short) edit_int ((u_short) d -> d_trackskew ,_("trackskew"));
1353 d -> d_cylskew = (u_short) edit_int ((u_short) d -> d_cylskew ,_("cylinderskew"));
1354 d -> d_headswitch = (u_long) edit_int ((u_long) d -> d_headswitch ,_("headswitch"));
1355 d -> d_trkseek = (u_long) edit_int ((u_long) d -> d_trkseek ,_("track-to-track seek"));
1357 d -> d_secperunit = d -> d_secpercyl * d -> d_ncylinders;
1361 xbsd_get_bootstrap (char *path, void *ptr, int size)
1365 if ((fdb = open (path, O_RDONLY)) < 0)
1370 if (read (fdb, ptr, size) < 0)
1376 printf (" ... %s\n", path);
1384 printf (_("\nSyncing disks.\n"));
1390 xbsd_write_bootstrap (void)
1392 char *bootdir = BSD_LINUX_BOOTDIR;
1393 char path[MAXPATHLEN];
1395 struct xbsd_disklabel dl;
1399 if (xbsd_dlabel.d_type == BSD_DTYPE_SCSI)
1404 printf (_("Bootstrap: %sboot -> boot%s (%s): "),
1405 dkbasename, dkbasename, dkbasename);
1407 line_ptr[strlen (line_ptr)-1] = '\0';
1408 dkbasename = line_ptr;
1410 snprintf (path, sizeof(path), "%s/%sboot", bootdir, dkbasename);
1411 if (!xbsd_get_bootstrap (path, disklabelbuffer, (int) xbsd_dlabel.d_secsize))
1414 /* We need a backup of the disklabel (xbsd_dlabel might have changed). */
1415 d = &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE];
1416 bcopy (d, &dl, sizeof (struct xbsd_disklabel));
1418 /* The disklabel will be overwritten by 0's from bootxx anyway */
1419 bzero (d, sizeof (struct xbsd_disklabel));
1421 snprintf (path, sizeof(path), "%s/boot%s", bootdir, dkbasename);
1422 if (!xbsd_get_bootstrap (path, &disklabelbuffer[xbsd_dlabel.d_secsize],
1423 (int) xbsd_dlabel.d_bbsize - xbsd_dlabel.d_secsize))
1426 e = d + sizeof (struct xbsd_disklabel);
1427 for (p=d; p < e; p++)
1429 fprintf (stderr, _("Bootstrap overlaps with disk label!\n"));
1430 exit ( EXIT_FAILURE );
1433 bcopy (&dl, d, sizeof (struct xbsd_disklabel));
1435 #if defined (__powerpc__) || defined (__hppa__)
1437 #elif defined (__alpha__)
1439 alpha_bootblock_checksum (disklabelbuffer);
1441 sector = get_start_sect(xbsd_part);
1444 if (fdisk_llseek (fd, (fdisk_loff_t) sector * SECTOR_SIZE, SEEK_SET) == -1)
1445 fdisk_fatal (unable_to_seek);
1446 if (BSD_BBSIZE != write (fd, disklabelbuffer, BSD_BBSIZE))
1447 fdisk_fatal (unable_to_write);
1449 #if defined (__alpha__)
1450 printf (_("Bootstrap installed on %s.\n"), disk_device);
1452 printf (_("Bootstrap installed on %s.\n"),
1453 partname (disk_device, xbsd_part_index+1, 0));
1460 xbsd_change_fstype (void)
1464 i = xbsd_get_part_index (xbsd_dlabel.d_npartitions);
1465 xbsd_dlabel.d_partitions[i].p_fstype = read_hex (xbsd_fstypes);
1469 xbsd_get_part_index (int max)
1474 snprintf (prompt, sizeof(prompt), _("Partition (a-%c): "), 'a' + max - 1);
1476 l = tolower (read_char (prompt));
1477 while (l < 'a' || l > 'a' + max - 1);
1482 xbsd_check_new_partition (int *i) {
1484 /* room for more? various BSD flavours have different maxima */
1485 if (xbsd_dlabel.d_npartitions == BSD_MAXPARTITIONS) {
1488 for (t = 0; t < BSD_MAXPARTITIONS; t++)
1489 if (xbsd_dlabel.d_partitions[t].p_size == 0)
1492 if (t == BSD_MAXPARTITIONS) {
1493 fprintf (stderr, _("The maximum number of partitions "
1494 "has been created\n"));
1499 *i = xbsd_get_part_index (BSD_MAXPARTITIONS);
1501 if (*i >= xbsd_dlabel.d_npartitions)
1502 xbsd_dlabel.d_npartitions = (*i) + 1;
1504 if (xbsd_dlabel.d_partitions[*i].p_size != 0) {
1505 fprintf (stderr, _("This partition already exists.\n"));
1513 xbsd_list_types (void) {
1514 list_types (xbsd_fstypes);
1518 xbsd_dkcksum (struct xbsd_disklabel *lp) {
1519 u_short *start, *end;
1522 start = (u_short *) lp;
1523 end = (u_short *) &lp->d_partitions[lp->d_npartitions];
1530 xbsd_initlabel (struct partition *p, struct xbsd_disklabel *d, int pindex) {
1531 struct xbsd_partition *pp;
1534 bzero (d, sizeof (struct xbsd_disklabel));
1536 d -> d_magic = BSD_DISKMAGIC;
1538 if (strncmp (disk_device, "/dev/sd", 7) == 0)
1539 d -> d_type = BSD_DTYPE_SCSI;
1541 d -> d_type = BSD_DTYPE_ST506;
1543 #if 0 /* not used (at least not written to disk) by NetBSD/i386 1.0 */
1544 d -> d_subtype = BSD_DSTYPE_INDOSPART & pindex;
1547 #if !defined (__alpha__)
1548 d -> d_flags = BSD_D_DOSPART;
1552 d -> d_secsize = SECTOR_SIZE; /* bytes/sector */
1553 d -> d_nsectors = sectors; /* sectors/track */
1554 d -> d_ntracks = heads; /* tracks/cylinder (heads) */
1555 d -> d_ncylinders = cylinders;
1556 d -> d_secpercyl = sectors * heads;/* sectors/cylinder */
1557 if (d -> d_secpercyl == 0)
1558 d -> d_secpercyl = 1; /* avoid segfaults */
1559 d -> d_secperunit = d -> d_secpercyl * d -> d_ncylinders;
1562 d -> d_interleave = 1;
1563 d -> d_trackskew = 0;
1565 d -> d_headswitch = 0;
1568 d -> d_magic2 = BSD_DISKMAGIC;
1569 d -> d_bbsize = BSD_BBSIZE;
1570 d -> d_sbsize = BSD_SBSIZE;
1572 #if !defined (__alpha__)
1573 d -> d_npartitions = 4;
1574 pp = &d -> d_partitions[2]; /* Partition C should be
1575 the NetBSD partition */
1576 pp -> p_offset = get_start_sect(p);
1577 pp -> p_size = get_nr_sects(p);
1578 pp -> p_fstype = BSD_FS_UNUSED;
1579 pp = &d -> d_partitions[3]; /* Partition D should be
1582 pp -> p_size = d -> d_secperunit;
1583 pp -> p_fstype = BSD_FS_UNUSED;
1584 #elif defined (__alpha__)
1585 d -> d_npartitions = 3;
1586 pp = &d -> d_partitions[2]; /* Partition C should be
1589 pp -> p_size = d -> d_secperunit;
1590 pp -> p_fstype = BSD_FS_UNUSED;
1597 * Read a xbsd_disklabel from sector 0 or from the starting sector of p.
1598 * If it has the right magic, return 1.
1601 xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d)
1605 /* p is used only to get the starting sector */
1606 #if !defined (__alpha__)
1607 sector = (p ? get_start_sect(p) : 0);
1608 #elif defined (__alpha__)
1612 if (fdisk_llseek (fd, (fdisk_loff_t) sector * SECTOR_SIZE, SEEK_SET) == -1)
1613 fdisk_fatal (unable_to_seek);
1614 if (BSD_BBSIZE != read (fd, disklabelbuffer, BSD_BBSIZE))
1615 fdisk_fatal (unable_to_read);
1617 bcopy (&disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
1618 d, sizeof (struct xbsd_disklabel));
1620 if (d -> d_magic != BSD_DISKMAGIC || d -> d_magic2 != BSD_DISKMAGIC)
1623 for (t = d -> d_npartitions; t < BSD_MAXPARTITIONS; t++) {
1624 d -> d_partitions[t].p_size = 0;
1625 d -> d_partitions[t].p_offset = 0;
1626 d -> d_partitions[t].p_fstype = BSD_FS_UNUSED;
1629 if (d -> d_npartitions > BSD_MAXPARTITIONS)
1630 fprintf (stderr, _("Warning: too many partitions "
1631 "(%d, maximum is %d).\n"),
1632 d -> d_npartitions, BSD_MAXPARTITIONS);
1637 xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d)
1639 unsigned int sector;
1641 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
1642 sector = get_start_sect(p) + BSD_LABELSECTOR;
1644 sector = BSD_LABELSECTOR;
1647 d -> d_checksum = 0;
1648 d -> d_checksum = xbsd_dkcksum (d);
1650 /* This is necessary if we want to write the bootstrap later,
1651 otherwise we'd write the old disklabel with the bootstrap.
1653 bcopy (d, &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
1654 sizeof (struct xbsd_disklabel));
1656 #if defined (__alpha__) && BSD_LABELSECTOR == 0
1657 alpha_bootblock_checksum (disklabelbuffer);
1658 if (fdisk_llseek (fd, (fdisk_loff_t) 0, SEEK_SET) == -1)
1659 fdisk_fatal (unable_to_seek);
1660 if (BSD_BBSIZE != write (fd, disklabelbuffer, BSD_BBSIZE))
1661 fdisk_fatal (unable_to_write);
1663 if (fdisk_llseek (fd, (fdisk_loff_t) sector * SECTOR_SIZE + BSD_LABELOFFSET,
1665 fdisk_fatal (unable_to_seek);
1666 if (sizeof (struct xbsd_disklabel) != write (fd, d, sizeof (struct xbsd_disklabel)))
1667 fdisk_fatal (unable_to_write);
1676 #if !defined (__alpha__)
1678 xbsd_translate_fstype (int linux_type)
1682 case 0x01: /* DOS 12-bit FAT */
1683 case 0x04: /* DOS 16-bit <32M */
1684 case 0x06: /* DOS 16-bit >=32M */
1685 case 0xe1: /* DOS access */
1686 case 0xe3: /* DOS R/O */
1687 case 0xf2: /* DOS secondary */
1688 return BSD_FS_MSDOS;
1689 case 0x07: /* OS/2 HPFS */
1692 return BSD_FS_OTHER;
1697 xbsd_link_part (void)
1700 struct partition *p;
1702 k = get_partition (1, partitions);
1704 if (!xbsd_check_new_partition (&i))
1707 p = get_part_table(k);
1709 xbsd_dlabel.d_partitions[i].p_size = get_nr_sects(p);
1710 xbsd_dlabel.d_partitions[i].p_offset = get_start_sect(p);
1711 xbsd_dlabel.d_partitions[i].p_fstype = xbsd_translate_fstype(p->sys_ind);
1715 #if defined (__alpha__)
1717 #if !defined(__GLIBC__)
1718 typedef unsigned long long u_int64_t;
1722 alpha_bootblock_checksum (char *boot)
1727 dp = (u_int64_t *)boot;
1729 for (i = 0; i < 63; i++)
1733 #endif /* __alpha__ */
1735 #endif /* OSF_LABEL */
1737 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
1738 static inline unsigned short
1739 __swap16(unsigned short x) {
1740 return (((uint16_t)(x) & 0xFF) << 8) | (((uint16_t)(x) & 0xFF00) >> 8);
1743 static inline uint32_t
1744 __swap32(uint32_t x) {
1745 return (((x & 0xFF) << 24) |
1746 ((x & 0xFF00) << 8) |
1747 ((x & 0xFF0000) >> 8) |
1748 ((x & 0xFF000000) >> 24));
1752 #ifdef CONFIG_FEATURE_SGI_LABEL
1757 * Copyright (C) Andreas Neuper, Sep 1998.
1758 * This file may be modified and redistributed under
1759 * the terms of the GNU Public License.
1761 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
1762 * Internationalization
1766 static int sgi_other_endian;
1768 static short sgi_volumes=1;
1771 * only dealing with free blocks here
1774 typedef struct { unsigned int first; unsigned int last; } freeblocks;
1775 static freeblocks freelist[17]; /* 16 partitions can produce 17 vacant slots */
1778 setfreelist(int i, unsigned int f, unsigned int l) {
1779 freelist[i].first = f;
1780 freelist[i].last = l;
1784 add2freelist(unsigned int f, unsigned int l) {
1786 for ( ; i < 17 ; i++)
1787 if (freelist[i].last == 0)
1789 setfreelist(i, f, l);
1793 clearfreelist(void) {
1796 for (i = 0; i < 17 ; i++)
1797 setfreelist(i, 0, 0);
1801 isinfreelist(unsigned int b) {
1804 for (i = 0; i < 17 ; i++)
1805 if (freelist[i].first <= b && freelist[i].last >= b)
1806 return freelist[i].last;
1809 /* return last vacant block of this stride (never 0). */
1810 /* the '>=' is not quite correct, but simplifies the code */
1812 * end of free blocks section
1815 static const struct systypes sgi_sys_types[] = {
1816 /* SGI_VOLHDR */ {"\x00" "SGI volhdr" },
1817 /* 0x01 */ {"\x01" "SGI trkrepl" },
1818 /* 0x02 */ {"\x02" "SGI secrepl" },
1819 /* SGI_SWAP */ {"\x03" "SGI raw" },
1820 /* 0x04 */ {"\x04" "SGI bsd" },
1821 /* 0x05 */ {"\x05" "SGI sysv" },
1822 /* ENTIRE_DISK */ {"\x06" "SGI volume" },
1823 /* SGI_EFS */ {"\x07" "SGI efs" },
1824 /* 0x08 */ {"\x08" "SGI lvol" },
1825 /* 0x09 */ {"\x09" "SGI rlvol" },
1826 /* SGI_XFS */ {"\x0a" "SGI xfs" },
1827 /* SGI_XFSLOG */ {"\x0b" "SGI xfslog" },
1828 /* SGI_XLV */ {"\x0c" "SGI xlv" },
1829 /* SGI_XVM */ {"\x0d" "SGI xvm" },
1830 /* LINUX_SWAP */ {"\x82" "Linux swap" },
1831 /* LINUX_NATIVE */ {"\x83" "Linux native" },
1832 /* LINUX_LVM */ {"\x8d" "Linux LVM" },
1833 /* LINUX_RAID */ {"\xfd" "Linux RAID" },
1839 sgi_get_nsect(void) {
1840 return SGI_SSWAP16(sgilabel->devparam.nsect);
1844 sgi_get_ntrks(void) {
1845 return SGI_SSWAP16(sgilabel->devparam.ntrks);
1850 sgilabel->magic = 0;
1856 two_s_complement_32bit_sum(unsigned int* base, int size /* in bytes */) {
1860 size /= sizeof(unsigned int);
1861 for (i = 0; i < size; i++)
1862 sum -= SGI_SSWAP32(base[i]);
1867 check_sgi_label(void) {
1868 if (sizeof(sgilabel) > 512) {
1870 _("According to MIPS Computer Systems, Inc the "
1871 "Label must not contain more than 512 bytes\n"));
1875 if (sgilabel->magic != SGI_LABEL_MAGIC &&
1876 sgilabel->magic != SGI_LABEL_MAGIC_SWAPPED) {
1878 sgi_other_endian = 0;
1882 sgi_other_endian = (sgilabel->magic == SGI_LABEL_MAGIC_SWAPPED);
1884 * test for correct checksum
1886 if (two_s_complement_32bit_sum((unsigned int*)sgilabel,
1887 sizeof(*sgilabel))) {
1889 _("Detected sgi disklabel with wrong checksum.\n"));
1899 sgi_get_start_sector(int i) {
1900 return SGI_SSWAP32(sgilabel->partitions[i].start_sector);
1904 sgi_get_num_sectors(int i) {
1905 return SGI_SSWAP32(sgilabel->partitions[i].num_sectors);
1909 sgi_get_sysid(int i)
1911 return SGI_SSWAP32(sgilabel->partitions[i].id);
1915 sgi_get_bootpartition(void)
1917 return SGI_SSWAP16(sgilabel->boot_part);
1921 sgi_get_swappartition(void)
1923 return SGI_SSWAP16(sgilabel->swap_part);
1927 sgi_list_table(int xtra) {
1929 int kpi = 0; /* kernel partition ID */
1932 printf(_("\nDisk %s (SGI disk label): %d heads, %d sectors\n"
1933 "%d cylinders, %d physical cylinders\n"
1934 "%d extra sects/cyl, interleave %d:1\n"
1936 "Units = %s of %d * 512 bytes\n\n"),
1937 disk_device, heads, sectors, cylinders,
1938 SGI_SSWAP16(sgiparam.pcylcount),
1939 SGI_SSWAP16(sgiparam.sparecyl),
1940 SGI_SSWAP16(sgiparam.ilfact),
1942 str_units(PLURAL), units_per_sector);
1944 printf( _("\nDisk %s (SGI disk label): "
1945 "%d heads, %d sectors, %d cylinders\n"
1946 "Units = %s of %d * 512 bytes\n\n"),
1947 disk_device, heads, sectors, cylinders,
1948 str_units(PLURAL), units_per_sector );
1951 w = strlen(disk_device);
1952 wd = strlen(_("Device"));
1956 printf(_("----- partitions -----\n"
1957 "Pt# %*s Info Start End Sectors Id System\n"),
1958 w + 2, _("Device"));
1959 for (i = 0 ; i < partitions; i++) {
1960 if( sgi_get_num_sectors(i) || debug ) {
1961 uint32_t start = sgi_get_start_sector(i);
1962 uint32_t len = sgi_get_num_sectors(i);
1963 kpi++; /* only count nonempty partitions */
1965 "%2d: %s %4s %9ld %9ld %9ld %2x %s\n",
1966 /* fdisk part number */ i+1,
1967 /* device */ partname(disk_device, kpi, w+3),
1968 /* flags */ (sgi_get_swappartition() == i) ? "swap" :
1969 /* flags */ (sgi_get_bootpartition() == i) ? "boot" : " ",
1970 /* start */ (long) scround(start),
1971 /* end */ (long) scround(start+len)-1,
1972 /* no odd flag on end */ (long) len,
1973 /* type id */ sgi_get_sysid(i),
1974 /* type name */ partition_type(sgi_get_sysid(i)));
1977 printf(_("----- Bootinfo -----\nBootfile: %s\n"
1978 "----- Directory Entries -----\n"),
1979 sgilabel->boot_file);
1980 for (i = 0 ; i < sgi_volumes; i++) {
1981 if (sgilabel->directory[i].vol_file_size) {
1982 uint32_t start = SGI_SSWAP32(sgilabel->directory[i].vol_file_start);
1983 uint32_t len = SGI_SSWAP32(sgilabel->directory[i].vol_file_size);
1984 char*name = sgilabel->directory[i].vol_file_name;
1986 printf(_("%2d: %-10s sector%5u size%8u\n"),
1987 i, name, (unsigned int) start, (unsigned int) len);
1993 sgi_set_bootpartition( int i )
1995 sgilabel->boot_part = SGI_SSWAP16(((short)i));
1999 sgi_get_lastblock(void) {
2000 return heads * sectors * cylinders;
2004 sgi_set_swappartition( int i ) {
2005 sgilabel->swap_part = SGI_SSWAP16(((short)i));
2009 sgi_check_bootfile(const char* aFile) {
2011 if (strlen(aFile) < 3) /* "/a\n" is minimum */ {
2012 printf(_("\nInvalid Bootfile!\n"
2013 "\tThe bootfile must be an absolute non-zero pathname,\n"
2014 "\te.g. \"/unix\" or \"/unix.save\".\n"));
2017 if (strlen(aFile) > 16) {
2018 printf(_("\n\tName of Bootfile too long: "
2019 "16 bytes maximum.\n"));
2022 if (aFile[0] != '/') {
2023 printf(_("\n\tBootfile must have a "
2024 "fully qualified pathname.\n"));
2029 if (strncmp(aFile, sgilabel->boot_file, 16)) {
2030 printf(_("\n\tBe aware, that the bootfile is not checked for existence.\n\t"
2031 "SGI's default is \"/unix\" and for backup \"/unix.save\".\n"));
2032 /* filename is correct and did change */
2035 return 0; /* filename did not change */
2039 sgi_get_bootfile(void) {
2040 return sgilabel->boot_file;
2044 sgi_set_bootfile(const char* aFile) {
2047 if (sgi_check_bootfile(aFile)) {
2049 if ((aFile[i] != '\n') /* in principle caught again by next line */
2050 && (strlen(aFile) > i))
2051 sgilabel->boot_file[i] = aFile[i];
2053 sgilabel->boot_file[i] = 0;
2056 printf(_("\n\tBootfile is changed to \"%s\".\n"), sgilabel->boot_file);
2061 create_sgiinfo(void)
2063 /* I keep SGI's habit to write the sgilabel to the second block */
2064 sgilabel->directory[0].vol_file_start = SGI_SSWAP32(2);
2065 sgilabel->directory[0].vol_file_size = SGI_SSWAP32(sizeof(sgiinfo));
2066 strncpy(sgilabel->directory[0].vol_file_name, "sgilabel", 8);
2069 static sgiinfo *fill_sgiinfo(void);
2072 sgi_write_table(void) {
2074 sgilabel->csum = SGI_SSWAP32(two_s_complement_32bit_sum(
2075 (unsigned int*)sgilabel,
2076 sizeof(*sgilabel)));
2077 assert(two_s_complement_32bit_sum(
2078 (unsigned int*)sgilabel, sizeof(*sgilabel)) == 0);
2079 if (lseek(fd, 0, SEEK_SET) < 0)
2080 fdisk_fatal(unable_to_seek);
2081 if (write(fd, sgilabel, SECTOR_SIZE) != SECTOR_SIZE)
2082 fdisk_fatal(unable_to_write);
2083 if (! strncmp(sgilabel->directory[0].vol_file_name, "sgilabel", 8)) {
2085 * keep this habit of first writing the "sgilabel".
2086 * I never tested whether it works without (AN 981002).
2088 sgiinfo *info = fill_sgiinfo();
2089 int infostartblock = SGI_SSWAP32(sgilabel->directory[0].vol_file_start);
2090 if (fdisk_llseek(fd, (long long)infostartblock*
2091 SECTOR_SIZE, SEEK_SET) < 0)
2092 fdisk_fatal(unable_to_seek);
2093 if (write(fd, info, SECTOR_SIZE) != SECTOR_SIZE)
2094 fdisk_fatal(unable_to_write);
2100 compare_start(int *x, int *y) {
2102 * sort according to start sectors
2103 * and prefers largest partition:
2104 * entry zero is entire disk entry
2106 unsigned int i = *x;
2107 unsigned int j = *y;
2108 unsigned int a = sgi_get_start_sector(i);
2109 unsigned int b = sgi_get_start_sector(j);
2110 unsigned int c = sgi_get_num_sectors(i);
2111 unsigned int d = sgi_get_num_sectors(j);
2114 return (d > c) ? 1 : (d == c) ? 0 : -1;
2115 return (a > b) ? 1 : -1;
2120 verify_sgi(int verbose)
2122 int Index[16]; /* list of valid partitions */
2123 int sortcount = 0; /* number of used partitions, i.e. non-zero lengths */
2124 int entire = 0, i = 0;
2125 unsigned int start = 0;
2126 long long gap = 0; /* count unused blocks */
2127 unsigned int lastblock = sgi_get_lastblock();
2130 for (i=0; i<16; i++) {
2131 if (sgi_get_num_sectors(i) != 0) {
2132 Index[sortcount++]=i;
2133 if (sgi_get_sysid(i) == ENTIRE_DISK) {
2134 if (entire++ == 1) {
2136 printf(_("More than one entire disk entry present.\n"));
2141 if (sortcount == 0) {
2143 printf(_("No partitions defined\n"));
2144 return (lastblock > 0) ? 1 : (lastblock == 0) ? 0 : -1;
2146 qsort(Index, sortcount, sizeof(Index[0]), (void*)compare_start);
2147 if (sgi_get_sysid(Index[0]) == ENTIRE_DISK) {
2148 if ((Index[0] != 10) && verbose)
2149 printf(_("IRIX likes when Partition 11 covers the entire disk.\n"));
2150 if ((sgi_get_start_sector(Index[0]) != 0) && verbose)
2151 printf(_("The entire disk partition should start "
2153 "not at diskblock %d.\n"),
2154 sgi_get_start_sector(Index[0]));
2155 if (debug) /* I do not understand how some disks fulfil it */
2156 if ((sgi_get_num_sectors(Index[0]) != lastblock) && verbose)
2157 printf(_("The entire disk partition is only %d diskblock large,\n"
2158 "but the disk is %d diskblocks long.\n"),
2159 sgi_get_num_sectors(Index[0]), lastblock);
2160 lastblock = sgi_get_num_sectors(Index[0]);
2163 printf(_("One Partition (#11) should cover the entire disk.\n"));
2165 printf("sysid=%d\tpartition=%d\n",
2166 sgi_get_sysid(Index[0]), Index[0]+1);
2168 for (i=1, start=0; i<sortcount; i++) {
2169 int cylsize = sgi_get_nsect() * sgi_get_ntrks();
2171 if ((sgi_get_start_sector(Index[i]) % cylsize) != 0) {
2172 if (debug) /* I do not understand how some disks fulfil it */
2174 printf(_("Partition %d does not start on cylinder boundary.\n"),
2177 if (sgi_get_num_sectors(Index[i]) % cylsize != 0) {
2178 if (debug) /* I do not understand how some disks fulfil it */
2180 printf(_("Partition %d does not end on cylinder boundary.\n"),
2183 /* We cannot handle several "entire disk" entries. */
2184 if (sgi_get_sysid(Index[i]) == ENTIRE_DISK) continue;
2185 if (start > sgi_get_start_sector(Index[i])) {
2187 printf(_("The Partition %d and %d overlap by %d sectors.\n"),
2188 Index[i-1]+1, Index[i]+1,
2189 start - sgi_get_start_sector(Index[i]));
2190 if (gap > 0) gap = -gap;
2191 if (gap == 0) gap = -1;
2193 if (start < sgi_get_start_sector(Index[i])) {
2195 printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"),
2196 sgi_get_start_sector(Index[i]) - start,
2197 start, sgi_get_start_sector(Index[i])-1);
2198 gap += sgi_get_start_sector(Index[i]) - start;
2199 add2freelist(start, sgi_get_start_sector(Index[i]));
2201 start = sgi_get_start_sector(Index[i])
2202 + sgi_get_num_sectors(Index[i]);
2205 printf("%2d:%12d\t%12d\t%12d\n", Index[i],
2206 sgi_get_start_sector(Index[i]),
2207 sgi_get_num_sectors(Index[i]),
2208 sgi_get_sysid(Index[i]));
2211 if (start < lastblock) {
2213 printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"),
2214 lastblock - start, start, lastblock-1);
2215 gap += lastblock - start;
2216 add2freelist(start, lastblock);
2219 * Done with arithmetics
2220 * Go for details now
2223 if (!sgi_get_num_sectors(sgi_get_bootpartition())) {
2224 printf(_("\nThe boot partition does not exist.\n"));
2226 if (!sgi_get_num_sectors(sgi_get_swappartition())) {
2227 printf(_("\nThe swap partition does not exist.\n"));
2229 if ((sgi_get_sysid(sgi_get_swappartition()) != SGI_SWAP)
2230 && (sgi_get_sysid(sgi_get_swappartition()) != LINUX_SWAP))
2231 printf(_("\nThe swap partition has no swap type.\n"));
2233 if (sgi_check_bootfile("/unix"))
2234 printf(_("\tYou have chosen an unusual boot file name.\n"));
2236 return (gap > 0) ? 1 : (gap == 0) ? 0 : -1;
2242 * returned value is:
2243 * = 0 : disk is properly filled to the rim
2244 * < 0 : there is an overlap
2245 * > 0 : there is still some vacant space
2247 return verify_sgi(0);
2251 sgi_change_sysid( int i, int sys )
2253 if( sgi_get_num_sectors(i) == 0 ) /* caught already before, ... */
2255 printf(_("Sorry You may change the Tag of non-empty partitions.\n"));
2258 if( ((sys != ENTIRE_DISK ) && (sys != SGI_VOLHDR))
2259 && (sgi_get_start_sector(i)<1) )
2262 _("It is highly recommended that the partition at offset 0\n"
2263 "is of type \"SGI volhdr\", the IRIX system will rely on it to\n"
2264 "retrieve from its directory standalone tools like sash and fx.\n"
2265 "Only the \"SGI volume\" entire disk section may violate this.\n"
2266 "Type YES if you are sure about tagging this partition differently.\n"));
2267 if (strcmp (line_ptr, _("YES\n")))
2270 sgilabel->partitions[i].id = SGI_SSWAP32(sys);
2273 /* returns partition index of first entry marked as entire disk */
2279 if(sgi_get_sysid(i) == SGI_VOLUME)
2285 sgi_set_partition(int i, unsigned int start, unsigned int length, int sys) {
2287 sgilabel->partitions[i].id = SGI_SSWAP32(sys);
2288 sgilabel->partitions[i].num_sectors = SGI_SSWAP32(length);
2289 sgilabel->partitions[i].start_sector = SGI_SSWAP32(start);
2291 if (sgi_gaps() < 0) /* rebuild freelist */
2292 printf(_("Do You know, You got a partition overlap on the disk?\n"));
2296 sgi_set_entire(void) {
2299 for(n=10; n < partitions; n++) {
2300 if(!sgi_get_num_sectors(n) ) {
2301 sgi_set_partition(n, 0, sgi_get_lastblock(), SGI_VOLUME);
2308 sgi_set_volhdr(void)
2311 for( n=8; n<partitions; n++ )
2313 if(!sgi_get_num_sectors( n ) )
2316 * 5 cylinders is an arbitrary value I like
2317 * IRIX 5.3 stored files in the volume header
2318 * (like sash, symmon, fx, ide) with ca. 3200
2321 if( heads * sectors * 5 < sgi_get_lastblock() )
2322 sgi_set_partition( n, 0, heads * sectors * 5, SGI_VOLHDR );
2329 sgi_delete_partition( int i )
2331 sgi_set_partition( i, 0, 0, 0 );
2335 sgi_add_partition( int n, int sys )
2338 unsigned int first=0, last=0;
2342 } else if ( n == 8 ) {
2345 if(sgi_get_num_sectors(n)) {
2346 printf(_("Partition %d is already defined. Delete "
2347 "it before re-adding it.\n"), n + 1);
2350 if( (sgi_entire() == -1) && (sys != SGI_VOLUME) ) {
2351 printf(_("Attempting to generate entire disk entry automatically.\n"));
2355 if( (sgi_gaps() == 0) && (sys != SGI_VOLUME) ) {
2356 printf(_("The entire disk is already covered with partitions.\n"));
2359 if(sgi_gaps() < 0) {
2360 printf(_("You got a partition overlap on the disk. Fix it first!\n"));
2363 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
2365 if(sys == SGI_VOLUME) {
2366 last = sgi_get_lastblock();
2367 first = read_int(0, 0, last-1, 0, mesg);
2369 printf(_("It is highly recommended that eleventh partition\n"
2370 "covers the entire disk and is of type `SGI volume'\n"));
2373 first = freelist[0].first;
2374 last = freelist[0].last;
2375 first = read_int(scround(first), scround(first), scround(last)-1,
2378 if (display_in_cyl_units)
2379 first *= units_per_sector;
2381 first = first; /* align to cylinder if you know how ... */
2383 last = isinfreelist(first);
2385 printf(_("You will get a partition overlap on the disk. "
2386 "Fix it first!\n"));
2390 snprintf(mesg, sizeof(mesg), _(" Last %s"), str_units(SINGULAR));
2391 last = read_int(scround(first), scround(last)-1, scround(last)-1,
2392 scround(first), mesg)+1;
2393 if (display_in_cyl_units)
2394 last *= units_per_sector;
2396 last = last; /* align to cylinder if You know how ... */
2397 if( (sys == SGI_VOLUME) && ( first != 0 || last != sgi_get_lastblock() ) )
2398 printf(_("It is highly recommended that eleventh partition\n"
2399 "covers the entire disk and is of type `SGI volume'\n"));
2400 sgi_set_partition( n, first, last-first, sys );
2403 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
2405 create_sgilabel(void)
2407 struct hd_geometry geometry;
2414 long longsectors; /* the number of sectors on the device */
2415 int res; /* the result from the ioctl */
2416 int sec_fac; /* the sector factor */
2418 sec_fac = sector_size / 512; /* determine the sector factor */
2421 _("Building a new SGI disklabel. Changes will remain in memory only,\n"
2422 "until you decide to write them. After that, of course, the previous\n"
2423 "content will be unrecoverably lost.\n\n"));
2425 sgi_other_endian = (BYTE_ORDER == LITTLE_ENDIAN);
2426 res = ioctl(fd, BLKGETSIZE, &longsectors);
2427 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
2428 heads = geometry.heads;
2429 sectors = geometry.sectors;
2431 /* the get device size ioctl was successful */
2432 cylinders = longsectors / (heads * sectors);
2433 cylinders /= sec_fac;
2435 /* otherwise print error and use truncated version */
2436 cylinders = geometry.cylinders;
2438 _("Warning: BLKGETSIZE ioctl failed on %s. "
2439 "Using geometry cylinder value of %d.\n"
2440 "This value may be truncated for devices"
2441 " > 33.8 GB.\n"), disk_device, cylinders);
2444 for (i = 0; i < 4; i++) {
2446 if(valid_part_table_flag(MBRbuffer)) {
2447 if(get_part_table(i)->sys_ind) {
2448 old[i].sysid = get_part_table(i)->sys_ind;
2449 old[i].start = get_start_sect(get_part_table(i));
2450 old[i].nsect = get_nr_sects(get_part_table(i));
2451 printf(_("Trying to keep parameters of partition %d.\n"), i);
2453 printf(_("ID=%02x\tSTART=%d\tLENGTH=%d\n"),
2454 old[i].sysid, old[i].start, old[i].nsect);
2459 memset(MBRbuffer, 0, sizeof(MBRbuffer));
2460 sgilabel->magic = SGI_SSWAP32(SGI_LABEL_MAGIC);
2461 sgilabel->boot_part = SGI_SSWAP16(0);
2462 sgilabel->swap_part = SGI_SSWAP16(1);
2464 /* sizeof(sgilabel->boot_file) = 16 > 6 */
2465 memset(sgilabel->boot_file, 0, 16);
2466 strcpy(sgilabel->boot_file, "/unix");
2468 sgilabel->devparam.skew = (0);
2469 sgilabel->devparam.gap1 = (0);
2470 sgilabel->devparam.gap2 = (0);
2471 sgilabel->devparam.sparecyl = (0);
2472 sgilabel->devparam.pcylcount = SGI_SSWAP16(geometry.cylinders);
2473 sgilabel->devparam.head_vol0 = SGI_SSWAP16(0);
2474 sgilabel->devparam.ntrks = SGI_SSWAP16(geometry.heads);
2475 /* tracks/cylinder (heads) */
2476 sgilabel->devparam.cmd_tag_queue_depth = (0);
2477 sgilabel->devparam.unused0 = (0);
2478 sgilabel->devparam.unused1 = SGI_SSWAP16(0);
2479 sgilabel->devparam.nsect = SGI_SSWAP16(geometry.sectors);
2481 sgilabel->devparam.bytes = SGI_SSWAP16(512);
2482 sgilabel->devparam.ilfact = SGI_SSWAP16(1);
2483 sgilabel->devparam.flags = SGI_SSWAP32(TRACK_FWD|
2484 IGNORE_ERRORS|RESEEK);
2485 sgilabel->devparam.datarate = SGI_SSWAP32(0);
2486 sgilabel->devparam.retries_on_error = SGI_SSWAP32(1);
2487 sgilabel->devparam.ms_per_word = SGI_SSWAP32(0);
2488 sgilabel->devparam.xylogics_gap1 = SGI_SSWAP16(0);
2489 sgilabel->devparam.xylogics_syncdelay = SGI_SSWAP16(0);
2490 sgilabel->devparam.xylogics_readdelay = SGI_SSWAP16(0);
2491 sgilabel->devparam.xylogics_gap2 = SGI_SSWAP16(0);
2492 sgilabel->devparam.xylogics_readgate = SGI_SSWAP16(0);
2493 sgilabel->devparam.xylogics_writecont = SGI_SSWAP16(0);
2494 memset( &(sgilabel->directory), 0, sizeof(struct volume_directory)*15 );
2495 memset( &(sgilabel->partitions), 0, sizeof(struct sgi_partition)*16 );
2501 for (i = 0; i < 4; i++) {
2503 sgi_set_partition(i, old[i].start, old[i].nsect, old[i].sysid);
2511 /* do nothing in the beginning */
2513 #endif /* CONFIG_FEATURE_FDISK_ADVANCED */
2515 /* _____________________________________________________________
2521 sgiinfo *info = calloc(1, sizeof(sgiinfo));
2523 info->magic=SGI_SSWAP32(SGI_INFO_MAGIC);
2524 info->b1=SGI_SSWAP32(-1);
2525 info->b2=SGI_SSWAP16(-1);
2526 info->b3=SGI_SSWAP16(1);
2527 /* You may want to replace this string !!!!!!! */
2528 strcpy( info->scsi_string, "IBM OEM 0662S12 3 30" );
2529 strcpy( info->serial, "0000" );
2530 info->check1816 = SGI_SSWAP16(18*256 +16 );
2531 strcpy( info->installer, "Sfx version 5.3, Oct 18, 1994" );
2534 #endif /* SGI_LABEL */
2537 #ifdef CONFIG_FEATURE_SUN_LABEL
2541 * I think this is mostly, or entirely, due to
2542 * Jakub Jelinek (jj@sunsite.mff.cuni.cz), July 1996
2544 * Merged with fdisk for other architectures, aeb, June 1998.
2546 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
2547 * Internationalization
2551 static int sun_other_endian;
2552 static int scsi_disk;
2556 #define IDE0_MAJOR 3
2559 #define IDE1_MAJOR 22
2562 static void guess_device_type(void) {
2563 struct stat bootstat;
2565 if (fstat (fd, &bootstat) < 0) {
2568 } else if (S_ISBLK(bootstat.st_mode)
2569 && (major(bootstat.st_rdev) == IDE0_MAJOR ||
2570 major(bootstat.st_rdev) == IDE1_MAJOR)) {
2573 } else if (S_ISBLK(bootstat.st_mode)
2574 && major(bootstat.st_rdev) == FLOPPY_MAJOR) {
2583 static const struct systypes sun_sys_types[] = {
2584 /* 0 */ {"\x00" "Empty" },
2585 /* 1 */ {"\x01" "Boot" },
2586 /* 2 */ {"\x02" "SunOS root" },
2587 /* SUNOS_SWAP */ {"\x03" "SunOS swap" },
2588 /* 4 */ {"\x04" "SunOS usr" },
2589 /* WHOLE_DISK */ {"\x05" "Whole disk" },
2590 /* 6 */ {"\x06" "SunOS stand" },
2591 /* 7 */ {"\x07" "SunOS var" },
2592 /* 8 */ {"\x08" "SunOS home" },
2593 /* LINUX_SWAP */ {"\x82" "Linux swap" },
2594 /* LINUX_NATIVE */ {"\x83" "Linux native" },
2595 /* 0x8e */ {"\x8e" "Linux LVM" },
2596 /* New (2.2.x) raid partition with autodetect using persistent superblock */
2597 /* 0xfd */ {"\xfd" "Linux raid autodetect" },
2603 set_sun_partition(int i, uint start, uint stop, int sysid) {
2604 sunlabel->infos[i].id = sysid;
2605 sunlabel->partitions[i].start_cylinder =
2606 SUN_SSWAP32(start / (heads * sectors));
2607 sunlabel->partitions[i].num_sectors =
2608 SUN_SSWAP32(stop - start);
2615 sunlabel->magic = 0;
2620 check_sun_label(void) {
2621 unsigned short *ush;
2624 if (sunlabel->magic != SUN_LABEL_MAGIC &&
2625 sunlabel->magic != SUN_LABEL_MAGIC_SWAPPED) {
2627 sun_other_endian = 0;
2630 sun_other_endian = (sunlabel->magic == SUN_LABEL_MAGIC_SWAPPED);
2631 ush = ((unsigned short *) (sunlabel + 1)) - 1;
2632 for (csum = 0; ush >= (unsigned short *)sunlabel;) csum ^= *ush--;
2634 fprintf(stderr,_("Detected sun disklabel with wrong checksum.\n"
2635 "Probably you'll have to set all the values,\n"
2636 "e.g. heads, sectors, cylinders and partitions\n"
2637 "or force a fresh label (s command in main menu)\n"));
2639 heads = SUN_SSWAP16(sunlabel->ntrks);
2640 cylinders = SUN_SSWAP16(sunlabel->ncyl);
2641 sectors = SUN_SSWAP16(sunlabel->nsect);
2649 static const struct sun_predefined_drives {
2652 unsigned short sparecyl;
2653 unsigned short ncyl;
2654 unsigned short nacyl;
2655 unsigned short pcylcount;
2656 unsigned short ntrks;
2657 unsigned short nsect;
2658 unsigned short rspeed;
2660 {"Quantum","ProDrive 80S",1,832,2,834,6,34,3662},
2661 {"Quantum","ProDrive 105S",1,974,2,1019,6,35,3662},
2662 {"CDC","Wren IV 94171-344",3,1545,2,1549,9,46,3600},
2663 {"IBM","DPES-31080",0,4901,2,4903,4,108,5400},
2664 {"IBM","DORS-32160",0,1015,2,1017,67,62,5400},
2665 {"IBM","DNES-318350",0,11199,2,11474,10,320,7200},
2666 {"SEAGATE","ST34371",0,3880,2,3882,16,135,7228},
2667 {"","SUN0104",1,974,2,1019,6,35,3662},
2668 {"","SUN0207",4,1254,2,1272,9,36,3600},
2669 {"","SUN0327",3,1545,2,1549,9,46,3600},
2670 {"","SUN0340",0,1538,2,1544,6,72,4200},
2671 {"","SUN0424",2,1151,2,2500,9,80,4400},
2672 {"","SUN0535",0,1866,2,2500,7,80,5400},
2673 {"","SUN0669",5,1614,2,1632,15,54,3600},
2674 {"","SUN1.0G",5,1703,2,1931,15,80,3597},
2675 {"","SUN1.05",0,2036,2,2038,14,72,5400},
2676 {"","SUN1.3G",6,1965,2,3500,17,80,5400},
2677 {"","SUN2.1G",0,2733,2,3500,19,80,5400},
2678 {"IOMEGA","Jaz",0,1019,2,1021,64,32,5394},
2681 static const struct sun_predefined_drives *
2682 sun_autoconfigure_scsi(void) {
2683 const struct sun_predefined_drives *p = NULL;
2685 #ifdef SCSI_IOCTL_GET_IDLUN
2695 if (!ioctl(fd, SCSI_IOCTL_GET_IDLUN, &id)) {
2697 "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n",
2699 ((id[0]>>24)&0xff)-/*PROC_SCSI_SCSI+PROC_SCSI_FILE*/33,
2701 /* This is very wrong (works only if you have one HBA),
2702 but I haven't found a way how to get hostno
2703 from the current kernel */
2709 pfd = fopen("/proc/scsi/scsi","r");
2711 while (fgets(buffer2,2048,pfd)) {
2712 if (!strcmp(buffer, buffer2)) {
2713 if (fgets(buffer2,2048,pfd)) {
2714 q = strstr(buffer2,"Vendor: ");
2719 *q++ = 0; /* truncate vendor name */
2720 q = strstr(q,"Model: ");
2725 q = strstr(q," Rev: ");
2728 for (i = 0; i < SIZE(sun_drives); i++) {
2729 if (*sun_drives[i].vendor && strcasecmp(sun_drives[i].vendor, vendor))
2731 if (!strstr(model, sun_drives[i].model))
2733 printf(_("Autoconfigure found a %s%s%s\n"),sun_drives[i].vendor,(*sun_drives[i].vendor) ? " " : "",sun_drives[i].model);
2751 static void create_sunlabel(void)
2753 struct hd_geometry geometry;
2757 const struct sun_predefined_drives *p = NULL;
2760 _("Building a new sun disklabel. Changes will remain in memory only,\n"
2761 "until you decide to write them. After that, of course, the previous\n"
2762 "content won't be recoverable.\n\n"));
2763 #if BYTE_ORDER == LITTLE_ENDIAN
2764 sun_other_endian = 1;
2766 sun_other_endian = 0;
2768 memset(MBRbuffer, 0, sizeof(MBRbuffer));
2769 sunlabel->magic = SUN_SSWAP16(SUN_LABEL_MAGIC);
2771 puts(_("Drive type\n"
2772 " ? auto configure\n"
2773 " 0 custom (with hardware detected defaults)"));
2774 for (i = 0; i < SIZE(sun_drives); i++) {
2775 printf(" %c %s%s%s\n",
2776 i + 'a', sun_drives[i].vendor,
2777 (*sun_drives[i].vendor) ? " " : "",
2778 sun_drives[i].model);
2781 c = read_char(_("Select type (? for auto, 0 for custom): "));
2782 if (c >= 'a' && c < 'a' + SIZE(sun_drives)) {
2783 p = sun_drives + c - 'a';
2785 } else if (c >= 'A' && c < 'A' + SIZE(sun_drives)) {
2786 p = sun_drives + c - 'A';
2788 } else if (c == '0') {
2790 } else if (c == '?' && scsi_disk) {
2791 p = sun_autoconfigure_scsi();
2793 printf(_("Autoconfigure failed.\n"));
2800 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
2801 heads = geometry.heads;
2802 sectors = geometry.sectors;
2803 cylinders = geometry.cylinders;
2810 sunlabel->nacyl = 0;
2811 sunlabel->pcylcount = SUN_SSWAP16(cylinders);
2812 sunlabel->rspeed = SUN_SSWAP16(300);
2813 sunlabel->ilfact = SUN_SSWAP16(1);
2814 sunlabel->sparecyl = 0;
2816 heads = read_int(1,heads,1024,0,_("Heads"));
2817 sectors = read_int(1,sectors,1024,0,_("Sectors/track"));
2819 cylinders = read_int(1,cylinders-2,65535,0,_("Cylinders"));
2821 cylinders = read_int(1,0,65535,0,_("Cylinders"));
2823 SUN_SSWAP16(read_int(0,2,65535,0,
2824 _("Alternate cylinders")));
2825 sunlabel->pcylcount =
2826 SUN_SSWAP16(read_int(0,cylinders+SUN_SSWAP16(sunlabel->nacyl),
2827 65535,0,_("Physical cylinders")));
2829 SUN_SSWAP16(read_int(1,5400,100000,0,
2830 _("Rotation speed (rpm)")));
2832 SUN_SSWAP16(read_int(1,1,32,0,_("Interleave factor")));
2833 sunlabel->sparecyl =
2834 SUN_SSWAP16(read_int(0,0,sectors,0,
2835 _("Extra sectors per cylinder")));
2838 sunlabel->sparecyl = SUN_SSWAP16(p->sparecyl);
2839 sunlabel->ncyl = SUN_SSWAP16(p->ncyl);
2840 sunlabel->nacyl = SUN_SSWAP16(p->nacyl);
2841 sunlabel->pcylcount = SUN_SSWAP16(p->pcylcount);
2842 sunlabel->ntrks = SUN_SSWAP16(p->ntrks);
2843 sunlabel->nsect = SUN_SSWAP16(p->nsect);
2844 sunlabel->rspeed = SUN_SSWAP16(p->rspeed);
2845 sunlabel->ilfact = SUN_SSWAP16(1);
2846 cylinders = p->ncyl;
2849 puts(_("You may change all the disk params from the x menu"));
2852 snprintf(sunlabel->info, sizeof(sunlabel->info),
2853 "%s%s%s cyl %d alt %d hd %d sec %d",
2854 p ? p->vendor : "", (p && *p->vendor) ? " " : "",
2856 : (floppy ? _("3,5\" floppy") : _("Linux custom")),
2857 cylinders, SUN_SSWAP16(sunlabel->nacyl), heads, sectors);
2859 sunlabel->ntrks = SUN_SSWAP16(heads);
2860 sunlabel->nsect = SUN_SSWAP16(sectors);
2861 sunlabel->ncyl = SUN_SSWAP16(cylinders);
2863 set_sun_partition(0, 0, cylinders * heads * sectors, LINUX_NATIVE);
2865 if (cylinders * heads * sectors >= 150 * 2048) {
2866 ndiv = cylinders - (50 * 2048 / (heads * sectors)); /* 50M swap */
2868 ndiv = cylinders * 2 / 3;
2869 set_sun_partition(0, 0, ndiv * heads * sectors, LINUX_NATIVE);
2870 set_sun_partition(1, ndiv * heads * sectors, cylinders * heads * sectors, LINUX_SWAP);
2871 sunlabel->infos[1].flags |= 0x01; /* Not mountable */
2873 set_sun_partition(2, 0, cylinders * heads * sectors, WHOLE_DISK);
2875 unsigned short *ush = (unsigned short *)sunlabel;
2876 unsigned short csum = 0;
2877 while(ush < (unsigned short *)(&sunlabel->csum))
2879 sunlabel->csum = csum;
2882 set_all_unchanged();
2884 get_boot(create_empty_sun);
2888 toggle_sunflags(int i, unsigned char mask) {
2889 if (sunlabel->infos[i].flags & mask)
2890 sunlabel->infos[i].flags &= ~mask;
2891 else sunlabel->infos[i].flags |= mask;
2896 fetch_sun(uint *starts, uint *lens, uint *start, uint *stop) {
2897 int i, continuous = 1;
2898 *start = 0; *stop = cylinders * heads * sectors;
2899 for (i = 0; i < partitions; i++) {
2900 if (sunlabel->partitions[i].num_sectors
2901 && sunlabel->infos[i].id
2902 && sunlabel->infos[i].id != WHOLE_DISK) {
2903 starts[i] = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
2904 lens[i] = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
2906 if (starts[i] == *start)
2908 else if (starts[i] + lens[i] >= *stop)
2912 /* There will be probably more gaps
2913 than one, so lets check afterwards */
2922 static uint *verify_sun_starts;
2925 verify_sun_cmp(int *a, int *b) {
2926 if (*a == -1) return 1;
2927 if (*b == -1) return -1;
2928 if (verify_sun_starts[*a] > verify_sun_starts[*b]) return 1;
2934 uint starts[8], lens[8], start, stop;
2935 int i,j,k,starto,endo;
2938 verify_sun_starts = starts;
2939 fetch_sun(starts,lens,&start,&stop);
2940 for (k = 0; k < 7; k++) {
2941 for (i = 0; i < 8; i++) {
2942 if (k && (lens[i] % (heads * sectors))) {
2943 printf(_("Partition %d doesn't end on cylinder boundary\n"), i+1);
2946 for (j = 0; j < i; j++)
2948 if (starts[j] == starts[i]+lens[i]) {
2949 starts[j] = starts[i]; lens[j] += lens[i];
2951 } else if (starts[i] == starts[j]+lens[j]){
2955 if (starts[i] < starts[j]+lens[j] &&
2956 starts[j] < starts[i]+lens[i]) {
2958 if (starts[j] > starto)
2960 endo = starts[i]+lens[i];
2961 if (starts[j]+lens[j] < endo)
2962 endo = starts[j]+lens[j];
2963 printf(_("Partition %d overlaps with others in "
2964 "sectors %d-%d\n"), i+1, starto, endo);
2971 for (i = 0; i < 8; i++) {
2977 qsort(array,SIZE(array),sizeof(array[0]),
2978 (int (*)(const void *,const void *)) verify_sun_cmp);
2979 if (array[0] == -1) {
2980 printf(_("No partitions defined\n"));
2983 stop = cylinders * heads * sectors;
2984 if (starts[array[0]])
2985 printf(_("Unused gap - sectors 0-%d\n"),starts[array[0]]);
2986 for (i = 0; i < 7 && array[i+1] != -1; i++) {
2987 printf(_("Unused gap - sectors %d-%d\n"),starts[array[i]]+lens[array[i]],starts[array[i+1]]);
2989 start = starts[array[i]]+lens[array[i]];
2991 printf(_("Unused gap - sectors %d-%d\n"),start,stop);
2995 add_sun_partition(int n, int sys) {
2996 uint start, stop, stop2;
2997 uint starts[8], lens[8];
3003 if (sunlabel->partitions[n].num_sectors && sunlabel->infos[n].id) {
3004 printf(_("Partition %d is already defined. Delete "
3005 "it before re-adding it.\n"), n + 1);
3009 fetch_sun(starts,lens,&start,&stop);
3010 if (stop <= start) {
3014 printf(_("Other partitions already cover the whole disk.\nDelete "
3015 "some/shrink them before retry.\n"));
3019 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
3022 first = read_int(0, 0, 0, 0, mesg);
3024 first = read_int(scround(start), scround(stop)+1,
3025 scround(stop), 0, mesg);
3026 if (display_in_cyl_units)
3027 first *= units_per_sector;
3029 /* Starting sector has to be properly aligned */
3030 first = (first + heads * sectors - 1) / (heads * sectors);
3031 if (n == 2 && first != 0)
3033 It is highly recommended that the third partition covers the whole disk\n\
3034 and is of type `Whole disk'\n");
3035 /* ewt asks to add: "don't start a partition at cyl 0"
3036 However, edmundo@rano.demon.co.uk writes:
3037 "In addition to having a Sun partition table, to be able to
3038 boot from the disc, the first partition, /dev/sdX1, must
3039 start at cylinder 0. This means that /dev/sdX1 contains
3040 the partition table and the boot block, as these are the
3041 first two sectors of the disc. Therefore you must be
3042 careful what you use /dev/sdX1 for. In particular, you must
3043 not use a partition starting at cylinder 0 for Linux swap,
3044 as that would overwrite the partition table and the boot
3045 block. You may, however, use such a partition for a UFS
3046 or EXT2 file system, as these file systems leave the first
3047 1024 bytes undisturbed. */
3048 /* On the other hand, one should not use partitions
3049 starting at block 0 in an md, or the label will
3051 for (i = 0; i < partitions; i++)
3052 if (lens[i] && starts[i] <= first
3053 && starts[i] + lens[i] > first)
3055 if (i < partitions && !whole_disk) {
3056 if (n == 2 && !first) {
3060 printf(_("Sector %d is already allocated\n"), first);
3064 stop = cylinders * heads * sectors;
3066 for (i = 0; i < partitions; i++) {
3067 if (starts[i] > first && starts[i] < stop)
3070 snprintf(mesg, sizeof(mesg),
3071 _("Last %s or +size or +sizeM or +sizeK"),
3072 str_units(SINGULAR));
3074 last = read_int(scround(stop2), scround(stop2), scround(stop2),
3076 else if (n == 2 && !first)
3077 last = read_int(scround(first), scround(stop2), scround(stop2),
3078 scround(first), mesg);
3080 last = read_int(scround(first), scround(stop), scround(stop),
3081 scround(first), mesg);
3082 if (display_in_cyl_units)
3083 last *= units_per_sector;
3084 if (n == 2 && !first) {
3085 if (last >= stop2) {
3088 } else if (last > stop) {
3090 _("You haven't covered the whole disk with the 3rd partition, but your value\n"
3091 "%d %s covers some other partition. Your entry has been changed\n"
3093 scround(last), str_units(SINGULAR),
3094 scround(stop), str_units(SINGULAR));
3097 } else if (!whole_disk && last > stop)
3100 if (whole_disk) sys = WHOLE_DISK;
3101 set_sun_partition(n, first, last, sys);
3105 sun_delete_partition(int i) {
3108 if (i == 2 && sunlabel->infos[i].id == WHOLE_DISK &&
3109 !sunlabel->partitions[i].start_cylinder &&
3110 (nsec = SUN_SSWAP32(sunlabel->partitions[i].num_sectors))
3111 == heads * sectors * cylinders)
3112 printf(_("If you want to maintain SunOS/Solaris compatibility, "
3113 "consider leaving this\n"
3114 "partition as Whole disk (5), starting at 0, with %u "
3115 "sectors\n"), nsec);
3116 sunlabel->infos[i].id = 0;
3117 sunlabel->partitions[i].num_sectors = 0;
3121 sun_change_sysid(int i, int sys) {
3122 if (sys == LINUX_SWAP && !sunlabel->partitions[i].start_cylinder) {
3124 _("It is highly recommended that the partition at offset 0\n"
3125 "is UFS, EXT2FS filesystem or SunOS swap. Putting Linux swap\n"
3126 "there may destroy your partition table and bootblock.\n"
3127 "Type YES if you're very sure you would like that partition\n"
3128 "tagged with 82 (Linux swap): "));
3129 if (strcmp (line_ptr, _("YES\n")))
3135 /* swaps are not mountable by default */
3136 sunlabel->infos[i].flags |= 0x01;
3139 /* assume other types are mountable;
3140 user can change it anyway */
3141 sunlabel->infos[i].flags &= ~0x01;
3144 sunlabel->infos[i].id = sys;
3148 sun_list_table(int xtra) {
3151 w = strlen(disk_device);
3154 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d rpm\n"
3155 "%d cylinders, %d alternate cylinders, %d physical cylinders\n"
3156 "%d extra sects/cyl, interleave %d:1\n"
3158 "Units = %s of %d * 512 bytes\n\n"),
3159 disk_device, heads, sectors, SUN_SSWAP16(sunlabel->rspeed),
3160 cylinders, SUN_SSWAP16(sunlabel->nacyl),
3161 SUN_SSWAP16(sunlabel->pcylcount),
3162 SUN_SSWAP16(sunlabel->sparecyl),
3163 SUN_SSWAP16(sunlabel->ilfact),
3165 str_units(PLURAL), units_per_sector);
3168 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d cylinders\n"
3169 "Units = %s of %d * 512 bytes\n\n"),
3170 disk_device, heads, sectors, cylinders,
3171 str_units(PLURAL), units_per_sector);
3173 printf(_("%*s Flag Start End Blocks Id System\n"),
3174 w + 1, _("Device"));
3175 for (i = 0 ; i < partitions; i++) {
3176 if (sunlabel->partitions[i].num_sectors) {
3177 uint32_t start = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
3178 uint32_t len = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
3180 "%s %c%c %9ld %9ld %9ld%c %2x %s\n",
3181 /* device */ partname(disk_device, i+1, w),
3182 /* flags */ (sunlabel->infos[i].flags & 0x01) ? 'u' : ' ',
3183 (sunlabel->infos[i].flags & 0x10) ? 'r' : ' ',
3184 /* start */ (long) scround(start),
3185 /* end */ (long) scround(start+len),
3186 /* odd flag on end */ (long) len / 2, len & 1 ? '+' : ' ',
3187 /* type id */ sunlabel->infos[i].id,
3188 /* type name */ partition_type(sunlabel->infos[i].id));
3193 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3196 sun_set_alt_cyl(void) {
3198 SUN_SSWAP16(read_int(0,SUN_SSWAP16(sunlabel->nacyl), 65535, 0,
3199 _("Number of alternate cylinders")));
3203 sun_set_ncyl(int cyl) {
3204 sunlabel->ncyl = SUN_SSWAP16(cyl);
3208 sun_set_xcyl(void) {
3209 sunlabel->sparecyl =
3210 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->sparecyl), sectors, 0,
3211 _("Extra sectors per cylinder")));
3215 sun_set_ilfact(void) {
3217 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->ilfact), 32, 0,
3218 _("Interleave factor")));
3222 sun_set_rspeed(void) {
3224 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->rspeed), 100000, 0,
3225 _("Rotation speed (rpm)")));
3229 sun_set_pcylcount(void) {
3230 sunlabel->pcylcount =
3231 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->pcylcount), 65535, 0,
3232 _("Number of physical cylinders")));
3234 #endif /* CONFIG_FEATURE_FDISK_ADVANCED */
3237 sun_write_table(void) {
3238 unsigned short *ush = (unsigned short *)sunlabel;
3239 unsigned short csum = 0;
3241 while(ush < (unsigned short *)(&sunlabel->csum))
3243 sunlabel->csum = csum;
3244 if (lseek(fd, 0, SEEK_SET) < 0)
3245 fdisk_fatal(unable_to_seek);
3246 if (write(fd, sunlabel, SECTOR_SIZE) != SECTOR_SIZE)
3247 fdisk_fatal(unable_to_write);
3249 #endif /* SUN_LABEL */
3251 /* DOS partition types */
3253 static const struct systypes i386_sys_types[] = {
3256 {"\x04" "FAT16 <32M"},
3257 {"\x05" "Extended"}, /* DOS 3.3+ extended partition */
3258 {"\x06" "FAT16"}, /* DOS 16-bit >=32M */
3259 {"\x07" "HPFS/NTFS"}, /* OS/2 IFS, eg, HPFS or NTFS or QNX */
3260 {"\x0a" "OS/2 Boot Manager"},/* OS/2 Boot Manager */
3261 {"\x0b" "Win95 FAT32"},
3262 {"\x0c" "Win95 FAT32 (LBA)"},/* LBA really is `Extended Int 13h' */
3263 {"\x0e" "Win95 FAT16 (LBA)"},
3264 {"\x0f" "Win95 Ext'd (LBA)"},
3265 {"\x11" "Hidden FAT12"},
3266 {"\x12" "Compaq diagnostics"},
3267 {"\x14" "Hidden FAT16 <32M"},
3268 {"\x16" "Hidden FAT16"},
3269 {"\x17" "Hidden HPFS/NTFS"},
3270 {"\x1b" "Hidden Win95 FAT32"},
3271 {"\x1c" "Hidden Win95 FAT32 (LBA)"},
3272 {"\x1e" "Hidden Win95 FAT16 (LBA)"},
3273 {"\x3c" "PartitionMagic recovery"},
3274 {"\x41" "PPC PReP Boot"},
3276 {"\x63" "GNU HURD or SysV"}, /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */
3277 {"\x80" "Old Minix"}, /* Minix 1.4a and earlier */
3278 {"\x81" "Minix / old Linux"},/* Minix 1.4b and later */
3279 {"\x82" "Linux swap"}, /* also Solaris */
3281 {"\x84" "OS/2 hidden C: drive"},
3282 {"\x85" "Linux extended"},
3283 {"\x86" "NTFS volume set"},
3284 {"\x87" "NTFS volume set"},
3285 {"\x8e" "Linux LVM"},
3286 {"\x9f" "BSD/OS"}, /* BSDI */
3287 {"\xa0" "IBM Thinkpad hibernation"},
3288 {"\xa5" "FreeBSD"}, /* various BSD flavours */
3290 {"\xa8" "Darwin UFS"},
3292 {"\xab" "Darwin boot"},
3294 {"\xb8" "BSDI swap"},
3295 {"\xbe" "Solaris boot"},
3297 {"\xee" "EFI GPT"}, /* Intel EFI GUID Partition Table */
3298 {"\xef" "EFI (FAT-12/16/32)"},/* Intel EFI System Partition */
3299 {"\xf0" "Linux/PA-RISC boot"},/* Linux/PA-RISC boot loader */
3300 {"\xf2" "DOS secondary"}, /* DOS 3.3+ secondary */
3301 {"\xfd" "Linux raid autodetect"},/* New (2.2.x) raid partition with
3302 autodetect using persistent
3304 #ifdef CONFIG_WEIRD_PARTITION_TYPES
3305 {"\x02" "XENIX root"},
3306 {"\x03" "XENIX usr"},
3307 {"\x08" "AIX"}, /* AIX boot (AIX -- PS/2 port) or SplitDrive */
3308 {"\x09" "AIX bootable"}, /* AIX data or Coherent */
3310 {"\x18" "AST SmartSleep"},
3313 {"\x40" "Venix 80286"},
3315 {"\x4e" "QNX4.x 2nd part"},
3316 {"\x4f" "QNX4.x 3rd part"},
3317 {"\x50" "OnTrack DM"},
3318 {"\x51" "OnTrack DM6 Aux1"}, /* (or Novell) */
3319 {"\x52" "CP/M"}, /* CP/M or Microport SysV/AT */
3320 {"\x53" "OnTrack DM6 Aux3"},
3321 {"\x54" "OnTrackDM6"},
3322 {"\x55" "EZ-Drive"},
3323 {"\x56" "Golden Bow"},
3324 {"\x5c" "Priam Edisk"},
3325 {"\x61" "SpeedStor"},
3326 {"\x64" "Novell Netware 286"},
3327 {"\x65" "Novell Netware 386"},
3328 {"\x70" "DiskSecure Multi-Boot"},
3331 {"\x94" "Amoeba BBT"}, /* (bad block table) */
3332 {"\xa7" "NeXTSTEP"},
3333 {"\xbb" "Boot Wizard hidden"},
3334 {"\xc1" "DRDOS/sec (FAT-12)"},
3335 {"\xc4" "DRDOS/sec (FAT-16 < 32M)"},
3336 {"\xc6" "DRDOS/sec (FAT-16)"},
3338 {"\xda" "Non-FS data"},
3339 {"\xdb" "CP/M / CTOS / ..."},/* CP/M or Concurrent CP/M or
3340 Concurrent DOS or CTOS */
3341 {"\xde" "Dell Utility"}, /* Dell PowerEdge Server utilities */
3342 {"\xdf" "BootIt"}, /* BootIt EMBRM */
3343 {"\xe1" "DOS access"}, /* DOS access or SpeedStor 12-bit FAT
3344 extended partition */
3345 {"\xe3" "DOS R/O"}, /* DOS R/O or SpeedStor */
3346 {"\xe4" "SpeedStor"}, /* SpeedStor 16-bit FAT extended
3347 partition < 1024 cyl. */
3348 {"\xf1" "SpeedStor"},
3349 {"\xf4" "SpeedStor"}, /* SpeedStor large partition */
3350 {"\xfe" "LANstep"}, /* SpeedStor >1024 cyl. or LANstep */
3351 {"\xff" "BBT"}, /* Xenix Bad Block Table */
3358 /* A valid partition table sector ends in 0x55 0xaa */
3360 part_table_flag(const char *b) {
3361 return ((uint) b[510]) + (((uint) b[511]) << 8);
3365 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3367 write_part_table_flag(char *b) {
3372 /* start_sect and nr_sects are stored little endian on all machines */
3373 /* moreover, they are not aligned correctly */
3375 store4_little_endian(unsigned char *cp, unsigned int val) {
3376 cp[0] = (val & 0xff);
3377 cp[1] = ((val >> 8) & 0xff);
3378 cp[2] = ((val >> 16) & 0xff);
3379 cp[3] = ((val >> 24) & 0xff);
3381 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3384 read4_little_endian(const unsigned char *cp) {
3385 return (uint)(cp[0]) + ((uint)(cp[1]) << 8)
3386 + ((uint)(cp[2]) << 16) + ((uint)(cp[3]) << 24);
3389 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3391 set_start_sect(struct partition *p, unsigned int start_sect) {
3392 store4_little_endian(p->start4, start_sect);
3397 get_start_sect(const struct partition *p) {
3398 return read4_little_endian(p->start4);
3401 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3403 set_nr_sects(struct partition *p, unsigned int nr_sects) {
3404 store4_little_endian(p->size4, nr_sects);
3409 get_nr_sects(const struct partition *p) {
3410 return read4_little_endian(p->size4);
3413 /* normally O_RDWR, -l option gives O_RDONLY */
3414 static int type_open = O_RDWR;
3417 static int ext_index, /* the prime extended partition */
3418 listing, /* no aborts for fdisk -l */
3419 dos_compatible_flag = ~0;
3420 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3421 static int dos_changed;
3422 static int nowarn; /* no warnings for fdisk -l/-s */
3427 static uint user_cylinders, user_heads, user_sectors;
3428 static uint pt_heads, pt_sectors;
3429 static uint kern_heads, kern_sectors;
3431 static uint extended_offset; /* offset of link pointers */
3433 static unsigned long long total_number_of_sectors;
3436 static jmp_buf listingbuf;
3438 static void fdisk_fatal(enum failure why) {
3439 const char *message;
3443 longjmp(listingbuf, 1);
3447 case unable_to_open:
3448 message = "Unable to open %s\n";
3450 case unable_to_read:
3451 message = "Unable to read %s\n";
3453 case unable_to_seek:
3454 message = "Unable to seek on %s\n";
3456 case unable_to_write:
3457 message = "Unable to write %s\n";
3460 message = "BLKGETSIZE ioctl failed on %s\n";
3463 message = "Fatal error\n";
3466 fputc('\n', stderr);
3467 fprintf(stderr, message, disk_device);
3472 seek_sector(uint secno) {
3473 fdisk_loff_t offset = (fdisk_loff_t) secno * sector_size;
3474 if (fdisk_llseek(fd, offset, SEEK_SET) == (fdisk_loff_t) -1)
3475 fdisk_fatal(unable_to_seek);
3478 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3480 write_sector(uint secno, char *buf) {
3482 if (write(fd, buf, sector_size) != sector_size)
3483 fdisk_fatal(unable_to_write);
3487 /* Allocate a buffer and read a partition table sector */
3489 read_pte(struct pte *pe, uint offset) {
3491 pe->offset = offset;
3492 pe->sectorbuffer = (char *) xmalloc(sector_size);
3493 seek_sector(offset);
3494 if (read(fd, pe->sectorbuffer, sector_size) != sector_size)
3495 fdisk_fatal(unable_to_read);
3496 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3499 pe->part_table = pe->ext_pointer = NULL;
3503 get_partition_start(const struct pte *pe) {
3504 return pe->offset + get_start_sect(pe->part_table);
3507 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3509 * Avoid warning about DOS partitions when no DOS partition was changed.
3510 * Here a heuristic "is probably dos partition".
3511 * We might also do the opposite and warn in all cases except
3512 * for "is probably nondos partition".
3515 is_dos_partition(int t) {
3516 return (t == 1 || t == 4 || t == 6 ||
3517 t == 0x0b || t == 0x0c || t == 0x0e ||
3518 t == 0x11 || t == 0x12 || t == 0x14 || t == 0x16 ||
3519 t == 0x1b || t == 0x1c || t == 0x1e || t == 0x24 ||
3520 t == 0xc1 || t == 0xc4 || t == 0xc6);
3525 #ifdef CONFIG_FEATURE_SUN_LABEL
3527 puts(_("Command action"));
3528 puts(_("\ta\ttoggle a read only flag")); /* sun */
3529 puts(_("\tb\tedit bsd disklabel"));
3530 puts(_("\tc\ttoggle the mountable flag")); /* sun */
3531 puts(_("\td\tdelete a partition"));
3532 puts(_("\tl\tlist known partition types"));
3533 puts(_("\tm\tprint this menu"));
3534 puts(_("\tn\tadd a new partition"));
3535 puts(_("\to\tcreate a new empty DOS partition table"));
3536 puts(_("\tp\tprint the partition table"));
3537 puts(_("\tq\tquit without saving changes"));
3538 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3539 puts(_("\tt\tchange a partition's system id"));
3540 puts(_("\tu\tchange display/entry units"));
3541 puts(_("\tv\tverify the partition table"));
3542 puts(_("\tw\twrite table to disk and exit"));
3543 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3544 puts(_("\tx\textra functionality (experts only)"));
3548 #ifdef CONFIG_FEATURE_SGI_LABEL
3550 puts(_("Command action"));
3551 puts(_("\ta\tselect bootable partition")); /* sgi flavour */
3552 puts(_("\tb\tedit bootfile entry")); /* sgi */
3553 puts(_("\tc\tselect sgi swap partition")); /* sgi flavour */
3554 puts(_("\td\tdelete a partition"));
3555 puts(_("\tl\tlist known partition types"));
3556 puts(_("\tm\tprint this menu"));
3557 puts(_("\tn\tadd a new partition"));
3558 puts(_("\to\tcreate a new empty DOS partition table"));
3559 puts(_("\tp\tprint the partition table"));
3560 puts(_("\tq\tquit without saving changes"));
3561 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3562 puts(_("\tt\tchange a partition's system id"));
3563 puts(_("\tu\tchange display/entry units"));
3564 puts(_("\tv\tverify the partition table"));
3565 puts(_("\tw\twrite table to disk and exit"));
3568 #ifdef CONFIG_FEATURE_AIX_LABEL
3570 puts(_("Command action"));
3571 puts(_("\tm\tprint this menu"));
3572 puts(_("\to\tcreate a new empty DOS partition table"));
3573 puts(_("\tq\tquit without saving changes"));
3574 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3578 puts(_("Command action"));
3579 puts(_("\ta\ttoggle a bootable flag"));
3580 puts(_("\tb\tedit bsd disklabel"));
3581 puts(_("\tc\ttoggle the dos compatibility flag"));
3582 puts(_("\td\tdelete a partition"));
3583 puts(_("\tl\tlist known partition types"));
3584 puts(_("\tm\tprint this menu"));
3585 puts(_("\tn\tadd a new partition"));
3586 puts(_("\to\tcreate a new empty DOS partition table"));
3587 puts(_("\tp\tprint the partition table"));
3588 puts(_("\tq\tquit without saving changes"));
3589 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3590 puts(_("\tt\tchange a partition's system id"));
3591 puts(_("\tu\tchange display/entry units"));
3592 puts(_("\tv\tverify the partition table"));
3593 puts(_("\tw\twrite table to disk and exit"));
3594 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3595 puts(_("\tx\textra functionality (experts only)"));
3599 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3602 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3605 #ifdef CONFIG_FEATURE_SUN_LABEL
3607 puts(_("Command action"));
3608 puts(_("\ta\tchange number of alternate cylinders")); /*sun*/
3609 puts(_("\tc\tchange number of cylinders"));
3610 puts(_("\td\tprint the raw data in the partition table"));
3611 puts(_("\te\tchange number of extra sectors per cylinder"));/*sun*/
3612 puts(_("\th\tchange number of heads"));
3613 puts(_("\ti\tchange interleave factor")); /*sun*/
3614 puts(_("\to\tchange rotation speed (rpm)")); /*sun*/
3615 puts(_("\tm\tprint this menu"));
3616 puts(_("\tp\tprint the partition table"));
3617 puts(_("\tq\tquit without saving changes"));
3618 puts(_("\tr\treturn to main menu"));
3619 puts(_("\ts\tchange number of sectors/track"));
3620 puts(_("\tv\tverify the partition table"));
3621 puts(_("\tw\twrite table to disk and exit"));
3622 puts(_("\ty\tchange number of physical cylinders")); /*sun*/
3625 #ifdef CONFIG_FEATURE_SGI_LABEL
3627 puts(_("Command action"));
3628 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3629 puts(_("\tc\tchange number of cylinders"));
3630 puts(_("\td\tprint the raw data in the partition table"));
3631 puts(_("\te\tlist extended partitions")); /* !sun */
3632 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3633 puts(_("\th\tchange number of heads"));
3634 puts(_("\tm\tprint this menu"));
3635 puts(_("\tp\tprint the partition table"));
3636 puts(_("\tq\tquit without saving changes"));
3637 puts(_("\tr\treturn to main menu"));
3638 puts(_("\ts\tchange number of sectors/track"));
3639 puts(_("\tv\tverify the partition table"));
3640 puts(_("\tw\twrite table to disk and exit"));
3643 #ifdef CONFIG_FEATURE_AIX_LABEL
3645 puts(_("Command action"));
3646 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3647 puts(_("\tc\tchange number of cylinders"));
3648 puts(_("\td\tprint the raw data in the partition table"));
3649 puts(_("\te\tlist extended partitions")); /* !sun */
3650 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3651 puts(_("\th\tchange number of heads"));
3652 puts(_("\tm\tprint this menu"));
3653 puts(_("\tp\tprint the partition table"));
3654 puts(_("\tq\tquit without saving changes"));
3655 puts(_("\tr\treturn to main menu"));
3656 puts(_("\ts\tchange number of sectors/track"));
3657 puts(_("\tv\tverify the partition table"));
3658 puts(_("\tw\twrite table to disk and exit"));
3662 puts(_("Command action"));
3663 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3664 puts(_("\tc\tchange number of cylinders"));
3665 puts(_("\td\tprint the raw data in the partition table"));
3666 puts(_("\te\tlist extended partitions")); /* !sun */
3667 puts(_("\tf\tfix partition order")); /* !sun, !aix, !sgi */
3668 #ifdef CONFIG_FEATURE_SGI_LABEL
3669 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3671 puts(_("\th\tchange number of heads"));
3672 puts(_("\tm\tprint this menu"));
3673 puts(_("\tp\tprint the partition table"));
3674 puts(_("\tq\tquit without saving changes"));
3675 puts(_("\tr\treturn to main menu"));
3676 puts(_("\ts\tchange number of sectors/track"));
3677 puts(_("\tv\tverify the partition table"));
3678 puts(_("\tw\twrite table to disk and exit"));
3681 #endif /* ADVANCED mode */
3683 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3684 static const struct systypes *
3685 get_sys_types(void) {
3687 #ifdef CONFIG_FEATURE_SUN_LABEL
3688 sun_label ? sun_sys_types :
3690 #ifdef CONFIG_FEATURE_SGI_LABEL
3691 sgi_label ? sgi_sys_types :
3696 #define get_sys_types() i386_sys_types
3697 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3699 static const char *partition_type(unsigned char type)
3702 const struct systypes *types = get_sys_types();
3704 for (i=0; types[i].name; i++)
3705 if (types[i].name[0] == type)
3706 return types[i].name + 1;
3708 return _("Unknown");
3712 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3716 #ifdef CONFIG_FEATURE_SUN_LABEL
3717 sun_label ? sunlabel->infos[i].id :
3719 #ifdef CONFIG_FEATURE_SGI_LABEL
3720 sgi_label ? sgi_get_sysid(i) :
3722 ptes[i].part_table->sys_ind);
3725 void list_types(const struct systypes *sys)
3727 uint last[4], done = 0, next = 0, size;
3730 for (i = 0; sys[i].name; i++);
3733 for (i = 3; i >= 0; i--)
3734 last[3 - i] = done += (size + i - done) / (i + 1);
3738 printf("%c%2x %-15.15s", i ? ' ' : '\n',
3739 sys[next].name[0], partition_type(sys[next].name[0]));
3740 next = last[i++] + done;
3741 if (i > 3 || next >= last[i]) {
3745 } while (done < last[0]);
3748 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3751 is_cleared_partition(const struct partition *p) {
3752 return !(!p || p->boot_ind || p->head || p->sector || p->cyl ||
3753 p->sys_ind || p->end_head || p->end_sector || p->end_cyl ||
3754 get_start_sect(p) || get_nr_sects(p));
3758 clear_partition(struct partition *p) {
3761 memset(p, 0, sizeof(struct partition));
3764 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3766 set_partition(int i, int doext, uint start, uint stop, int sysid) {
3767 struct partition *p;
3771 p = ptes[i].ext_pointer;
3772 offset = extended_offset;
3774 p = ptes[i].part_table;
3775 offset = ptes[i].offset;
3779 set_start_sect(p, start - offset);
3780 set_nr_sects(p, stop - start + 1);
3781 if (dos_compatible_flag && (start/(sectors*heads) > 1023))
3782 start = heads*sectors*1024 - 1;
3783 set_hsc(p->head, p->sector, p->cyl, start);
3784 if (dos_compatible_flag && (stop/(sectors*heads) > 1023))
3785 stop = heads*sectors*1024 - 1;
3786 set_hsc(p->end_head, p->end_sector, p->end_cyl, stop);
3787 ptes[i].changed = 1;
3792 test_c(const char **m, const char *mesg) {
3795 fprintf(stderr, _("You must set"));
3797 fprintf(stderr, " %s", *m);
3805 warn_geometry(void) {
3806 const char *m = NULL;
3810 prev = test_c(&m, _("heads"));
3812 prev = test_c(&m, _("sectors"));
3814 prev = test_c(&m, _("cylinders"));
3818 fprintf(stderr, "%s%s.\n"
3819 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3820 "You can do this from the extra functions menu.\n"
3822 , prev ? _(" and ") : " ", m);
3827 static void update_units(void)
3829 int cyl_units = heads * sectors;
3831 if (display_in_cyl_units && cyl_units)
3832 units_per_sector = cyl_units;
3834 units_per_sector = 1; /* in sectors */
3837 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3839 warn_cylinders(void) {
3840 if (dos_label && cylinders > 1024 && !nowarn)
3841 fprintf(stderr, _("\n"
3842 "The number of cylinders for this disk is set to %d.\n"
3843 "There is nothing wrong with that, but this is larger than 1024,\n"
3844 "and could in certain setups cause problems with:\n"
3845 "1) software that runs at boot time (e.g., old versions of LILO)\n"
3846 "2) booting and partitioning software from other OSs\n"
3847 " (e.g., DOS FDISK, OS/2 FDISK)\n"),
3853 read_extended(int ext) {
3856 struct partition *p, *q;
3860 pex->ext_pointer = pex->part_table;
3862 p = pex->part_table;
3863 if (!get_start_sect(p)) {
3865 _("Bad offset in primary extended partition\n"));
3869 while (IS_EXTENDED (p->sys_ind)) {
3870 struct pte *pe = &ptes[partitions];
3872 if (partitions >= MAXIMUM_PARTS) {
3873 /* This is not a Linux restriction, but
3874 this program uses arrays of size MAXIMUM_PARTS.
3875 Do not try to `improve' this test. */
3876 struct pte *pre = &ptes[partitions-1];
3877 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3879 _("Warning: deleting partitions after %d\n"),
3883 clear_partition(pre->ext_pointer);
3887 read_pte(pe, extended_offset + get_start_sect(p));
3889 if (!extended_offset)
3890 extended_offset = get_start_sect(p);
3892 q = p = pt_offset(pe->sectorbuffer, 0);
3893 for (i = 0; i < 4; i++, p++) if (get_nr_sects(p)) {
3894 if (IS_EXTENDED (p->sys_ind)) {
3895 if (pe->ext_pointer)
3897 _("Warning: extra link "
3898 "pointer in partition table"
3899 " %d\n"), partitions + 1);
3901 pe->ext_pointer = p;
3902 } else if (p->sys_ind) {
3905 _("Warning: ignoring extra "
3906 "data in partition table"
3907 " %d\n"), partitions + 1);
3913 /* very strange code here... */
3914 if (!pe->part_table) {
3915 if (q != pe->ext_pointer)
3918 pe->part_table = q + 1;
3920 if (!pe->ext_pointer) {
3921 if (q != pe->part_table)
3922 pe->ext_pointer = q;
3924 pe->ext_pointer = q + 1;
3927 p = pe->ext_pointer;
3931 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3932 /* remove empty links */
3934 for (i = 4; i < partitions; i++) {
3935 struct pte *pe = &ptes[i];
3937 if (!get_nr_sects(pe->part_table) &&
3938 (partitions > 5 || ptes[4].part_table->sys_ind)) {
3939 printf("omitting empty partition (%d)\n", i+1);
3940 delete_partition(i);
3941 goto remove; /* numbering changed */
3947 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3949 create_doslabel(void) {
3953 _("Building a new DOS disklabel. Changes will remain in memory only,\n"
3954 "until you decide to write them. After that, of course, the previous\n"
3955 "content won't be recoverable.\n\n"));
3956 #ifdef CONFIG_FEATURE_SUN_LABEL
3957 sun_nolabel(); /* otherwise always recognised as sun */
3959 #ifdef CONFIG_FEATURE_SGI_LABEL
3960 sgi_nolabel(); /* otherwise always recognised as sgi */
3962 #ifdef CONFIG_FEATURE_AIX_LABEL
3965 #ifdef CONFIG_FEATURE_OSF_LABEL
3967 possibly_osf_label = 0;
3971 for (i = 510-64; i < 510; i++)
3973 write_part_table_flag(MBRbuffer);
3974 extended_offset = 0;
3975 set_all_unchanged();
3977 get_boot(create_empty_dos);
3979 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3982 get_sectorsize(void) {
3983 if (!user_set_sector_size &&
3984 get_kernel_revision() >= MAKE_VERSION(2,3,3)) {
3986 if (ioctl(fd, BLKSSZGET, &arg) == 0)
3988 if (sector_size != DEFAULT_SECTOR_SIZE)
3989 printf(_("Note: sector size is %d (not %d)\n"),
3990 sector_size, DEFAULT_SECTOR_SIZE);
3995 get_kernel_geometry(void) {
3996 struct hd_geometry geometry;
3998 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
3999 kern_heads = geometry.heads;
4000 kern_sectors = geometry.sectors;
4001 /* never use geometry.cylinders - it is truncated */
4006 get_partition_table_geometry(void) {
4007 const unsigned char *bufp = MBRbuffer;
4008 struct partition *p;
4009 int i, h, s, hh, ss;
4013 if (!(valid_part_table_flag(bufp)))
4017 for (i=0; i<4; i++) {
4018 p = pt_offset(bufp, i);
4019 if (p->sys_ind != 0) {
4020 h = p->end_head + 1;
4021 s = (p->end_sector & 077);
4026 } else if (hh != h || ss != s)
4031 if (!first && !bad) {
4038 get_geometry(void) {
4040 unsigned long long bytes; /* really u64 */
4043 sec_fac = sector_size / 512;
4044 #ifdef CONFIG_FEATURE_SUN_LABEL
4045 guess_device_type();
4047 heads = cylinders = sectors = 0;
4048 kern_heads = kern_sectors = 0;
4049 pt_heads = pt_sectors = 0;
4051 get_kernel_geometry();
4052 get_partition_table_geometry();
4054 heads = user_heads ? user_heads :
4055 pt_heads ? pt_heads :
4056 kern_heads ? kern_heads : 255;
4057 sectors = user_sectors ? user_sectors :
4058 pt_sectors ? pt_sectors :
4059 kern_sectors ? kern_sectors : 63;
4060 if (ioctl(fd, BLKGETSIZE64, &bytes) == 0) {
4063 unsigned long longsectors;
4065 if (ioctl(fd, BLKGETSIZE, &longsectors))
4067 bytes = ((unsigned long long) longsectors) << 9;
4070 total_number_of_sectors = (bytes >> 9);
4073 if (dos_compatible_flag)
4074 sector_offset = sectors;
4076 cylinders = total_number_of_sectors / (heads * sectors * sec_fac);
4078 cylinders = user_cylinders;
4082 * Read MBR. Returns:
4083 * -1: no 0xaa55 flag present (possibly entire disk BSD)
4084 * 0: found or created label
4088 get_boot(enum action what) {
4093 for (i = 0; i < 4; i++) {
4094 struct pte *pe = &ptes[i];
4096 pe->part_table = pt_offset(MBRbuffer, i);
4097 pe->ext_pointer = NULL;
4099 pe->sectorbuffer = MBRbuffer;
4100 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4101 pe->changed = (what == create_empty_dos);
4105 #ifdef CONFIG_FEATURE_SUN_LABEL
4106 if (what == create_empty_sun && check_sun_label())
4110 memset(MBRbuffer, 0, 512);
4112 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4113 if (what == create_empty_dos)
4114 goto got_dos_table; /* skip reading disk */
4116 if ((fd = open(disk_device, type_open)) < 0) {
4117 if ((fd = open(disk_device, O_RDONLY)) < 0) {
4118 if (what == try_only)
4120 fdisk_fatal(unable_to_open);
4122 printf(_("You will not be able to write "
4123 "the partition table.\n"));
4126 if (512 != read(fd, MBRbuffer, 512)) {
4127 if (what == try_only)
4129 fdisk_fatal(unable_to_read);
4132 if ((fd = open(disk_device, O_RDONLY)) < 0)
4134 if (512 != read(fd, MBRbuffer, 512))
4142 #ifdef CONFIG_FEATURE_SUN_LABEL
4143 if (check_sun_label())
4147 #ifdef CONFIG_FEATURE_SGI_LABEL
4148 if (check_sgi_label())
4152 #ifdef CONFIG_FEATURE_AIX_LABEL
4153 if (check_aix_label())
4157 #ifdef CONFIG_FEATURE_OSF_LABEL
4158 if (check_osf_label()) {
4159 possibly_osf_label = 1;
4160 if (!valid_part_table_flag(MBRbuffer)) {
4164 printf(_("This disk has both DOS and BSD magic.\n"
4165 "Give the 'b' command to go to BSD mode.\n"));
4169 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4173 if (!valid_part_table_flag(MBRbuffer)) {
4174 #ifndef CONFIG_FEATURE_FDISK_WRITABLE
4180 _("Device contains neither a valid DOS "
4181 "partition table, nor Sun, SGI or OSF "
4184 #ifdef CONFIG_FEATURE_SUN_LABEL
4193 case create_empty_dos:
4194 #ifdef CONFIG_FEATURE_SUN_LABEL
4195 case create_empty_sun:
4199 fprintf(stderr, _("Internal error\n"));
4202 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
4205 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4210 for (i = 0; i < 4; i++) {
4211 struct pte *pe = &ptes[i];
4213 if (IS_EXTENDED (pe->part_table->sys_ind)) {
4214 if (partitions != 4)
4215 fprintf(stderr, _("Ignoring extra extended "
4216 "partition %d\n"), i + 1);
4222 for (i = 3; i < partitions; i++) {
4223 struct pte *pe = &ptes[i];
4225 if (!valid_part_table_flag(pe->sectorbuffer)) {
4227 _("Warning: invalid flag 0x%04x of partition "
4228 "table %d will be corrected by w(rite)\n"),
4229 part_table_flag(pe->sectorbuffer), i + 1);
4230 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4239 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4241 * Print the message MESG, then read an integer between LOW and HIGH (inclusive).
4242 * If the user hits Enter, DFLT is returned.
4243 * Answers like +10 are interpreted as offsets from BASE.
4245 * There is no default if DFLT is not between LOW and HIGH.
4248 read_int(uint low, uint dflt, uint high, uint base, char *mesg)
4252 static char *ms = NULL;
4253 static int mslen = 0;
4255 if (!ms || strlen(mesg)+100 > mslen) {
4256 mslen = strlen(mesg)+200;
4257 ms = xrealloc(ms,mslen);
4260 if (dflt < low || dflt > high)
4264 snprintf(ms, mslen, _("%s (%u-%u, default %u): "),
4265 mesg, low, high, dflt);
4267 snprintf(ms, mslen, "%s (%u-%u): ",
4271 int use_default = default_ok;
4273 /* ask question and read answer */
4274 while (read_chars(ms) != '\n' && !isdigit(*line_ptr)
4275 && *line_ptr != '-' && *line_ptr != '+')
4278 if (*line_ptr == '+' || *line_ptr == '-') {
4279 int minus = (*line_ptr == '-');
4282 i = atoi(line_ptr+1);
4284 while (isdigit(*++line_ptr))
4287 switch (*line_ptr) {
4290 if (!display_in_cyl_units)
4291 i *= heads * sectors;
4305 absolute = 1000000000;
4311 unsigned long long bytes;
4314 bytes = (unsigned long long) i * absolute;
4315 unit = sector_size * units_per_sector;
4316 bytes += unit/2; /* round */
4325 while (isdigit(*line_ptr)) {
4331 printf(_("Using default value %u\n"), i = dflt);
4332 if (i >= low && i <= high)
4335 printf(_("Value out of range.\n"));
4341 get_partition(int warn, int max) {
4345 i = read_int(1, 0, max, 0, _("Partition number")) - 1;
4349 if ((!sun_label && !sgi_label && !pe->part_table->sys_ind)
4350 #ifdef CONFIG_FEATURE_SUN_LABEL
4352 (!sunlabel->partitions[i].num_sectors ||
4353 !sunlabel->infos[i].id))
4355 #ifdef CONFIG_FEATURE_SGI_LABEL
4356 || (sgi_label && (!sgi_get_num_sectors(i)))
4360 _("Warning: partition %d has empty type\n"),
4367 get_existing_partition(int warn, int max) {
4371 for (i = 0; i < max; i++) {
4372 struct pte *pe = &ptes[i];
4373 struct partition *p = pe->part_table;
4375 if (p && !is_cleared_partition(p)) {
4382 printf(_("Selected partition %d\n"), pno+1);
4385 printf(_("No partition is defined yet!\n"));
4389 return get_partition(warn, max);
4393 get_nonexisting_partition(int warn, int max) {
4397 for (i = 0; i < max; i++) {
4398 struct pte *pe = &ptes[i];
4399 struct partition *p = pe->part_table;
4401 if (p && is_cleared_partition(p)) {
4408 printf(_("Selected partition %d\n"), pno+1);
4411 printf(_("All primary partitions have been defined already!\n"));
4415 return get_partition(warn, max);
4419 void change_units(void)
4421 display_in_cyl_units = !display_in_cyl_units;
4423 printf(_("Changing display/entry units to %s\n"),
4428 toggle_active(int i) {
4429 struct pte *pe = &ptes[i];
4430 struct partition *p = pe->part_table;
4432 if (IS_EXTENDED (p->sys_ind) && !p->boot_ind)
4434 _("WARNING: Partition %d is an extended partition\n"),
4436 p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG);
4441 toggle_dos_compatibility_flag(void) {
4442 dos_compatible_flag = ~dos_compatible_flag;
4443 if (dos_compatible_flag) {
4444 sector_offset = sectors;
4445 printf(_("DOS Compatibility flag is set\n"));
4449 printf(_("DOS Compatibility flag is not set\n"));
4454 delete_partition(int i) {
4455 struct pte *pe = &ptes[i];
4456 struct partition *p = pe->part_table;
4457 struct partition *q = pe->ext_pointer;
4459 /* Note that for the fifth partition (i == 4) we don't actually
4460 * decrement partitions.
4463 if (warn_geometry())
4464 return; /* C/H/S not set */
4467 #ifdef CONFIG_FEATURE_SUN_LABEL
4469 sun_delete_partition(i);
4473 #ifdef CONFIG_FEATURE_SGI_LABEL
4475 sgi_delete_partition(i);
4481 if (IS_EXTENDED (p->sys_ind) && i == ext_index) {
4483 ptes[ext_index].ext_pointer = NULL;
4484 extended_offset = 0;
4490 if (!q->sys_ind && i > 4) {
4491 /* the last one in the chain - just delete */
4494 clear_partition(ptes[i].ext_pointer);
4495 ptes[i].changed = 1;
4497 /* not the last one - further ones will be moved down */
4499 /* delete this link in the chain */
4500 p = ptes[i-1].ext_pointer;
4502 set_start_sect(p, get_start_sect(q));
4503 set_nr_sects(p, get_nr_sects(q));
4504 ptes[i-1].changed = 1;
4505 } else if (partitions > 5) { /* 5 will be moved to 4 */
4506 /* the first logical in a longer chain */
4509 if (pe->part_table) /* prevent SEGFAULT */
4510 set_start_sect(pe->part_table,
4511 get_partition_start(pe) -
4513 pe->offset = extended_offset;
4517 if (partitions > 5) {
4519 while (i < partitions) {
4520 ptes[i] = ptes[i+1];
4524 /* the only logical: clear only */
4525 clear_partition(ptes[i].part_table);
4530 change_sysid(void) {
4531 int i, sys, origsys;
4532 struct partition *p;
4534 #ifdef CONFIG_FEATURE_SGI_LABEL
4535 /* If sgi_label then don't use get_existing_partition,
4536 let the user select a partition, since get_existing_partition()
4537 only works for Linux like partition tables. */
4539 i = get_existing_partition(0, partitions);
4541 i = get_partition(0, partitions);
4544 i = get_existing_partition(0, partitions);
4548 p = ptes[i].part_table;
4549 origsys = sys = get_sysid(i);
4551 /* if changing types T to 0 is allowed, then
4552 the reverse change must be allowed, too */
4553 if (!sys && !sgi_label && !sun_label && !get_nr_sects(p))
4554 printf(_("Partition %d does not exist yet!\n"), i + 1);
4556 sys = read_hex (get_sys_types());
4558 if (!sys && !sgi_label && !sun_label) {
4559 printf(_("Type 0 means free space to many systems\n"
4560 "(but not to Linux). Having partitions of\n"
4561 "type 0 is probably unwise. You can delete\n"
4562 "a partition using the `d' command.\n"));
4566 if (!sun_label && !sgi_label) {
4567 if (IS_EXTENDED (sys) != IS_EXTENDED (p->sys_ind)) {
4568 printf(_("You cannot change a partition into"
4569 " an extended one or vice versa\n"
4570 "Delete it first.\n"));
4576 #ifdef CONFIG_FEATURE_SUN_LABEL
4577 if (sun_label && i == 2 && sys != WHOLE_DISK)
4578 printf(_("Consider leaving partition 3 "
4579 "as Whole disk (5),\n"
4580 "as SunOS/Solaris expects it and "
4581 "even Linux likes it.\n\n"));
4583 #ifdef CONFIG_FEATURE_SGI_LABEL
4584 if (sgi_label && ((i == 10 && sys != ENTIRE_DISK)
4585 || (i == 8 && sys != 0)))
4586 printf(_("Consider leaving partition 9 "
4587 "as volume header (0),\nand "
4588 "partition 11 as entire volume (6)"
4589 "as IRIX expects it.\n\n"));
4593 #ifdef CONFIG_FEATURE_SUN_LABEL
4595 sun_change_sysid(i, sys);
4598 #ifdef CONFIG_FEATURE_SGI_LABEL
4600 sgi_change_sysid(i, sys);
4604 printf (_("Changed system type of partition %d "
4605 "to %x (%s)\n"), i + 1, sys,
4606 partition_type(sys));
4607 ptes[i].changed = 1;
4608 if (is_dos_partition(origsys) ||
4609 is_dos_partition(sys))
4615 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
4618 /* check_consistency() and long2chs() added Sat Mar 6 12:28:16 1993,
4619 * faith@cs.unc.edu, based on code fragments from pfdisk by Gordon W. Ross,
4620 * Jan. 1990 (version 1.2.1 by Gordon W. Ross Aug. 1990; Modified by S.
4621 * Lubkin Oct. 1991). */
4623 static void long2chs(ulong ls, uint *c, uint *h, uint *s) {
4624 int spc = heads * sectors;
4629 *s = ls % sectors + 1; /* sectors count from 1 */
4632 static void check_consistency(const struct partition *p, int partition) {
4633 uint pbc, pbh, pbs; /* physical beginning c, h, s */
4634 uint pec, peh, pes; /* physical ending c, h, s */
4635 uint lbc, lbh, lbs; /* logical beginning c, h, s */
4636 uint lec, leh, les; /* logical ending c, h, s */
4638 if (!heads || !sectors || (partition >= 4))
4639 return; /* do not check extended partitions */
4641 /* physical beginning c, h, s */
4642 pbc = (p->cyl & 0xff) | ((p->sector << 2) & 0x300);
4644 pbs = p->sector & 0x3f;
4646 /* physical ending c, h, s */
4647 pec = (p->end_cyl & 0xff) | ((p->end_sector << 2) & 0x300);
4649 pes = p->end_sector & 0x3f;
4651 /* compute logical beginning (c, h, s) */
4652 long2chs(get_start_sect(p), &lbc, &lbh, &lbs);
4654 /* compute logical ending (c, h, s) */
4655 long2chs(get_start_sect(p) + get_nr_sects(p) - 1, &lec, &leh, &les);
4657 /* Same physical / logical beginning? */
4658 if (cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) {
4659 printf(_("Partition %d has different physical/logical "
4660 "beginnings (non-Linux?):\n"), partition + 1);
4661 printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs);
4662 printf(_("logical=(%d, %d, %d)\n"),lbc, lbh, lbs);
4665 /* Same physical / logical ending? */
4666 if (cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) {
4667 printf(_("Partition %d has different physical/logical "
4668 "endings:\n"), partition + 1);
4669 printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
4670 printf(_("logical=(%d, %d, %d)\n"),lec, leh, les);
4674 /* Beginning on cylinder boundary? */
4675 if (pbh != !pbc || pbs != 1) {
4676 printf(_("Partition %i does not start on cylinder "
4677 "boundary:\n"), partition + 1);
4678 printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs);
4679 printf(_("should be (%d, %d, 1)\n"), pbc, !pbc);
4683 /* Ending on cylinder boundary? */
4684 if (peh != (heads - 1) || pes != sectors) {
4685 printf(_("Partition %i does not end on cylinder boundary.\n"),
4688 printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
4689 printf(_("should be (%d, %d, %d)\n"),
4690 pec, heads - 1, sectors);
4696 list_disk_geometry(void) {
4697 long long bytes = (total_number_of_sectors << 9);
4698 long megabytes = bytes/1000000;
4700 if (megabytes < 10000)
4701 printf(_("\nDisk %s: %ld MB, %lld bytes\n"),
4702 disk_device, megabytes, bytes);
4704 printf(_("\nDisk %s: %ld.%ld GB, %lld bytes\n"),
4705 disk_device, megabytes/1000, (megabytes/100)%10, bytes);
4706 printf(_("%d heads, %d sectors/track, %d cylinders"),
4707 heads, sectors, cylinders);
4708 if (units_per_sector == 1)
4709 printf(_(", total %llu sectors"),
4710 total_number_of_sectors / (sector_size/512));
4711 printf(_("\nUnits = %s of %d * %d = %d bytes\n\n"),
4713 units_per_sector, sector_size, units_per_sector * sector_size);
4717 * Check whether partition entries are ordered by their starting positions.
4718 * Return 0 if OK. Return i if partition i should have been earlier.
4719 * Two separate checks: primary and logical partitions.
4722 wrong_p_order(int *prev) {
4723 const struct pte *pe;
4724 const struct partition *p;
4725 uint last_p_start_pos = 0, p_start_pos;
4728 for (i = 0 ; i < partitions; i++) {
4731 last_p_start_pos = 0;
4734 if ((p = pe->part_table)->sys_ind) {
4735 p_start_pos = get_partition_start(pe);
4737 if (last_p_start_pos > p_start_pos) {
4743 last_p_start_pos = p_start_pos;
4750 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
4752 * Fix the chain of logicals.
4753 * extended_offset is unchanged, the set of sectors used is unchanged
4754 * The chain is sorted so that sectors increase, and so that
4755 * starting sectors increase.
4757 * After this it may still be that cfdisk doesnt like the table.
4758 * (This is because cfdisk considers expanded parts, from link to
4759 * end of partition, and these may still overlap.)
4761 * sfdisk /dev/hda > ohda; sfdisk /dev/hda < ohda
4765 fix_chain_of_logicals(void) {
4766 int j, oj, ojj, sj, sjj;
4767 struct partition *pj,*pjj,tmp;
4769 /* Stage 1: sort sectors but leave sector of part 4 */
4770 /* (Its sector is the global extended_offset.) */
4772 for (j = 5; j < partitions-1; j++) {
4773 oj = ptes[j].offset;
4774 ojj = ptes[j+1].offset;
4776 ptes[j].offset = ojj;
4777 ptes[j+1].offset = oj;
4778 pj = ptes[j].part_table;
4779 set_start_sect(pj, get_start_sect(pj)+oj-ojj);
4780 pjj = ptes[j+1].part_table;
4781 set_start_sect(pjj, get_start_sect(pjj)+ojj-oj);
4782 set_start_sect(ptes[j-1].ext_pointer,
4783 ojj-extended_offset);
4784 set_start_sect(ptes[j].ext_pointer,
4785 oj-extended_offset);
4790 /* Stage 2: sort starting sectors */
4792 for (j = 4; j < partitions-1; j++) {
4793 pj = ptes[j].part_table;
4794 pjj = ptes[j+1].part_table;
4795 sj = get_start_sect(pj);
4796 sjj = get_start_sect(pjj);
4797 oj = ptes[j].offset;
4798 ojj = ptes[j+1].offset;
4799 if (oj+sj > ojj+sjj) {
4803 set_start_sect(pj, ojj+sjj-oj);
4804 set_start_sect(pjj, oj+sj-ojj);
4809 /* Probably something was changed */
4810 for (j = 4; j < partitions; j++)
4811 ptes[j].changed = 1;
4816 fix_partition_table_order(void) {
4817 struct pte *pei, *pek;
4820 if (!wrong_p_order(NULL)) {
4821 printf(_("Nothing to do. Ordering is correct already.\n\n"));
4825 while ((i = wrong_p_order(&k)) != 0 && i < 4) {
4826 /* partition i should have come earlier, move it */
4827 /* We have to move data in the MBR */
4828 struct partition *pi, *pk, *pe, pbuf;
4832 pe = pei->ext_pointer;
4833 pei->ext_pointer = pek->ext_pointer;
4834 pek->ext_pointer = pe;
4836 pi = pei->part_table;
4837 pk = pek->part_table;
4839 memmove(&pbuf, pi, sizeof(struct partition));
4840 memmove(pi, pk, sizeof(struct partition));
4841 memmove(pk, &pbuf, sizeof(struct partition));
4843 pei->changed = pek->changed = 1;
4847 fix_chain_of_logicals();
4855 list_table(int xtra) {
4856 const struct partition *p;
4859 #ifdef CONFIG_FEATURE_SUN_LABEL
4861 sun_list_table(xtra);
4866 #ifdef CONFIG_FEATURE_SGI_LABEL
4868 sgi_list_table(xtra);
4873 list_disk_geometry();
4875 #ifdef CONFIG_FEATURE_OSF_LABEL
4877 xbsd_print_disklabel(xtra);
4882 /* Heuristic: we list partition 3 of /dev/foo as /dev/foo3,
4883 but if the device name ends in a digit, say /dev/foo1,
4884 then the partition is called /dev/foo1p3. */
4885 w = strlen(disk_device);
4886 if (w && isdigit(disk_device[w-1]))
4891 printf(_("%*s Boot Start End Blocks Id System\n"),
4894 for (i = 0; i < partitions; i++) {
4895 const struct pte *pe = &ptes[i];
4898 if (p && !is_cleared_partition(p)) {
4899 unsigned int psects = get_nr_sects(p);
4900 unsigned int pblocks = psects;
4901 unsigned int podd = 0;
4903 if (sector_size < 1024) {
4904 pblocks /= (1024 / sector_size);
4905 podd = psects % (1024 / sector_size);
4907 if (sector_size > 1024)
4908 pblocks *= (sector_size / 1024);
4910 "%s %c %11lu %11lu %11lu%c %2x %s\n",
4911 partname(disk_device, i+1, w+2),
4912 /* boot flag */ !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG
4914 /* start */ (unsigned long) cround(get_partition_start(pe)),
4915 /* end */ (unsigned long) cround(get_partition_start(pe) + psects
4916 - (psects ? 1 : 0)),
4917 /* odd flag on end */ (unsigned long) pblocks, podd ? '+' : ' ',
4918 /* type id */ p->sys_ind,
4919 /* type name */ partition_type(p->sys_ind));
4920 check_consistency(p, i);
4924 /* Is partition table in disk order? It need not be, but... */
4925 /* partition table entries are not checked for correct order if this
4926 is a sgi, sun or aix labeled disk... */
4927 if (dos_label && wrong_p_order(NULL)) {
4928 printf(_("\nPartition table entries are not in disk order\n"));
4932 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
4934 x_list_table(int extend) {
4935 const struct pte *pe;
4936 const struct partition *p;
4939 printf(_("\nDisk %s: %d heads, %d sectors, %d cylinders\n\n"),
4940 disk_device, heads, sectors, cylinders);
4941 printf(_("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n"));
4942 for (i = 0 ; i < partitions; i++) {
4944 p = (extend ? pe->ext_pointer : pe->part_table);
4946 printf("%2d %02x%4d%4d%5d%4d%4d%5d%11u%11u %02x\n",
4947 i + 1, p->boot_ind, p->head,
4949 cylinder(p->sector, p->cyl), p->end_head,
4950 sector(p->end_sector),
4951 cylinder(p->end_sector, p->end_cyl),
4952 get_start_sect(p), get_nr_sects(p), p->sys_ind);
4954 check_consistency(p, i);
4960 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4962 fill_bounds(uint *first, uint *last) {
4964 const struct pte *pe = &ptes[0];
4965 const struct partition *p;
4967 for (i = 0; i < partitions; pe++,i++) {
4969 if (!p->sys_ind || IS_EXTENDED (p->sys_ind)) {
4970 first[i] = 0xffffffff;
4973 first[i] = get_partition_start(pe);
4974 last[i] = first[i] + get_nr_sects(p) - 1;
4980 check(int n, uint h, uint s, uint c, uint start) {
4981 uint total, real_s, real_c;
4983 real_s = sector(s) - 1;
4984 real_c = cylinder(s, c);
4985 total = (real_c * sectors + real_s) * heads + h;
4987 fprintf(stderr, _("Warning: partition %d contains sector 0\n"), n);
4990 _("Partition %d: head %d greater than maximum %d\n"),
4992 if (real_s >= sectors)
4993 fprintf(stderr, _("Partition %d: sector %d greater than "
4994 "maximum %d\n"), n, s, sectors);
4995 if (real_c >= cylinders)
4996 fprintf(stderr, _("Partitions %d: cylinder %d greater than "
4997 "maximum %d\n"), n, real_c + 1, cylinders);
4998 if (cylinders <= 1024 && start != total)
5000 _("Partition %d: previous sectors %d disagrees with "
5001 "total %d\n"), n, start, total);
5008 uint first[partitions], last[partitions];
5009 struct partition *p;
5011 if (warn_geometry())
5014 #ifdef CONFIG_FEATURE_SUN_LABEL
5020 #ifdef CONFIG_FEATURE_SGI_LABEL
5027 fill_bounds(first, last);
5028 for (i = 0; i < partitions; i++) {
5029 struct pte *pe = &ptes[i];
5032 if (p->sys_ind && !IS_EXTENDED (p->sys_ind)) {
5033 check_consistency(p, i);
5034 if (get_partition_start(pe) < first[i])
5035 printf(_("Warning: bad start-of-data in "
5036 "partition %d\n"), i + 1);
5037 check(i + 1, p->end_head, p->end_sector, p->end_cyl,
5039 total += last[i] + 1 - first[i];
5040 for (j = 0; j < i; j++)
5041 if ((first[i] >= first[j] && first[i] <= last[j])
5042 || ((last[i] <= last[j] && last[i] >= first[j]))) {
5043 printf(_("Warning: partition %d overlaps "
5044 "partition %d.\n"), j + 1, i + 1);
5045 total += first[i] >= first[j] ?
5046 first[i] : first[j];
5047 total -= last[i] <= last[j] ?
5053 if (extended_offset) {
5054 struct pte *pex = &ptes[ext_index];
5055 uint e_last = get_start_sect(pex->part_table) +
5056 get_nr_sects(pex->part_table) - 1;
5058 for (i = 4; i < partitions; i++) {
5060 p = ptes[i].part_table;
5062 if (i != 4 || i + 1 < partitions)
5063 printf(_("Warning: partition %d "
5064 "is empty\n"), i + 1);
5066 else if (first[i] < extended_offset ||
5068 printf(_("Logical partition %d not entirely in "
5069 "partition %d\n"), i + 1, ext_index + 1);
5073 if (total > heads * sectors * cylinders)
5074 printf(_("Total allocated sectors %d greater than the maximum "
5075 "%d\n"), total, heads * sectors * cylinders);
5076 else if ((total = heads * sectors * cylinders - total) != 0)
5077 printf(_("%d unallocated sectors\n"), total);
5081 add_partition(int n, int sys) {
5082 char mesg[256]; /* 48 does not suffice in Japanese */
5084 struct partition *p = ptes[n].part_table;
5085 struct partition *q = ptes[ext_index].part_table;
5087 uint start, stop = 0, limit, temp,
5088 first[partitions], last[partitions];
5090 if (p && p->sys_ind) {
5091 printf(_("Partition %d is already defined. Delete "
5092 "it before re-adding it.\n"), n + 1);
5095 fill_bounds(first, last);
5097 start = sector_offset;
5098 if (display_in_cyl_units || !total_number_of_sectors)
5099 llimit = heads * sectors * cylinders - 1;
5101 llimit = total_number_of_sectors - 1;
5103 if (limit != llimit)
5105 if (extended_offset) {
5106 first[ext_index] = extended_offset;
5107 last[ext_index] = get_start_sect(q) +
5108 get_nr_sects(q) - 1;
5111 start = extended_offset + sector_offset;
5112 limit = get_start_sect(q) + get_nr_sects(q) - 1;
5114 if (display_in_cyl_units)
5115 for (i = 0; i < partitions; i++)
5116 first[i] = (cround(first[i]) - 1) * units_per_sector;
5118 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
5121 for (i = 0; i < partitions; i++) {
5124 if (start == ptes[i].offset)
5125 start += sector_offset;
5126 lastplusoff = last[i] + ((n<4) ? 0 : sector_offset);
5127 if (start >= first[i] && start <= lastplusoff)
5128 start = lastplusoff + 1;
5132 if (start >= temp+units_per_sector && readed) {
5133 printf(_("Sector %d is already allocated\n"), temp);
5137 if (!readed && start == temp) {
5140 saved_start = start;
5141 start = read_int(cround(saved_start), cround(saved_start), cround(limit),
5143 if (display_in_cyl_units) {
5144 start = (start - 1) * units_per_sector;
5145 if (start < saved_start) start = saved_start;
5149 } while (start != temp || !readed);
5150 if (n > 4) { /* NOT for fifth partition */
5151 struct pte *pe = &ptes[n];
5153 pe->offset = start - sector_offset;
5154 if (pe->offset == extended_offset) { /* must be corrected */
5156 if (sector_offset == 1)
5161 for (i = 0; i < partitions; i++) {
5162 struct pte *pe = &ptes[i];
5164 if (start < pe->offset && limit >= pe->offset)
5165 limit = pe->offset - 1;
5166 if (start < first[i] && limit >= first[i])
5167 limit = first[i] - 1;
5169 if (start > limit) {
5170 printf(_("No free sectors available\n"));
5175 if (cround(start) == cround(limit)) {
5178 snprintf(mesg, sizeof(mesg),
5179 _("Last %s or +size or +sizeM or +sizeK"),
5180 str_units(SINGULAR));
5181 stop = read_int(cround(start), cround(limit), cround(limit),
5182 cround(start), mesg);
5183 if (display_in_cyl_units) {
5184 stop = stop * units_per_sector - 1;
5190 set_partition(n, 0, start, stop, sys);
5192 set_partition(n - 1, 1, ptes[n].offset, stop, EXTENDED);
5194 if (IS_EXTENDED (sys)) {
5195 struct pte *pe4 = &ptes[4];
5196 struct pte *pen = &ptes[n];
5199 pen->ext_pointer = p;
5200 pe4->offset = extended_offset = start;
5201 pe4->sectorbuffer = xcalloc(1, sector_size);
5202 pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
5203 pe4->ext_pointer = pe4->part_table + 1;
5211 if (partitions > 5 || ptes[4].part_table->sys_ind) {
5212 struct pte *pe = &ptes[partitions];
5214 pe->sectorbuffer = xcalloc(1, sector_size);
5215 pe->part_table = pt_offset(pe->sectorbuffer, 0);
5216 pe->ext_pointer = pe->part_table + 1;
5221 add_partition(partitions - 1, LINUX_NATIVE);
5225 new_partition(void) {
5226 int i, free_primary = 0;
5228 if (warn_geometry())
5231 #ifdef CONFIG_FEATURE_SUN_LABEL
5233 add_sun_partition(get_partition(0, partitions), LINUX_NATIVE);
5237 #ifdef CONFIG_FEATURE_SGI_LABEL
5239 sgi_add_partition(get_partition(0, partitions), LINUX_NATIVE);
5243 #ifdef CONFIG_FEATURE_AIX_LABEL
5245 printf(_("\tSorry - this fdisk cannot handle AIX disk labels."
5246 "\n\tIf you want to add DOS-type partitions, create"
5247 "\n\ta new empty DOS partition table first. (Use o.)"
5249 "This will destroy the present disk contents.\n"));
5254 for (i = 0; i < 4; i++)
5255 free_primary += !ptes[i].part_table->sys_ind;
5257 if (!free_primary && partitions >= MAXIMUM_PARTS) {
5258 printf(_("The maximum number of partitions has been created\n"));
5262 if (!free_primary) {
5263 if (extended_offset)
5266 printf(_("You must delete some partition and add "
5267 "an extended partition first\n"));
5269 char c, line[LINE_LENGTH];
5270 snprintf(line, sizeof(line), "%s\n %s\n p primary "
5271 "partition (1-4)\n",
5272 "Command action", (extended_offset ?
5273 "l logical (5 or over)" : "e extended"));
5275 if ((c = read_char(line)) == 'p' || c == 'P') {
5276 i = get_nonexisting_partition(0, 4);
5278 add_partition(i, LINUX_NATIVE);
5281 else if (c == 'l' && extended_offset) {
5285 else if (c == 'e' && !extended_offset) {
5286 i = get_nonexisting_partition(0, 4);
5288 add_partition(i, EXTENDED);
5292 printf(_("Invalid partition number "
5293 "for type `%c'\n"), c);
5304 if (ptes[i].changed)
5305 ptes[3].changed = 1;
5306 for (i = 3; i < partitions; i++) {
5307 struct pte *pe = &ptes[i];
5310 write_part_table_flag(pe->sectorbuffer);
5311 write_sector(pe->offset, pe->sectorbuffer);
5315 #ifdef CONFIG_FEATURE_SGI_LABEL
5316 else if (sgi_label) {
5317 /* no test on change? the printf below might be mistaken */
5321 #ifdef CONFIG_FEATURE_SUN_LABEL
5322 else if (sun_label) {
5326 if (ptes[i].changed)
5333 printf(_("The partition table has been altered!\n\n"));
5334 reread_partition_table(1);
5338 reread_partition_table(int leave) {
5342 printf(_("Calling ioctl() to re-read partition table.\n"));
5345 if ((i = ioctl(fd, BLKRRPART)) != 0) {
5348 /* some kernel versions (1.2.x) seem to have trouble
5349 rereading the partition table, but if asked to do it
5350 twice, the second time works. - biro@yggdrasil.com */
5353 if ((i = ioctl(fd, BLKRRPART)) != 0)
5358 printf(_("\nWARNING: Re-reading the partition table "
5359 "failed with error %d: %s.\n"
5360 "The kernel still uses the old table.\n"
5361 "The new table will be used "
5362 "at the next reboot.\n"),
5363 error, strerror(error));
5368 _("\nWARNING: If you have created or modified any DOS 6.x\n"
5369 "partitions, please see the fdisk manual page for additional\n"
5375 printf(_("Syncing disks.\n"));
5377 sleep(4); /* for sync() */
5381 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
5383 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
5384 #define MAX_PER_LINE 16
5386 print_buffer(char pbuffer[]) {
5390 for (i = 0, l = 0; i < sector_size; i++, l++) {
5392 printf("0x%03X:", i);
5393 printf(" %02X", (unsigned char) pbuffer[i]);
5394 if (l == MAX_PER_LINE - 1) {
5409 printf(_("Device: %s\n"), disk_device);
5410 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
5411 if (sun_label || sgi_label)
5412 print_buffer(MBRbuffer);
5415 for (i = 3; i < partitions; i++)
5416 print_buffer(ptes[i].sectorbuffer);
5421 struct pte *pe = &ptes[i];
5422 struct partition *p = pe->part_table;
5425 if (warn_geometry())
5427 if (!p->sys_ind || !get_nr_sects(p) || IS_EXTENDED (p->sys_ind)) {
5428 printf(_("Partition %d has no data area\n"), i + 1);
5431 first = get_partition_start(pe);
5432 new = read_int(first, first, first + get_nr_sects(p) - 1, first,
5433 _("New beginning of data")) - pe->offset;
5435 if (new != get_nr_sects(p)) {
5436 first = get_nr_sects(p) + get_start_sect(p) - new;
5437 set_nr_sects(p, first);
5438 set_start_sect(p, new);
5449 c = tolower(read_char(_("Expert command (m for help): ")));
5452 #ifdef CONFIG_FEATURE_SUN_LABEL
5459 move_begin(get_partition(0, partitions));
5462 user_cylinders = cylinders =
5463 read_int(1, cylinders, 1048576, 0,
5464 _("Number of cylinders"));
5465 #ifdef CONFIG_FEATURE_SUN_LABEL
5467 sun_set_ncyl(cylinders);
5476 #ifdef CONFIG_FEATURE_SGI_LABEL
5481 #ifdef CONFIG_FEATURE_SUN_LABEL
5491 fix_partition_table_order();
5494 #ifdef CONFIG_FEATURE_SGI_LABEL
5499 user_heads = heads = read_int(1, heads, 256, 0,
5500 _("Number of heads"));
5504 #ifdef CONFIG_FEATURE_SUN_LABEL
5510 #ifdef CONFIG_FEATURE_SUN_LABEL
5516 #ifdef CONFIG_FEATURE_SUN_LABEL
5530 user_sectors = sectors = read_int(1, sectors, 63, 0,
5531 _("Number of sectors"));
5532 if (dos_compatible_flag) {
5533 sector_offset = sectors;
5534 fprintf(stderr, _("Warning: setting "
5535 "sector offset for DOS "
5544 write_table(); /* does not return */
5547 #ifdef CONFIG_FEATURE_SUN_LABEL
5549 sun_set_pcylcount();
5557 #endif /* ADVANCED mode */
5560 is_ide_cdrom_or_tape(const char *device) {
5563 struct stat statbuf;
5566 /* No device was given explicitly, and we are trying some
5567 likely things. But opening /dev/hdc may produce errors like
5568 "hdc: tray open or drive not ready"
5569 if it happens to be a CD-ROM drive. It even happens that
5570 the process hangs on the attempt to read a music CD.
5571 So try to be careful. This only works since 2.1.73. */
5573 if (strncmp("/dev/hd", device, 7))
5576 snprintf(buf, sizeof(buf), "/proc/ide/%s/media", device+5);
5577 procf = fopen(buf, "r");
5578 if (procf != NULL && fgets(buf, sizeof(buf), procf))
5579 is_ide = (!strncmp(buf, "cdrom", 5) ||
5580 !strncmp(buf, "tape", 4));
5582 /* Now when this proc file does not exist, skip the
5583 device when it is read-only. */
5584 if (stat(device, &statbuf) == 0)
5585 is_ide = ((statbuf.st_mode & 0222) == 0);
5593 try(const char *device, int user_specified) {
5596 disk_device = device;
5597 if (setjmp(listingbuf))
5599 if (!user_specified)
5600 if (is_ide_cdrom_or_tape(device))
5602 if ((fd = open(disk_device, type_open)) >= 0) {
5603 gb = get_boot(try_only);
5604 if (gb > 0) { /* I/O error */
5606 } else if (gb < 0) { /* no DOS signature */
5607 list_disk_geometry();
5610 #ifdef CONFIG_FEATURE_OSF_LABEL
5611 if (btrydev(device) < 0)
5614 _("Disk %s doesn't contain a valid "
5615 "partition table\n"), device);
5620 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5621 if (!sun_label && partitions > 4)
5622 delete_partition(ext_index);
5626 /* Ignore other errors, since we try IDE
5627 and SCSI hard disks which may not be
5628 installed on the system. */
5629 if (errno == EACCES) {
5630 fprintf(stderr, _("Cannot open %s\n"), device);
5636 /* for fdisk -l: try all things in /proc/partitions
5637 that look like a partition name (do not end in a digit) */
5641 char line[100], ptname[100], devname[120], *s;
5644 procpt = bb_wfopen(PROC_PARTITIONS, "r");
5646 while (fgets(line, sizeof(line), procpt)) {
5647 if (sscanf (line, " %d %d %d %[^\n ]",
5648 &ma, &mi, &sz, ptname) != 4)
5650 for (s = ptname; *s; s++);
5653 sprintf(devname, "/dev/%s", ptname);
5656 #ifdef CONFIG_FEATURE_CLEAN_UP
5661 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5663 unknown_command(int c) {
5664 printf(_("%c: unknown command\n"), c);
5668 int fdisk_main(int argc, char **argv) {
5670 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5673 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5679 * fdisk -l [-b sectorsize] [-u] device ...
5680 * fdisk -s [partition] ...
5681 * fdisk [-b sectorsize] [-u] device
5683 * Options -C, -H, -S set the geometry.
5686 while ((c = getopt(argc, argv, "b:C:H:lS:uvV"
5687 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5693 /* Ugly: this sector size is really per device,
5694 so cannot be combined with multiple disks,
5695 and te same goes for the C/H/S options.
5697 sector_size = atoi(optarg);
5698 if (sector_size != 512 && sector_size != 1024 &&
5699 sector_size != 2048)
5702 user_set_sector_size = 1;
5705 user_cylinders = atoi(optarg);
5708 user_heads = atoi(optarg);
5709 if (user_heads <= 0 || user_heads >= 256)
5713 user_sectors = atoi(optarg);
5714 if (user_sectors <= 0 || user_sectors >= 64)
5718 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5722 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5728 display_in_cyl_units = 0;
5732 printf("fdisk v" UTIL_LINUX_VERSION "\n");
5740 printf(_("This kernel finds the sector size itself - "
5741 "-b option ignored\n"));
5743 if (user_set_sector_size && argc-optind != 1)
5744 printf(_("Warning: the -b (set sector size) option should"
5745 " be used with one specified device\n"));
5748 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5752 type_open = O_RDONLY;
5753 if (argc > optind) {
5756 /* avoid gcc warning:
5757 variable `k' might be clobbered by `longjmp' */
5761 for (k=optind; k<argc; k++)
5764 /* we no longer have default device names */
5765 /* but, we can use /proc/partitions instead */
5769 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5773 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5779 type_open = O_RDONLY;
5781 opts = argc - optind;
5785 for (j = optind; j < argc; j++) {
5786 disk_device = argv[j];
5787 if ((fd = open(disk_device, type_open)) < 0)
5788 fdisk_fatal(unable_to_open);
5789 if (ioctl(fd, BLKGETSIZE, &size))
5790 fdisk_fatal(ioctl_error);
5793 printf("%ld\n", size/2);
5795 printf("%s: %ld\n", argv[j], size/2);
5801 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5802 if (argc-optind == 1)
5803 disk_device = argv[optind];
5809 #ifdef CONFIG_FEATURE_OSF_LABEL
5811 /* OSF label, and no DOS label */
5812 printf(_("Detected an OSF/1 disklabel on %s, entering "
5813 "disklabel mode.\n"),
5817 /* If we return we may want to make an empty DOS label? */
5823 c = tolower(read_char(_("Command (m for help): ")));
5827 toggle_active(get_partition(1, partitions));
5828 #ifdef CONFIG_FEATURE_SUN_LABEL
5830 toggle_sunflags(get_partition(1, partitions),
5833 #ifdef CONFIG_FEATURE_SGI_LABEL
5835 sgi_set_bootpartition(
5836 get_partition(1, partitions));
5842 #ifdef CONFIG_FEATURE_SGI_LABEL
5844 printf(_("\nThe current boot file is: %s\n"),
5845 sgi_get_bootfile());
5846 if (read_chars(_("Please enter the name of the "
5847 "new boot file: ")) == '\n')
5848 printf(_("Boot file unchanged\n"));
5850 sgi_set_bootfile(line_ptr);
5853 #ifdef CONFIG_FEATURE_OSF_LABEL
5859 toggle_dos_compatibility_flag();
5860 #ifdef CONFIG_FEATURE_SUN_LABEL
5862 toggle_sunflags(get_partition(1, partitions),
5865 #ifdef CONFIG_FEATURE_SGI_LABEL
5867 sgi_set_swappartition(
5868 get_partition(1, partitions));
5876 #ifdef CONFIG_FEATURE_SGI_LABEL
5877 /* If sgi_label then don't use get_existing_partition,
5878 let the user select a partition, since
5879 get_existing_partition() only works for Linux-like
5882 j = get_existing_partition(1, partitions);
5884 j = get_partition(1, partitions);
5887 j = get_existing_partition(1, partitions);
5890 delete_partition(j);
5894 #ifdef CONFIG_FEATURE_SGI_LABEL
5901 list_types(get_sys_types());
5920 #ifdef CONFIG_FEATURE_SUN_LABEL
5934 write_table(); /* does not return */
5936 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
5938 #ifdef CONFIG_FEATURE_SGI_LABEL
5941 _("\n\tSorry, no experts menu for SGI "
5942 "partition tables available.\n\n"));
5955 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */