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 * For detailed old history, see older versions.
11 * Contributions before 2001 by faith@cs.unc.edu, Michael Bischoff,
12 * LeBlanc@mcc.ac.uk, martin@cs.unc.edu, leisner@sdsp.mc.xerox.com,
13 * esr@snark.thyrsus.com, aeb@cwi.nl, quinlan@yggdrasil.com,
14 * fasten@cs.bonn.edu, orschaer@cip.informatik.uni-erlangen.de,
15 * jj@sunsite.mff.cuni.cz, fasten@shw.com, ANeuper@GUUG.de,
16 * kgw@suse.de, kalium@gmx.de, dhuggins@linuxcare.com,
17 * michal@ellpspace.math.ualberta.ca and probably others.
19 * Vladimir Oleynik <dzo@simtreas.ru> 2001,2002 Busybox port
22 #define UTIL_LINUX_VERSION "2.11w"
24 #define PROC_PARTITIONS "/proc/partitions"
26 #include <sys/types.h>
27 #include <sys/stat.h> /* stat */
36 #include <assert.h> /* assert */
40 #define u_char unsigned char
41 #include <scsi/scsi.h> /* SCSI_IOCTL_GET_IDLUN */
44 #include <sys/ioctl.h>
45 #include <sys/param.h>
47 #include <stdint.h> /* for uint32_t, uint16_t, uint8_t, int16_t, etc */
49 /* Copied from linux/major.h */
50 #define FLOPPY_MAJOR 2
52 #include <sys/utsname.h>
56 #define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r))
62 #define BLKRRPART _IO(0x12,95) /* re-read partition table */
63 #define BLKGETSIZE _IO(0x12,96) /* return device size */
64 #define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */
65 #define BLKSSZGET _IO(0x12,104) /* get block device sector size */
72 #define DEFAULT_SECTOR_SIZE 512
73 #define MAX_SECTOR_SIZE 2048
74 #define SECTOR_SIZE 512 /* still used in BSD code */
75 #define MAXIMUM_PARTS 60
77 #define ACTIVE_FLAG 0x80
80 #define WIN98_EXTENDED 0x0f
81 #define LINUX_PARTITION 0x81
82 #define LINUX_SWAP 0x82
83 #define LINUX_NATIVE 0x83
84 #define LINUX_EXTENDED 0x85
85 #define LINUX_LVM 0x8e
86 #define LINUX_RAID 0xfd
91 #define IS_EXTENDED(i) \
92 ((i) == EXTENDED || (i) == WIN98_EXTENDED || (i) == LINUX_EXTENDED)
94 #define SIZE(a) (sizeof(a)/sizeof((a)[0]))
96 #define cround(n) (display_in_cyl_units ? ((n)/units_per_sector)+1 : (n))
97 #define scround(x) (((x)+units_per_sector-1)/units_per_sector)
99 #if defined(__GNUC__) || defined(HAS_LONG_LONG)
100 typedef long long ext2_loff_t;
102 typedef long ext2_loff_t;
105 /* including <linux/hdreg.h> also fails */
108 unsigned char sectors;
109 unsigned short cylinders;
113 #define HDIO_GETGEO 0x0301 /* get device geometry */
117 const unsigned char *name;
122 * Raw disk label. For DOS-type partition tables the MBR,
123 * with descriptions of the primary partitions.
125 static char MBRbuffer[MAX_SECTOR_SIZE];
127 #ifdef CONFIG_FEATURE_SUN_LABEL
128 static int sun_label; /* looking at sun disklabel */
132 #ifdef CONFIG_FEATURE_SGI_LABEL
133 static int sgi_label; /* looking at sgi disklabel */
137 #ifdef CONFIG_FEATURE_AIX_LABEL
138 static int aix_label; /* looking at aix disklabel */
142 #ifdef CONFIG_FEATURE_OSF_LABEL
143 static int osf_label; /* looking at OSF/1 disklabel */
144 static int possibly_osf_label;
149 #define dos_label (!sun_label && !sgi_label && !aix_label && !osf_label)
151 static uint heads, sectors, cylinders;
152 static void update_units(void);
156 * return partition name - uses static storage unless buf is supplied
159 partname(const char *dev, int pno, int lth) {
160 static char buffer[80];
167 bufsiz = sizeof(buffer);
172 if (isdigit(dev[w-1]))
175 /* devfs kludge - note: fdisk partition names are not supposed
176 to equal kernel names, so there is no reason to do this */
177 if (strcmp (dev + w - 4, "disc") == 0) {
185 snprintf(bufp, bufsiz, "%*.*s%s%-2u",
186 lth-wp-2, w, dev, p, pno);
188 snprintf(bufp, bufsiz, "%.*s%s%-2u", w, dev, p, pno);
194 unsigned char boot_ind; /* 0x80 - active */
195 unsigned char head; /* starting head */
196 unsigned char sector; /* starting sector */
197 unsigned char cyl; /* starting cylinder */
198 unsigned char sys_ind; /* What partition type */
199 unsigned char end_head; /* end head */
200 unsigned char end_sector; /* end sector */
201 unsigned char end_cyl; /* end cylinder */
202 unsigned char start4[4]; /* starting sector counting from 0 */
203 unsigned char size4[4]; /* nr of sectors in partition */
207 ioctl_error, unable_to_open, unable_to_read, unable_to_seek,
211 enum action {fdisk, require, try_only, create_empty_dos, create_empty_sun};
213 static const char *disk_device;
214 static int fd; /* the disk */
215 static int partitions = 4; /* maximum partition + 1 */
216 static uint display_in_cyl_units = 1;
217 static uint units_per_sector = 1;
218 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
219 static char *line_ptr;
220 static void change_units(void);
221 static void reread_partition_table(int leave);
222 static void delete_partition(int i);
223 static int get_partition(int warn, int max);
224 static void list_types(const struct systypes *sys);
225 static uint read_int(uint low, uint dflt, uint high, uint base, char *mesg);
227 static const char *partition_type(unsigned char type);
228 static void fdisk_fatal(enum failure why) __attribute__ ((noreturn));
229 static void get_geometry(void);
230 static int get_boot(enum action what);
235 #define hex_val(c) ({ \
237 isdigit(_c) ? _c - '0' : \
238 tolower(_c) + 10 - 'a'; \
242 #define LINE_LENGTH 800
243 #define pt_offset(b, n) ((struct partition *)((b) + 0x1be + \
244 (n) * sizeof(struct partition)))
245 #define sector(s) ((s) & 0x3f)
246 #define cylinder(s, c) ((c) | (((s) & 0xc0) << 2))
248 #define hsc2sector(h,s,c) (sector(s) - 1 + sectors * \
249 ((h) + heads * cylinder(s,c)))
250 #define set_hsc(h,s,c,sector) { \
251 s = sector % sectors + 1; \
253 h = sector % heads; \
256 s |= (sector >> 2) & 0xc0; \
260 static unsigned int get_start_sect(const struct partition *p);
261 static unsigned int get_nr_sects(const struct partition *p);
264 * per partition table entry data
266 * The four primary partitions have the same sectorbuffer (MBRbuffer)
267 * and have NULL ext_pointer.
268 * Each logical partition table entry has two pointers, one for the
269 * partition and one link to the next one.
272 struct partition *part_table; /* points into sectorbuffer */
273 struct partition *ext_pointer; /* points into sectorbuffer */
274 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
275 char changed; /* boolean */
277 uint offset; /* disk sector number */
278 char *sectorbuffer; /* disk sector contents */
279 } ptes[MAXIMUM_PARTS];
282 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
284 set_all_unchanged(void) {
287 for (i = 0; i < MAXIMUM_PARTS; i++)
295 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
297 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_OSF_LABEL)
298 static struct partition *
299 get_part_table(int i) {
300 return ptes[i].part_table;
305 str_units(int n) { /* n==1: use singular */
307 return display_in_cyl_units ? _("cylinder") : _("sector");
309 return display_in_cyl_units ? _("cylinders") : _("sectors");
313 valid_part_table_flag(const unsigned char *b) {
314 return (b[510] == 0x55 && b[511] == 0xaa);
317 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
318 static char line_buffer[LINE_LENGTH];
320 /* read line; return 0 or first char */
324 static int got_eof = 0;
326 fflush (stdout); /* requested by niles@scyld.com */
327 line_ptr = line_buffer;
328 if (!fgets(line_buffer, LINE_LENGTH, stdin)) {
330 got_eof++; /* user typed ^D ? */
332 fprintf(stderr, _("\ngot EOF thrice - exiting..\n"));
337 while (*line_ptr && !isgraph(*line_ptr))
343 read_char(const char *mesg)
347 } while (!read_line());
352 read_chars(const char *mesg)
363 read_hex(const struct systypes *sys)
369 read_char(_("Hex code (type L to list codes): "));
370 if (*line_ptr == 'l' || *line_ptr == 'L')
372 else if (isxdigit (*line_ptr))
376 hex = hex << 4 | hex_val(*line_ptr++);
377 while (isxdigit(*line_ptr));
382 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
384 #ifdef CONFIG_FEATURE_AIX_LABEL
386 * Copyright (C) Andreas Neuper, Sep 1998.
387 * This file may be redistributed under
388 * the terms of the GNU Public License.
392 unsigned int magic; /* expect AIX_LABEL_MAGIC */
393 unsigned int fillbytes1[124];
394 unsigned int physical_volume_id;
395 unsigned int fillbytes2[124];
398 #define AIX_LABEL_MAGIC 0xc9c2d4c1
399 #define AIX_LABEL_MAGIC_SWAPPED 0xc1d4c2c9
400 #define AIX_INFO_MAGIC 0x00072959
401 #define AIX_INFO_MAGIC_SWAPPED 0x59290700
403 #define aixlabel ((aix_partition *)MBRbuffer)
408 Sat Mar 20 09:51:38 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
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
519 #error unknown architecture
522 #define BSD_BBSIZE 8192 /* size of boot area, with label */
523 #define BSD_SBSIZE 8192 /* max size of fs superblock */
525 struct xbsd_disklabel {
526 uint32_t d_magic; /* the magic number */
527 int16_t d_type; /* drive type */
528 int16_t d_subtype; /* controller/d_type specific */
529 char d_typename[16]; /* type name, e.g. "eagle" */
530 char d_packname[16]; /* pack identifier */
532 uint32_t d_secsize; /* # of bytes per sector */
533 uint32_t d_nsectors; /* # of data sectors per track */
534 uint32_t d_ntracks; /* # of tracks per cylinder */
535 uint32_t d_ncylinders; /* # of data cylinders per unit */
536 uint32_t d_secpercyl; /* # of data sectors per cylinder */
537 uint32_t d_secperunit; /* # of data sectors per unit */
539 * Spares (bad sector replacements) below
540 * are not counted in d_nsectors or d_secpercyl.
541 * Spare sectors are assumed to be physical sectors
542 * which occupy space at the end of each track and/or cylinder.
544 uint16_t d_sparespertrack; /* # of spare sectors per track */
545 uint16_t d_sparespercyl; /* # of spare sectors per cylinder */
547 * Alternate cylinders include maintenance, replacement,
548 * configuration description areas, etc.
550 uint32_t d_acylinders; /* # of alt. cylinders per unit */
552 /* hardware characteristics: */
554 * d_interleave, d_trackskew and d_cylskew describe perturbations
555 * in the media format used to compensate for a slow controller.
556 * Interleave is physical sector interleave, set up by the formatter
557 * or controller when formatting. When interleaving is in use,
558 * logically adjacent sectors are not physically contiguous,
559 * but instead are separated by some number of sectors.
560 * It is specified as the ratio of physical sectors traversed
561 * per logical sector. Thus an interleave of 1:1 implies contiguous
562 * layout, while 2:1 implies that logical sector 0 is separated
563 * by one sector from logical sector 1.
564 * d_trackskew is the offset of sector 0 on track N
565 * relative to sector 0 on track N-1 on the same cylinder.
566 * Finally, d_cylskew is the offset of sector 0 on cylinder N
567 * relative to sector 0 on cylinder N-1.
569 uint16_t d_rpm; /* rotational speed */
570 uint16_t d_interleave; /* hardware sector interleave */
571 uint16_t d_trackskew; /* sector 0 skew, per track */
572 uint16_t d_cylskew; /* sector 0 skew, per cylinder */
573 uint32_t d_headswitch; /* head switch time, usec */
574 uint32_t d_trkseek; /* track-to-track seek, usec */
575 uint32_t d_flags; /* generic flags */
577 uint32_t d_drivedata[NDDATA]; /* drive-type specific information */
579 uint32_t d_spare[NSPARE]; /* reserved for future use */
580 uint32_t d_magic2; /* the magic number (again) */
581 uint16_t d_checksum; /* xor of data incl. partitions */
582 /* filesystem and partition information: */
583 uint16_t d_npartitions; /* number of partitions in following */
584 uint32_t d_bbsize; /* size of boot area at sn0, bytes */
585 uint32_t d_sbsize; /* max size of fs superblock, bytes */
586 struct xbsd_partition { /* the partition table */
587 uint32_t p_size; /* number of sectors in partition */
588 uint32_t p_offset; /* starting sector */
589 uint32_t p_fsize; /* filesystem basic fragment size */
590 uint8_t p_fstype; /* filesystem type, see below */
591 uint8_t p_frag; /* filesystem fragments per block */
592 uint16_t p_cpg; /* filesystem cylinders per group */
593 } d_partitions[BSD_MAXPARTITIONS]; /* actually may be more */
597 #define BSD_DTYPE_SMD 1 /* SMD, XSMD; VAX hp/up */
598 #define BSD_DTYPE_MSCP 2 /* MSCP */
599 #define BSD_DTYPE_DEC 3 /* other DEC (rk, rl) */
600 #define BSD_DTYPE_SCSI 4 /* SCSI */
601 #define BSD_DTYPE_ESDI 5 /* ESDI interface */
602 #define BSD_DTYPE_ST506 6 /* ST506 etc. */
603 #define BSD_DTYPE_HPIB 7 /* CS/80 on HP-IB */
604 #define BSD_DTYPE_HPFL 8 /* HP Fiber-link */
605 #define BSD_DTYPE_FLOPPY 10 /* floppy */
607 /* d_subtype values: */
608 #define BSD_DSTYPE_INDOSPART 0x8 /* is inside dos partition */
609 #define BSD_DSTYPE_DOSPART(s) ((s) & 3) /* dos partition number */
610 #define BSD_DSTYPE_GEOMETRY 0x10 /* drive params in label */
613 static const char * const xbsd_dktypenames[] = {
627 #define BSD_DKMAXTYPES (sizeof(xbsd_dktypenames) / sizeof(xbsd_dktypenames[0]) - 1)
631 * Filesystem type and version.
632 * Used to interpret other filesystem-specific
633 * per-partition information.
635 #define BSD_FS_UNUSED 0 /* unused */
636 #define BSD_FS_SWAP 1 /* swap */
637 #define BSD_FS_V6 2 /* Sixth Edition */
638 #define BSD_FS_V7 3 /* Seventh Edition */
639 #define BSD_FS_SYSV 4 /* System V */
640 #define BSD_FS_V71K 5 /* V7 with 1K blocks (4.1, 2.9) */
641 #define BSD_FS_V8 6 /* Eighth Edition, 4K blocks */
642 #define BSD_FS_BSDFFS 7 /* 4.2BSD fast file system */
643 #define BSD_FS_BSDLFS 9 /* 4.4BSD log-structured file system */
644 #define BSD_FS_OTHER 10 /* in use, but unknown/unsupported */
645 #define BSD_FS_HPFS 11 /* OS/2 high-performance file system */
646 #define BSD_FS_ISO9660 12 /* ISO-9660 filesystem (cdrom) */
647 #define BSD_FS_ISOFS BSD_FS_ISO9660
648 #define BSD_FS_BOOT 13 /* partition contains bootstrap */
649 #define BSD_FS_ADOS 14 /* AmigaDOS fast file system */
650 #define BSD_FS_HFS 15 /* Macintosh HFS */
651 #define BSD_FS_ADVFS 16 /* Digital Unix AdvFS */
653 /* this is annoying, but it's also the way it is :-( */
655 #define BSD_FS_EXT2 8 /* ext2 file system */
657 #define BSD_FS_MSDOS 8 /* MS-DOS file system */
661 static const struct systypes xbsd_fstypes[] = {
662 /* BSD_FS_UNUSED */ {"\x00" "unused"},
663 /* BSD_FS_SWAP */ {"\x01" "swap"},
664 /* BSD_FS_V6 */ {"\x02" "Version 6"},
665 /* BSD_FS_V7 */ {"\x03" "Version 7"},
666 /* BSD_FS_SYSV */ {"\x04" "System V"},
667 /* BSD_FS_V71K */ {"\x05" "4.1BSD"},
668 /* BSD_FS_V8 */ {"\x06" "Eighth Edition"},
669 /* BSD_FS_BSDFFS */ {"\x07" "4.2BSD"},
671 /* BSD_FS_EXT2 */ {"\x08" "ext2"},
673 /* BSD_FS_MSDOS */ {"\x08" "MS-DOS"},
675 /* BSD_FS_BSDLFS */ {"\x09" "4.4LFS"},
676 /* BSD_FS_OTHER */ {"\x0a" "unknown"},
677 /* BSD_FS_HPFS */ {"\x0b" "HPFS"},
678 /* BSD_FS_ISO9660 */ {"\x0c" "ISO-9660"},
679 /* BSD_FS_BOOT */ {"\x0d" "boot"},
680 /* BSD_FS_ADOS */ {"\x0e" "ADOS"},
681 /* BSD_FS_HFS */ {"\x0f" "HFS"},
682 /* BSD_FS_ADVFS */ {"\x10" "AdvFS"},
685 #define BSD_FSMAXTYPES (SIZE(xbsd_fstypes)-1)
690 * flags shared by various drives:
692 #define BSD_D_REMOVABLE 0x01 /* removable media */
693 #define BSD_D_ECC 0x02 /* supports ECC */
694 #define BSD_D_BADSECT 0x04 /* supports bad sector forw. */
695 #define BSD_D_RAMDISK 0x08 /* disk emulator */
696 #define BSD_D_CHAIN 0x10 /* can do back-back transfers */
697 #define BSD_D_DOSPART 0x20 /* within MSDOS partition */
699 #endif /* OSF_LABEL */
702 * Copyright (C) Andreas Neuper, Sep 1998.
703 * This file may be modified and redistributed under
704 * the terms of the GNU Public License.
707 struct device_parameter { /* 48 bytes */
711 unsigned char sparecyl;
712 unsigned short pcylcount;
713 unsigned short head_vol0;
714 unsigned short ntrks; /* tracks in cyl 0 or vol 0 */
715 unsigned char cmd_tag_queue_depth;
716 unsigned char unused0;
717 unsigned short unused1;
718 unsigned short nsect; /* sectors/tracks in cyl 0 or vol 0 */
719 unsigned short bytes;
720 unsigned short ilfact;
721 unsigned int flags; /* controller flags */
722 unsigned int datarate;
723 unsigned int retries_on_error;
724 unsigned int ms_per_word;
725 unsigned short xylogics_gap1;
726 unsigned short xylogics_syncdelay;
727 unsigned short xylogics_readdelay;
728 unsigned short xylogics_gap2;
729 unsigned short xylogics_readgate;
730 unsigned short xylogics_writecont;
733 #define SGI_VOLHDR 0x00
734 /* 1 and 2 were used for drive types no longer supported by SGI */
735 #define SGI_SWAP 0x03
736 /* 4 and 5 were for filesystem types SGI haven't ever supported on MIPS CPUs */
737 #define SGI_VOLUME 0x06
739 #define SGI_LVOL 0x08
740 #define SGI_RLVOL 0x09
742 #define SGI_XFSLOG 0x0b
745 #define ENTIRE_DISK SGI_VOLUME
749 #define SECTOR_SLIP 0x01
750 #define SECTOR_FWD 0x02
751 #define TRACK_FWD 0x04
752 #define TRACK_MULTIVOL 0x08
753 #define IGNORE_ERRORS 0x10
755 #define ENABLE_CMDTAGQ 0x40
758 unsigned int magic; /* expect SGI_LABEL_MAGIC */
759 unsigned short boot_part; /* active boot partition */
760 unsigned short swap_part; /* active swap partition */
761 unsigned char boot_file[16]; /* name of the bootfile */
762 struct device_parameter devparam; /* 1 * 48 bytes */
763 struct volume_directory { /* 15 * 16 bytes */
764 unsigned char vol_file_name[8]; /* a character array */
765 unsigned int vol_file_start; /* number of logical block */
766 unsigned int vol_file_size; /* number of bytes */
768 struct sgi_partition { /* 16 * 12 bytes */
769 unsigned int num_sectors; /* number of blocks */
770 unsigned int start_sector; /* must be cylinder aligned */
774 unsigned int fillbytes;
778 unsigned int magic; /* looks like a magic number */
787 unsigned char scsi_string[50];
788 unsigned char serial[137];
789 unsigned short check1816;
790 unsigned char installer[225];
793 #define SGI_LABEL_MAGIC 0x0be5a941
794 #define SGI_LABEL_MAGIC_SWAPPED 0x41a9e50b
795 #define SGI_INFO_MAGIC 0x00072959
796 #define SGI_INFO_MAGIC_SWAPPED 0x59290700
797 #define SGI_SSWAP16(x) (sgi_other_endian ? __swap16(x) \
799 #define SGI_SSWAP32(x) (sgi_other_endian ? __swap32(x) \
802 #define sgilabel ((sgi_partition *)MBRbuffer)
803 #define sgiparam (sgilabel->devparam)
806 unsigned char info[128]; /* Informative text string */
807 unsigned char spare0[14];
809 unsigned char spare1;
811 unsigned char spare2;
814 unsigned char spare1[246]; /* Boot information etc. */
815 unsigned short rspeed; /* Disk rotational speed */
816 unsigned short pcylcount; /* Physical cylinder count */
817 unsigned short sparecyl; /* extra sects per cylinder */
818 unsigned char spare2[4]; /* More magic... */
819 unsigned short ilfact; /* Interleave factor */
820 unsigned short ncyl; /* Data cylinder count */
821 unsigned short nacyl; /* Alt. cylinder count */
822 unsigned short ntrks; /* Tracks per cylinder */
823 unsigned short nsect; /* Sectors per track */
824 unsigned char spare3[4]; /* Even more magic... */
825 struct sun_partition {
826 uint32_t start_cylinder;
827 uint32_t num_sectors;
829 unsigned short magic; /* Magic number */
830 unsigned short csum; /* Label xor'd checksum */
833 #define SUN_LABEL_MAGIC 0xDABE
834 #define SUN_LABEL_MAGIC_SWAPPED 0xBEDA
835 #define sunlabel ((sun_partition *)MBRbuffer)
836 #define SUN_SSWAP16(x) (sun_other_endian ? __swap16(x) \
838 #define SUN_SSWAP32(x) (sun_other_endian ? __swap32(x) \
842 * llseek.c -- stub calling the llseek system call
844 * Copyright (C) 1994 Remy Card. This file may be redistributed
845 * under the terms of the GNU Public License.
854 #else /* HAVE_LLSEEK */
856 #if defined(__alpha__) || defined(__ia64__)
858 #define my_llseek lseek
861 #include <asm/unistd.h> /* for __NR__llseek */
863 static int _llseek (unsigned int, unsigned long,
864 unsigned long, ext2_loff_t *, unsigned int);
868 static _syscall5(int,_llseek,unsigned int,f_d,unsigned long,offset_high,
869 unsigned long, offset_low,ext2_loff_t *,result,
870 unsigned int, origin)
874 /* no __NR__llseek on compilation machine - might give it explicitly */
875 static int _llseek (unsigned int f_d, unsigned long oh,
876 unsigned long ol, ext2_loff_t *result,
877 unsigned int origin) {
884 static ext2_loff_t my_llseek (unsigned int f_d, ext2_loff_t offset,
890 retval = _llseek (f_d, ((unsigned long long) offset) >> 32,
891 ((unsigned long long) offset) & 0xffffffff,
893 return (retval == -1 ? (ext2_loff_t) retval : result);
896 #endif /* __alpha__ */
898 #endif /* HAVE_LLSEEK */
900 static ext2_loff_t ext2_llseek (unsigned int f_d, ext2_loff_t offset,
904 static int do_compat = 0;
907 result = my_llseek (f_d, offset, origin);
908 if (!(result == -1 && errno == ENOSYS))
912 * Just in case this code runs on top of an old kernel
913 * which does not support the llseek system call
917 * Now try ordinary lseek.
921 if ((sizeof(off_t) >= sizeof(ext2_loff_t)) ||
922 (offset < ((ext2_loff_t) 1 << ((sizeof(off_t)*8) -1))))
923 return lseek(f_d, (off_t) offset, origin);
931 static ext2_loff_t ext2_llseek (unsigned int f_d, ext2_loff_t offset,
934 if ((sizeof(off_t) < sizeof(ext2_loff_t)) &&
935 (offset >= ((ext2_loff_t) 1 << ((sizeof(off_t)*8) -1)))) {
939 return lseek (f_d, (off_t) offset, origin);
945 #ifdef CONFIG_FEATURE_OSF_LABEL
948 19990319 - Arnaldo Carvalho de Melo <acme@conectiva.com.br> - i18n/nls
950 20000101 - David Huggins-Daines <dhuggins@linuxcare.com> - Better
951 support for OSF/1 disklabels on Alpha.
952 Also fixed unaligned accesses in alpha_bootblock_checksum()
955 #define FREEBSD_PARTITION 0xa5
956 #define NETBSD_PARTITION 0xa9
958 static void xbsd_delete_part (void);
959 static void xbsd_new_part (void);
960 static void xbsd_write_disklabel (void);
961 static int xbsd_create_disklabel (void);
962 static void xbsd_edit_disklabel (void);
963 static void xbsd_write_bootstrap (void);
964 static void xbsd_change_fstype (void);
965 static int xbsd_get_part_index (int max);
966 static int xbsd_check_new_partition (int *i);
967 static void xbsd_list_types (void);
968 static u_short xbsd_dkcksum (struct xbsd_disklabel *lp);
969 static int xbsd_initlabel (struct partition *p, struct xbsd_disklabel *d,
971 static int xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d);
972 static int xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d);
974 #if defined (__alpha__)
975 static void alpha_bootblock_checksum (char *boot);
978 #if !defined (__alpha__)
979 static int xbsd_translate_fstype (int linux_type);
980 static void xbsd_link_part (void);
981 static struct partition *xbsd_part;
982 static int xbsd_part_index;
985 #if defined (__alpha__)
986 /* We access this through a u_int64_t * when checksumming */
987 static char disklabelbuffer[BSD_BBSIZE] __attribute__((aligned(8)));
989 static char disklabelbuffer[BSD_BBSIZE];
992 static struct xbsd_disklabel xbsd_dlabel;
994 #define bsd_cround(n) \
995 (display_in_cyl_units ? ((n)/xbsd_dlabel.d_secpercyl) + 1 : (n))
998 * Test whether the whole disk has BSD disk label magic.
1000 * Note: often reformatting with DOS-type label leaves the BSD magic,
1001 * so this does not mean that there is a BSD disk label.
1004 check_osf_label(void) {
1005 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
1010 static void xbsd_print_disklabel(int);
1013 btrydev (const char * dev) {
1014 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
1016 printf(_("\nBSD label for device: %s\n"), dev);
1017 xbsd_print_disklabel (0);
1023 puts (_("Command action"));
1024 puts (_("\td\tdelete a BSD partition"));
1025 puts (_("\te\tedit drive data"));
1026 puts (_("\ti\tinstall bootstrap"));
1027 puts (_("\tl\tlist known filesystem types"));
1028 puts (_("\tm\tprint this menu"));
1029 puts (_("\tn\tadd a new BSD partition"));
1030 puts (_("\tp\tprint BSD partition table"));
1031 puts (_("\tq\tquit without saving changes"));
1032 puts (_("\tr\treturn to main menu"));
1033 puts (_("\ts\tshow complete disklabel"));
1034 puts (_("\tt\tchange a partition's filesystem id"));
1035 puts (_("\tu\tchange units (cylinders/sectors)"));
1036 puts (_("\tw\twrite disklabel to disk"));
1037 #if !defined (__alpha__)
1038 puts (_("\tx\tlink BSD partition to non-BSD partition"));
1042 #if !defined (__alpha__)
1049 is_bsd_partition_type(int type) {
1050 return (type == FREEBSD_PARTITION ||
1051 type == hidden(FREEBSD_PARTITION) ||
1052 type == NETBSD_PARTITION ||
1053 type == hidden(NETBSD_PARTITION));
1059 #if !defined (__alpha__)
1061 struct partition *p;
1063 for (t=0; t<4; t++) {
1064 p = get_part_table(t);
1065 if (p && is_bsd_partition_type(p->sys_ind)) {
1067 xbsd_part_index = t;
1068 ss = get_start_sect(xbsd_part);
1070 fprintf (stderr, _("Partition %s has invalid starting sector 0.\n"),
1071 partname(disk_device, t+1, 0));
1074 printf (_("Reading disklabel of %s at sector %d.\n"),
1075 partname(disk_device, t+1, 0), ss + BSD_LABELSECTOR);
1076 if (xbsd_readlabel (xbsd_part, &xbsd_dlabel) == 0)
1077 if (xbsd_create_disklabel () == 0)
1084 printf (_("There is no *BSD partition on %s.\n"), disk_device);
1088 #elif defined (__alpha__)
1090 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
1091 if (xbsd_create_disklabel () == 0)
1092 exit ( EXIT_SUCCESS );
1098 switch (tolower (read_char (_("BSD disklabel command (m for help): ")))) {
1100 xbsd_delete_part ();
1103 xbsd_edit_disklabel ();
1106 xbsd_write_bootstrap ();
1115 xbsd_print_disklabel (0);
1119 exit ( EXIT_SUCCESS );
1123 xbsd_print_disklabel (1);
1126 xbsd_change_fstype ();
1132 xbsd_write_disklabel ();
1134 #if !defined (__alpha__)
1147 xbsd_delete_part (void)
1151 i = xbsd_get_part_index (xbsd_dlabel.d_npartitions);
1152 xbsd_dlabel.d_partitions[i].p_size = 0;
1153 xbsd_dlabel.d_partitions[i].p_offset = 0;
1154 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
1155 if (xbsd_dlabel.d_npartitions == i + 1)
1156 while (xbsd_dlabel.d_partitions[xbsd_dlabel.d_npartitions-1].p_size == 0)
1157 xbsd_dlabel.d_npartitions--;
1161 xbsd_new_part (void)
1167 if (!xbsd_check_new_partition (&i))
1170 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
1171 begin = get_start_sect(xbsd_part);
1172 end = begin + get_nr_sects(xbsd_part) - 1;
1175 end = xbsd_dlabel.d_secperunit - 1;
1178 snprintf (mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
1179 begin = read_int (bsd_cround (begin), bsd_cround (begin), bsd_cround (end),
1182 if (display_in_cyl_units)
1183 begin = (begin - 1) * xbsd_dlabel.d_secpercyl;
1185 snprintf (mesg, sizeof(mesg), _("Last %s or +size or +sizeM or +sizeK"),
1186 str_units(SINGULAR));
1187 end = read_int (bsd_cround (begin), bsd_cround (end), bsd_cround (end),
1188 bsd_cround (begin), mesg);
1190 if (display_in_cyl_units)
1191 end = end * xbsd_dlabel.d_secpercyl - 1;
1193 xbsd_dlabel.d_partitions[i].p_size = end - begin + 1;
1194 xbsd_dlabel.d_partitions[i].p_offset = begin;
1195 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
1199 xbsd_print_disklabel (int show_all) {
1200 struct xbsd_disklabel *lp = &xbsd_dlabel;
1201 struct xbsd_partition *pp;
1205 #if defined (__alpha__)
1206 printf("# %s:\n", disk_device);
1208 printf("# %s:\n", partname(disk_device, xbsd_part_index+1, 0));
1210 if ((unsigned) lp->d_type < BSD_DKMAXTYPES)
1211 printf(_("type: %s\n"), xbsd_dktypenames[lp->d_type]);
1213 printf(_("type: %d\n"), lp->d_type);
1214 printf(_("disk: %.*s\n"), (int) sizeof(lp->d_typename), lp->d_typename);
1215 printf(_("label: %.*s\n"), (int) sizeof(lp->d_packname), lp->d_packname);
1216 printf(_("flags:"));
1217 if (lp->d_flags & BSD_D_REMOVABLE)
1218 printf(_(" removable"));
1219 if (lp->d_flags & BSD_D_ECC)
1221 if (lp->d_flags & BSD_D_BADSECT)
1222 printf(_(" badsect"));
1224 /* On various machines the fields of *lp are short/int/long */
1225 /* In order to avoid problems, we cast them all to long. */
1226 printf(_("bytes/sector: %ld\n"), (long) lp->d_secsize);
1227 printf(_("sectors/track: %ld\n"), (long) lp->d_nsectors);
1228 printf(_("tracks/cylinder: %ld\n"), (long) lp->d_ntracks);
1229 printf(_("sectors/cylinder: %ld\n"), (long) lp->d_secpercyl);
1230 printf(_("cylinders: %ld\n"), (long) lp->d_ncylinders);
1231 printf(_("rpm: %d\n"), lp->d_rpm);
1232 printf(_("interleave: %d\n"), lp->d_interleave);
1233 printf(_("trackskew: %d\n"), lp->d_trackskew);
1234 printf(_("cylinderskew: %d\n"), lp->d_cylskew);
1235 printf(_("headswitch: %ld\t\t# milliseconds\n"),
1236 (long) lp->d_headswitch);
1237 printf(_("track-to-track seek: %ld\t# milliseconds\n"),
1238 (long) lp->d_trkseek);
1239 printf(_("drivedata: "));
1240 for (i = NDDATA - 1; i >= 0; i--)
1241 if (lp->d_drivedata[i])
1245 for (j = 0; j <= i; j++)
1246 printf("%ld ", (long) lp->d_drivedata[j]);
1248 printf(_("\n%d partitions:\n"), lp->d_npartitions);
1249 printf(_("# start end size fstype [fsize bsize cpg]\n"));
1250 pp = lp->d_partitions;
1251 for (i = 0; i < lp->d_npartitions; i++, pp++) {
1253 if (display_in_cyl_units && lp->d_secpercyl) {
1254 printf(" %c: %8ld%c %8ld%c %8ld%c ",
1256 (long) pp->p_offset / lp->d_secpercyl + 1,
1257 (pp->p_offset % lp->d_secpercyl) ? '*' : ' ',
1258 (long) (pp->p_offset + pp->p_size + lp->d_secpercyl - 1)
1260 ((pp->p_offset + pp->p_size) % lp->d_secpercyl) ? '*' : ' ',
1261 (long) pp->p_size / lp->d_secpercyl,
1262 (pp->p_size % lp->d_secpercyl) ? '*' : ' ');
1264 printf(" %c: %8ld %8ld %8ld ",
1266 (long) pp->p_offset,
1267 (long) pp->p_offset + pp->p_size - 1,
1270 if ((unsigned) pp->p_fstype < BSD_FSMAXTYPES)
1271 printf("%8.8s", xbsd_fstypes[pp->p_fstype].name);
1273 printf("%8x", pp->p_fstype);
1274 switch (pp->p_fstype) {
1276 printf(" %5ld %5ld %5.5s ",
1277 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, "");
1281 printf(" %5ld %5ld %5d ",
1282 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag,
1287 printf("%22.22s", "");
1296 xbsd_write_disklabel (void) {
1297 #if defined (__alpha__)
1298 printf (_("Writing disklabel to %s.\n"), disk_device);
1299 xbsd_writelabel (NULL, &xbsd_dlabel);
1301 printf (_("Writing disklabel to %s.\n"),
1302 partname(disk_device, xbsd_part_index+1, 0));
1303 xbsd_writelabel (xbsd_part, &xbsd_dlabel);
1305 reread_partition_table(0); /* no exit yet */
1309 xbsd_create_disklabel (void) {
1312 #if defined (__alpha__)
1313 fprintf (stderr, _("%s contains no disklabel.\n"), disk_device);
1315 fprintf (stderr, _("%s contains no disklabel.\n"),
1316 partname(disk_device, xbsd_part_index+1, 0));
1320 c = read_char (_("Do you want to create a disklabel? (y/n) "));
1321 if (c == 'y' || c == 'Y') {
1322 if (xbsd_initlabel (
1323 #if defined (__alpha__) || defined (__powerpc__) || defined (__hppa__)
1324 NULL, &xbsd_dlabel, 0
1326 xbsd_part, &xbsd_dlabel, xbsd_part_index
1329 xbsd_print_disklabel (1);
1333 } else if (c == 'n')
1339 edit_int (int def, char *mesg)
1342 fputs (mesg, stdout);
1343 printf (" (%d): ", def);
1347 while (!isdigit (*line_ptr));
1348 return atoi (line_ptr);
1352 xbsd_edit_disklabel (void)
1354 struct xbsd_disklabel *d;
1358 #if defined (__alpha__) || defined (__ia64__)
1359 d -> d_secsize = (u_long) edit_int ((u_long) d -> d_secsize ,_("bytes/sector"));
1360 d -> d_nsectors = (u_long) edit_int ((u_long) d -> d_nsectors ,_("sectors/track"));
1361 d -> d_ntracks = (u_long) edit_int ((u_long) d -> d_ntracks ,_("tracks/cylinder"));
1362 d -> d_ncylinders = (u_long) edit_int ((u_long) d -> d_ncylinders ,_("cylinders"));
1365 /* d -> d_secpercyl can be != d -> d_nsectors * d -> d_ntracks */
1368 d -> d_secpercyl = (u_long) edit_int ((u_long) d -> d_nsectors * d -> d_ntracks,
1369 _("sectors/cylinder"));
1370 if (d -> d_secpercyl <= d -> d_nsectors * d -> d_ntracks)
1373 printf (_("Must be <= sectors/track * tracks/cylinder (default).\n"));
1375 d -> d_rpm = (u_short) edit_int ((u_short) d -> d_rpm ,_("rpm"));
1376 d -> d_interleave = (u_short) edit_int ((u_short) d -> d_interleave,_("interleave"));
1377 d -> d_trackskew = (u_short) edit_int ((u_short) d -> d_trackskew ,_("trackskew"));
1378 d -> d_cylskew = (u_short) edit_int ((u_short) d -> d_cylskew ,_("cylinderskew"));
1379 d -> d_headswitch = (u_long) edit_int ((u_long) d -> d_headswitch ,_("headswitch"));
1380 d -> d_trkseek = (u_long) edit_int ((u_long) d -> d_trkseek ,_("track-to-track seek"));
1382 d -> d_secperunit = d -> d_secpercyl * d -> d_ncylinders;
1386 xbsd_get_bootstrap (char *path, void *ptr, int size)
1390 if ((fdb = open (path, O_RDONLY)) < 0)
1395 if (read (fdb, ptr, size) < 0)
1401 printf (" ... %s\n", path);
1409 printf (_("\nSyncing disks.\n"));
1415 xbsd_write_bootstrap (void)
1417 char *bootdir = BSD_LINUX_BOOTDIR;
1418 char path[MAXPATHLEN];
1420 struct xbsd_disklabel dl;
1424 if (xbsd_dlabel.d_type == BSD_DTYPE_SCSI)
1429 printf (_("Bootstrap: %sboot -> boot%s (%s): "),
1430 dkbasename, dkbasename, dkbasename);
1432 line_ptr[strlen (line_ptr)-1] = '\0';
1433 dkbasename = line_ptr;
1435 snprintf (path, sizeof(path), "%s/%sboot", bootdir, dkbasename);
1436 if (!xbsd_get_bootstrap (path, disklabelbuffer, (int) xbsd_dlabel.d_secsize))
1439 /* We need a backup of the disklabel (xbsd_dlabel might have changed). */
1440 d = &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE];
1441 bcopy (d, &dl, sizeof (struct xbsd_disklabel));
1443 /* The disklabel will be overwritten by 0's from bootxx anyway */
1444 bzero (d, sizeof (struct xbsd_disklabel));
1446 snprintf (path, sizeof(path), "%s/boot%s", bootdir, dkbasename);
1447 if (!xbsd_get_bootstrap (path, &disklabelbuffer[xbsd_dlabel.d_secsize],
1448 (int) xbsd_dlabel.d_bbsize - xbsd_dlabel.d_secsize))
1451 e = d + sizeof (struct xbsd_disklabel);
1452 for (p=d; p < e; p++)
1454 fprintf (stderr, _("Bootstrap overlaps with disk label!\n"));
1455 exit ( EXIT_FAILURE );
1458 bcopy (&dl, d, sizeof (struct xbsd_disklabel));
1460 #if defined (__powerpc__) || defined (__hppa__)
1462 #elif defined (__alpha__)
1464 alpha_bootblock_checksum (disklabelbuffer);
1466 sector = get_start_sect(xbsd_part);
1469 if (ext2_llseek (fd, (ext2_loff_t) sector * SECTOR_SIZE, SEEK_SET) == -1)
1470 fdisk_fatal (unable_to_seek);
1471 if (BSD_BBSIZE != write (fd, disklabelbuffer, BSD_BBSIZE))
1472 fdisk_fatal (unable_to_write);
1474 #if defined (__alpha__)
1475 printf (_("Bootstrap installed on %s.\n"), disk_device);
1477 printf (_("Bootstrap installed on %s.\n"),
1478 partname (disk_device, xbsd_part_index+1, 0));
1485 xbsd_change_fstype (void)
1489 i = xbsd_get_part_index (xbsd_dlabel.d_npartitions);
1490 xbsd_dlabel.d_partitions[i].p_fstype = read_hex (xbsd_fstypes);
1494 xbsd_get_part_index (int max)
1499 snprintf (prompt, sizeof(prompt), _("Partition (a-%c): "), 'a' + max - 1);
1501 l = tolower (read_char (prompt));
1502 while (l < 'a' || l > 'a' + max - 1);
1507 xbsd_check_new_partition (int *i) {
1509 /* room for more? various BSD flavours have different maxima */
1510 if (xbsd_dlabel.d_npartitions == BSD_MAXPARTITIONS) {
1513 for (t = 0; t < BSD_MAXPARTITIONS; t++)
1514 if (xbsd_dlabel.d_partitions[t].p_size == 0)
1517 if (t == BSD_MAXPARTITIONS) {
1518 fprintf (stderr, _("The maximum number of partitions "
1519 "has been created\n"));
1524 *i = xbsd_get_part_index (BSD_MAXPARTITIONS);
1526 if (*i >= xbsd_dlabel.d_npartitions)
1527 xbsd_dlabel.d_npartitions = (*i) + 1;
1529 if (xbsd_dlabel.d_partitions[*i].p_size != 0) {
1530 fprintf (stderr, _("This partition already exists.\n"));
1538 xbsd_list_types (void) {
1539 list_types (xbsd_fstypes);
1543 xbsd_dkcksum (struct xbsd_disklabel *lp) {
1544 u_short *start, *end;
1547 start = (u_short *) lp;
1548 end = (u_short *) &lp->d_partitions[lp->d_npartitions];
1555 xbsd_initlabel (struct partition *p, struct xbsd_disklabel *d, int pindex) {
1556 struct xbsd_partition *pp;
1559 bzero (d, sizeof (struct xbsd_disklabel));
1561 d -> d_magic = BSD_DISKMAGIC;
1563 if (strncmp (disk_device, "/dev/sd", 7) == 0)
1564 d -> d_type = BSD_DTYPE_SCSI;
1566 d -> d_type = BSD_DTYPE_ST506;
1568 #if 0 /* not used (at least not written to disk) by NetBSD/i386 1.0 */
1569 d -> d_subtype = BSD_DSTYPE_INDOSPART & pindex;
1572 #if !defined (__alpha__)
1573 d -> d_flags = BSD_D_DOSPART;
1577 d -> d_secsize = SECTOR_SIZE; /* bytes/sector */
1578 d -> d_nsectors = sectors; /* sectors/track */
1579 d -> d_ntracks = heads; /* tracks/cylinder (heads) */
1580 d -> d_ncylinders = cylinders;
1581 d -> d_secpercyl = sectors * heads;/* sectors/cylinder */
1582 if (d -> d_secpercyl == 0)
1583 d -> d_secpercyl = 1; /* avoid segfaults */
1584 d -> d_secperunit = d -> d_secpercyl * d -> d_ncylinders;
1587 d -> d_interleave = 1;
1588 d -> d_trackskew = 0;
1590 d -> d_headswitch = 0;
1593 d -> d_magic2 = BSD_DISKMAGIC;
1594 d -> d_bbsize = BSD_BBSIZE;
1595 d -> d_sbsize = BSD_SBSIZE;
1597 #if !defined (__alpha__)
1598 d -> d_npartitions = 4;
1599 pp = &d -> d_partitions[2]; /* Partition C should be
1600 the NetBSD partition */
1601 pp -> p_offset = get_start_sect(p);
1602 pp -> p_size = get_nr_sects(p);
1603 pp -> p_fstype = BSD_FS_UNUSED;
1604 pp = &d -> d_partitions[3]; /* Partition D should be
1607 pp -> p_size = d -> d_secperunit;
1608 pp -> p_fstype = BSD_FS_UNUSED;
1609 #elif defined (__alpha__)
1610 d -> d_npartitions = 3;
1611 pp = &d -> d_partitions[2]; /* Partition C should be
1614 pp -> p_size = d -> d_secperunit;
1615 pp -> p_fstype = BSD_FS_UNUSED;
1622 * Read a xbsd_disklabel from sector 0 or from the starting sector of p.
1623 * If it has the right magic, return 1.
1626 xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d)
1630 /* p is used only to get the starting sector */
1631 #if !defined (__alpha__)
1632 sector = (p ? get_start_sect(p) : 0);
1633 #elif defined (__alpha__)
1637 if (ext2_llseek (fd, (ext2_loff_t) sector * SECTOR_SIZE, SEEK_SET) == -1)
1638 fdisk_fatal (unable_to_seek);
1639 if (BSD_BBSIZE != read (fd, disklabelbuffer, BSD_BBSIZE))
1640 fdisk_fatal (unable_to_read);
1642 bcopy (&disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
1643 d, sizeof (struct xbsd_disklabel));
1645 if (d -> d_magic != BSD_DISKMAGIC || d -> d_magic2 != BSD_DISKMAGIC)
1648 for (t = d -> d_npartitions; t < BSD_MAXPARTITIONS; t++) {
1649 d -> d_partitions[t].p_size = 0;
1650 d -> d_partitions[t].p_offset = 0;
1651 d -> d_partitions[t].p_fstype = BSD_FS_UNUSED;
1654 if (d -> d_npartitions > BSD_MAXPARTITIONS)
1655 fprintf (stderr, _("Warning: too many partitions "
1656 "(%d, maximum is %d).\n"),
1657 d -> d_npartitions, BSD_MAXPARTITIONS);
1662 xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d)
1666 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
1667 sector = get_start_sect(p) + BSD_LABELSECTOR;
1669 sector = BSD_LABELSECTOR;
1672 d -> d_checksum = 0;
1673 d -> d_checksum = xbsd_dkcksum (d);
1675 /* This is necessary if we want to write the bootstrap later,
1676 otherwise we'd write the old disklabel with the bootstrap.
1678 bcopy (d, &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
1679 sizeof (struct xbsd_disklabel));
1681 #if defined (__alpha__) && BSD_LABELSECTOR == 0
1682 alpha_bootblock_checksum (disklabelbuffer);
1683 if (ext2_llseek (fd, (ext2_loff_t) 0, SEEK_SET) == -1)
1684 fdisk_fatal (unable_to_seek);
1685 if (BSD_BBSIZE != write (fd, disklabelbuffer, BSD_BBSIZE))
1686 fdisk_fatal (unable_to_write);
1688 if (ext2_llseek (fd, (ext2_loff_t) sector * SECTOR_SIZE + BSD_LABELOFFSET,
1690 fdisk_fatal (unable_to_seek);
1691 if (sizeof (struct xbsd_disklabel) != write (fd, d, sizeof (struct xbsd_disklabel)))
1692 fdisk_fatal (unable_to_write);
1701 #if !defined (__alpha__)
1703 xbsd_translate_fstype (int linux_type)
1707 case 0x01: /* DOS 12-bit FAT */
1708 case 0x04: /* DOS 16-bit <32M */
1709 case 0x06: /* DOS 16-bit >=32M */
1710 case 0xe1: /* DOS access */
1711 case 0xe3: /* DOS R/O */
1712 case 0xf2: /* DOS secondary */
1713 return BSD_FS_MSDOS;
1714 case 0x07: /* OS/2 HPFS */
1717 return BSD_FS_OTHER;
1722 xbsd_link_part (void)
1725 struct partition *p;
1727 k = get_partition (1, partitions);
1729 if (!xbsd_check_new_partition (&i))
1732 p = get_part_table(k);
1734 xbsd_dlabel.d_partitions[i].p_size = get_nr_sects(p);
1735 xbsd_dlabel.d_partitions[i].p_offset = get_start_sect(p);
1736 xbsd_dlabel.d_partitions[i].p_fstype = xbsd_translate_fstype(p->sys_ind);
1740 #if defined (__alpha__)
1742 #if !defined(__GLIBC__)
1743 typedef unsigned long long u_int64_t;
1747 alpha_bootblock_checksum (char *boot)
1752 dp = (u_int64_t *)boot;
1754 for (i = 0; i < 63; i++)
1758 #endif /* __alpha__ */
1760 #endif /* OSF_LABEL */
1762 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
1763 static inline unsigned short
1764 __swap16(unsigned short x) {
1765 return (((uint16_t)(x) & 0xFF) << 8) | (((uint16_t)(x) & 0xFF00) >> 8);
1768 static inline uint32_t
1769 __swap32(uint32_t x) {
1770 return (((uint32_t)(x) & 0xFF) << 24) | (((uint32_t)(x) & 0xFF00) << 8) | (((uint32_t)(x) & 0xFF0000) >> 8) | (((uint32_t)(x) & 0xFF000000) >> 24);
1774 #ifdef CONFIG_FEATURE_SGI_LABEL
1779 * Copyright (C) Andreas Neuper, Sep 1998.
1780 * This file may be modified and redistributed under
1781 * the terms of the GNU Public License.
1783 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
1784 * Internationalization
1788 static int sgi_other_endian;
1790 static short sgi_volumes=1;
1793 * only dealing with free blocks here
1796 typedef struct { int first; int last; } freeblocks;
1797 static freeblocks freelist[17]; /* 16 partitions can produce 17 vacant slots */
1800 setfreelist( int i, int f, int l ) {
1801 freelist[i].first = f;
1802 freelist[i].last = l;
1806 add2freelist( int f, int l ) {
1808 for( ; i<17 ; i++ ) {
1809 if(freelist[i].last==0) break;
1811 setfreelist( i, f, l );
1815 clearfreelist(void) {
1817 for( ; i<17 ; i++ ) {
1818 setfreelist( i, 0, 0 );
1823 isinfreelist( int b ) {
1825 for( ; i<17 ; i++ ) {
1826 if (freelist[i].first <= b && freelist[i].last >= b) {
1827 return freelist[i].last;
1832 /* return last vacant block of this stride (never 0). */
1833 /* the '>=' is not quite correct, but simplifies the code */
1835 * end of free blocks section
1838 static const struct systypes sgi_sys_types[] = {
1839 /* SGI_VOLHDR */ {"\x00" "SGI volhdr" },
1840 /* 0x01 */ {"\x01" "SGI trkrepl" },
1841 /* 0x02 */ {"\x02" "SGI secrepl" },
1842 /* SGI_SWAP */ {"\x03" "SGI raw" },
1843 /* 0x04 */ {"\x04" "SGI bsd" },
1844 /* 0x05 */ {"\x05" "SGI sysv" },
1845 /* ENTIRE_DISK */ {"\x06" "SGI volume" },
1846 /* SGI_EFS */ {"\x07" "SGI efs" },
1847 /* 0x08 */ {"\x08" "SGI lvol" },
1848 /* 0x09 */ {"\x09" "SGI rlvol" },
1849 /* SGI_XFS */ {"\x0a" "SGI xfs" },
1850 /* SGI_XFSLOG */ {"\x0b" "SGI xfslog" },
1851 /* SGI_XLV */ {"\x0c" "SGI xlv" },
1852 /* SGI_XVM */ {"\x0d" "SGI xvm" },
1853 /* LINUX_SWAP */ {"\x82" "Linux swap" },
1854 /* LINUX_NATIVE */ {"\x83" "Linux native" },
1855 /* LINUX_LVM */ {"\x8d" "Linux LVM" },
1856 /* LINUX_RAID */ {"\xfd" "Linux RAID" },
1862 sgi_get_nsect(void) {
1863 return SGI_SSWAP16(sgilabel->devparam.nsect);
1867 sgi_get_ntrks(void) {
1868 return SGI_SSWAP16(sgilabel->devparam.ntrks);
1872 sgi_get_pcylcount(void) {
1873 return SGI_SSWAP16(sgilabel->devparam.pcylcount);
1878 sgilabel->magic = 0;
1884 two_s_complement_32bit_sum(unsigned int* base, int size /* in bytes */ ) {
1888 size = size / sizeof( unsigned int );
1889 for( i=0; i<size; i++ )
1890 sum = sum - SGI_SSWAP32(base[i]);
1895 check_sgi_label(void) {
1896 if (sizeof(sgilabel) > 512) {
1898 _("According to MIPS Computer Systems, Inc the "
1899 "Label must not contain more than 512 bytes\n"));
1903 if (sgilabel->magic != SGI_LABEL_MAGIC &&
1904 sgilabel->magic != SGI_LABEL_MAGIC_SWAPPED) {
1906 sgi_other_endian = 0;
1910 sgi_other_endian = (sgilabel->magic == SGI_LABEL_MAGIC_SWAPPED);
1912 * test for correct checksum
1914 if( two_s_complement_32bit_sum( (unsigned int*)sgilabel,
1915 sizeof(*sgilabel) ) )
1917 fprintf( stderr, _("Detected sgi disklabel with wrong checksum.\n"));
1920 heads = sgi_get_ntrks();
1921 cylinders = sgi_get_pcylcount();
1922 sectors = sgi_get_nsect();
1932 sgi_get_start_sector( int i ) {
1933 return SGI_SSWAP32(sgilabel->partitions[i].start_sector);
1937 sgi_get_num_sectors( int i ) {
1938 return SGI_SSWAP32(sgilabel->partitions[i].num_sectors);
1942 sgi_get_sysid( int i )
1944 return SGI_SSWAP32(sgilabel->partitions[i].id);
1948 sgi_get_bootpartition(void)
1950 return SGI_SSWAP16(sgilabel->boot_part);
1954 sgi_get_swappartition(void)
1956 return SGI_SSWAP16(sgilabel->swap_part);
1960 sgi_list_table( int xtra ) {
1962 int kpi = 0; /* kernel partition ID */
1964 w = strlen( disk_device );
1967 printf(_("\nDisk %s (SGI disk label): %d heads, %d sectors\n"
1968 "%d cylinders, %d physical cylinders\n"
1969 "%d extra sects/cyl, interleave %d:1\n"
1971 "Units = %s of %d * 512 bytes\n\n"),
1972 disk_device, heads, sectors, cylinders,
1973 SGI_SSWAP16(sgiparam.pcylcount),
1974 SGI_SSWAP16(sgiparam.sparecyl),
1975 SGI_SSWAP16(sgiparam.ilfact),
1977 str_units(PLURAL), units_per_sector);
1979 printf( _("\nDisk %s (SGI disk label): "
1980 "%d heads, %d sectors, %d cylinders\n"
1981 "Units = %s of %d * 512 bytes\n\n"),
1982 disk_device, heads, sectors, cylinders,
1983 str_units(PLURAL), units_per_sector );
1985 printf(_("----- partitions -----\n"
1986 "Pt# %*s Info Start End Sectors Id System\n"),
1987 w + 1, _("Device"));
1988 for (i = 0 ; i < partitions; i++) {
1989 if( sgi_get_num_sectors(i) || debug ) {
1990 uint32_t start = sgi_get_start_sector(i);
1991 uint32_t len = sgi_get_num_sectors(i);
1992 kpi++; /* only count nonempty partitions */
1994 "%2d: %s %4s %9ld %9ld %9ld %2x %s\n",
1995 /* fdisk part number */ i+1,
1996 /* device */ partname(disk_device, kpi, w+2),
1997 /* flags */ (sgi_get_swappartition() == i) ? "swap" :
1998 /* flags */ (sgi_get_bootpartition() == i) ? "boot" : " ",
1999 /* start */ (long) scround(start),
2000 /* end */ (long) scround(start+len)-1,
2001 /* no odd flag on end */ (long) len,
2002 /* type id */ sgi_get_sysid(i),
2003 /* type name */ partition_type(sgi_get_sysid(i)));
2006 printf(_("----- Bootinfo -----\nBootfile: %s\n"
2007 "----- Directory Entries -----\n"),
2008 sgilabel->boot_file );
2009 for (i = 0 ; i < sgi_volumes; i++)
2011 if (sgilabel->directory[i].vol_file_size)
2013 uint32_t start = SGI_SSWAP32(sgilabel->directory[i].vol_file_start);
2014 uint32_t len = SGI_SSWAP32(sgilabel->directory[i].vol_file_size);
2015 char*name = sgilabel->directory[i].vol_file_name;
2016 printf(_("%2d: %-10s sector%5u size%8u\n"),
2017 i, name, (unsigned int) start, (unsigned int) len);
2023 sgi_set_bootpartition( int i )
2025 sgilabel->boot_part = SGI_SSWAP16(((short)i));
2029 sgi_get_lastblock(void) {
2030 return heads * sectors * cylinders;
2034 sgi_set_swappartition( int i ) {
2035 sgilabel->swap_part = SGI_SSWAP16(((short)i));
2039 sgi_check_bootfile( const char* aFile ) {
2040 if( strlen( aFile ) < 3 ) /* "/a\n" is minimum */
2042 printf( _("\nInvalid Bootfile!\n"
2043 "\tThe bootfile must be an absolute non-zero pathname,\n"
2044 "\te.g. \"/unix\" or \"/unix.save\".\n") );
2047 if( strlen( aFile ) > 16 )
2049 printf( _("\n\tName of Bootfile too long: 16 bytes maximum.\n") );
2052 if( aFile[0] != '/' )
2054 printf( _("\n\tBootfile must have a fully qualified pathname.\n") );
2057 if( strncmp( aFile, sgilabel->boot_file, 16 ) )
2059 printf( _("\n\tBe aware, that the bootfile is not checked for existence.\n\t"
2060 "SGI's default is \"/unix\" and for backup \"/unix.save\".\n") );
2061 /* filename is correct and did change */
2064 return 0; /* filename did not change */
2068 sgi_get_bootfile(void) {
2069 return sgilabel->boot_file;
2073 sgi_set_bootfile( const char* aFile )
2076 if( sgi_check_bootfile( aFile ) )
2080 if( (aFile[i] != '\n') /* in principle caught again by next line */
2081 && (strlen( aFile ) > i ) )
2082 sgilabel->boot_file[i] = aFile[i];
2084 sgilabel->boot_file[i] = 0;
2087 printf( _("\n\tBootfile is changed to \"%s\".\n"), sgilabel->boot_file );
2092 create_sgiinfo(void)
2094 /* I keep SGI's habit to write the sgilabel to the second block */
2095 sgilabel->directory[0].vol_file_start = SGI_SSWAP32( 2 );
2096 sgilabel->directory[0].vol_file_size = SGI_SSWAP32( sizeof( sgiinfo ) );
2097 strncpy( sgilabel->directory[0].vol_file_name, "sgilabel", 8 );
2100 static sgiinfo * fill_sgiinfo(void);
2103 sgi_write_table(void)
2106 sgilabel->csum = SGI_SSWAP32( two_s_complement_32bit_sum(
2107 (unsigned int*)sgilabel,
2108 sizeof(*sgilabel) ) );
2109 assert( two_s_complement_32bit_sum(
2110 (unsigned int*)sgilabel, sizeof(*sgilabel) ) == 0 );
2111 if( lseek(fd, 0, SEEK_SET) < 0 )
2112 fdisk_fatal(unable_to_seek);
2113 if( write(fd, sgilabel, SECTOR_SIZE) != SECTOR_SIZE )
2114 fdisk_fatal(unable_to_write);
2115 if( ! strncmp( sgilabel->directory[0].vol_file_name, "sgilabel",8 ) )
2118 * keep this habbit of first writing the "sgilabel".
2119 * I never tested whether it works without (AN 981002).
2121 sgiinfo*info = fill_sgiinfo(); /* fills the block appropriately */
2122 int infostartblock = SGI_SSWAP32( sgilabel->directory[0].vol_file_start );
2123 if( ext2_llseek(fd, (ext2_loff_t)infostartblock*
2124 SECTOR_SIZE, SEEK_SET) < 0 )
2125 fdisk_fatal(unable_to_seek);
2126 if( write(fd, info, SECTOR_SIZE) != SECTOR_SIZE )
2127 fdisk_fatal(unable_to_write);
2133 compare_start( int *x, int *y ) {
2135 * sort according to start sectors
2136 * and prefers largest partition:
2137 * entry zero is entire disk entry
2141 int a = sgi_get_start_sector(i);
2142 int b = sgi_get_start_sector(j);
2143 int c = sgi_get_num_sectors(i);
2144 int d = sgi_get_num_sectors(j);
2154 verify_sgi( int verbose )
2156 int Index[16]; /* list of valid partitions */
2157 int sortcount = 0; /* number of used partitions, i.e. non-zero lengths */
2158 int entire = 0, i = 0; /* local counters */
2160 int gap = 0; /* count unused blocks */
2161 int lastblock = sgi_get_lastblock();
2165 for( i=0; i<16; i++ )
2167 if( sgi_get_num_sectors(i)!=0 )
2169 Index[sortcount++]=i;
2170 if( sgi_get_sysid(i) == ENTIRE_DISK )
2175 printf(_("More than one entire disk entry present.\n"));
2180 if( sortcount == 0 )
2183 printf(_("No partitions defined\n"));
2186 qsort( Index, sortcount, sizeof(Index[0]), (void*)compare_start );
2187 if( sgi_get_sysid( Index[0] ) == ENTIRE_DISK )
2189 if( ( Index[0] != 10 ) && verbose )
2190 printf( _("IRIX likes when Partition 11 covers the entire disk.\n") );
2191 if( ( sgi_get_start_sector( Index[0] ) != 0 ) && verbose )
2192 printf( _("The entire disk partition should start at block 0,\nnot "
2193 "at diskblock %d.\n"), sgi_get_start_sector(Index[0] ) );
2194 if(debug) /* I do not understand how some disks fulfil it */
2195 if( ( sgi_get_num_sectors( Index[0] ) != lastblock ) && verbose )
2196 printf( _("The entire disk partition is only %d diskblock large,\n"
2197 "but the disk is %d diskblocks long.\n"),
2198 sgi_get_num_sectors( Index[0] ), lastblock );
2199 lastblock = sgi_get_num_sectors( Index[0] );
2203 printf( _("One Partition (#11) should cover the entire disk.\n") );
2205 printf( "sysid=%d\tpartition=%d\n",
2206 sgi_get_sysid( Index[0] ), Index[0]+1 );
2208 for( i=1, start=0; i<sortcount; i++ )
2210 int cylsize = sgi_get_nsect() * sgi_get_ntrks();
2211 if( (sgi_get_start_sector( Index[i] ) % cylsize) != 0 )
2213 if(debug) /* I do not understand how some disks fulfil it */
2215 printf( _("Partition %d does not start on cylinder boundary.\n"),
2218 if( sgi_get_num_sectors( Index[i] ) % cylsize != 0 )
2220 if(debug) /* I do not understand how some disks fulfil it */
2222 printf( _("Partition %d does not end on cylinder boundary.\n"),
2225 /* We cannot handle several "entire disk" entries. */
2226 if( sgi_get_sysid( Index[i] ) == ENTIRE_DISK ) continue;
2227 if( start > sgi_get_start_sector( Index[i] ) )
2230 printf( _("The Partition %d and %d overlap by %d sectors.\n"),
2231 Index[i-1]+1, Index[i]+1,
2232 start - sgi_get_start_sector( Index[i] ) );
2233 if( gap > 0 ) gap = -gap;
2234 if( gap == 0 ) gap = -1;
2236 if( start < sgi_get_start_sector( Index[i] ) )
2239 printf( _("Unused gap of %8d sectors - sectors %8d-%d\n"),
2240 sgi_get_start_sector( Index[i] ) - start,
2241 start, sgi_get_start_sector( Index[i] )-1 );
2242 gap += sgi_get_start_sector( Index[i] ) - start;
2243 add2freelist( start, sgi_get_start_sector( Index[i] ) );
2245 start = sgi_get_start_sector( Index[i] )
2246 + sgi_get_num_sectors( Index[i] );
2250 printf( "%2d:%12d\t%12d\t%12d\n", Index[i],
2251 sgi_get_start_sector(Index[i]),
2252 sgi_get_num_sectors(Index[i]),
2253 sgi_get_sysid(Index[i]) );
2256 if( ( start < lastblock ) )
2259 printf( _("Unused gap of %8d sectors - sectors %8d-%d\n"),
2260 lastblock - start, start, lastblock-1 );
2261 gap += lastblock - start;
2262 add2freelist( start, lastblock );
2265 * Done with arithmetics
2266 * Go for details now
2270 if( !sgi_get_num_sectors( sgi_get_bootpartition() ) )
2272 printf( _("\nThe boot partition does not exist.\n") );
2274 if( !sgi_get_num_sectors( sgi_get_swappartition() ) )
2276 printf( _("\nThe swap partition does not exist.\n") );
2278 if( ( sgi_get_sysid( sgi_get_swappartition() ) != SGI_SWAP )
2279 && ( sgi_get_sysid( sgi_get_swappartition() ) != LINUX_SWAP ) )
2281 printf( _("\nThe swap partition has no swap type.\n") );
2283 if( sgi_check_bootfile( "/unix" ) )
2285 printf( _("\tYou have chosen an unusual boot file name.\n") );
2294 * returned value is:
2295 * = 0 : disk is properly filled to the rim
2296 * < 0 : there is an overlap
2297 * > 0 : there is still some vacant space
2299 return verify_sgi(0);
2303 sgi_change_sysid( int i, int sys )
2305 if( sgi_get_num_sectors(i) == 0 ) /* caught already before, ... */
2307 printf(_("Sorry You may change the Tag of non-empty partitions.\n"));
2310 if( ((sys != ENTIRE_DISK ) && (sys != SGI_VOLHDR))
2311 && (sgi_get_start_sector(i)<1) )
2314 _("It is highly recommended that the partition at offset 0\n"
2315 "is of type \"SGI volhdr\", the IRIX system will rely on it to\n"
2316 "retrieve from its directory standalone tools like sash and fx.\n"
2317 "Only the \"SGI volume\" entire disk section may violate this.\n"
2318 "Type YES if you are sure about tagging this partition differently.\n"));
2319 if (strcmp (line_ptr, _("YES\n")))
2322 sgilabel->partitions[i].id = SGI_SSWAP32(sys);
2325 /* returns partition index of first entry marked as entire disk */
2329 for( i=0; i<16; i++ )
2330 if( sgi_get_sysid(i) == SGI_VOLUME )
2336 sgi_set_partition( int i, uint start, uint length, int sys ) {
2337 sgilabel->partitions[i].id =
2339 sgilabel->partitions[i].num_sectors =
2340 SGI_SSWAP32( length );
2341 sgilabel->partitions[i].start_sector =
2342 SGI_SSWAP32( start );
2344 if( sgi_gaps() < 0 ) /* rebuild freelist */
2345 printf(_("Do You know, You got a partition overlap on the disk?\n"));
2349 sgi_set_entire(void) {
2351 for( n=10; n<partitions; n++ ) {
2352 if(!sgi_get_num_sectors( n ) ) {
2353 sgi_set_partition( n, 0, sgi_get_lastblock(), SGI_VOLUME );
2360 sgi_set_volhdr(void)
2363 for( n=8; n<partitions; n++ )
2365 if(!sgi_get_num_sectors( n ) )
2368 * 5 cylinders is an arbitrary value I like
2369 * IRIX 5.3 stored files in the volume header
2370 * (like sash, symmon, fx, ide) with ca. 3200
2373 if( heads * sectors * 5 < sgi_get_lastblock() )
2374 sgi_set_partition( n, 0, heads * sectors * 5, SGI_VOLHDR );
2381 sgi_delete_partition( int i )
2383 sgi_set_partition( i, 0, 0, 0 );
2387 sgi_add_partition( int n, int sys )
2390 int first=0, last=0;
2394 } else if ( n == 8 ) {
2397 if( sgi_get_num_sectors(n) )
2399 printf(_("Partition %d is already defined. Delete "
2400 "it before re-adding it.\n"), n + 1);
2403 if( (sgi_entire() == -1)
2404 && (sys != SGI_VOLUME) )
2406 printf(_("Attempting to generate entire disk entry automatically.\n"));
2410 if( (sgi_gaps() == 0)
2411 && (sys != SGI_VOLUME) )
2413 printf(_("The entire disk is already covered with partitions.\n"));
2416 if( sgi_gaps() < 0 )
2418 printf(_("You got a partition overlap on the disk. Fix it first!\n"));
2421 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
2423 if(sys == SGI_VOLUME) {
2424 last = sgi_get_lastblock();
2425 first = read_int(0, 0, last-1, 0, mesg);
2427 printf(_("It is highly recommended that eleventh partition\n"
2428 "covers the entire disk and is of type `SGI volume'\n"));
2431 first = freelist[0].first;
2432 last = freelist[0].last;
2433 first = read_int(scround(first), scround(first), scround(last)-1,
2436 if (display_in_cyl_units)
2437 first *= units_per_sector;
2439 first = first; /* align to cylinder if you know how ... */
2441 last = isinfreelist(first);
2443 printf(_("You will get a partition overlap on the disk. "
2444 "Fix it first!\n"));
2448 snprintf(mesg, sizeof(mesg), _(" Last %s"), str_units(SINGULAR));
2449 last = read_int(scround(first), scround(last)-1, scround(last)-1,
2450 scround(first), mesg)+1;
2451 if (display_in_cyl_units)
2452 last *= units_per_sector;
2454 last = last; /* align to cylinder if You know how ... */
2455 if( (sys == SGI_VOLUME) && ( first != 0 || last != sgi_get_lastblock() ) )
2456 printf(_("It is highly recommended that eleventh partition\n"
2457 "covers the entire disk and is of type `SGI volume'\n"));
2458 sgi_set_partition( n, first, last-first, sys );
2462 create_sgilabel(void)
2464 struct hd_geometry geometry;
2467 int sysid; } old[4];
2470 _("Building a new SGI disklabel. Changes will remain in memory only,\n"
2471 "until you decide to write them. After that, of course, the previous\n"
2472 "content will be unrecoverably lost.\n\n"));
2474 sgi_other_endian = (BYTE_ORDER == LITTLE_ENDIAN);
2477 if (!ioctl(fd, HDIO_REQ, &geometry))
2479 if (!ioctl(fd, HDIO_GETGEO, &geometry))
2482 heads = geometry.heads;
2483 sectors = geometry.sectors;
2484 cylinders = geometry.cylinders;
2486 for (i = 0; i < 4; i++)
2489 if( valid_part_table_flag(MBRbuffer) )
2491 if( get_part_table(i)->sys_ind )
2493 old[i].sysid = get_part_table(i)->sys_ind;
2494 old[i].start = get_start_sect( get_part_table(i) );
2495 old[i].nsect = get_nr_sects( get_part_table(i) );
2496 printf( _("Trying to keep parameters of partition %d.\n"), i );
2498 printf( _("ID=%02x\tSTART=%d\tLENGTH=%d\n"),
2499 old[i].sysid, old[i].start, old[i].nsect );
2503 memset(MBRbuffer, 0, sizeof(MBRbuffer));
2504 sgilabel->magic = SGI_SSWAP32(SGI_LABEL_MAGIC);
2505 sgilabel->boot_part = SGI_SSWAP16(0);
2506 sgilabel->swap_part = SGI_SSWAP16(1);
2508 /* sizeof(sgilabel->boot_file) = 16 > 6 */
2509 memset(sgilabel->boot_file, 0, 16);
2510 strcpy(sgilabel->boot_file, "/unix");
2512 sgilabel->devparam.skew = (0);
2513 sgilabel->devparam.gap1 = (0);
2514 sgilabel->devparam.gap2 = (0);
2515 sgilabel->devparam.sparecyl = (0);
2516 sgilabel->devparam.pcylcount = SGI_SSWAP16(geometry.cylinders);
2517 sgilabel->devparam.head_vol0 = SGI_SSWAP16(0);
2518 sgilabel->devparam.ntrks = SGI_SSWAP16(geometry.heads);
2519 /* tracks/cylinder (heads) */
2520 sgilabel->devparam.cmd_tag_queue_depth = (0);
2521 sgilabel->devparam.unused0 = (0);
2522 sgilabel->devparam.unused1 = SGI_SSWAP16(0);
2523 sgilabel->devparam.nsect = SGI_SSWAP16(geometry.sectors);
2525 sgilabel->devparam.bytes = SGI_SSWAP16(512);
2526 sgilabel->devparam.ilfact = SGI_SSWAP16(1);
2527 sgilabel->devparam.flags = SGI_SSWAP32(TRACK_FWD|
2528 IGNORE_ERRORS|RESEEK);
2529 sgilabel->devparam.datarate = SGI_SSWAP32(0);
2530 sgilabel->devparam.retries_on_error = SGI_SSWAP32(1);
2531 sgilabel->devparam.ms_per_word = SGI_SSWAP32(0);
2532 sgilabel->devparam.xylogics_gap1 = SGI_SSWAP16(0);
2533 sgilabel->devparam.xylogics_syncdelay = SGI_SSWAP16(0);
2534 sgilabel->devparam.xylogics_readdelay = SGI_SSWAP16(0);
2535 sgilabel->devparam.xylogics_gap2 = SGI_SSWAP16(0);
2536 sgilabel->devparam.xylogics_readgate = SGI_SSWAP16(0);
2537 sgilabel->devparam.xylogics_writecont = SGI_SSWAP16(0);
2538 memset( &(sgilabel->directory), 0, sizeof(struct volume_directory)*15 );
2539 memset( &(sgilabel->partitions), 0, sizeof(struct sgi_partition)*16 );
2545 for (i = 0; i < 4; i++)
2549 sgi_set_partition( i, old[i].start, old[i].nsect, old[i].sysid );
2557 /* do nothing in the beginning */
2560 /* _____________________________________________________________
2566 sgiinfo*info=calloc( 1, sizeof(sgiinfo) );
2567 info->magic=SGI_SSWAP32(SGI_INFO_MAGIC);
2568 info->b1=SGI_SSWAP32(-1);
2569 info->b2=SGI_SSWAP16(-1);
2570 info->b3=SGI_SSWAP16(1);
2571 /* You may want to replace this string !!!!!!! */
2572 strcpy( info->scsi_string, "IBM OEM 0662S12 3 30" );
2573 strcpy( info->serial, "0000" );
2574 info->check1816 = SGI_SSWAP16(18*256 +16 );
2575 strcpy( info->installer, "Sfx version 5.3, Oct 18, 1994" );
2578 #endif /* SGI_LABEL */
2581 #ifdef CONFIG_FEATURE_SUN_LABEL
2585 * I think this is mostly, or entirely, due to
2586 * Jakub Jelinek (jj@sunsite.mff.cuni.cz), July 1996
2588 * Merged with fdisk for other architectures, aeb, June 1998.
2590 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
2591 * Internationalization
2595 static int sun_other_endian;
2596 static int scsi_disk;
2600 #define IDE0_MAJOR 3
2603 #define IDE1_MAJOR 22
2605 static void guess_device_type(void) {
2606 struct stat bootstat;
2608 if (fstat (fd, &bootstat) < 0) {
2611 } else if (S_ISBLK(bootstat.st_mode)
2612 && ((bootstat.st_rdev >> 8) == IDE0_MAJOR ||
2613 (bootstat.st_rdev >> 8) == IDE1_MAJOR)) {
2616 } else if (S_ISBLK(bootstat.st_mode)
2617 && (bootstat.st_rdev >> 8) == FLOPPY_MAJOR) {
2626 static const struct systypes sun_sys_types[] = {
2627 /* 0 */ {"\x00" "Empty" },
2628 /* 1 */ {"\x01" "Boot" },
2629 /* 2 */ {"\x02" "SunOS root" },
2630 /* SUNOS_SWAP */ {"\x03" "SunOS swap" },
2631 /* 4 */ {"\x04" "SunOS usr" },
2632 /* WHOLE_DISK */ {"\x05" "Whole disk" },
2633 /* 6 */ {"\x06" "SunOS stand" },
2634 /* 7 */ {"\x07" "SunOS var" },
2635 /* 8 */ {"\x08" "SunOS home" },
2636 /* LINUX_SWAP */ {"\x82" "Linux swap" },
2637 /* LINUX_NATIVE */ {"\x83" "Linux native" },
2638 /* 0x8e */ {"\x8e" "Linux LVM" },
2639 /* New (2.2.x) raid partition with autodetect using persistent superblock */
2640 /* 0xfd */ {"\xfd" "Linux raid autodetect" },
2646 set_sun_partition(int i, uint start, uint stop, int sysid) {
2647 sunlabel->infos[i].id = sysid;
2648 sunlabel->partitions[i].start_cylinder =
2649 SUN_SSWAP32(start / (heads * sectors));
2650 sunlabel->partitions[i].num_sectors =
2651 SUN_SSWAP32(stop - start);
2658 sunlabel->magic = 0;
2663 check_sun_label(void) {
2664 unsigned short *ush;
2667 if (sunlabel->magic != SUN_LABEL_MAGIC &&
2668 sunlabel->magic != SUN_LABEL_MAGIC_SWAPPED) {
2670 sun_other_endian = 0;
2673 sun_other_endian = (sunlabel->magic == SUN_LABEL_MAGIC_SWAPPED);
2674 ush = ((unsigned short *) (sunlabel + 1)) - 1;
2675 for (csum = 0; ush >= (unsigned short *)sunlabel;) csum ^= *ush--;
2677 fprintf(stderr,_("Detected sun disklabel with wrong checksum.\n"
2678 "Probably you'll have to set all the values,\n"
2679 "e.g. heads, sectors, cylinders and partitions\n"
2680 "or force a fresh label (s command in main menu)\n"));
2682 heads = SUN_SSWAP16(sunlabel->ntrks);
2683 cylinders = SUN_SSWAP16(sunlabel->ncyl);
2684 sectors = SUN_SSWAP16(sunlabel->nsect);
2692 static const struct sun_predefined_drives {
2695 unsigned short sparecyl;
2696 unsigned short ncyl;
2697 unsigned short nacyl;
2698 unsigned short pcylcount;
2699 unsigned short ntrks;
2700 unsigned short nsect;
2701 unsigned short rspeed;
2703 {"Quantum","ProDrive 80S",1,832,2,834,6,34,3662},
2704 {"Quantum","ProDrive 105S",1,974,2,1019,6,35,3662},
2705 {"CDC","Wren IV 94171-344",3,1545,2,1549,9,46,3600},
2706 {"IBM","DPES-31080",0,4901,2,4903,4,108,5400},
2707 {"IBM","DORS-32160",0,1015,2,1017,67,62,5400},
2708 {"IBM","DNES-318350",0,11199,2,11474,10,320,7200},
2709 {"SEAGATE","ST34371",0,3880,2,3882,16,135,7228},
2710 {"","SUN0104",1,974,2,1019,6,35,3662},
2711 {"","SUN0207",4,1254,2,1272,9,36,3600},
2712 {"","SUN0327",3,1545,2,1549,9,46,3600},
2713 {"","SUN0340",0,1538,2,1544,6,72,4200},
2714 {"","SUN0424",2,1151,2,2500,9,80,4400},
2715 {"","SUN0535",0,1866,2,2500,7,80,5400},
2716 {"","SUN0669",5,1614,2,1632,15,54,3600},
2717 {"","SUN1.0G",5,1703,2,1931,15,80,3597},
2718 {"","SUN1.05",0,2036,2,2038,14,72,5400},
2719 {"","SUN1.3G",6,1965,2,3500,17,80,5400},
2720 {"","SUN2.1G",0,2733,2,3500,19,80,5400},
2721 {"IOMEGA","Jaz",0,1019,2,1021,64,32,5394},
2724 static const struct sun_predefined_drives *
2725 sun_autoconfigure_scsi(void) {
2726 const struct sun_predefined_drives *p = NULL;
2728 #ifdef SCSI_IOCTL_GET_IDLUN
2738 if (!ioctl(fd, SCSI_IOCTL_GET_IDLUN, &id)) {
2740 "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n",
2742 ((id[0]>>24)&0xff)-/*PROC_SCSI_SCSI+PROC_SCSI_FILE*/33,
2744 /* This is very wrong (works only if you have one HBA),
2745 but I haven't found a way how to get hostno
2746 from the current kernel */
2752 pfd = fopen("/proc/scsi/scsi","r");
2754 while (fgets(buffer2,2048,pfd)) {
2755 if (!strcmp(buffer, buffer2)) {
2756 if (fgets(buffer2,2048,pfd)) {
2757 q = strstr(buffer2,"Vendor: ");
2762 *q++ = 0; /* truncate vendor name */
2763 q = strstr(q,"Model: ");
2768 q = strstr(q," Rev: ");
2771 for (i = 0; i < SIZE(sun_drives); i++) {
2772 if (*sun_drives[i].vendor && strcasecmp(sun_drives[i].vendor, vendor))
2774 if (!strstr(model, sun_drives[i].model))
2776 printf(_("Autoconfigure found a %s%s%s\n"),sun_drives[i].vendor,(*sun_drives[i].vendor) ? " " : "",sun_drives[i].model);
2794 static void create_sunlabel(void)
2796 struct hd_geometry geometry;
2800 const struct sun_predefined_drives *p = NULL;
2803 _("Building a new sun disklabel. Changes will remain in memory only,\n"
2804 "until you decide to write them. After that, of course, the previous\n"
2805 "content won't be recoverable.\n\n"));
2806 #if BYTE_ORDER == LITTLE_ENDIAN
2807 sun_other_endian = 1;
2809 sun_other_endian = 0;
2811 memset(MBRbuffer, 0, sizeof(MBRbuffer));
2812 sunlabel->magic = SUN_SSWAP16(SUN_LABEL_MAGIC);
2814 puts(_("Drive type\n"
2815 " ? auto configure\n"
2816 " 0 custom (with hardware detected defaults)"));
2817 for (i = 0; i < SIZE(sun_drives); i++) {
2818 printf(" %c %s%s%s\n",
2819 i + 'a', sun_drives[i].vendor,
2820 (*sun_drives[i].vendor) ? " " : "",
2821 sun_drives[i].model);
2824 c = read_char(_("Select type (? for auto, 0 for custom): "));
2825 if (c >= 'a' && c < 'a' + SIZE(sun_drives)) {
2826 p = sun_drives + c - 'a';
2828 } else if (c >= 'A' && c < 'A' + SIZE(sun_drives)) {
2829 p = sun_drives + c - 'A';
2831 } else if (c == '0') {
2833 } else if (c == '?' && scsi_disk) {
2834 p = sun_autoconfigure_scsi();
2836 printf(_("Autoconfigure failed.\n"));
2844 if (!ioctl(fd, HDIO_REQ, &geometry)) {
2846 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
2848 heads = geometry.heads;
2849 sectors = geometry.sectors;
2850 cylinders = geometry.cylinders;
2857 sunlabel->nacyl = 0;
2858 sunlabel->pcylcount = SUN_SSWAP16(cylinders);
2859 sunlabel->rspeed = SUN_SSWAP16(300);
2860 sunlabel->ilfact = SUN_SSWAP16(1);
2861 sunlabel->sparecyl = 0;
2863 heads = read_int(1,heads,1024,0,_("Heads"));
2864 sectors = read_int(1,sectors,1024,0,_("Sectors/track"));
2866 cylinders = read_int(1,cylinders-2,65535,0,_("Cylinders"));
2868 cylinders = read_int(1,0,65535,0,_("Cylinders"));
2870 SUN_SSWAP16(read_int(0,2,65535,0,
2871 _("Alternate cylinders")));
2872 sunlabel->pcylcount =
2873 SUN_SSWAP16(read_int(0,cylinders+SUN_SSWAP16(sunlabel->nacyl),
2874 65535,0,_("Physical cylinders")));
2876 SUN_SSWAP16(read_int(1,5400,100000,0,
2877 _("Rotation speed (rpm)")));
2879 SUN_SSWAP16(read_int(1,1,32,0,_("Interleave factor")));
2880 sunlabel->sparecyl =
2881 SUN_SSWAP16(read_int(0,0,sectors,0,
2882 _("Extra sectors per cylinder")));
2885 sunlabel->sparecyl = SUN_SSWAP16(p->sparecyl);
2886 sunlabel->ncyl = SUN_SSWAP16(p->ncyl);
2887 sunlabel->nacyl = SUN_SSWAP16(p->nacyl);
2888 sunlabel->pcylcount = SUN_SSWAP16(p->pcylcount);
2889 sunlabel->ntrks = SUN_SSWAP16(p->ntrks);
2890 sunlabel->nsect = SUN_SSWAP16(p->nsect);
2891 sunlabel->rspeed = SUN_SSWAP16(p->rspeed);
2892 sunlabel->ilfact = SUN_SSWAP16(1);
2893 cylinders = p->ncyl;
2896 puts(_("You may change all the disk params from the x menu"));
2899 snprintf(sunlabel->info, sizeof(sunlabel->info),
2900 "%s%s%s cyl %d alt %d hd %d sec %d",
2901 p ? p->vendor : "", (p && *p->vendor) ? " " : "",
2903 : (floppy ? _("3,5\" floppy") : _("Linux custom")),
2904 cylinders, SUN_SSWAP16(sunlabel->nacyl), heads, sectors);
2906 sunlabel->ntrks = SUN_SSWAP16(heads);
2907 sunlabel->nsect = SUN_SSWAP16(sectors);
2908 sunlabel->ncyl = SUN_SSWAP16(cylinders);
2910 set_sun_partition(0, 0, cylinders * heads * sectors, LINUX_NATIVE);
2912 if (cylinders * heads * sectors >= 150 * 2048) {
2913 ndiv = cylinders - (50 * 2048 / (heads * sectors)); /* 50M swap */
2915 ndiv = cylinders * 2 / 3;
2916 set_sun_partition(0, 0, ndiv * heads * sectors, LINUX_NATIVE);
2917 set_sun_partition(1, ndiv * heads * sectors, cylinders * heads * sectors, LINUX_SWAP);
2918 sunlabel->infos[1].flags |= 0x01; /* Not mountable */
2920 set_sun_partition(2, 0, cylinders * heads * sectors, WHOLE_DISK);
2922 unsigned short *ush = (unsigned short *)sunlabel;
2923 unsigned short csum = 0;
2924 while(ush < (unsigned short *)(&sunlabel->csum))
2926 sunlabel->csum = csum;
2929 set_all_unchanged();
2931 get_boot(create_empty_sun);
2935 toggle_sunflags(int i, unsigned char mask) {
2936 if (sunlabel->infos[i].flags & mask)
2937 sunlabel->infos[i].flags &= ~mask;
2938 else sunlabel->infos[i].flags |= mask;
2943 fetch_sun(uint *starts, uint *lens, uint *start, uint *stop) {
2944 int i, continuous = 1;
2945 *start = 0; *stop = cylinders * heads * sectors;
2946 for (i = 0; i < partitions; i++) {
2947 if (sunlabel->partitions[i].num_sectors
2948 && sunlabel->infos[i].id
2949 && sunlabel->infos[i].id != WHOLE_DISK) {
2950 starts[i] = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
2951 lens[i] = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
2953 if (starts[i] == *start)
2955 else if (starts[i] + lens[i] >= *stop)
2959 /* There will be probably more gaps
2960 than one, so lets check afterwards */
2969 static uint *verify_sun_starts;
2972 verify_sun_cmp(int *a, int *b) {
2973 if (*a == -1) return 1;
2974 if (*b == -1) return -1;
2975 if (verify_sun_starts[*a] > verify_sun_starts[*b]) return 1;
2981 uint starts[8], lens[8], start, stop;
2982 int i,j,k,starto,endo;
2985 verify_sun_starts = starts;
2986 fetch_sun(starts,lens,&start,&stop);
2987 for (k = 0; k < 7; k++) {
2988 for (i = 0; i < 8; i++) {
2989 if (k && (lens[i] % (heads * sectors))) {
2990 printf(_("Partition %d doesn't end on cylinder boundary\n"), i+1);
2993 for (j = 0; j < i; j++)
2995 if (starts[j] == starts[i]+lens[i]) {
2996 starts[j] = starts[i]; lens[j] += lens[i];
2998 } else if (starts[i] == starts[j]+lens[j]){
3002 if (starts[i] < starts[j]+lens[j] &&
3003 starts[j] < starts[i]+lens[i]) {
3005 if (starts[j] > starto)
3007 endo = starts[i]+lens[i];
3008 if (starts[j]+lens[j] < endo)
3009 endo = starts[j]+lens[j];
3010 printf(_("Partition %d overlaps with others in "
3011 "sectors %d-%d\n"), i+1, starto, endo);
3018 for (i = 0; i < 8; i++) {
3024 qsort(array,SIZE(array),sizeof(array[0]),
3025 (int (*)(const void *,const void *)) verify_sun_cmp);
3026 if (array[0] == -1) {
3027 printf(_("No partitions defined\n"));
3030 stop = cylinders * heads * sectors;
3031 if (starts[array[0]])
3032 printf(_("Unused gap - sectors 0-%d\n"),starts[array[0]]);
3033 for (i = 0; i < 7 && array[i+1] != -1; i++) {
3034 printf(_("Unused gap - sectors %d-%d\n"),starts[array[i]]+lens[array[i]],starts[array[i+1]]);
3036 start = starts[array[i]]+lens[array[i]];
3038 printf(_("Unused gap - sectors %d-%d\n"),start,stop);
3042 add_sun_partition(int n, int sys) {
3043 uint start, stop, stop2;
3044 uint starts[8], lens[8];
3050 if (sunlabel->partitions[n].num_sectors && sunlabel->infos[n].id) {
3051 printf(_("Partition %d is already defined. Delete "
3052 "it before re-adding it.\n"), n + 1);
3056 fetch_sun(starts,lens,&start,&stop);
3057 if (stop <= start) {
3061 printf(_("Other partitions already cover the whole disk.\nDelete "
3062 "some/shrink them before retry.\n"));
3066 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
3069 first = read_int(0, 0, 0, 0, mesg);
3071 first = read_int(scround(start), scround(stop)+1,
3072 scround(stop), 0, mesg);
3073 if (display_in_cyl_units)
3074 first *= units_per_sector;
3076 /* Starting sector has to be properly aligned */
3077 first = (first + heads * sectors - 1) / (heads * sectors);
3078 if (n == 2 && first != 0)
3080 It is highly recommended that the third partition covers the whole disk\n\
3081 and is of type `Whole disk'\n");
3082 /* ewt asks to add: "don't start a partition at cyl 0"
3083 However, edmundo@rano.demon.co.uk writes:
3084 "In addition to having a Sun partition table, to be able to
3085 boot from the disc, the first partition, /dev/sdX1, must
3086 start at cylinder 0. This means that /dev/sdX1 contains
3087 the partition table and the boot block, as these are the
3088 first two sectors of the disc. Therefore you must be
3089 careful what you use /dev/sdX1 for. In particular, you must
3090 not use a partition starting at cylinder 0 for Linux swap,
3091 as that would overwrite the partition table and the boot
3092 block. You may, however, use such a partition for a UFS
3093 or EXT2 file system, as these file systems leave the first
3094 1024 bytes undisturbed. */
3095 /* On the other hand, one should not use partitions
3096 starting at block 0 in an md, or the label will
3098 for (i = 0; i < partitions; i++)
3099 if (lens[i] && starts[i] <= first
3100 && starts[i] + lens[i] > first)
3102 if (i < partitions && !whole_disk) {
3103 if (n == 2 && !first) {
3107 printf(_("Sector %d is already allocated\n"), first);
3111 stop = cylinders * heads * sectors;
3113 for (i = 0; i < partitions; i++) {
3114 if (starts[i] > first && starts[i] < stop)
3117 snprintf(mesg, sizeof(mesg),
3118 _("Last %s or +size or +sizeM or +sizeK"),
3119 str_units(SINGULAR));
3121 last = read_int(scround(stop2), scround(stop2), scround(stop2),
3123 else if (n == 2 && !first)
3124 last = read_int(scround(first), scround(stop2), scround(stop2),
3125 scround(first), mesg);
3127 last = read_int(scround(first), scround(stop), scround(stop),
3128 scround(first), mesg);
3129 if (display_in_cyl_units)
3130 last *= units_per_sector;
3131 if (n == 2 && !first) {
3132 if (last >= stop2) {
3135 } else if (last > stop) {
3137 _("You haven't covered the whole disk with the 3rd partition, but your value\n"
3138 "%d %s covers some other partition. Your entry has been changed\n"
3140 scround(last), str_units(SINGULAR),
3141 scround(stop), str_units(SINGULAR));
3144 } else if (!whole_disk && last > stop)
3147 if (whole_disk) sys = WHOLE_DISK;
3148 set_sun_partition(n, first, last, sys);
3152 sun_delete_partition(int i) {
3153 if (i == 2 && sunlabel->infos[i].id == WHOLE_DISK &&
3154 !sunlabel->partitions[i].start_cylinder &&
3155 SUN_SSWAP32(sunlabel->partitions[i].num_sectors)
3156 == heads * sectors * cylinders)
3157 printf(_("If you want to maintain SunOS/Solaris compatibility, "
3158 "consider leaving this\n"
3159 "partition as Whole disk (5), starting at 0, with %u "
3161 (uint) SUN_SSWAP32(sunlabel->partitions[i].num_sectors));
3162 sunlabel->infos[i].id = 0;
3163 sunlabel->partitions[i].num_sectors = 0;
3167 sun_change_sysid(int i, int sys) {
3168 if (sys == LINUX_SWAP && !sunlabel->partitions[i].start_cylinder) {
3170 _("It is highly recommended that the partition at offset 0\n"
3171 "is UFS, EXT2FS filesystem or SunOS swap. Putting Linux swap\n"
3172 "there may destroy your partition table and bootblock.\n"
3173 "Type YES if you're very sure you would like that partition\n"
3174 "tagged with 82 (Linux swap): "));
3175 if (strcmp (line_ptr, _("YES\n")))
3181 /* swaps are not mountable by default */
3182 sunlabel->infos[i].flags |= 0x01;
3185 /* assume other types are mountable;
3186 user can change it anyway */
3187 sunlabel->infos[i].flags &= ~0x01;
3190 sunlabel->infos[i].id = sys;
3194 sun_list_table(int xtra) {
3197 w = strlen(disk_device);
3200 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d rpm\n"
3201 "%d cylinders, %d alternate cylinders, %d physical cylinders\n"
3202 "%d extra sects/cyl, interleave %d:1\n"
3204 "Units = %s of %d * 512 bytes\n\n"),
3205 disk_device, heads, sectors, SUN_SSWAP16(sunlabel->rspeed),
3206 cylinders, SUN_SSWAP16(sunlabel->nacyl),
3207 SUN_SSWAP16(sunlabel->pcylcount),
3208 SUN_SSWAP16(sunlabel->sparecyl),
3209 SUN_SSWAP16(sunlabel->ilfact),
3211 str_units(PLURAL), units_per_sector);
3214 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d cylinders\n"
3215 "Units = %s of %d * 512 bytes\n\n"),
3216 disk_device, heads, sectors, cylinders,
3217 str_units(PLURAL), units_per_sector);
3219 printf(_("%*s Flag Start End Blocks Id System\n"),
3220 w + 1, _("Device"));
3221 for (i = 0 ; i < partitions; i++) {
3222 if (sunlabel->partitions[i].num_sectors) {
3223 uint32_t start = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
3224 uint32_t len = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
3226 "%s %c%c %9ld %9ld %9ld%c %2x %s\n",
3227 /* device */ partname(disk_device, i+1, w),
3228 /* flags */ (sunlabel->infos[i].flags & 0x01) ? 'u' : ' ',
3229 (sunlabel->infos[i].flags & 0x10) ? 'r' : ' ',
3230 /* start */ (long) scround(start),
3231 /* end */ (long) scround(start+len),
3232 /* odd flag on end */ (long) len / 2, len & 1 ? '+' : ' ',
3233 /* type id */ sunlabel->infos[i].id,
3234 /* type name */ partition_type(sunlabel->infos[i].id));
3240 sun_set_alt_cyl(void) {
3242 SUN_SSWAP16(read_int(0,SUN_SSWAP16(sunlabel->nacyl), 65535, 0,
3243 _("Number of alternate cylinders")));
3247 sun_set_ncyl(int cyl) {
3248 sunlabel->ncyl = SUN_SSWAP16(cyl);
3252 sun_set_xcyl(void) {
3253 sunlabel->sparecyl =
3254 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->sparecyl), sectors, 0,
3255 _("Extra sectors per cylinder")));
3259 sun_set_ilfact(void) {
3261 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->ilfact), 32, 0,
3262 _("Interleave factor")));
3266 sun_set_rspeed(void) {
3268 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->rspeed), 100000, 0,
3269 _("Rotation speed (rpm)")));
3273 sun_set_pcylcount(void) {
3274 sunlabel->pcylcount =
3275 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->pcylcount), 65535, 0,
3276 _("Number of physical cylinders")));
3280 sun_write_table(void) {
3281 unsigned short *ush = (unsigned short *)sunlabel;
3282 unsigned short csum = 0;
3284 while(ush < (unsigned short *)(&sunlabel->csum))
3286 sunlabel->csum = csum;
3287 if (lseek(fd, 0, SEEK_SET) < 0)
3288 fdisk_fatal(unable_to_seek);
3289 if (write(fd, sunlabel, SECTOR_SIZE) != SECTOR_SIZE)
3290 fdisk_fatal(unable_to_write);
3292 #endif /* SUN_LABEL */
3294 /* DOS partition types */
3296 static const struct systypes i386_sys_types[] = {
3299 {"\x04" "FAT16 <32M"},
3300 {"\x05" "Extended"}, /* DOS 3.3+ extended partition */
3301 {"\x06" "FAT16"}, /* DOS 16-bit >=32M */
3302 {"\x07" "HPFS/NTFS"}, /* OS/2 IFS, eg, HPFS or NTFS or QNX */
3303 {"\x0a" "OS/2 Boot Manager"},/* OS/2 Boot Manager */
3304 {"\x0b" "Win95 FAT32"},
3305 {"\x0c" "Win95 FAT32 (LBA)"},/* LBA really is `Extended Int 13h' */
3306 {"\x0e" "Win95 FAT16 (LBA)"},
3307 {"\x0f" "Win95 Ext'd (LBA)"},
3308 {"\x11" "Hidden FAT12"},
3309 {"\x12" "Compaq diagnostics"},
3310 {"\x14" "Hidden FAT16 <32M"},
3311 {"\x16" "Hidden FAT16"},
3312 {"\x17" "Hidden HPFS/NTFS"},
3313 {"\x1b" "Hidden Win95 FAT32"},
3314 {"\x1c" "Hidden Win95 FAT32 (LBA)"},
3315 {"\x1e" "Hidden Win95 FAT16 (LBA)"},
3316 {"\x3c" "PartitionMagic recovery"},
3317 {"\x41" "PPC PReP Boot"},
3319 {"\x63" "GNU HURD or SysV"}, /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */
3320 {"\x80" "Old Minix"}, /* Minix 1.4a and earlier */
3321 {"\x81" "Minix / old Linux"},/* Minix 1.4b and later */
3322 {"\x82" "Linux swap"}, /* also Solaris */
3324 {"\x84" "OS/2 hidden C: drive"},
3325 {"\x85" "Linux extended"},
3326 {"\x86" "NTFS volume set"},
3327 {"\x87" "NTFS volume set"},
3328 {"\x8e" "Linux LVM"},
3329 {"\x9f" "BSD/OS"}, /* BSDI */
3330 {"\xa0" "IBM Thinkpad hibernation"},
3331 {"\xa5" "FreeBSD"}, /* various BSD flavours */
3333 {"\xa8" "Darwin UFS"},
3335 {"\xab" "Darwin boot"},
3337 {"\xb8" "BSDI swap"},
3338 {"\xbe" "Solaris boot"},
3340 {"\xee" "EFI GPT"}, /* Intel EFI GUID Partition Table */
3341 {"\xef" "EFI (FAT-12/16/32)"},/* Intel EFI System Partition */
3342 {"\xf0" "Linux/PA-RISC boot"},/* Linux/PA-RISC boot loader */
3343 {"\xf2" "DOS secondary"}, /* DOS 3.3+ secondary */
3344 {"\xfd" "Linux raid autodetect"},/* New (2.2.x) raid partition with
3345 autodetect using persistent
3347 #ifdef CONFIG_WEIRD_PARTITION_TYPES
3348 {"\x02" "XENIX root"},
3349 {"\x03" "XENIX usr"},
3350 {"\x08" "AIX"}, /* AIX boot (AIX -- PS/2 port) or SplitDrive */
3351 {"\x09" "AIX bootable"}, /* AIX data or Coherent */
3353 {"\x18" "AST SmartSleep"},
3356 {"\x40" "Venix 80286"},
3358 {"\x4e" "QNX4.x 2nd part"},
3359 {"\x4f" "QNX4.x 3rd part"},
3360 {"\x50" "OnTrack DM"},
3361 {"\x51" "OnTrack DM6 Aux1"}, /* (or Novell) */
3362 {"\x52" "CP/M"}, /* CP/M or Microport SysV/AT */
3363 {"\x53" "OnTrack DM6 Aux3"},
3364 {"\x54" "OnTrackDM6"},
3365 {"\x55" "EZ-Drive"},
3366 {"\x56" "Golden Bow"},
3367 {"\x5c" "Priam Edisk"},
3368 {"\x61" "SpeedStor"},
3369 {"\x64" "Novell Netware 286"},
3370 {"\x65" "Novell Netware 386"},
3371 {"\x70" "DiskSecure Multi-Boot"},
3374 {"\x94" "Amoeba BBT"}, /* (bad block table) */
3375 {"\xa7" "NeXTSTEP"},
3376 {"\xbb" "Boot Wizard hidden"},
3377 {"\xc1" "DRDOS/sec (FAT-12)"},
3378 {"\xc4" "DRDOS/sec (FAT-16 < 32M)"},
3379 {"\xc6" "DRDOS/sec (FAT-16)"},
3381 {"\xda" "Non-FS data"},
3382 {"\xdb" "CP/M / CTOS / ..."},/* CP/M or Concurrent CP/M or
3383 Concurrent DOS or CTOS */
3384 {"\xde" "Dell Utility"}, /* Dell PowerEdge Server utilities */
3385 {"\xdf" "BootIt"}, /* BootIt EMBRM */
3386 {"\xe1" "DOS access"}, /* DOS access or SpeedStor 12-bit FAT
3387 extended partition */
3388 {"\xe3" "DOS R/O"}, /* DOS R/O or SpeedStor */
3389 {"\xe4" "SpeedStor"}, /* SpeedStor 16-bit FAT extended
3390 partition < 1024 cyl. */
3391 {"\xf1" "SpeedStor"},
3392 {"\xf4" "SpeedStor"}, /* SpeedStor large partition */
3393 {"\xfe" "LANstep"}, /* SpeedStor >1024 cyl. or LANstep */
3394 {"\xff" "BBT"}, /* Xenix Bad Block Table */
3401 /* A valid partition table sector ends in 0x55 0xaa */
3403 part_table_flag(const char *b) {
3404 return ((uint) b[510]) + (((uint) b[511]) << 8);
3408 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3410 write_part_table_flag(char *b) {
3415 /* start_sect and nr_sects are stored little endian on all machines */
3416 /* moreover, they are not aligned correctly */
3418 store4_little_endian(unsigned char *cp, unsigned int val) {
3419 cp[0] = (val & 0xff);
3420 cp[1] = ((val >> 8) & 0xff);
3421 cp[2] = ((val >> 16) & 0xff);
3422 cp[3] = ((val >> 24) & 0xff);
3424 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3427 read4_little_endian(const unsigned char *cp) {
3428 return (uint)(cp[0]) + ((uint)(cp[1]) << 8)
3429 + ((uint)(cp[2]) << 16) + ((uint)(cp[3]) << 24);
3432 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3434 set_start_sect(struct partition *p, unsigned int start_sect) {
3435 store4_little_endian(p->start4, start_sect);
3440 get_start_sect(const struct partition *p) {
3441 return read4_little_endian(p->start4);
3444 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3446 set_nr_sects(struct partition *p, unsigned int nr_sects) {
3447 store4_little_endian(p->size4, nr_sects);
3452 get_nr_sects(const struct partition *p) {
3453 return read4_little_endian(p->size4);
3456 /* normally O_RDWR, -l option gives O_RDONLY */
3457 static int type_open = O_RDWR;
3460 static int ext_index, /* the prime extended partition */
3461 listing, /* no aborts for fdisk -l */
3462 dos_compatible_flag = ~0;
3463 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3464 static int dos_changed;
3465 static int nowarn; /* no warnings for fdisk -l/-s */
3470 static uint user_cylinders, user_heads, user_sectors;
3471 static uint pt_heads, pt_sectors;
3472 static uint kern_heads, kern_sectors;
3474 static uint extended_offset; /* offset of link pointers */
3475 static uint sector_size = DEFAULT_SECTOR_SIZE,
3476 user_set_sector_size,
3479 static unsigned long total_number_of_sectors;
3482 static jmp_buf listingbuf;
3484 static void fdisk_fatal(enum failure why) {
3485 const char *message;
3489 longjmp(listingbuf, 1);
3493 case unable_to_open:
3494 message = "Unable to open %s\n";
3496 case unable_to_read:
3497 message = "Unable to read %s\n";
3499 case unable_to_seek:
3500 message = "Unable to seek on %s\n";
3502 case unable_to_write:
3503 message = "Unable to write %s\n";
3506 message = "BLKGETSIZE ioctl failed on %s\n";
3509 message = "Fatal error\n";
3512 fputc('\n', stderr);
3513 fprintf(stderr, message, disk_device);
3518 seek_sector(uint secno) {
3519 ext2_loff_t offset = (ext2_loff_t) secno * sector_size;
3520 if (ext2_llseek(fd, offset, SEEK_SET) == (ext2_loff_t) -1)
3521 fdisk_fatal(unable_to_seek);
3524 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3526 write_sector(uint secno, char *buf) {
3528 if (write(fd, buf, sector_size) != sector_size)
3529 fdisk_fatal(unable_to_write);
3533 /* Allocate a buffer and read a partition table sector */
3535 read_pte(struct pte *pe, uint offset) {
3537 pe->offset = offset;
3538 pe->sectorbuffer = (char *) xmalloc(sector_size);
3539 seek_sector(offset);
3540 if (read(fd, pe->sectorbuffer, sector_size) != sector_size)
3541 fdisk_fatal(unable_to_read);
3542 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3545 pe->part_table = pe->ext_pointer = NULL;
3549 get_partition_start(const struct pte *pe) {
3550 return pe->offset + get_start_sect(pe->part_table);
3553 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3555 * Avoid warning about DOS partitions when no DOS partition was changed.
3556 * Here a heuristic "is probably dos partition".
3557 * We might also do the opposite and warn in all cases except
3558 * for "is probably nondos partition".
3561 is_dos_partition(int t) {
3562 return (t == 1 || t == 4 || t == 6 ||
3563 t == 0x0b || t == 0x0c || t == 0x0e ||
3564 t == 0x11 || t == 0x12 || t == 0x14 || t == 0x16 ||
3565 t == 0x1b || t == 0x1c || t == 0x1e || t == 0x24 ||
3566 t == 0xc1 || t == 0xc4 || t == 0xc6);
3571 #ifdef CONFIG_FEATURE_SUN_LABEL
3573 puts(_("Command action"));
3574 puts(_("\ta\ttoggle a read only flag")); /* sun */
3575 puts(_("\tb\tedit bsd disklabel"));
3576 puts(_("\tc\ttoggle the mountable flag")); /* sun */
3577 puts(_("\td\tdelete a partition"));
3578 puts(_("\tl\tlist known partition types"));
3579 puts(_("\tm\tprint this menu"));
3580 puts(_("\tn\tadd a new partition"));
3581 puts(_("\to\tcreate a new empty DOS partition table"));
3582 puts(_("\tp\tprint the partition table"));
3583 puts(_("\tq\tquit without saving changes"));
3584 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3585 puts(_("\tt\tchange a partition's system id"));
3586 puts(_("\tu\tchange display/entry units"));
3587 puts(_("\tv\tverify the partition table"));
3588 puts(_("\tw\twrite table to disk and exit"));
3589 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3590 puts(_("\tx\textra functionality (experts only)"));
3594 #ifdef CONFIG_FEATURE_SGI_LABEL
3596 puts(_("Command action"));
3597 puts(_("\ta\tselect bootable partition")); /* sgi flavour */
3598 puts(_("\tb\tedit bootfile entry")); /* sgi */
3599 puts(_("\tc\tselect sgi swap partition")); /* sgi flavour */
3600 puts(_("\td\tdelete a partition"));
3601 puts(_("\tl\tlist known partition types"));
3602 puts(_("\tm\tprint this menu"));
3603 puts(_("\tn\tadd a new partition"));
3604 puts(_("\to\tcreate a new empty DOS partition table"));
3605 puts(_("\tp\tprint the partition table"));
3606 puts(_("\tq\tquit without saving changes"));
3607 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3608 puts(_("\tt\tchange a partition's system id"));
3609 puts(_("\tu\tchange display/entry units"));
3610 puts(_("\tv\tverify the partition table"));
3611 puts(_("\tw\twrite table to disk and exit"));
3614 #ifdef CONFIG_FEATURE_AIX_LABEL
3616 puts(_("Command action"));
3617 puts(_("\tm\tprint this menu"));
3618 puts(_("\to\tcreate a new empty DOS partition table"));
3619 puts(_("\tq\tquit without saving changes"));
3620 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3624 puts(_("Command action"));
3625 puts(_("\ta\ttoggle a bootable flag"));
3626 puts(_("\tb\tedit bsd disklabel"));
3627 puts(_("\tc\ttoggle the dos compatibility flag"));
3628 puts(_("\td\tdelete a partition"));
3629 puts(_("\tl\tlist known partition types"));
3630 puts(_("\tm\tprint this menu"));
3631 puts(_("\tn\tadd a new partition"));
3632 puts(_("\to\tcreate a new empty DOS partition table"));
3633 puts(_("\tp\tprint the partition table"));
3634 puts(_("\tq\tquit without saving changes"));
3635 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3636 puts(_("\tt\tchange a partition's system id"));
3637 puts(_("\tu\tchange display/entry units"));
3638 puts(_("\tv\tverify the partition table"));
3639 puts(_("\tw\twrite table to disk and exit"));
3640 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3641 puts(_("\tx\textra functionality (experts only)"));
3645 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3648 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3651 #ifdef CONFIG_FEATURE_SUN_LABEL
3653 puts(_("Command action"));
3654 puts(_("\ta\tchange number of alternate cylinders")); /*sun*/
3655 puts(_("\tc\tchange number of cylinders"));
3656 puts(_("\td\tprint the raw data in the partition table"));
3657 puts(_("\te\tchange number of extra sectors per cylinder"));/*sun*/
3658 puts(_("\th\tchange number of heads"));
3659 puts(_("\ti\tchange interleave factor")); /*sun*/
3660 puts(_("\to\tchange rotation speed (rpm)")); /*sun*/
3661 puts(_("\tm\tprint this menu"));
3662 puts(_("\tp\tprint the partition table"));
3663 puts(_("\tq\tquit without saving changes"));
3664 puts(_("\tr\treturn to main menu"));
3665 puts(_("\ts\tchange number of sectors/track"));
3666 puts(_("\tv\tverify the partition table"));
3667 puts(_("\tw\twrite table to disk and exit"));
3668 puts(_("\ty\tchange number of physical cylinders")); /*sun*/
3671 #ifdef CONFIG_FEATURE_SGI_LABEL
3673 puts(_("Command action"));
3674 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3675 puts(_("\tc\tchange number of cylinders"));
3676 puts(_("\td\tprint the raw data in the partition table"));
3677 puts(_("\te\tlist extended partitions")); /* !sun */
3678 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3679 puts(_("\th\tchange number of heads"));
3680 puts(_("\tm\tprint this menu"));
3681 puts(_("\tp\tprint the partition table"));
3682 puts(_("\tq\tquit without saving changes"));
3683 puts(_("\tr\treturn to main menu"));
3684 puts(_("\ts\tchange number of sectors/track"));
3685 puts(_("\tv\tverify the partition table"));
3686 puts(_("\tw\twrite table to disk and exit"));
3689 #ifdef CONFIG_FEATURE_AIX_LABEL
3691 puts(_("Command action"));
3692 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3693 puts(_("\tc\tchange number of cylinders"));
3694 puts(_("\td\tprint the raw data in the partition table"));
3695 puts(_("\te\tlist extended partitions")); /* !sun */
3696 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3697 puts(_("\th\tchange number of heads"));
3698 puts(_("\tm\tprint this menu"));
3699 puts(_("\tp\tprint the partition table"));
3700 puts(_("\tq\tquit without saving changes"));
3701 puts(_("\tr\treturn to main menu"));
3702 puts(_("\ts\tchange number of sectors/track"));
3703 puts(_("\tv\tverify the partition table"));
3704 puts(_("\tw\twrite table to disk and exit"));
3708 puts(_("Command action"));
3709 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3710 puts(_("\tc\tchange number of cylinders"));
3711 puts(_("\td\tprint the raw data in the partition table"));
3712 puts(_("\te\tlist extended partitions")); /* !sun */
3713 puts(_("\tf\tfix partition order")); /* !sun, !aix, !sgi */
3714 #ifdef CONFIG_FEATURE_SGI_LABEL
3715 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3717 puts(_("\th\tchange number of heads"));
3718 puts(_("\tm\tprint this menu"));
3719 puts(_("\tp\tprint the partition table"));
3720 puts(_("\tq\tquit without saving changes"));
3721 puts(_("\tr\treturn to main menu"));
3722 puts(_("\ts\tchange number of sectors/track"));
3723 puts(_("\tv\tverify the partition table"));
3724 puts(_("\tw\twrite table to disk and exit"));
3727 #endif /* ADVANCED mode */
3729 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3730 static const struct systypes *
3731 get_sys_types(void) {
3733 #ifdef CONFIG_FEATURE_SUN_LABEL
3734 sun_label ? sun_sys_types :
3736 #ifdef CONFIG_FEATURE_SGI_LABEL
3737 sgi_label ? sgi_sys_types :
3742 #define get_sys_types() i386_sys_types
3743 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3745 static const char *partition_type(unsigned char type)
3748 const struct systypes *types = get_sys_types();
3750 for (i=0; types[i].name; i++)
3751 if (types[i].name[0] == type)
3752 return types[i].name + 1;
3754 return _("Unknown");
3758 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3762 #ifdef CONFIG_FEATURE_SUN_LABEL
3763 sun_label ? sunlabel->infos[i].id :
3765 #ifdef CONFIG_FEATURE_SGI_LABEL
3766 sgi_label ? sgi_get_sysid(i) :
3768 ptes[i].part_table->sys_ind);
3771 void list_types(const struct systypes *sys)
3773 uint last[4], done = 0, next = 0, size;
3776 for (i = 0; sys[i].name; i++);
3779 for (i = 3; i >= 0; i--)
3780 last[3 - i] = done += (size + i - done) / (i + 1);
3784 printf("%c%2x %-15.15s", i ? ' ' : '\n',
3785 sys[next].name[0], partition_type(sys[next].name[0]));
3786 next = last[i++] + done;
3787 if (i > 3 || next >= last[i]) {
3791 } while (done < last[0]);
3794 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3797 is_cleared_partition(const struct partition *p) {
3798 return !(!p || p->boot_ind || p->head || p->sector || p->cyl ||
3799 p->sys_ind || p->end_head || p->end_sector || p->end_cyl ||
3800 get_start_sect(p) || get_nr_sects(p));
3804 clear_partition(struct partition *p) {
3807 memset(p, 0, sizeof(struct partition));
3810 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3812 set_partition(int i, int doext, uint start, uint stop, int sysid) {
3813 struct partition *p;
3817 p = ptes[i].ext_pointer;
3818 offset = extended_offset;
3820 p = ptes[i].part_table;
3821 offset = ptes[i].offset;
3825 set_start_sect(p, start - offset);
3826 set_nr_sects(p, stop - start + 1);
3827 if (dos_compatible_flag && (start/(sectors*heads) > 1023))
3828 start = heads*sectors*1024 - 1;
3829 set_hsc(p->head, p->sector, p->cyl, start);
3830 if (dos_compatible_flag && (stop/(sectors*heads) > 1023))
3831 stop = heads*sectors*1024 - 1;
3832 set_hsc(p->end_head, p->end_sector, p->end_cyl, stop);
3833 ptes[i].changed = 1;
3838 test_c(const char **m, const char *mesg) {
3841 fprintf(stderr, _("You must set"));
3843 fprintf(stderr, " %s", *m);
3851 warn_geometry(void) {
3852 const char *m = NULL;
3856 prev = test_c(&m, _("heads"));
3858 prev = test_c(&m, _("sectors"));
3860 prev = test_c(&m, _("cylinders"));
3864 fprintf(stderr, "%s%s.\n"
3865 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3866 "You can do this from the extra functions menu.\n"
3868 , prev ? _(" and ") : " ", m);
3873 static void update_units(void)
3875 int cyl_units = heads * sectors;
3877 if (display_in_cyl_units && cyl_units)
3878 units_per_sector = cyl_units;
3880 units_per_sector = 1; /* in sectors */
3883 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3885 warn_cylinders(void) {
3886 if (dos_label && cylinders > 1024 && !nowarn)
3887 fprintf(stderr, _("\n"
3888 "The number of cylinders for this disk is set to %d.\n"
3889 "There is nothing wrong with that, but this is larger than 1024,\n"
3890 "and could in certain setups cause problems with:\n"
3891 "1) software that runs at boot time (e.g., old versions of LILO)\n"
3892 "2) booting and partitioning software from other OSs\n"
3893 " (e.g., DOS FDISK, OS/2 FDISK)\n"),
3899 read_extended(int ext) {
3902 struct partition *p, *q;
3906 pex->ext_pointer = pex->part_table;
3908 p = pex->part_table;
3909 if (!get_start_sect(p)) {
3911 _("Bad offset in primary extended partition\n"));
3915 while (IS_EXTENDED (p->sys_ind)) {
3916 struct pte *pe = &ptes[partitions];
3918 if (partitions >= MAXIMUM_PARTS) {
3919 /* This is not a Linux restriction, but
3920 this program uses arrays of size MAXIMUM_PARTS.
3921 Do not try to `improve' this test. */
3922 struct pte *pre = &ptes[partitions-1];
3923 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3925 _("Warning: deleting partitions after %d\n"),
3929 clear_partition(pre->ext_pointer);
3933 read_pte(pe, extended_offset + get_start_sect(p));
3935 if (!extended_offset)
3936 extended_offset = get_start_sect(p);
3938 q = p = pt_offset(pe->sectorbuffer, 0);
3939 for (i = 0; i < 4; i++, p++) if (get_nr_sects(p)) {
3940 if (IS_EXTENDED (p->sys_ind)) {
3941 if (pe->ext_pointer)
3943 _("Warning: extra link "
3944 "pointer in partition table"
3945 " %d\n"), partitions + 1);
3947 pe->ext_pointer = p;
3948 } else if (p->sys_ind) {
3951 _("Warning: ignoring extra "
3952 "data in partition table"
3953 " %d\n"), partitions + 1);
3959 /* very strange code here... */
3960 if (!pe->part_table) {
3961 if (q != pe->ext_pointer)
3964 pe->part_table = q + 1;
3966 if (!pe->ext_pointer) {
3967 if (q != pe->part_table)
3968 pe->ext_pointer = q;
3970 pe->ext_pointer = q + 1;
3973 p = pe->ext_pointer;
3977 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3978 /* remove empty links */
3980 for (i = 4; i < partitions; i++) {
3981 struct pte *pe = &ptes[i];
3983 if (!get_nr_sects(pe->part_table) &&
3984 (partitions > 5 || ptes[4].part_table->sys_ind)) {
3985 printf("omitting empty partition (%d)\n", i+1);
3986 delete_partition(i);
3987 goto remove; /* numbering changed */
3993 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3995 create_doslabel(void) {
3999 _("Building a new DOS disklabel. Changes will remain in memory only,\n"
4000 "until you decide to write them. After that, of course, the previous\n"
4001 "content won't be recoverable.\n\n"));
4002 #ifdef CONFIG_FEATURE_SUN_LABEL
4003 sun_nolabel(); /* otherwise always recognised as sun */
4005 #ifdef CONFIG_FEATURE_SGI_LABEL
4006 sgi_nolabel(); /* otherwise always recognised as sgi */
4008 #ifdef CONFIG_FEATURE_AIX_LABEL
4011 #ifdef CONFIG_FEATURE_OSF_LABEL
4013 possibly_osf_label = 0;
4017 for (i = 510-64; i < 510; i++)
4019 write_part_table_flag(MBRbuffer);
4020 extended_offset = 0;
4021 set_all_unchanged();
4023 get_boot(create_empty_dos);
4025 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
4028 get_sectorsize(void) {
4029 if (!user_set_sector_size &&
4030 get_kernel_revision() >= MAKE_VERSION(2,3,3)) {
4032 if (ioctl(fd, BLKSSZGET, &arg) == 0)
4034 if (sector_size != DEFAULT_SECTOR_SIZE)
4035 printf(_("Note: sector size is %d (not %d)\n"),
4036 sector_size, DEFAULT_SECTOR_SIZE);
4041 get_kernel_geometry(void) {
4042 struct hd_geometry geometry;
4044 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
4045 kern_heads = geometry.heads;
4046 kern_sectors = geometry.sectors;
4047 /* never use geometry.cylinders - it is truncated */
4052 get_partition_table_geometry(void) {
4053 const unsigned char *bufp = MBRbuffer;
4054 struct partition *p;
4055 int i, h, s, hh, ss;
4059 if (!(valid_part_table_flag(bufp)))
4063 for (i=0; i<4; i++) {
4064 p = pt_offset(bufp, i);
4065 if (p->sys_ind != 0) {
4066 h = p->end_head + 1;
4067 s = (p->end_sector & 077);
4072 } else if (hh != h || ss != s)
4077 if (!first && !bad) {
4084 get_geometry(void) {
4086 unsigned long longsectors;
4089 sec_fac = sector_size / 512;
4090 #ifdef CONFIG_FEATURE_SUN_LABEL
4091 guess_device_type();
4093 heads = cylinders = sectors = 0;
4094 kern_heads = kern_sectors = 0;
4095 pt_heads = pt_sectors = 0;
4097 get_kernel_geometry();
4098 get_partition_table_geometry();
4100 heads = user_heads ? user_heads :
4101 pt_heads ? pt_heads :
4102 kern_heads ? kern_heads : 255;
4103 sectors = user_sectors ? user_sectors :
4104 pt_sectors ? pt_sectors :
4105 kern_sectors ? kern_sectors : 63;
4107 if (ioctl(fd, BLKGETSIZE, &longsectors))
4111 if (dos_compatible_flag)
4112 sector_offset = sectors;
4114 cylinders = longsectors / (heads * sectors);
4115 cylinders /= sec_fac;
4117 cylinders = user_cylinders;
4119 total_number_of_sectors = longsectors;
4123 * Read MBR. Returns:
4124 * -1: no 0xaa55 flag present (possibly entire disk BSD)
4125 * 0: found or created label
4129 get_boot(enum action what) {
4134 for (i = 0; i < 4; i++) {
4135 struct pte *pe = &ptes[i];
4137 pe->part_table = pt_offset(MBRbuffer, i);
4138 pe->ext_pointer = NULL;
4140 pe->sectorbuffer = MBRbuffer;
4141 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4142 pe->changed = (what == create_empty_dos);
4146 #ifdef CONFIG_FEATURE_SUN_LABEL
4147 if (what == create_empty_sun && check_sun_label())
4151 memset(MBRbuffer, 0, 512);
4153 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4154 if (what == create_empty_dos)
4155 goto got_dos_table; /* skip reading disk */
4157 if ((fd = open(disk_device, type_open)) < 0) {
4158 if ((fd = open(disk_device, O_RDONLY)) < 0) {
4159 if (what == try_only)
4161 fdisk_fatal(unable_to_open);
4163 printf(_("You will not be able to write "
4164 "the partition table.\n"));
4167 if (512 != read(fd, MBRbuffer, 512)) {
4168 if (what == try_only)
4170 fdisk_fatal(unable_to_read);
4173 if ((fd = open(disk_device, O_RDONLY)) < 0)
4175 if (512 != read(fd, MBRbuffer, 512))
4183 #ifdef CONFIG_FEATURE_SUN_LABEL
4184 if (check_sun_label())
4188 #ifdef CONFIG_FEATURE_SGI_LABEL
4189 if (check_sgi_label())
4193 #ifdef CONFIG_FEATURE_AIX_LABEL
4194 if (check_aix_label())
4198 #ifdef CONFIG_FEATURE_OSF_LABEL
4199 if (check_osf_label()) {
4200 possibly_osf_label = 1;
4201 if (!valid_part_table_flag(MBRbuffer)) {
4205 printf(_("This disk has both DOS and BSD magic.\n"
4206 "Give the 'b' command to go to BSD mode.\n"));
4210 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4214 if (!valid_part_table_flag(MBRbuffer)) {
4215 #ifndef CONFIG_FEATURE_FDISK_WRITABLE
4221 _("Device contains neither a valid DOS "
4222 "partition table, nor Sun, SGI or OSF "
4225 #ifdef CONFIG_FEATURE_SUN_LABEL
4234 case create_empty_dos:
4235 #ifdef CONFIG_FEATURE_SUN_LABEL
4236 case create_empty_sun:
4240 fprintf(stderr, _("Internal error\n"));
4243 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
4246 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4251 for (i = 0; i < 4; i++) {
4252 struct pte *pe = &ptes[i];
4254 if (IS_EXTENDED (pe->part_table->sys_ind)) {
4255 if (partitions != 4)
4256 fprintf(stderr, _("Ignoring extra extended "
4257 "partition %d\n"), i + 1);
4263 for (i = 3; i < partitions; i++) {
4264 struct pte *pe = &ptes[i];
4266 if (!valid_part_table_flag(pe->sectorbuffer)) {
4268 _("Warning: invalid flag 0x%04x of partition "
4269 "table %d will be corrected by w(rite)\n"),
4270 part_table_flag(pe->sectorbuffer), i + 1);
4271 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4280 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4282 * Print the message MESG, then read an integer between LOW and HIGH (inclusive).
4283 * If the user hits Enter, DFLT is returned.
4284 * Answers like +10 are interpreted as offsets from BASE.
4286 * There is no default if DFLT is not between LOW and HIGH.
4289 read_int(uint low, uint dflt, uint high, uint base, char *mesg)
4293 static char *ms = NULL;
4294 static int mslen = 0;
4296 if (!ms || strlen(mesg)+100 > mslen) {
4297 mslen = strlen(mesg)+200;
4298 ms = xrealloc(ms,mslen);
4301 if (dflt < low || dflt > high)
4305 snprintf(ms, mslen, _("%s (%d-%d, default %d): "),
4306 mesg, low, high, dflt);
4308 snprintf(ms, mslen, "%s (%d-%d): ",
4312 int use_default = default_ok;
4314 /* ask question and read answer */
4315 while (read_chars(ms) != '\n' && !isdigit(*line_ptr)
4316 && *line_ptr != '-' && *line_ptr != '+')
4319 if (*line_ptr == '+' || *line_ptr == '-') {
4320 i = atoi(line_ptr+1);
4321 if (*line_ptr == '-')
4323 while (isdigit(*++line_ptr))
4325 switch (*line_ptr) {
4328 if (!display_in_cyl_units)
4329 i *= heads * sectors;
4334 i /= (sector_size / 512);
4335 i /= units_per_sector;
4340 i /= (sector_size / 512);
4341 i /= units_per_sector;
4346 i /= (sector_size / 512);
4347 i /= units_per_sector;
4355 while (isdigit(*line_ptr)) {
4361 printf(_("Using default value %d\n"), i = dflt);
4362 if (i >= low && i <= high)
4365 printf(_("Value out of range.\n"));
4371 get_partition(int warn, int max) {
4375 i = read_int(1, 0, max, 0, _("Partition number")) - 1;
4379 if ((!sun_label && !sgi_label && !pe->part_table->sys_ind)
4380 #ifdef CONFIG_FEATURE_SUN_LABEL
4382 (!sunlabel->partitions[i].num_sectors ||
4383 !sunlabel->infos[i].id))
4385 #ifdef CONFIG_FEATURE_SGI_LABEL
4386 || (sgi_label && (!sgi_get_num_sectors(i)))
4390 _("Warning: partition %d has empty type\n"),
4397 get_existing_partition(int warn, int max) {
4401 for (i = 0; i < max; i++) {
4402 struct pte *pe = &ptes[i];
4403 struct partition *p = pe->part_table;
4405 if (p && !is_cleared_partition(p)) {
4412 printf(_("Selected partition %d\n"), pno+1);
4415 printf(_("No partition is defined yet!\n"));
4419 return get_partition(warn, max);
4423 get_nonexisting_partition(int warn, int max) {
4427 for (i = 0; i < max; i++) {
4428 struct pte *pe = &ptes[i];
4429 struct partition *p = pe->part_table;
4431 if (p && is_cleared_partition(p)) {
4438 printf(_("Selected partition %d\n"), pno+1);
4441 printf(_("All primary partitions have been defined already!\n"));
4445 return get_partition(warn, max);
4449 void change_units(void)
4451 display_in_cyl_units = !display_in_cyl_units;
4453 printf(_("Changing display/entry units to %s\n"),
4458 toggle_active(int i) {
4459 struct pte *pe = &ptes[i];
4460 struct partition *p = pe->part_table;
4462 if (IS_EXTENDED (p->sys_ind) && !p->boot_ind)
4464 _("WARNING: Partition %d is an extended partition\n"),
4466 p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG);
4471 toggle_dos_compatibility_flag(void) {
4472 dos_compatible_flag = ~dos_compatible_flag;
4473 if (dos_compatible_flag) {
4474 sector_offset = sectors;
4475 printf(_("DOS Compatibility flag is set\n"));
4479 printf(_("DOS Compatibility flag is not set\n"));
4484 delete_partition(int i) {
4485 struct pte *pe = &ptes[i];
4486 struct partition *p = pe->part_table;
4487 struct partition *q = pe->ext_pointer;
4489 /* Note that for the fifth partition (i == 4) we don't actually
4490 * decrement partitions.
4493 if (warn_geometry())
4494 return; /* C/H/S not set */
4497 #ifdef CONFIG_FEATURE_SUN_LABEL
4499 sun_delete_partition(i);
4503 #ifdef CONFIG_FEATURE_SGI_LABEL
4505 sgi_delete_partition(i);
4511 if (IS_EXTENDED (p->sys_ind) && i == ext_index) {
4513 ptes[ext_index].ext_pointer = NULL;
4514 extended_offset = 0;
4520 if (!q->sys_ind && i > 4) {
4521 /* the last one in the chain - just delete */
4524 clear_partition(ptes[i].ext_pointer);
4525 ptes[i].changed = 1;
4527 /* not the last one - further ones will be moved down */
4529 /* delete this link in the chain */
4530 p = ptes[i-1].ext_pointer;
4532 set_start_sect(p, get_start_sect(q));
4533 set_nr_sects(p, get_nr_sects(q));
4534 ptes[i-1].changed = 1;
4535 } else if (partitions > 5) { /* 5 will be moved to 4 */
4536 /* the first logical in a longer chain */
4539 if (pe->part_table) /* prevent SEGFAULT */
4540 set_start_sect(pe->part_table,
4541 get_partition_start(pe) -
4543 pe->offset = extended_offset;
4547 if (partitions > 5) {
4549 while (i < partitions) {
4550 ptes[i] = ptes[i+1];
4554 /* the only logical: clear only */
4555 clear_partition(ptes[i].part_table);
4560 change_sysid(void) {
4561 int i, sys, origsys;
4562 struct partition *p;
4564 i = get_existing_partition(0, partitions);
4567 p = ptes[i].part_table;
4568 origsys = sys = get_sysid(i);
4570 /* if changing types T to 0 is allowed, then
4571 the reverse change must be allowed, too */
4572 if (!sys && !sgi_label && !sun_label && !get_nr_sects(p))
4573 printf(_("Partition %d does not exist yet!\n"), i + 1);
4575 sys = read_hex (get_sys_types());
4577 if (!sys && !sgi_label && !sun_label) {
4578 printf(_("Type 0 means free space to many systems\n"
4579 "(but not to Linux). Having partitions of\n"
4580 "type 0 is probably unwise. You can delete\n"
4581 "a partition using the `d' command.\n"));
4585 if (!sun_label && !sgi_label) {
4586 if (IS_EXTENDED (sys) != IS_EXTENDED (p->sys_ind)) {
4587 printf(_("You cannot change a partition into"
4588 " an extended one or vice versa\n"
4589 "Delete it first.\n"));
4595 #ifdef CONFIG_FEATURE_SUN_LABEL
4596 if (sun_label && i == 2 && sys != WHOLE_DISK)
4597 printf(_("Consider leaving partition 3 "
4598 "as Whole disk (5),\n"
4599 "as SunOS/Solaris expects it and "
4600 "even Linux likes it.\n\n"));
4602 #ifdef CONFIG_FEATURE_SGI_LABEL
4603 if (sgi_label && ((i == 10 && sys != ENTIRE_DISK)
4604 || (i == 8 && sys != 0)))
4605 printf(_("Consider leaving partition 9 "
4606 "as volume header (0),\nand "
4607 "partition 11 as entire volume (6)"
4608 "as IRIX expects it.\n\n"));
4612 #ifdef CONFIG_FEATURE_SUN_LABEL
4614 sun_change_sysid(i, sys);
4617 #ifdef CONFIG_FEATURE_SGI_LABEL
4619 sgi_change_sysid(i, sys);
4623 printf (_("Changed system type of partition %d "
4624 "to %x (%s)\n"), i + 1, sys,
4625 partition_type(sys));
4626 ptes[i].changed = 1;
4627 if (is_dos_partition(origsys) ||
4628 is_dos_partition(sys))
4634 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
4637 /* check_consistency() and long2chs() added Sat Mar 6 12:28:16 1993,
4638 * faith@cs.unc.edu, based on code fragments from pfdisk by Gordon W. Ross,
4639 * Jan. 1990 (version 1.2.1 by Gordon W. Ross Aug. 1990; Modified by S.
4640 * Lubkin Oct. 1991). */
4642 static void long2chs(ulong ls, uint *c, uint *h, uint *s) {
4643 int spc = heads * sectors;
4648 *s = ls % sectors + 1; /* sectors count from 1 */
4651 static void check_consistency(const struct partition *p, int partition) {
4652 uint pbc, pbh, pbs; /* physical beginning c, h, s */
4653 uint pec, peh, pes; /* physical ending c, h, s */
4654 uint lbc, lbh, lbs; /* logical beginning c, h, s */
4655 uint lec, leh, les; /* logical ending c, h, s */
4657 if (!heads || !sectors || (partition >= 4))
4658 return; /* do not check extended partitions */
4660 /* physical beginning c, h, s */
4661 pbc = (p->cyl & 0xff) | ((p->sector << 2) & 0x300);
4663 pbs = p->sector & 0x3f;
4665 /* physical ending c, h, s */
4666 pec = (p->end_cyl & 0xff) | ((p->end_sector << 2) & 0x300);
4668 pes = p->end_sector & 0x3f;
4670 /* compute logical beginning (c, h, s) */
4671 long2chs(get_start_sect(p), &lbc, &lbh, &lbs);
4673 /* compute logical ending (c, h, s) */
4674 long2chs(get_start_sect(p) + get_nr_sects(p) - 1, &lec, &leh, &les);
4676 /* Same physical / logical beginning? */
4677 if (cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) {
4678 printf(_("Partition %d has different physical/logical "
4679 "beginnings (non-Linux?):\n"), partition + 1);
4680 printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs);
4681 printf(_("logical=(%d, %d, %d)\n"),lbc, lbh, lbs);
4684 /* Same physical / logical ending? */
4685 if (cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) {
4686 printf(_("Partition %d has different physical/logical "
4687 "endings:\n"), partition + 1);
4688 printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
4689 printf(_("logical=(%d, %d, %d)\n"),lec, leh, les);
4693 /* Beginning on cylinder boundary? */
4694 if (pbh != !pbc || pbs != 1) {
4695 printf(_("Partition %i does not start on cylinder "
4696 "boundary:\n"), partition + 1);
4697 printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs);
4698 printf(_("should be (%d, %d, 1)\n"), pbc, !pbc);
4702 /* Ending on cylinder boundary? */
4703 if (peh != (heads - 1) || pes != sectors) {
4704 printf(_("Partition %i does not end on cylinder boundary:\n"),
4707 printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
4708 printf(_("should be (%d, %d, %d)\n"),
4709 pec, heads - 1, sectors);
4715 list_disk_geometry(void) {
4716 long long bytes = (long long) total_number_of_sectors * 512;
4717 long megabytes = bytes/1000000;
4719 if (megabytes < 10000)
4720 printf(_("\nDisk %s: %ld MB, %lld bytes\n"),
4721 disk_device, megabytes, bytes);
4723 printf(_("\nDisk %s: %ld.%ld GB, %lld bytes\n"),
4724 disk_device, megabytes/1000, (megabytes/100)%10, bytes);
4725 printf(_("%d heads, %d sectors/track, %d cylinders"),
4726 heads, sectors, cylinders);
4727 if (units_per_sector == 1)
4728 printf(_(", total %lu sectors"),
4729 total_number_of_sectors / (sector_size/512));
4730 printf(_("\nUnits = %s of %d * %d = %d bytes\n\n"),
4732 units_per_sector, sector_size, units_per_sector * sector_size);
4736 * Check whether partition entries are ordered by their starting positions.
4737 * Return 0 if OK. Return i if partition i should have been earlier.
4738 * Two separate checks: primary and logical partitions.
4741 wrong_p_order(int *prev) {
4742 const struct pte *pe;
4743 const struct partition *p;
4744 uint last_p_start_pos = 0, p_start_pos;
4747 for (i = 0 ; i < partitions; i++) {
4750 last_p_start_pos = 0;
4753 if ((p = pe->part_table)->sys_ind) {
4754 p_start_pos = get_partition_start(pe);
4756 if (last_p_start_pos > p_start_pos) {
4762 last_p_start_pos = p_start_pos;
4769 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
4771 * Fix the chain of logicals.
4772 * extended_offset is unchanged, the set of sectors used is unchanged
4773 * The chain is sorted so that sectors increase, and so that
4774 * starting sectors increase.
4776 * After this it may still be that cfdisk doesnt like the table.
4777 * (This is because cfdisk considers expanded parts, from link to
4778 * end of partition, and these may still overlap.)
4780 * sfdisk /dev/hda > ohda; sfdisk /dev/hda < ohda
4784 fix_chain_of_logicals(void) {
4785 int j, oj, ojj, sj, sjj;
4786 struct partition *pj,*pjj,tmp;
4788 /* Stage 1: sort sectors but leave sector of part 4 */
4789 /* (Its sector is the global extended_offset.) */
4791 for (j = 5; j < partitions-1; j++) {
4792 oj = ptes[j].offset;
4793 ojj = ptes[j+1].offset;
4795 ptes[j].offset = ojj;
4796 ptes[j+1].offset = oj;
4797 pj = ptes[j].part_table;
4798 set_start_sect(pj, get_start_sect(pj)+oj-ojj);
4799 pjj = ptes[j+1].part_table;
4800 set_start_sect(pjj, get_start_sect(pjj)+ojj-oj);
4801 set_start_sect(ptes[j-1].ext_pointer,
4802 ojj-extended_offset);
4803 set_start_sect(ptes[j].ext_pointer,
4804 oj-extended_offset);
4809 /* Stage 2: sort starting sectors */
4811 for (j = 4; j < partitions-1; j++) {
4812 pj = ptes[j].part_table;
4813 pjj = ptes[j+1].part_table;
4814 sj = get_start_sect(pj);
4815 sjj = get_start_sect(pjj);
4816 oj = ptes[j].offset;
4817 ojj = ptes[j+1].offset;
4818 if (oj+sj > ojj+sjj) {
4822 set_start_sect(pj, ojj+sjj-oj);
4823 set_start_sect(pjj, oj+sj-ojj);
4828 /* Probably something was changed */
4829 for (j = 4; j < partitions; j++)
4830 ptes[j].changed = 1;
4835 fix_partition_table_order(void) {
4836 struct pte *pei, *pek;
4839 if (!wrong_p_order(NULL)) {
4840 printf(_("Nothing to do. Ordering is correct already.\n\n"));
4844 while ((i = wrong_p_order(&k)) != 0 && i < 4) {
4845 /* partition i should have come earlier, move it */
4846 /* We have to move data in the MBR */
4847 struct partition *pi, *pk, *pe, pbuf;
4851 pe = pei->ext_pointer;
4852 pei->ext_pointer = pek->ext_pointer;
4853 pek->ext_pointer = pe;
4855 pi = pei->part_table;
4856 pk = pek->part_table;
4858 memmove(&pbuf, pi, sizeof(struct partition));
4859 memmove(pi, pk, sizeof(struct partition));
4860 memmove(pk, &pbuf, sizeof(struct partition));
4862 pei->changed = pek->changed = 1;
4866 fix_chain_of_logicals();
4874 list_table(int xtra) {
4875 const struct partition *p;
4878 #ifdef CONFIG_FEATURE_SUN_LABEL
4880 sun_list_table(xtra);
4885 #ifdef CONFIG_FEATURE_SGI_LABEL
4887 sgi_list_table(xtra);
4892 list_disk_geometry();
4894 #ifdef CONFIG_FEATURE_OSF_LABEL
4896 xbsd_print_disklabel(xtra);
4901 /* Heuristic: we list partition 3 of /dev/foo as /dev/foo3,
4902 but if the device name ends in a digit, say /dev/foo1,
4903 then the partition is called /dev/foo1p3. */
4904 w = strlen(disk_device);
4905 if (w && isdigit(disk_device[w-1]))
4910 printf(_("%*s Boot Start End Blocks Id System\n"),
4913 for (i = 0; i < partitions; i++) {
4914 const struct pte *pe = &ptes[i];
4917 if (p && !is_cleared_partition(p)) {
4918 unsigned int psects = get_nr_sects(p);
4919 unsigned int pblocks = psects;
4920 unsigned int podd = 0;
4922 if (sector_size < 1024) {
4923 pblocks /= (1024 / sector_size);
4924 podd = psects % (1024 / sector_size);
4926 if (sector_size > 1024)
4927 pblocks *= (sector_size / 1024);
4929 "%s %c %9ld %9ld %9ld%c %2x %s\n",
4930 partname(disk_device, i+1, w+2),
4931 /* boot flag */ !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG
4933 /* start */ (long) cround(get_partition_start(pe)),
4934 /* end */ (long) cround(get_partition_start(pe) + psects
4935 - (psects ? 1 : 0)),
4936 /* odd flag on end */ (long) pblocks, podd ? '+' : ' ',
4937 /* type id */ p->sys_ind,
4938 /* type name */ partition_type(p->sys_ind));
4939 check_consistency(p, i);
4943 /* Is partition table in disk order? It need not be, but... */
4944 /* partition table entries are not checked for correct order if this
4945 is a sgi, sun or aix labeled disk... */
4946 if (dos_label && wrong_p_order(NULL)) {
4947 printf(_("\nPartition table entries are not in disk order\n"));
4951 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
4953 x_list_table(int extend) {
4954 const struct pte *pe;
4955 const struct partition *p;
4958 printf(_("\nDisk %s: %d heads, %d sectors, %d cylinders\n\n"),
4959 disk_device, heads, sectors, cylinders);
4960 printf(_("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n"));
4961 for (i = 0 ; i < partitions; i++) {
4963 p = (extend ? pe->ext_pointer : pe->part_table);
4965 printf("%2d %02x%4d%4d%5d%4d%4d%5d%9d%9d %02x\n",
4966 i + 1, p->boot_ind, p->head,
4968 cylinder(p->sector, p->cyl), p->end_head,
4969 sector(p->end_sector),
4970 cylinder(p->end_sector, p->end_cyl),
4971 get_start_sect(p), get_nr_sects(p), p->sys_ind);
4973 check_consistency(p, i);
4979 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4981 fill_bounds(uint *first, uint *last) {
4983 const struct pte *pe = &ptes[0];
4984 const struct partition *p;
4986 for (i = 0; i < partitions; pe++,i++) {
4988 if (!p->sys_ind || IS_EXTENDED (p->sys_ind)) {
4989 first[i] = 0xffffffff;
4992 first[i] = get_partition_start(pe);
4993 last[i] = first[i] + get_nr_sects(p) - 1;
4999 check(int n, uint h, uint s, uint c, uint start) {
5000 uint total, real_s, real_c;
5002 real_s = sector(s) - 1;
5003 real_c = cylinder(s, c);
5004 total = (real_c * sectors + real_s) * heads + h;
5006 fprintf(stderr, _("Warning: partition %d contains sector 0\n"), n);
5009 _("Partition %d: head %d greater than maximum %d\n"),
5011 if (real_s >= sectors)
5012 fprintf(stderr, _("Partition %d: sector %d greater than "
5013 "maximum %d\n"), n, s, sectors);
5014 if (real_c >= cylinders)
5015 fprintf(stderr, _("Partitions %d: cylinder %d greater than "
5016 "maximum %d\n"), n, real_c + 1, cylinders);
5017 if (cylinders <= 1024 && start != total)
5019 _("Partition %d: previous sectors %d disagrees with "
5020 "total %d\n"), n, start, total);
5027 uint first[partitions], last[partitions];
5028 struct partition *p;
5030 if (warn_geometry())
5033 #ifdef CONFIG_FEATURE_SUN_LABEL
5039 #ifdef CONFIG_FEATURE_SGI_LABEL
5046 fill_bounds(first, last);
5047 for (i = 0; i < partitions; i++) {
5048 struct pte *pe = &ptes[i];
5051 if (p->sys_ind && !IS_EXTENDED (p->sys_ind)) {
5052 check_consistency(p, i);
5053 if (get_partition_start(pe) < first[i])
5054 printf(_("Warning: bad start-of-data in "
5055 "partition %d\n"), i + 1);
5056 check(i + 1, p->end_head, p->end_sector, p->end_cyl,
5058 total += last[i] + 1 - first[i];
5059 for (j = 0; j < i; j++)
5060 if ((first[i] >= first[j] && first[i] <= last[j])
5061 || ((last[i] <= last[j] && last[i] >= first[j]))) {
5062 printf(_("Warning: partition %d overlaps "
5063 "partition %d.\n"), j + 1, i + 1);
5064 total += first[i] >= first[j] ?
5065 first[i] : first[j];
5066 total -= last[i] <= last[j] ?
5072 if (extended_offset) {
5073 struct pte *pex = &ptes[ext_index];
5074 uint e_last = get_start_sect(pex->part_table) +
5075 get_nr_sects(pex->part_table) - 1;
5077 for (i = 4; i < partitions; i++) {
5079 p = ptes[i].part_table;
5081 if (i != 4 || i + 1 < partitions)
5082 printf(_("Warning: partition %d "
5083 "is empty\n"), i + 1);
5085 else if (first[i] < extended_offset ||
5087 printf(_("Logical partition %d not entirely in "
5088 "partition %d\n"), i + 1, ext_index + 1);
5092 if (total > heads * sectors * cylinders)
5093 printf(_("Total allocated sectors %d greater than the maximum "
5094 "%d\n"), total, heads * sectors * cylinders);
5095 else if ((total = heads * sectors * cylinders - total) != 0)
5096 printf(_("%d unallocated sectors\n"), total);
5100 add_partition(int n, int sys) {
5101 char mesg[256]; /* 48 does not suffice in Japanese */
5103 struct partition *p = ptes[n].part_table;
5104 struct partition *q = ptes[ext_index].part_table;
5105 uint start, stop = 0, limit, temp,
5106 first[partitions], last[partitions];
5108 if (p && p->sys_ind) {
5109 printf(_("Partition %d is already defined. Delete "
5110 "it before re-adding it.\n"), n + 1);
5113 fill_bounds(first, last);
5115 start = sector_offset;
5116 if (display_in_cyl_units)
5117 limit = heads * sectors * cylinders - 1;
5119 limit = total_number_of_sectors - 1;
5120 if (extended_offset) {
5121 first[ext_index] = extended_offset;
5122 last[ext_index] = get_start_sect(q) +
5123 get_nr_sects(q) - 1;
5126 start = extended_offset + sector_offset;
5127 limit = get_start_sect(q) + get_nr_sects(q) - 1;
5129 if (display_in_cyl_units)
5130 for (i = 0; i < partitions; i++)
5131 first[i] = (cround(first[i]) - 1) * units_per_sector;
5133 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
5136 for (i = 0; i < partitions; i++) {
5139 if (start == ptes[i].offset)
5140 start += sector_offset;
5141 lastplusoff = last[i] + ((n<4) ? 0 : sector_offset);
5142 if (start >= first[i] && start <= lastplusoff)
5143 start = lastplusoff + 1;
5147 if (start >= temp+units_per_sector && readed) {
5148 printf(_("Sector %d is already allocated\n"), temp);
5152 if (!readed && start == temp) {
5155 saved_start = start;
5156 start = read_int(cround(saved_start), cround(saved_start), cround(limit),
5158 if (display_in_cyl_units) {
5159 start = (start - 1) * units_per_sector;
5160 if (start < saved_start) start = saved_start;
5164 } while (start != temp || !readed);
5165 if (n > 4) { /* NOT for fifth partition */
5166 struct pte *pe = &ptes[n];
5168 pe->offset = start - sector_offset;
5169 if (pe->offset == extended_offset) { /* must be corrected */
5171 if (sector_offset == 1)
5176 for (i = 0; i < partitions; i++) {
5177 struct pte *pe = &ptes[i];
5179 if (start < pe->offset && limit >= pe->offset)
5180 limit = pe->offset - 1;
5181 if (start < first[i] && limit >= first[i])
5182 limit = first[i] - 1;
5184 if (start > limit) {
5185 printf(_("No free sectors available\n"));
5190 if (cround(start) == cround(limit)) {
5193 snprintf(mesg, sizeof(mesg),
5194 _("Last %s or +size or +sizeM or +sizeK"),
5195 str_units(SINGULAR));
5196 stop = read_int(cround(start), cround(limit), cround(limit),
5197 cround(start), mesg);
5198 if (display_in_cyl_units) {
5199 stop = stop * units_per_sector - 1;
5205 set_partition(n, 0, start, stop, sys);
5207 set_partition(n - 1, 1, ptes[n].offset, stop, EXTENDED);
5209 if (IS_EXTENDED (sys)) {
5210 struct pte *pe4 = &ptes[4];
5211 struct pte *pen = &ptes[n];
5214 pen->ext_pointer = p;
5215 pe4->offset = extended_offset = start;
5216 pe4->sectorbuffer = xcalloc(1, sector_size);
5217 pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
5218 pe4->ext_pointer = pe4->part_table + 1;
5226 if (partitions > 5 || ptes[4].part_table->sys_ind) {
5227 struct pte *pe = &ptes[partitions];
5229 pe->sectorbuffer = xcalloc(1, sector_size);
5230 pe->part_table = pt_offset(pe->sectorbuffer, 0);
5231 pe->ext_pointer = pe->part_table + 1;
5236 add_partition(partitions - 1, LINUX_NATIVE);
5240 new_partition(void) {
5241 int i, free_primary = 0;
5243 if (warn_geometry())
5246 #ifdef CONFIG_FEATURE_SUN_LABEL
5248 add_sun_partition(get_partition(0, partitions), LINUX_NATIVE);
5252 #ifdef CONFIG_FEATURE_SGI_LABEL
5254 sgi_add_partition(get_partition(0, partitions), LINUX_NATIVE);
5258 #ifdef CONFIG_FEATURE_AIX_LABEL
5260 printf(_("\tSorry - this fdisk cannot handle AIX disk labels."
5261 "\n\tIf you want to add DOS-type partitions, create"
5262 "\n\ta new empty DOS partition table first. (Use o.)"
5264 "This will destroy the present disk contents.\n"));
5269 if (partitions >= MAXIMUM_PARTS) {
5270 printf(_("The maximum number of partitions has been created\n"));
5274 for (i = 0; i < 4; i++)
5275 free_primary += !ptes[i].part_table->sys_ind;
5276 if (!free_primary) {
5277 if (extended_offset)
5280 printf(_("You must delete some partition and add "
5281 "an extended partition first\n"));
5283 char c, line[LINE_LENGTH];
5284 snprintf(line, sizeof(line), "%s\n %s\n p primary "
5285 "partition (1-4)\n",
5286 "Command action", (extended_offset ?
5287 "l logical (5 or over)" : "e extended"));
5289 if ((c = read_char(line)) == 'p' || c == 'P') {
5290 i = get_nonexisting_partition(0, 4);
5292 add_partition(i, LINUX_NATIVE);
5295 else if (c == 'l' && extended_offset) {
5299 else if (c == 'e' && !extended_offset) {
5300 i = get_nonexisting_partition(0, 4);
5302 add_partition(i, EXTENDED);
5306 printf(_("Invalid partition number "
5307 "for type `%c'\n"), c);
5318 if (ptes[i].changed)
5319 ptes[3].changed = 1;
5320 for (i = 3; i < partitions; i++) {
5321 struct pte *pe = &ptes[i];
5324 write_part_table_flag(pe->sectorbuffer);
5325 write_sector(pe->offset, pe->sectorbuffer);
5329 #ifdef CONFIG_FEATURE_SGI_LABEL
5330 else if (sgi_label) {
5331 /* no test on change? the printf below might be mistaken */
5335 #ifdef CONFIG_FEATURE_SUN_LABEL
5336 else if (sun_label) {
5340 if (ptes[i].changed)
5347 printf(_("The partition table has been altered!\n\n"));
5348 reread_partition_table(1);
5352 reread_partition_table(int leave) {
5356 printf(_("Calling ioctl() to re-read partition table.\n"));
5359 if ((i = ioctl(fd, BLKRRPART)) != 0) {
5362 /* some kernel versions (1.2.x) seem to have trouble
5363 rereading the partition table, but if asked to do it
5364 twice, the second time works. - biro@yggdrasil.com */
5367 if ((i = ioctl(fd, BLKRRPART)) != 0)
5372 printf(_("\nWARNING: Re-reading the partition table "
5373 "failed with error %d: %s.\n"
5374 "The kernel still uses the old table.\n"
5375 "The new table will be used "
5376 "at the next reboot.\n"),
5377 error, strerror(error));
5382 _("\nWARNING: If you have created or modified any DOS 6.x\n"
5383 "partitions, please see the fdisk manual page for additional\n"
5389 printf(_("Syncing disks.\n"));
5391 sleep(4); /* for sync() */
5395 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
5397 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
5398 #define MAX_PER_LINE 16
5400 print_buffer(char pbuffer[]) {
5404 for (i = 0, l = 0; i < sector_size; i++, l++) {
5406 printf("0x%03X:", i);
5407 printf(" %02X", (unsigned char) pbuffer[i]);
5408 if (l == MAX_PER_LINE - 1) {
5423 printf(_("Device: %s\n"), disk_device);
5424 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
5425 if (sun_label || sgi_label)
5426 print_buffer(MBRbuffer);
5429 for (i = 3; i < partitions; i++)
5430 print_buffer(ptes[i].sectorbuffer);
5435 struct pte *pe = &ptes[i];
5436 struct partition *p = pe->part_table;
5439 if (warn_geometry())
5441 if (!p->sys_ind || !get_nr_sects(p) || IS_EXTENDED (p->sys_ind)) {
5442 printf(_("Partition %d has no data area\n"), i + 1);
5445 first = get_partition_start(pe);
5446 new = read_int(first, first, first + get_nr_sects(p) - 1, first,
5447 _("New beginning of data")) - pe->offset;
5449 if (new != get_nr_sects(p)) {
5450 first = get_nr_sects(p) + get_start_sect(p) - new;
5451 set_nr_sects(p, first);
5452 set_start_sect(p, new);
5463 c = tolower(read_char(_("Expert command (m for help): ")));
5466 #ifdef CONFIG_FEATURE_SUN_LABEL
5473 move_begin(get_partition(0, partitions));
5476 user_cylinders = cylinders =
5477 read_int(1, cylinders, 1048576, 0,
5478 _("Number of cylinders"));
5479 #ifdef CONFIG_FEATURE_SUN_LABEL
5481 sun_set_ncyl(cylinders);
5490 #ifdef CONFIG_FEATURE_SGI_LABEL
5495 #ifdef CONFIG_FEATURE_SUN_LABEL
5505 fix_partition_table_order();
5508 #ifdef CONFIG_FEATURE_SGI_LABEL
5513 user_heads = heads = read_int(1, heads, 256, 0,
5514 _("Number of heads"));
5518 #ifdef CONFIG_FEATURE_SUN_LABEL
5524 #ifdef CONFIG_FEATURE_SUN_LABEL
5530 #ifdef CONFIG_FEATURE_SUN_LABEL
5544 user_sectors = sectors = read_int(1, sectors, 63, 0,
5545 _("Number of sectors"));
5546 if (dos_compatible_flag) {
5547 sector_offset = sectors;
5548 fprintf(stderr, _("Warning: setting "
5549 "sector offset for DOS "
5558 write_table(); /* does not return */
5561 #ifdef CONFIG_FEATURE_SUN_LABEL
5563 sun_set_pcylcount();
5571 #endif /* ADVANCED mode */
5574 is_ide_cdrom_or_tape(const char *device) {
5577 struct stat statbuf;
5580 /* No device was given explicitly, and we are trying some
5581 likely things. But opening /dev/hdc may produce errors like
5582 "hdc: tray open or drive not ready"
5583 if it happens to be a CD-ROM drive. It even happens that
5584 the process hangs on the attempt to read a music CD.
5585 So try to be careful. This only works since 2.1.73. */
5587 if (strncmp("/dev/hd", device, 7))
5590 snprintf(buf, sizeof(buf), "/proc/ide/%s/media", device+5);
5591 procf = fopen(buf, "r");
5592 if (procf != NULL && fgets(buf, sizeof(buf), procf))
5593 is_ide = (!strncmp(buf, "cdrom", 5) ||
5594 !strncmp(buf, "tape", 4));
5596 /* Now when this proc file does not exist, skip the
5597 device when it is read-only. */
5598 if (stat(device, &statbuf) == 0)
5599 is_ide = ((statbuf.st_mode & 0222) == 0);
5607 try(const char *device, int user_specified) {
5610 disk_device = device;
5611 if (setjmp(listingbuf))
5613 if (!user_specified)
5614 if (is_ide_cdrom_or_tape(device))
5616 if ((fd = open(disk_device, type_open)) >= 0) {
5617 gb = get_boot(try_only);
5618 if (gb > 0) { /* I/O error */
5620 } else if (gb < 0) { /* no DOS signature */
5621 list_disk_geometry();
5624 #ifdef CONFIG_FEATURE_OSF_LABEL
5625 if (btrydev(device) < 0)
5628 _("Disk %s doesn't contain a valid "
5629 "partition table\n"), device);
5634 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5635 if (!sun_label && partitions > 4)
5636 delete_partition(ext_index);
5640 /* Ignore other errors, since we try IDE
5641 and SCSI hard disks which may not be
5642 installed on the system. */
5643 if (errno == EACCES) {
5644 fprintf(stderr, _("Cannot open %s\n"), device);
5650 /* for fdisk -l: try all things in /proc/partitions
5651 that look like a partition name (do not end in a digit) */
5655 char line[100], ptname[100], devname[120], *s;
5658 procpt = wfopen(PROC_PARTITIONS, "r");
5660 while (fgets(line, sizeof(line), procpt)) {
5661 if (sscanf (line, " %d %d %d %[^\n ]",
5662 &ma, &mi, &sz, ptname) != 4)
5664 for (s = ptname; *s; s++);
5667 sprintf(devname, "/dev/%s", ptname);
5670 #ifdef CONFIG_FEATURE_CLEAN_UP
5675 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5677 unknown_command(int c) {
5678 printf(_("%c: unknown command\n"), c);
5682 int fdisk_main(int argc, char **argv) {
5684 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5687 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5693 * fdisk -l [-b sectorsize] [-u] device ...
5694 * fdisk -s [partition] ...
5695 * fdisk [-b sectorsize] [-u] device
5697 * Options -C, -H, -S set the geometry.
5700 while ((c = getopt(argc, argv, "b:C:H:lS:uvV"
5701 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5707 /* Ugly: this sector size is really per device,
5708 so cannot be combined with multiple disks,
5709 and te same goes for the C/H/S options.
5711 sector_size = atoi(optarg);
5712 if (sector_size != 512 && sector_size != 1024 &&
5713 sector_size != 2048)
5716 user_set_sector_size = 1;
5719 user_cylinders = atoi(optarg);
5722 user_heads = atoi(optarg);
5723 if (user_heads <= 0 || user_heads >= 256)
5727 user_sectors = atoi(optarg);
5728 if (user_sectors <= 0 || user_sectors >= 64)
5732 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5736 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5742 display_in_cyl_units = 0;
5746 printf("fdisk v" UTIL_LINUX_VERSION "\n");
5754 printf(_("This kernel finds the sector size itself - "
5755 "-b option ignored\n"));
5757 if (user_set_sector_size && argc-optind != 1)
5758 printf(_("Warning: the -b (set sector size) option should"
5759 " be used with one specified device\n"));
5762 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5766 type_open = O_RDONLY;
5767 if (argc > optind) {
5770 /* avoid gcc warning:
5771 variable `k' might be clobbered by `longjmp' */
5775 for (k=optind; k<argc; k++)
5778 /* we no longer have default device names */
5779 /* but, we can use /proc/partitions instead */
5783 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5787 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5793 type_open = O_RDONLY;
5795 opts = argc - optind;
5799 for (j = optind; j < argc; j++) {
5800 disk_device = argv[j];
5801 if ((fd = open(disk_device, type_open)) < 0)
5802 fdisk_fatal(unable_to_open);
5803 if (ioctl(fd, BLKGETSIZE, &size))
5804 fdisk_fatal(ioctl_error);
5807 printf("%ld\n", size/2);
5809 printf("%s: %ld\n", argv[j], size/2);
5815 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5816 if (argc-optind == 1)
5817 disk_device = argv[optind];
5823 #ifdef CONFIG_FEATURE_OSF_LABEL
5825 /* OSF label, and no DOS label */
5826 printf(_("Detected an OSF/1 disklabel on %s, entering "
5827 "disklabel mode.\n"),
5831 /* If we return we may want to make an empty DOS label? */
5837 c = tolower(read_char(_("Command (m for help): ")));
5841 toggle_active(get_partition(1, partitions));
5842 #ifdef CONFIG_FEATURE_SUN_LABEL
5844 toggle_sunflags(get_partition(1, partitions),
5847 #ifdef CONFIG_FEATURE_SGI_LABEL
5849 sgi_set_bootpartition(
5850 get_partition(1, partitions));
5856 #ifdef CONFIG_FEATURE_SGI_LABEL
5858 printf(_("\nThe current boot file is: %s\n"),
5859 sgi_get_bootfile());
5860 if (read_chars(_("Please enter the name of the "
5861 "new boot file: ")) == '\n')
5862 printf(_("Boot file unchanged\n"));
5864 sgi_set_bootfile(line_ptr);
5867 #ifdef CONFIG_FEATURE_OSF_LABEL
5873 toggle_dos_compatibility_flag();
5874 #ifdef CONFIG_FEATURE_SUN_LABEL
5876 toggle_sunflags(get_partition(1, partitions),
5879 #ifdef CONFIG_FEATURE_SGI_LABEL
5881 sgi_set_swappartition(
5882 get_partition(1, partitions));
5889 int j = get_existing_partition(1, partitions);
5891 delete_partition(j);
5895 #ifdef CONFIG_FEATURE_SGI_LABEL
5902 list_types(get_sys_types());
5921 #ifdef CONFIG_FEATURE_SUN_LABEL
5935 write_table(); /* does not return */
5937 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
5939 #ifdef CONFIG_FEATURE_SGI_LABEL
5942 _("\n\tSorry, no experts menu for SGI "
5943 "partition tables available.\n\n"));
5956 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */