1 /* fdisk.c -- Partition table manipulator for Linux.
3 * Copyright (C) 1992 A. V. Le Blanc (LeBlanc@mcc.ac.uk)
4 * Copyright (C) 2001,2002 Vladimir Oleynik <dzo@simtreas.ru> (initial bb port)
6 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
9 /* Current changes have not compatibility with this version */
10 #define UTIL_LINUX_VERSION "2.12"
15 #define PROC_PARTITIONS "/proc/partitions"
18 #include <sys/types.h>
19 #include <sys/stat.h> /* stat */
28 #include <assert.h> /* assert */
31 #include <sys/ioctl.h>
32 #include <sys/param.h>
33 #include <sys/sysmacros.h> /* major */
35 #include <stdint.h> /* for uint32_t, uint16_t, uint8_t, int16_t, etc */
37 /* Copied from linux/major.h */
38 #define FLOPPY_MAJOR 2
40 #include <sys/utsname.h>
46 #define BLKRRPART _IO(0x12,95) /* re-read partition table */
47 #define BLKGETSIZE _IO(0x12,96) /* return device size */
48 #define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */
49 #define BLKSSZGET _IO(0x12,104) /* get block device sector size */
55 #define DEFAULT_SECTOR_SIZE 512
56 #define MAX_SECTOR_SIZE 2048
57 #define SECTOR_SIZE 512 /* still used in BSD code */
58 #define MAXIMUM_PARTS 60
60 #define ACTIVE_FLAG 0x80
63 #define WIN98_EXTENDED 0x0f
64 #define LINUX_PARTITION 0x81
65 #define LINUX_SWAP 0x82
66 #define LINUX_NATIVE 0x83
67 #define LINUX_EXTENDED 0x85
68 #define LINUX_LVM 0x8e
69 #define LINUX_RAID 0xfd
74 #define IS_EXTENDED(i) \
75 ((i) == EXTENDED || (i) == WIN98_EXTENDED || (i) == LINUX_EXTENDED)
77 #define SIZE(a) (sizeof(a)/sizeof((a)[0]))
79 #define cround(n) (display_in_cyl_units ? ((n)/units_per_sector)+1 : (n))
80 #define scround(x) (((x)+units_per_sector-1)/units_per_sector)
82 #ifdef CONFIG_FEATURE_SUN_LABEL
83 #define SCSI_IOCTL_GET_IDLUN 0x5382
87 /* including <linux/hdreg.h> also fails */
90 unsigned char sectors;
91 unsigned short cylinders;
95 #define HDIO_GETGEO 0x0301 /* get device geometry */
102 static uint sector_size = DEFAULT_SECTOR_SIZE;
103 static uint user_set_sector_size;
104 static uint sector_offset = 1;
107 * Raw disk label. For DOS-type partition tables the MBR,
108 * with descriptions of the primary partitions.
110 #if (MAX_SECTOR_SIZE) > (BUFSIZ+1)
111 static char MBRbuffer[MAX_SECTOR_SIZE];
113 # define MBRbuffer bb_common_bufsiz1
116 #ifdef CONFIG_FEATURE_OSF_LABEL
117 static int possibly_osf_label;
120 static uint heads, sectors, cylinders;
121 static void update_units(void);
125 * return partition name - uses static storage unless buf is supplied
128 partname(const char *dev, int pno, int lth)
130 static char buffer[80];
137 bufsiz = sizeof(buffer);
142 if (isdigit(dev[w-1]))
145 /* devfs kludge - note: fdisk partition names are not supposed
146 to equal kernel names, so there is no reason to do this */
147 if (strcmp(dev + w - 4, "disc") == 0) {
155 snprintf(bufp, bufsiz, "%*.*s%s%-2u",
156 lth-wp-2, w, dev, p, pno);
158 snprintf(bufp, bufsiz, "%.*s%s%-2u", w, dev, p, pno);
164 unsigned char boot_ind; /* 0x80 - active */
165 unsigned char head; /* starting head */
166 unsigned char sector; /* starting sector */
167 unsigned char cyl; /* starting cylinder */
168 unsigned char sys_ind; /* What partition type */
169 unsigned char end_head; /* end head */
170 unsigned char end_sector; /* end sector */
171 unsigned char end_cyl; /* end cylinder */
172 unsigned char start4[4]; /* starting sector counting from 0 */
173 unsigned char size4[4]; /* nr of sectors in partition */
177 ioctl_error, unable_to_open, unable_to_read, unable_to_seek,
182 label_dos, label_sun, label_sgi, label_aix, label_osf
185 enum action { fdisk, require, try_only, create_empty_dos, create_empty_sun };
187 static enum label_type current_label_type;
189 static const char *disk_device;
190 static int fd; /* the disk */
191 static int partitions = 4; /* maximum partition + 1 */
192 static uint display_in_cyl_units = 1;
193 static uint units_per_sector = 1;
194 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
195 static char *line_ptr;
196 static void change_units(void);
197 static void reread_partition_table(int leave);
198 static void delete_partition(int i);
199 static int get_partition(int warn, int max);
200 static void list_types(const struct systypes *sys);
201 static uint read_int(uint low, uint dflt, uint high, uint base, char *mesg);
203 static const char *partition_type(unsigned char type);
204 static void fdisk_fatal(enum failure why) ATTRIBUTE_NORETURN;
205 static void get_geometry(void);
206 static int get_boot(enum action what);
211 #define hex_val(c) ({ \
213 isdigit(_c) ? _c - '0' : \
214 tolower(_c) + 10 - 'a'; \
218 #define LINE_LENGTH 800
219 #define pt_offset(b, n) ((struct partition *)((b) + 0x1be + \
220 (n) * sizeof(struct partition)))
221 #define sector(s) ((s) & 0x3f)
222 #define cylinder(s, c) ((c) | (((s) & 0xc0) << 2))
224 #define hsc2sector(h,s,c) (sector(s) - 1 + sectors * \
225 ((h) + heads * cylinder(s,c)))
226 #define set_hsc(h,s,c,sector) { \
227 s = sector % sectors + 1; \
229 h = sector % heads; \
232 s |= (sector >> 2) & 0xc0; \
236 static int32_t get_start_sect(const struct partition *p);
237 static int32_t get_nr_sects(const struct partition *p);
240 * per partition table entry data
242 * The four primary partitions have the same sectorbuffer (MBRbuffer)
243 * and have NULL ext_pointer.
244 * Each logical partition table entry has two pointers, one for the
245 * partition and one link to the next one.
248 struct partition *part_table; /* points into sectorbuffer */
249 struct partition *ext_pointer; /* points into sectorbuffer */
250 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
251 char changed; /* boolean */
253 off_t offset; /* disk sector number */
254 char *sectorbuffer; /* disk sector contents */
255 } ptes[MAXIMUM_PARTS];
258 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
260 set_all_unchanged(void)
264 for (i = 0; i < MAXIMUM_PARTS; i++)
273 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
275 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_OSF_LABEL)
276 static struct partition *
277 get_part_table(int i)
279 return ptes[i].part_table;
285 { /* n==1: use singular */
287 return display_in_cyl_units ? _("cylinder") : _("sector");
289 return display_in_cyl_units ? _("cylinders") : _("sectors");
293 valid_part_table_flag(const char *mbuffer) {
294 const unsigned char *b = (const unsigned char *)mbuffer;
295 return (b[510] == 0x55 && b[511] == 0xaa);
298 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
299 static char line_buffer[LINE_LENGTH];
301 /* read line; return 0 or first char */
305 static int got_eof = 0;
307 fflush (stdout); /* requested by niles@scyld.com */
308 line_ptr = line_buffer;
309 if (!fgets(line_buffer, LINE_LENGTH, stdin)) {
311 got_eof++; /* user typed ^D ? */
313 fprintf(stderr, _("\ngot EOF thrice - exiting..\n"));
318 while (*line_ptr && !isgraph(*line_ptr))
324 read_char(const char *mesg)
328 } while (!read_line());
333 read_chars(const char *mesg)
344 read_hex(const struct systypes *sys)
349 read_char(_("Hex code (type L to list codes): "));
350 if (*line_ptr == 'l' || *line_ptr == 'L')
352 else if (isxdigit (*line_ptr)) {
355 hex = hex << 4 | hex_val(*line_ptr++);
356 while (isxdigit(*line_ptr));
361 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
363 #ifdef CONFIG_FEATURE_AIX_LABEL
365 * Copyright (C) Andreas Neuper, Sep 1998.
366 * This file may be redistributed under
367 * the terms of the GNU Public License.
371 unsigned int magic; /* expect AIX_LABEL_MAGIC */
372 unsigned int fillbytes1[124];
373 unsigned int physical_volume_id;
374 unsigned int fillbytes2[124];
377 #define AIX_LABEL_MAGIC 0xc9c2d4c1
378 #define AIX_LABEL_MAGIC_SWAPPED 0xc1d4c2c9
379 #define AIX_INFO_MAGIC 0x00072959
380 #define AIX_INFO_MAGIC_SWAPPED 0x59290700
382 #define aixlabel ((aix_partition *)MBRbuffer)
387 * 1999-03-20 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
388 * Internationalization
390 * 2003-03-20 Phillip Kesling <pkesling@sgi.com>
394 static int aix_other_endian;
395 static short aix_volumes = 1;
398 * only dealing with free blocks here
405 _("\n\tThere is a valid AIX label on this disk.\n"
406 "\tUnfortunately Linux cannot handle these\n"
407 "\tdisks at the moment. Nevertheless some\n"
409 "\t1. fdisk will destroy its contents on write.\n"
410 "\t2. Be sure that this disk is NOT a still vital\n"
411 "\t part of a volume group. (Otherwise you may\n"
412 "\t erase the other disks as well, if unmirrored.)\n"
413 "\t3. Before deleting this physical volume be sure\n"
414 "\t to remove the disk logically from your AIX\n"
415 "\t machine. (Otherwise you become an AIXpert).")
420 check_aix_label(void)
422 if (aixlabel->magic != AIX_LABEL_MAGIC &&
423 aixlabel->magic != AIX_LABEL_MAGIC_SWAPPED) {
424 current_label_type = 0;
425 aix_other_endian = 0;
428 aix_other_endian = (aixlabel->magic == AIX_LABEL_MAGIC_SWAPPED);
430 current_label_type = label_aix;
434 /*aix_nolabel();*/ /* %% */
435 /*aix_label = 1;*/ /* %% */
438 #endif /* AIX_LABEL */
440 #ifdef CONFIG_FEATURE_OSF_LABEL
442 * Copyright (c) 1987, 1988 Regents of the University of California.
443 * All rights reserved.
445 * Redistribution and use in source and binary forms, with or without
446 * modification, are permitted provided that the following conditions
448 * 1. Redistributions of source code must retain the above copyright
449 * notice, this list of conditions and the following disclaimer.
450 * 2. Redistributions in binary form must reproduce the above copyright
451 * notice, this list of conditions and the following disclaimer in the
452 * documentation and/or other materials provided with the distribution.
453 * 3. All advertising materials mentioning features or use of this software
454 * must display the following acknowledgment:
455 * This product includes software developed by the University of
456 * California, Berkeley and its contributors.
457 * 4. Neither the name of the University nor the names of its contributors
458 * may be used to endorse or promote products derived from this software
459 * without specific prior written permission.
461 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
462 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
463 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
464 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
465 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
466 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
467 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
468 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
469 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
470 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
475 #ifndef BSD_DISKMAGIC
476 #define BSD_DISKMAGIC ((uint32_t) 0x82564557)
479 #ifndef BSD_MAXPARTITIONS
480 #define BSD_MAXPARTITIONS 16
483 #define BSD_LINUX_BOOTDIR "/usr/ucb/mdec"
485 #if defined (i386) || defined (__sparc__) || defined (__arm__) || defined (__mips__) || defined (__s390__) || defined (__sh__) || defined(__x86_64__)
486 #define BSD_LABELSECTOR 1
487 #define BSD_LABELOFFSET 0
488 #elif defined (__alpha__) || defined (__powerpc__) || defined (__ia64__) || defined (__hppa__)
489 #define BSD_LABELSECTOR 0
490 #define BSD_LABELOFFSET 64
491 #elif defined (__s390__) || defined (__s390x__)
492 #define BSD_LABELSECTOR 1
493 #define BSD_LABELOFFSET 0
495 #error unknown architecture
498 #define BSD_BBSIZE 8192 /* size of boot area, with label */
499 #define BSD_SBSIZE 8192 /* max size of fs superblock */
501 struct xbsd_disklabel {
502 uint32_t d_magic; /* the magic number */
503 int16_t d_type; /* drive type */
504 int16_t d_subtype; /* controller/d_type specific */
505 char d_typename[16]; /* type name, e.g. "eagle" */
506 char d_packname[16]; /* pack identifier */
508 uint32_t d_secsize; /* # of bytes per sector */
509 uint32_t d_nsectors; /* # of data sectors per track */
510 uint32_t d_ntracks; /* # of tracks per cylinder */
511 uint32_t d_ncylinders; /* # of data cylinders per unit */
512 uint32_t d_secpercyl; /* # of data sectors per cylinder */
513 uint32_t d_secperunit; /* # of data sectors per unit */
515 * Spares (bad sector replacements) below
516 * are not counted in d_nsectors or d_secpercyl.
517 * Spare sectors are assumed to be physical sectors
518 * which occupy space at the end of each track and/or cylinder.
520 uint16_t d_sparespertrack; /* # of spare sectors per track */
521 uint16_t d_sparespercyl; /* # of spare sectors per cylinder */
523 * Alternate cylinders include maintenance, replacement,
524 * configuration description areas, etc.
526 uint32_t d_acylinders; /* # of alt. cylinders per unit */
528 /* hardware characteristics: */
530 * d_interleave, d_trackskew and d_cylskew describe perturbations
531 * in the media format used to compensate for a slow controller.
532 * Interleave is physical sector interleave, set up by the formatter
533 * or controller when formatting. When interleaving is in use,
534 * logically adjacent sectors are not physically contiguous,
535 * but instead are separated by some number of sectors.
536 * It is specified as the ratio of physical sectors traversed
537 * per logical sector. Thus an interleave of 1:1 implies contiguous
538 * layout, while 2:1 implies that logical sector 0 is separated
539 * by one sector from logical sector 1.
540 * d_trackskew is the offset of sector 0 on track N
541 * relative to sector 0 on track N-1 on the same cylinder.
542 * Finally, d_cylskew is the offset of sector 0 on cylinder N
543 * relative to sector 0 on cylinder N-1.
545 uint16_t d_rpm; /* rotational speed */
546 uint16_t d_interleave; /* hardware sector interleave */
547 uint16_t d_trackskew; /* sector 0 skew, per track */
548 uint16_t d_cylskew; /* sector 0 skew, per cylinder */
549 uint32_t d_headswitch; /* head switch time, usec */
550 uint32_t d_trkseek; /* track-to-track seek, usec */
551 uint32_t d_flags; /* generic flags */
553 uint32_t d_drivedata[NDDATA]; /* drive-type specific information */
555 uint32_t d_spare[NSPARE]; /* reserved for future use */
556 uint32_t d_magic2; /* the magic number (again) */
557 uint16_t d_checksum; /* xor of data incl. partitions */
558 /* filesystem and partition information: */
559 uint16_t d_npartitions; /* number of partitions in following */
560 uint32_t d_bbsize; /* size of boot area at sn0, bytes */
561 uint32_t d_sbsize; /* max size of fs superblock, bytes */
562 struct xbsd_partition { /* the partition table */
563 uint32_t p_size; /* number of sectors in partition */
564 uint32_t p_offset; /* starting sector */
565 uint32_t p_fsize; /* filesystem basic fragment size */
566 uint8_t p_fstype; /* filesystem type, see below */
567 uint8_t p_frag; /* filesystem fragments per block */
568 uint16_t p_cpg; /* filesystem cylinders per group */
569 } d_partitions[BSD_MAXPARTITIONS]; /* actually may be more */
573 #define BSD_DTYPE_SMD 1 /* SMD, XSMD; VAX hp/up */
574 #define BSD_DTYPE_MSCP 2 /* MSCP */
575 #define BSD_DTYPE_DEC 3 /* other DEC (rk, rl) */
576 #define BSD_DTYPE_SCSI 4 /* SCSI */
577 #define BSD_DTYPE_ESDI 5 /* ESDI interface */
578 #define BSD_DTYPE_ST506 6 /* ST506 etc. */
579 #define BSD_DTYPE_HPIB 7 /* CS/80 on HP-IB */
580 #define BSD_DTYPE_HPFL 8 /* HP Fiber-link */
581 #define BSD_DTYPE_FLOPPY 10 /* floppy */
583 /* d_subtype values: */
584 #define BSD_DSTYPE_INDOSPART 0x8 /* is inside dos partition */
585 #define BSD_DSTYPE_DOSPART(s) ((s) & 3) /* dos partition number */
586 #define BSD_DSTYPE_GEOMETRY 0x10 /* drive params in label */
589 static const char * const xbsd_dktypenames[] = {
603 #define BSD_DKMAXTYPES (sizeof(xbsd_dktypenames) / sizeof(xbsd_dktypenames[0]) - 1)
607 * Filesystem type and version.
608 * Used to interpret other filesystem-specific
609 * per-partition information.
611 #define BSD_FS_UNUSED 0 /* unused */
612 #define BSD_FS_SWAP 1 /* swap */
613 #define BSD_FS_V6 2 /* Sixth Edition */
614 #define BSD_FS_V7 3 /* Seventh Edition */
615 #define BSD_FS_SYSV 4 /* System V */
616 #define BSD_FS_V71K 5 /* V7 with 1K blocks (4.1, 2.9) */
617 #define BSD_FS_V8 6 /* Eighth Edition, 4K blocks */
618 #define BSD_FS_BSDFFS 7 /* 4.2BSD fast file system */
619 #define BSD_FS_BSDLFS 9 /* 4.4BSD log-structured file system */
620 #define BSD_FS_OTHER 10 /* in use, but unknown/unsupported */
621 #define BSD_FS_HPFS 11 /* OS/2 high-performance file system */
622 #define BSD_FS_ISO9660 12 /* ISO-9660 filesystem (cdrom) */
623 #define BSD_FS_ISOFS BSD_FS_ISO9660
624 #define BSD_FS_BOOT 13 /* partition contains bootstrap */
625 #define BSD_FS_ADOS 14 /* AmigaDOS fast file system */
626 #define BSD_FS_HFS 15 /* Macintosh HFS */
627 #define BSD_FS_ADVFS 16 /* Digital Unix AdvFS */
629 /* this is annoying, but it's also the way it is :-( */
631 #define BSD_FS_EXT2 8 /* ext2 file system */
633 #define BSD_FS_MSDOS 8 /* MS-DOS file system */
637 static const struct systypes xbsd_fstypes[] = {
638 { "\x00" "unused" }, /* BSD_FS_UNUSED */
639 { "\x01" "swap" }, /* BSD_FS_SWAP */
640 { "\x02" "Version 6" }, /* BSD_FS_V6 */
641 { "\x03" "Version 7" }, /* BSD_FS_V7 */
642 { "\x04" "System V" }, /* BSD_FS_SYSV */
643 { "\x05" "4.1BSD" }, /* BSD_FS_V71K */
644 { "\x06" "Eighth Edition" }, /* BSD_FS_V8 */
645 { "\x07" "4.2BSD" }, /* BSD_FS_BSDFFS */
647 { "\x08" "ext2" }, /* BSD_FS_EXT2 */
649 { "\x08" "MS-DOS" }, /* BSD_FS_MSDOS */
651 { "\x09" "4.4LFS" }, /* BSD_FS_BSDLFS */
652 { "\x0a" "unknown" }, /* BSD_FS_OTHER */
653 { "\x0b" "HPFS" }, /* BSD_FS_HPFS */
654 { "\x0c" "ISO-9660" }, /* BSD_FS_ISO9660 */
655 { "\x0d" "boot" }, /* BSD_FS_BOOT */
656 { "\x0e" "ADOS" }, /* BSD_FS_ADOS */
657 { "\x0f" "HFS" }, /* BSD_FS_HFS */
658 { "\x10" "AdvFS" }, /* BSD_FS_ADVFS */
661 #define BSD_FSMAXTYPES (SIZE(xbsd_fstypes)-1)
666 * flags shared by various drives:
668 #define BSD_D_REMOVABLE 0x01 /* removable media */
669 #define BSD_D_ECC 0x02 /* supports ECC */
670 #define BSD_D_BADSECT 0x04 /* supports bad sector forw. */
671 #define BSD_D_RAMDISK 0x08 /* disk emulator */
672 #define BSD_D_CHAIN 0x10 /* can do back-back transfers */
673 #define BSD_D_DOSPART 0x20 /* within MSDOS partition */
675 #endif /* OSF_LABEL */
678 * Copyright (C) Andreas Neuper, Sep 1998.
679 * This file may be modified and redistributed under
680 * the terms of the GNU Public License.
683 struct device_parameter { /* 48 bytes */
687 unsigned char sparecyl;
688 unsigned short pcylcount;
689 unsigned short head_vol0;
690 unsigned short ntrks; /* tracks in cyl 0 or vol 0 */
691 unsigned char cmd_tag_queue_depth;
692 unsigned char unused0;
693 unsigned short unused1;
694 unsigned short nsect; /* sectors/tracks in cyl 0 or vol 0 */
695 unsigned short bytes;
696 unsigned short ilfact;
697 unsigned int flags; /* controller flags */
698 unsigned int datarate;
699 unsigned int retries_on_error;
700 unsigned int ms_per_word;
701 unsigned short xylogics_gap1;
702 unsigned short xylogics_syncdelay;
703 unsigned short xylogics_readdelay;
704 unsigned short xylogics_gap2;
705 unsigned short xylogics_readgate;
706 unsigned short xylogics_writecont;
709 #define SGI_VOLHDR 0x00
710 /* 1 and 2 were used for drive types no longer supported by SGI */
711 #define SGI_SWAP 0x03
712 /* 4 and 5 were for filesystem types SGI haven't ever supported on MIPS CPUs */
713 #define SGI_VOLUME 0x06
715 #define SGI_LVOL 0x08
716 #define SGI_RLVOL 0x09
718 #define SGI_XFSLOG 0x0b
721 #define ENTIRE_DISK SGI_VOLUME
725 #define SECTOR_SLIP 0x01
726 #define SECTOR_FWD 0x02
727 #define TRACK_FWD 0x04
728 #define TRACK_MULTIVOL 0x08
729 #define IGNORE_ERRORS 0x10
731 #define ENABLE_CMDTAGQ 0x40
734 unsigned int magic; /* expect SGI_LABEL_MAGIC */
735 unsigned short boot_part; /* active boot partition */
736 unsigned short swap_part; /* active swap partition */
737 unsigned char boot_file[16]; /* name of the bootfile */
738 struct device_parameter devparam; /* 1 * 48 bytes */
739 struct volume_directory { /* 15 * 16 bytes */
740 unsigned char vol_file_name[8]; /* a character array */
741 unsigned int vol_file_start; /* number of logical block */
742 unsigned int vol_file_size; /* number of bytes */
744 struct sgi_partition { /* 16 * 12 bytes */
745 unsigned int num_sectors; /* number of blocks */
746 unsigned int start_sector; /* must be cylinder aligned */
750 unsigned int fillbytes;
754 unsigned int magic; /* looks like a magic number */
763 unsigned char scsi_string[50];
764 unsigned char serial[137];
765 unsigned short check1816;
766 unsigned char installer[225];
769 #define SGI_LABEL_MAGIC 0x0be5a941
770 #define SGI_LABEL_MAGIC_SWAPPED 0x41a9e50b
771 #define SGI_INFO_MAGIC 0x00072959
772 #define SGI_INFO_MAGIC_SWAPPED 0x59290700
773 #define SGI_SSWAP16(x) (sgi_other_endian ? __swap16(x) \
775 #define SGI_SSWAP32(x) (sgi_other_endian ? __swap32(x) \
778 #define sgilabel ((sgi_partition *)MBRbuffer)
779 #define sgiparam (sgilabel->devparam)
782 unsigned char info[128]; /* Informative text string */
783 unsigned char spare0[14];
785 unsigned char spare1;
787 unsigned char spare2;
790 unsigned char spare1[246]; /* Boot information etc. */
791 unsigned short rspeed; /* Disk rotational speed */
792 unsigned short pcylcount; /* Physical cylinder count */
793 unsigned short sparecyl; /* extra sects per cylinder */
794 unsigned char spare2[4]; /* More magic... */
795 unsigned short ilfact; /* Interleave factor */
796 unsigned short ncyl; /* Data cylinder count */
797 unsigned short nacyl; /* Alt. cylinder count */
798 unsigned short ntrks; /* Tracks per cylinder */
799 unsigned short nsect; /* Sectors per track */
800 unsigned char spare3[4]; /* Even more magic... */
801 struct sun_partition {
802 uint32_t start_cylinder;
803 uint32_t num_sectors;
805 unsigned short magic; /* Magic number */
806 unsigned short csum; /* Label xor'd checksum */
810 #define SUN_LABEL_MAGIC 0xDABE
811 #define SUN_LABEL_MAGIC_SWAPPED 0xBEDA
812 #define sunlabel ((sun_partition *)MBRbuffer)
813 #define SUN_SSWAP16(x) (sun_other_endian ? __swap16(x) \
815 #define SUN_SSWAP32(x) (sun_other_endian ? __swap32(x) \
819 #ifdef CONFIG_FEATURE_OSF_LABEL
822 19990319 - Arnaldo Carvalho de Melo <acme@conectiva.com.br> - i18n/nls
824 20000101 - David Huggins-Daines <dhuggins@linuxcare.com> - Better
825 support for OSF/1 disklabels on Alpha.
826 Also fixed unaligned accesses in alpha_bootblock_checksum()
829 #define FREEBSD_PARTITION 0xa5
830 #define NETBSD_PARTITION 0xa9
832 static void xbsd_delete_part(void);
833 static void xbsd_new_part(void);
834 static void xbsd_write_disklabel(void);
835 static int xbsd_create_disklabel(void);
836 static void xbsd_edit_disklabel(void);
837 static void xbsd_write_bootstrap(void);
838 static void xbsd_change_fstype(void);
839 static int xbsd_get_part_index(int max);
840 static int xbsd_check_new_partition(int *i);
841 static void xbsd_list_types(void);
842 static u_short xbsd_dkcksum(struct xbsd_disklabel *lp);
843 static int xbsd_initlabel(struct partition *p, struct xbsd_disklabel *d);
844 static int xbsd_readlabel(struct partition *p, struct xbsd_disklabel *d);
845 static int xbsd_writelabel(struct partition *p, struct xbsd_disklabel *d);
847 #if defined (__alpha__)
848 static void alpha_bootblock_checksum(char *boot);
851 #if !defined (__alpha__)
852 static int xbsd_translate_fstype(int linux_type);
853 static void xbsd_link_part(void);
854 static struct partition *xbsd_part;
855 static int xbsd_part_index;
858 #if defined (__alpha__)
859 /* We access this through a uint64_t * when checksumming */
860 static char disklabelbuffer[BSD_BBSIZE] ATTRIBUTE_ALIGNED(8);
862 static char disklabelbuffer[BSD_BBSIZE];
865 static struct xbsd_disklabel xbsd_dlabel;
867 #define bsd_cround(n) \
868 (display_in_cyl_units ? ((n)/xbsd_dlabel.d_secpercyl) + 1 : (n))
871 * Test whether the whole disk has BSD disk label magic.
873 * Note: often reformatting with DOS-type label leaves the BSD magic,
874 * so this does not mean that there is a BSD disk label.
877 check_osf_label(void)
879 if (xbsd_readlabel(NULL, &xbsd_dlabel) == 0)
884 static void xbsd_print_disklabel(int);
887 btrydev(const char * dev)
889 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
891 printf(_("\nBSD label for device: %s\n"), dev);
892 xbsd_print_disklabel (0);
899 puts (_("Command action"));
900 puts (_("\td\tdelete a BSD partition"));
901 puts (_("\te\tedit drive data"));
902 puts (_("\ti\tinstall bootstrap"));
903 puts (_("\tl\tlist known filesystem types"));
904 puts (_("\tm\tprint this menu"));
905 puts (_("\tn\tadd a new BSD partition"));
906 puts (_("\tp\tprint BSD partition table"));
907 puts (_("\tq\tquit without saving changes"));
908 puts (_("\tr\treturn to main menu"));
909 puts (_("\ts\tshow complete disklabel"));
910 puts (_("\tt\tchange a partition's filesystem id"));
911 puts (_("\tu\tchange units (cylinders/sectors)"));
912 puts (_("\tw\twrite disklabel to disk"));
913 #if !defined (__alpha__)
914 puts (_("\tx\tlink BSD partition to non-BSD partition"));
918 #if !defined (__alpha__)
926 is_bsd_partition_type(int type)
928 return (type == FREEBSD_PARTITION ||
929 type == hidden(FREEBSD_PARTITION) ||
930 type == NETBSD_PARTITION ||
931 type == hidden(NETBSD_PARTITION));
938 #if !defined (__alpha__)
942 for (t = 0; t < 4; t++) {
943 p = get_part_table(t);
944 if (p && is_bsd_partition_type(p->sys_ind)) {
947 ss = get_start_sect(xbsd_part);
949 fprintf(stderr, _("Partition %s has invalid starting sector 0.\n"),
950 partname(disk_device, t+1, 0));
953 printf(_("Reading disklabel of %s at sector %d.\n"),
954 partname(disk_device, t+1, 0), ss + BSD_LABELSECTOR);
955 if (xbsd_readlabel(xbsd_part, &xbsd_dlabel) == 0)
956 if (xbsd_create_disklabel() == 0)
963 printf(_("There is no *BSD partition on %s.\n"), disk_device);
967 #elif defined (__alpha__)
969 if (xbsd_readlabel(NULL, &xbsd_dlabel) == 0)
970 if (xbsd_create_disklabel() == 0)
977 switch (tolower(read_char(_("BSD disklabel command (m for help): ")))) {
982 xbsd_edit_disklabel();
985 xbsd_write_bootstrap();
994 xbsd_print_disklabel(0);
1002 xbsd_print_disklabel(1);
1005 xbsd_change_fstype();
1011 xbsd_write_disklabel();
1013 #if !defined (__alpha__)
1026 xbsd_delete_part(void)
1030 i = xbsd_get_part_index(xbsd_dlabel.d_npartitions);
1031 xbsd_dlabel.d_partitions[i].p_size = 0;
1032 xbsd_dlabel.d_partitions[i].p_offset = 0;
1033 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
1034 if (xbsd_dlabel.d_npartitions == i + 1)
1035 while (xbsd_dlabel.d_partitions[xbsd_dlabel.d_npartitions-1].p_size == 0)
1036 xbsd_dlabel.d_npartitions--;
1046 if (!xbsd_check_new_partition(&i))
1049 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
1050 begin = get_start_sect(xbsd_part);
1051 end = begin + get_nr_sects(xbsd_part) - 1;
1054 end = xbsd_dlabel.d_secperunit - 1;
1057 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
1058 begin = read_int(bsd_cround(begin), bsd_cround(begin), bsd_cround(end),
1061 if (display_in_cyl_units)
1062 begin = (begin - 1) * xbsd_dlabel.d_secpercyl;
1064 snprintf(mesg, sizeof(mesg), _("Last %s or +size or +sizeM or +sizeK"),
1065 str_units(SINGULAR));
1066 end = read_int(bsd_cround (begin), bsd_cround (end), bsd_cround (end),
1067 bsd_cround (begin), mesg);
1069 if (display_in_cyl_units)
1070 end = end * xbsd_dlabel.d_secpercyl - 1;
1072 xbsd_dlabel.d_partitions[i].p_size = end - begin + 1;
1073 xbsd_dlabel.d_partitions[i].p_offset = begin;
1074 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
1078 xbsd_print_disklabel(int show_all)
1080 struct xbsd_disklabel *lp = &xbsd_dlabel;
1081 struct xbsd_partition *pp;
1085 #if defined (__alpha__)
1086 printf("# %s:\n", disk_device);
1088 printf("# %s:\n", partname(disk_device, xbsd_part_index+1, 0));
1090 if ((unsigned) lp->d_type < BSD_DKMAXTYPES)
1091 printf(_("type: %s\n"), xbsd_dktypenames[lp->d_type]);
1093 printf(_("type: %d\n"), lp->d_type);
1094 printf(_("disk: %.*s\n"), (int) sizeof(lp->d_typename), lp->d_typename);
1095 printf(_("label: %.*s\n"), (int) sizeof(lp->d_packname), lp->d_packname);
1096 printf(_("flags:"));
1097 if (lp->d_flags & BSD_D_REMOVABLE)
1098 printf(_(" removable"));
1099 if (lp->d_flags & BSD_D_ECC)
1101 if (lp->d_flags & BSD_D_BADSECT)
1102 printf(_(" badsect"));
1104 /* On various machines the fields of *lp are short/int/long */
1105 /* In order to avoid problems, we cast them all to long. */
1106 printf(_("bytes/sector: %ld\n"), (long) lp->d_secsize);
1107 printf(_("sectors/track: %ld\n"), (long) lp->d_nsectors);
1108 printf(_("tracks/cylinder: %ld\n"), (long) lp->d_ntracks);
1109 printf(_("sectors/cylinder: %ld\n"), (long) lp->d_secpercyl);
1110 printf(_("cylinders: %ld\n"), (long) lp->d_ncylinders);
1111 printf(_("rpm: %d\n"), lp->d_rpm);
1112 printf(_("interleave: %d\n"), lp->d_interleave);
1113 printf(_("trackskew: %d\n"), lp->d_trackskew);
1114 printf(_("cylinderskew: %d\n"), lp->d_cylskew);
1115 printf(_("headswitch: %ld\t\t# milliseconds\n"),
1116 (long) lp->d_headswitch);
1117 printf(_("track-to-track seek: %ld\t# milliseconds\n"),
1118 (long) lp->d_trkseek);
1119 printf(_("drivedata: "));
1120 for (i = NDDATA - 1; i >= 0; i--)
1121 if (lp->d_drivedata[i])
1125 for (j = 0; j <= i; j++)
1126 printf("%ld ", (long) lp->d_drivedata[j]);
1128 printf(_("\n%d partitions:\n"), lp->d_npartitions);
1129 printf(_("# start end size fstype [fsize bsize cpg]\n"));
1130 pp = lp->d_partitions;
1131 for (i = 0; i < lp->d_npartitions; i++, pp++) {
1133 if (display_in_cyl_units && lp->d_secpercyl) {
1134 printf(" %c: %8ld%c %8ld%c %8ld%c ",
1136 (long) pp->p_offset / lp->d_secpercyl + 1,
1137 (pp->p_offset % lp->d_secpercyl) ? '*' : ' ',
1138 (long) (pp->p_offset + pp->p_size + lp->d_secpercyl - 1) / lp->d_secpercyl,
1139 ((pp->p_offset + pp->p_size) % lp->d_secpercyl) ? '*' : ' ',
1140 (long) pp->p_size / lp->d_secpercyl,
1141 (pp->p_size % lp->d_secpercyl) ? '*' : ' '
1144 printf(" %c: %8ld %8ld %8ld ",
1146 (long) pp->p_offset,
1147 (long) pp->p_offset + pp->p_size - 1,
1152 if ((unsigned) pp->p_fstype < BSD_FSMAXTYPES)
1153 printf("%8.8s", xbsd_fstypes[pp->p_fstype].name);
1155 printf("%8x", pp->p_fstype);
1157 switch (pp->p_fstype) {
1159 printf(" %5ld %5ld %5.5s ",
1160 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, "");
1163 printf(" %5ld %5ld %5d ",
1164 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, pp->p_cpg);
1167 printf("%22.22s", "");
1176 xbsd_write_disklabel(void)
1178 #if defined (__alpha__)
1179 printf(_("Writing disklabel to %s.\n"), disk_device);
1180 xbsd_writelabel(NULL, &xbsd_dlabel);
1182 printf(_("Writing disklabel to %s.\n"),
1183 partname(disk_device, xbsd_part_index + 1, 0));
1184 xbsd_writelabel(xbsd_part, &xbsd_dlabel);
1186 reread_partition_table(0); /* no exit yet */
1190 xbsd_create_disklabel(void)
1194 #if defined (__alpha__)
1195 fprintf(stderr, _("%s contains no disklabel.\n"), disk_device);
1197 fprintf(stderr, _("%s contains no disklabel.\n"),
1198 partname(disk_device, xbsd_part_index + 1, 0));
1202 c = read_char(_("Do you want to create a disklabel? (y/n) "));
1203 if (c == 'y' || c == 'Y') {
1205 #if defined (__alpha__) || defined (__powerpc__) || defined (__hppa__) || \
1206 defined (__s390__) || defined (__s390x__)
1209 xbsd_part, &xbsd_dlabel/* not used, xbsd_part_index*/
1212 xbsd_print_disklabel (1);
1216 } else if (c == 'n')
1222 edit_int(int def, char *mesg)
1225 fputs(mesg, stdout);
1226 printf(" (%d): ", def);
1230 while (!isdigit(*line_ptr)); /* FIXME: ?!! */
1231 return atoi(line_ptr);
1235 xbsd_edit_disklabel(void)
1237 struct xbsd_disklabel *d;
1241 #if defined (__alpha__) || defined (__ia64__)
1242 d->d_secsize = (u_long) edit_int((u_long) d->d_secsize ,_("bytes/sector"));
1243 d->d_nsectors = (u_long) edit_int((u_long) d->d_nsectors ,_("sectors/track"));
1244 d->d_ntracks = (u_long) edit_int((u_long) d->d_ntracks ,_("tracks/cylinder"));
1245 d->d_ncylinders = (u_long) edit_int((u_long) d->d_ncylinders ,_("cylinders"));
1248 /* d->d_secpercyl can be != d->d_nsectors * d->d_ntracks */
1250 d->d_secpercyl = (u_long) edit_int((u_long) d->d_nsectors * d->d_ntracks,
1251 _("sectors/cylinder"));
1252 if (d->d_secpercyl <= d->d_nsectors * d->d_ntracks)
1255 printf(_("Must be <= sectors/track * tracks/cylinder (default).\n"));
1257 d->d_rpm = (u_short) edit_int((u_short) d->d_rpm ,_("rpm"));
1258 d->d_interleave = (u_short) edit_int((u_short) d->d_interleave,_("interleave"));
1259 d->d_trackskew = (u_short) edit_int((u_short) d->d_trackskew ,_("trackskew"));
1260 d->d_cylskew = (u_short) edit_int((u_short) d->d_cylskew ,_("cylinderskew"));
1261 d->d_headswitch = (u_long) edit_int((u_long) d->d_headswitch ,_("headswitch"));
1262 d->d_trkseek = (u_long) edit_int((u_long) d->d_trkseek ,_("track-to-track seek"));
1264 d->d_secperunit = d->d_secpercyl * d->d_ncylinders;
1268 xbsd_get_bootstrap (char *path, void *ptr, int size)
1272 if ((fdb = open (path, O_RDONLY)) < 0) {
1276 if (read(fdb, ptr, size) < 0) {
1281 printf(" ... %s\n", path);
1289 printf(_("\nSyncing disks.\n"));
1291 sleep(4); /* What? */
1295 xbsd_write_bootstrap(void)
1297 char *bootdir = BSD_LINUX_BOOTDIR;
1298 char path[MAXPATHLEN];
1300 struct xbsd_disklabel dl;
1304 if (xbsd_dlabel.d_type == BSD_DTYPE_SCSI)
1309 printf(_("Bootstrap: %sboot -> boot%s (%s): "),
1310 dkbasename, dkbasename, dkbasename);
1312 line_ptr[strlen(line_ptr)-1] = '\0';
1313 dkbasename = line_ptr;
1315 snprintf(path, sizeof(path), "%s/%sboot", bootdir, dkbasename);
1316 if (!xbsd_get_bootstrap(path, disklabelbuffer, (int) xbsd_dlabel.d_secsize))
1319 /* We need a backup of the disklabel (xbsd_dlabel might have changed). */
1320 d = &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE];
1321 memmove(&dl, d, sizeof(struct xbsd_disklabel));
1323 /* The disklabel will be overwritten by 0's from bootxx anyway */
1324 memset(d, 0, sizeof(struct xbsd_disklabel));
1326 snprintf(path, sizeof(path), "%s/boot%s", bootdir, dkbasename);
1327 if (!xbsd_get_bootstrap (path, &disklabelbuffer[xbsd_dlabel.d_secsize],
1328 (int) xbsd_dlabel.d_bbsize - xbsd_dlabel.d_secsize))
1331 e = d + sizeof(struct xbsd_disklabel);
1332 for (p = d; p < e; p++)
1334 fprintf(stderr, _("Bootstrap overlaps with disk label!\n"));
1338 memmove(d, &dl, sizeof(struct xbsd_disklabel));
1340 #if defined (__powerpc__) || defined (__hppa__)
1342 #elif defined (__alpha__)
1344 alpha_bootblock_checksum(disklabelbuffer);
1346 sector = get_start_sect(xbsd_part);
1349 if (lseek(fd, sector * SECTOR_SIZE, SEEK_SET) == -1)
1350 fdisk_fatal(unable_to_seek);
1351 if (BSD_BBSIZE != write(fd, disklabelbuffer, BSD_BBSIZE))
1352 fdisk_fatal(unable_to_write);
1354 #if defined (__alpha__)
1355 printf(_("Bootstrap installed on %s.\n"), disk_device);
1357 printf(_("Bootstrap installed on %s.\n"),
1358 partname (disk_device, xbsd_part_index+1, 0));
1365 xbsd_change_fstype(void)
1369 i = xbsd_get_part_index(xbsd_dlabel.d_npartitions);
1370 xbsd_dlabel.d_partitions[i].p_fstype = read_hex(xbsd_fstypes);
1374 xbsd_get_part_index(int max)
1379 snprintf(prompt, sizeof(prompt), _("Partition (a-%c): "), 'a' + max - 1);
1381 l = tolower(read_char(prompt));
1382 while (l < 'a' || l > 'a' + max - 1);
1387 xbsd_check_new_partition(int *i)
1389 /* room for more? various BSD flavours have different maxima */
1390 if (xbsd_dlabel.d_npartitions == BSD_MAXPARTITIONS) {
1393 for (t = 0; t < BSD_MAXPARTITIONS; t++)
1394 if (xbsd_dlabel.d_partitions[t].p_size == 0)
1397 if (t == BSD_MAXPARTITIONS) {
1398 fprintf(stderr, _("The maximum number of partitions "
1399 "has been created\n"));
1404 *i = xbsd_get_part_index (BSD_MAXPARTITIONS);
1406 if (*i >= xbsd_dlabel.d_npartitions)
1407 xbsd_dlabel.d_npartitions = (*i) + 1;
1409 if (xbsd_dlabel.d_partitions[*i].p_size != 0) {
1410 fprintf(stderr, _("This partition already exists.\n"));
1418 xbsd_list_types(void)
1420 list_types(xbsd_fstypes);
1424 xbsd_dkcksum(struct xbsd_disklabel *lp)
1426 u_short *start, *end;
1429 start = (u_short *) lp;
1430 end = (u_short *) &lp->d_partitions[lp->d_npartitions];
1437 xbsd_initlabel(struct partition *p, struct xbsd_disklabel *d)
1439 struct xbsd_partition *pp;
1442 memset(d, 0, sizeof(struct xbsd_disklabel));
1444 d->d_magic = BSD_DISKMAGIC;
1446 if (strncmp(disk_device, "/dev/sd", 7) == 0)
1447 d->d_type = BSD_DTYPE_SCSI;
1449 d->d_type = BSD_DTYPE_ST506;
1451 #if 0 /* not used (at least not written to disk) by NetBSD/i386 1.0 */
1452 d->d_subtype = BSD_DSTYPE_INDOSPART & pindex;
1455 #if !defined (__alpha__)
1456 d->d_flags = BSD_D_DOSPART;
1460 d->d_secsize = SECTOR_SIZE; /* bytes/sector */
1461 d->d_nsectors = sectors; /* sectors/track */
1462 d->d_ntracks = heads; /* tracks/cylinder (heads) */
1463 d->d_ncylinders = cylinders;
1464 d->d_secpercyl = sectors * heads;/* sectors/cylinder */
1465 if (d->d_secpercyl == 0)
1466 d->d_secpercyl = 1; /* avoid segfaults */
1467 d->d_secperunit = d->d_secpercyl * d->d_ncylinders;
1470 d->d_interleave = 1;
1473 d->d_headswitch = 0;
1476 d->d_magic2 = BSD_DISKMAGIC;
1477 d->d_bbsize = BSD_BBSIZE;
1478 d->d_sbsize = BSD_SBSIZE;
1480 #if !defined (__alpha__)
1481 d->d_npartitions = 4;
1482 pp = &d->d_partitions[2]; /* Partition C should be
1483 the NetBSD partition */
1484 pp->p_offset = get_start_sect(p);
1485 pp->p_size = get_nr_sects(p);
1486 pp->p_fstype = BSD_FS_UNUSED;
1487 pp = &d->d_partitions[3]; /* Partition D should be
1490 pp->p_size = d->d_secperunit;
1491 pp->p_fstype = BSD_FS_UNUSED;
1492 #elif defined (__alpha__)
1493 d->d_npartitions = 3;
1494 pp = &d->d_partitions[2]; /* Partition C should be
1497 pp->p_size = d->d_secperunit;
1498 pp->p_fstype = BSD_FS_UNUSED;
1505 * Read a xbsd_disklabel from sector 0 or from the starting sector of p.
1506 * If it has the right magic, return 1.
1509 xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d)
1513 /* p is used only to get the starting sector */
1514 #if !defined (__alpha__)
1515 sector = (p ? get_start_sect(p) : 0);
1516 #elif defined (__alpha__)
1520 if (lseek(fd, sector * SECTOR_SIZE, SEEK_SET) == -1)
1521 fdisk_fatal(unable_to_seek);
1522 if (BSD_BBSIZE != read(fd, disklabelbuffer, BSD_BBSIZE))
1523 fdisk_fatal(unable_to_read);
1525 memmove(d, &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
1526 sizeof(struct xbsd_disklabel));
1528 if (d->d_magic != BSD_DISKMAGIC || d->d_magic2 != BSD_DISKMAGIC)
1531 for (t = d->d_npartitions; t < BSD_MAXPARTITIONS; t++) {
1532 d->d_partitions[t].p_size = 0;
1533 d->d_partitions[t].p_offset = 0;
1534 d->d_partitions[t].p_fstype = BSD_FS_UNUSED;
1537 if (d->d_npartitions > BSD_MAXPARTITIONS)
1538 fprintf(stderr, _("Warning: too many partitions "
1539 "(%d, maximum is %d).\n"),
1540 d->d_npartitions, BSD_MAXPARTITIONS);
1545 xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d)
1547 unsigned int sector;
1549 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
1550 sector = get_start_sect(p) + BSD_LABELSECTOR;
1552 sector = BSD_LABELSECTOR;
1556 d->d_checksum = xbsd_dkcksum (d);
1558 /* This is necessary if we want to write the bootstrap later,
1559 otherwise we'd write the old disklabel with the bootstrap.
1561 memmove(&disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
1562 d, sizeof(struct xbsd_disklabel));
1564 #if defined (__alpha__) && BSD_LABELSECTOR == 0
1565 alpha_bootblock_checksum (disklabelbuffer);
1566 if (lseek(fd, 0, SEEK_SET) == -1)
1567 fdisk_fatal(unable_to_seek);
1568 if (BSD_BBSIZE != write(fd, disklabelbuffer, BSD_BBSIZE))
1569 fdisk_fatal(unable_to_write);
1571 if (lseek(fd, sector * SECTOR_SIZE + BSD_LABELOFFSET, SEEK_SET) == -1)
1572 fdisk_fatal(unable_to_seek);
1573 if (sizeof(struct xbsd_disklabel) != write(fd, d, sizeof(struct xbsd_disklabel)))
1574 fdisk_fatal(unable_to_write);
1581 #if !defined (__alpha__)
1583 xbsd_translate_fstype(int linux_type)
1585 switch (linux_type) {
1586 case 0x01: /* DOS 12-bit FAT */
1587 case 0x04: /* DOS 16-bit <32M */
1588 case 0x06: /* DOS 16-bit >=32M */
1589 case 0xe1: /* DOS access */
1590 case 0xe3: /* DOS R/O */
1591 case 0xf2: /* DOS secondary */
1592 return BSD_FS_MSDOS;
1593 case 0x07: /* OS/2 HPFS */
1596 return BSD_FS_OTHER;
1601 xbsd_link_part(void)
1604 struct partition *p;
1606 k = get_partition(1, partitions);
1608 if (!xbsd_check_new_partition(&i))
1611 p = get_part_table(k);
1613 xbsd_dlabel.d_partitions[i].p_size = get_nr_sects(p);
1614 xbsd_dlabel.d_partitions[i].p_offset = get_start_sect(p);
1615 xbsd_dlabel.d_partitions[i].p_fstype = xbsd_translate_fstype(p->sys_ind);
1619 #if defined (__alpha__)
1621 #if !defined(__GLIBC__)
1622 typedef unsigned long long uint64_t;
1626 alpha_bootblock_checksum(char *boot)
1631 dp = (uint64_t *)boot;
1633 for (i = 0; i < 63; i++)
1637 #endif /* __alpha__ */
1639 #endif /* OSF_LABEL */
1641 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
1642 static inline unsigned short
1643 __swap16(unsigned short x)
1645 return (((uint16_t)(x) & 0xFF) << 8) | (((uint16_t)(x) & 0xFF00) >> 8);
1648 static inline uint32_t
1649 __swap32(uint32_t x)
1651 return (((x & 0xFF) << 24) |
1652 ((x & 0xFF00) << 8) |
1653 ((x & 0xFF0000) >> 8) |
1654 ((x & 0xFF000000) >> 24));
1658 #ifdef CONFIG_FEATURE_SGI_LABEL
1663 * Copyright (C) Andreas Neuper, Sep 1998.
1664 * This file may be modified and redistributed under
1665 * the terms of the GNU Public License.
1667 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
1668 * Internationalization
1672 static int sgi_other_endian;
1674 static short sgi_volumes = 1;
1677 * only dealing with free blocks here
1684 static freeblocks freelist[17]; /* 16 partitions can produce 17 vacant slots */
1687 setfreelist(int i, unsigned int f, unsigned int l)
1689 freelist[i].first = f;
1690 freelist[i].last = l;
1694 add2freelist(unsigned int f, unsigned int l)
1697 for (i = 0; i < 17 ; i++)
1698 if (freelist[i].last == 0)
1700 setfreelist(i, f, l);
1708 for (i = 0; i < 17 ; i++)
1709 setfreelist(i, 0, 0);
1713 isinfreelist(unsigned int b)
1717 for (i = 0; i < 17 ; i++)
1718 if (freelist[i].first <= b && freelist[i].last >= b)
1719 return freelist[i].last;
1722 /* return last vacant block of this stride (never 0). */
1723 /* the '>=' is not quite correct, but simplifies the code */
1725 * end of free blocks section
1728 static const struct systypes sgi_sys_types[] = {
1729 /* SGI_VOLHDR */ { "\x00" "SGI volhdr" },
1730 /* 0x01 */ { "\x01" "SGI trkrepl" },
1731 /* 0x02 */ { "\x02" "SGI secrepl" },
1732 /* SGI_SWAP */ { "\x03" "SGI raw" },
1733 /* 0x04 */ { "\x04" "SGI bsd" },
1734 /* 0x05 */ { "\x05" "SGI sysv" },
1735 /* ENTIRE_DISK */ { "\x06" "SGI volume" },
1736 /* SGI_EFS */ { "\x07" "SGI efs" },
1737 /* 0x08 */ { "\x08" "SGI lvol" },
1738 /* 0x09 */ { "\x09" "SGI rlvol" },
1739 /* SGI_XFS */ { "\x0a" "SGI xfs" },
1740 /* SGI_XFSLOG */ { "\x0b" "SGI xfslog" },
1741 /* SGI_XLV */ { "\x0c" "SGI xlv" },
1742 /* SGI_XVM */ { "\x0d" "SGI xvm" },
1743 /* LINUX_SWAP */ { "\x82" "Linux swap" },
1744 /* LINUX_NATIVE */ { "\x83" "Linux native" },
1745 /* LINUX_LVM */ { "\x8d" "Linux LVM" },
1746 /* LINUX_RAID */ { "\xfd" "Linux RAID" },
1754 return SGI_SSWAP16(sgilabel->devparam.nsect);
1760 return SGI_SSWAP16(sgilabel->devparam.ntrks);
1764 two_s_complement_32bit_sum(unsigned int* base, int size /* in bytes */)
1767 unsigned int sum = 0;
1769 size /= sizeof(unsigned int);
1770 for (i = 0; i < size; i++)
1771 sum -= SGI_SSWAP32(base[i]);
1776 check_sgi_label(void)
1778 if (sizeof(sgilabel) > 512) {
1780 _("According to MIPS Computer Systems, Inc the "
1781 "Label must not contain more than 512 bytes\n"));
1785 if (sgilabel->magic != SGI_LABEL_MAGIC
1786 && sgilabel->magic != SGI_LABEL_MAGIC_SWAPPED) {
1787 current_label_type = label_dos;
1791 sgi_other_endian = (sgilabel->magic == SGI_LABEL_MAGIC_SWAPPED);
1793 * test for correct checksum
1795 if (two_s_complement_32bit_sum((unsigned int*)sgilabel,
1796 sizeof(*sgilabel))) {
1798 _("Detected sgi disklabel with wrong checksum.\n"));
1801 current_label_type = label_sgi;
1808 sgi_get_start_sector(int i)
1810 return SGI_SSWAP32(sgilabel->partitions[i].start_sector);
1814 sgi_get_num_sectors(int i)
1816 return SGI_SSWAP32(sgilabel->partitions[i].num_sectors);
1820 sgi_get_sysid(int i)
1822 return SGI_SSWAP32(sgilabel->partitions[i].id);
1826 sgi_get_bootpartition(void)
1828 return SGI_SSWAP16(sgilabel->boot_part);
1832 sgi_get_swappartition(void)
1834 return SGI_SSWAP16(sgilabel->swap_part);
1838 sgi_list_table(int xtra)
1841 int kpi = 0; /* kernel partition ID */
1844 printf(_("\nDisk %s (SGI disk label): %d heads, %d sectors\n"
1845 "%d cylinders, %d physical cylinders\n"
1846 "%d extra sects/cyl, interleave %d:1\n"
1848 "Units = %s of %d * 512 bytes\n\n"),
1849 disk_device, heads, sectors, cylinders,
1850 SGI_SSWAP16(sgiparam.pcylcount),
1851 SGI_SSWAP16(sgiparam.sparecyl),
1852 SGI_SSWAP16(sgiparam.ilfact),
1854 str_units(PLURAL), units_per_sector);
1856 printf( _("\nDisk %s (SGI disk label): "
1857 "%d heads, %d sectors, %d cylinders\n"
1858 "Units = %s of %d * 512 bytes\n\n"),
1859 disk_device, heads, sectors, cylinders,
1860 str_units(PLURAL), units_per_sector );
1863 w = strlen(disk_device);
1864 wd = strlen(_("Device"));
1868 printf(_("----- partitions -----\n"
1869 "Pt# %*s Info Start End Sectors Id System\n"),
1870 w + 2, _("Device"));
1871 for (i = 0 ; i < partitions; i++) {
1872 if( sgi_get_num_sectors(i) || debug ) {
1873 uint32_t start = sgi_get_start_sector(i);
1874 uint32_t len = sgi_get_num_sectors(i);
1875 kpi++; /* only count nonempty partitions */
1877 "%2d: %s %4s %9ld %9ld %9ld %2x %s\n",
1878 /* fdisk part number */ i+1,
1879 /* device */ partname(disk_device, kpi, w+3),
1880 /* flags */ (sgi_get_swappartition() == i) ? "swap" :
1881 /* flags */ (sgi_get_bootpartition() == i) ? "boot" : " ",
1882 /* start */ (long) scround(start),
1883 /* end */ (long) scround(start+len)-1,
1884 /* no odd flag on end */(long) len,
1885 /* type id */ sgi_get_sysid(i),
1886 /* type name */ partition_type(sgi_get_sysid(i)));
1889 printf(_("----- Bootinfo -----\nBootfile: %s\n"
1890 "----- Directory Entries -----\n"),
1891 sgilabel->boot_file);
1892 for (i = 0 ; i < sgi_volumes; i++) {
1893 if (sgilabel->directory[i].vol_file_size) {
1894 uint32_t start = SGI_SSWAP32(sgilabel->directory[i].vol_file_start);
1895 uint32_t len = SGI_SSWAP32(sgilabel->directory[i].vol_file_size);
1896 unsigned char *name = sgilabel->directory[i].vol_file_name;
1898 printf(_("%2d: %-10s sector%5u size%8u\n"),
1899 i, (char*)name, (unsigned int) start, (unsigned int) len);
1905 sgi_set_bootpartition(int i)
1907 sgilabel->boot_part = SGI_SSWAP16(((short)i));
1911 sgi_get_lastblock(void)
1913 return heads * sectors * cylinders;
1917 sgi_set_swappartition(int i)
1919 sgilabel->swap_part = SGI_SSWAP16(((short)i));
1923 sgi_check_bootfile(const char* aFile)
1925 if (strlen(aFile) < 3) /* "/a\n" is minimum */ {
1926 printf(_("\nInvalid Bootfile!\n"
1927 "\tThe bootfile must be an absolute non-zero pathname,\n"
1928 "\te.g. \"/unix\" or \"/unix.save\".\n"));
1931 if (strlen(aFile) > 16) {
1932 printf(_("\n\tName of Bootfile too long: "
1933 "16 bytes maximum.\n"));
1936 if (aFile[0] != '/') {
1937 printf(_("\n\tBootfile must have a "
1938 "fully qualified pathname.\n"));
1943 if (strncmp(aFile, (char*)sgilabel->boot_file, 16)) {
1944 printf(_("\n\tBe aware, that the bootfile is not checked for existence.\n\t"
1945 "SGI's default is \"/unix\" and for backup \"/unix.save\".\n"));
1946 /* filename is correct and did change */
1949 return 0; /* filename did not change */
1953 sgi_get_bootfile(void)
1955 return (char*)sgilabel->boot_file;
1959 sgi_set_bootfile(const char* aFile)
1963 if (sgi_check_bootfile(aFile)) {
1965 if ((aFile[i] != '\n') /* in principle caught again by next line */
1966 && (strlen(aFile) > i))
1967 sgilabel->boot_file[i] = aFile[i];
1969 sgilabel->boot_file[i] = 0;
1972 printf(_("\n\tBootfile is changed to \"%s\".\n"), sgilabel->boot_file);
1977 create_sgiinfo(void)
1979 /* I keep SGI's habit to write the sgilabel to the second block */
1980 sgilabel->directory[0].vol_file_start = SGI_SSWAP32(2);
1981 sgilabel->directory[0].vol_file_size = SGI_SSWAP32(sizeof(sgiinfo));
1982 strncpy((char*)sgilabel->directory[0].vol_file_name, "sgilabel", 8);
1985 static sgiinfo *fill_sgiinfo(void);
1988 sgi_write_table(void)
1991 sgilabel->csum = SGI_SSWAP32(two_s_complement_32bit_sum(
1992 (unsigned int*)sgilabel, sizeof(*sgilabel)));
1993 assert(two_s_complement_32bit_sum(
1994 (unsigned int*)sgilabel, sizeof(*sgilabel)) == 0);
1996 if (lseek(fd, 0, SEEK_SET) < 0)
1997 fdisk_fatal(unable_to_seek);
1998 if (write(fd, sgilabel, SECTOR_SIZE) != SECTOR_SIZE)
1999 fdisk_fatal(unable_to_write);
2000 if (!strncmp((char*)sgilabel->directory[0].vol_file_name, "sgilabel", 8)) {
2002 * keep this habit of first writing the "sgilabel".
2003 * I never tested whether it works without (AN 981002).
2005 sgiinfo *info = fill_sgiinfo();
2006 int infostartblock = SGI_SSWAP32(sgilabel->directory[0].vol_file_start);
2007 if (lseek(fd, infostartblock*SECTOR_SIZE, SEEK_SET) < 0)
2008 fdisk_fatal(unable_to_seek);
2009 if (write(fd, info, SECTOR_SIZE) != SECTOR_SIZE)
2010 fdisk_fatal(unable_to_write);
2016 compare_start(int *x, int *y)
2019 * sort according to start sectors
2020 * and prefers largest partition:
2021 * entry zero is entire disk entry
2023 unsigned int i = *x;
2024 unsigned int j = *y;
2025 unsigned int a = sgi_get_start_sector(i);
2026 unsigned int b = sgi_get_start_sector(j);
2027 unsigned int c = sgi_get_num_sectors(i);
2028 unsigned int d = sgi_get_num_sectors(j);
2031 return (d > c) ? 1 : (d == c) ? 0 : -1;
2032 return (a > b) ? 1 : -1;
2037 verify_sgi(int verbose)
2039 int Index[16]; /* list of valid partitions */
2040 int sortcount = 0; /* number of used partitions, i.e. non-zero lengths */
2041 int entire = 0, i = 0;
2042 unsigned int start = 0;
2043 long long gap = 0; /* count unused blocks */
2044 unsigned int lastblock = sgi_get_lastblock();
2047 for (i = 0; i < 16; i++) {
2048 if (sgi_get_num_sectors(i) != 0) {
2049 Index[sortcount++] = i;
2050 if (sgi_get_sysid(i) == ENTIRE_DISK) {
2051 if (entire++ == 1) {
2053 printf(_("More than one entire disk entry present.\n"));
2058 if (sortcount == 0) {
2060 printf(_("No partitions defined\n"));
2061 return (lastblock > 0) ? 1 : (lastblock == 0) ? 0 : -1;
2063 qsort(Index, sortcount, sizeof(Index[0]), (void*)compare_start);
2064 if (sgi_get_sysid(Index[0]) == ENTIRE_DISK) {
2065 if ((Index[0] != 10) && verbose)
2066 printf(_("IRIX likes when Partition 11 covers the entire disk.\n"));
2067 if ((sgi_get_start_sector(Index[0]) != 0) && verbose)
2068 printf(_("The entire disk partition should start "
2070 "not at diskblock %d.\n"),
2071 sgi_get_start_sector(Index[0]));
2072 if (debug) /* I do not understand how some disks fulfil it */
2073 if ((sgi_get_num_sectors(Index[0]) != lastblock) && verbose)
2074 printf(_("The entire disk partition is only %d diskblock large,\n"
2075 "but the disk is %d diskblocks long.\n"),
2076 sgi_get_num_sectors(Index[0]), lastblock);
2077 lastblock = sgi_get_num_sectors(Index[0]);
2080 printf(_("One Partition (#11) should cover the entire disk.\n"));
2082 printf("sysid=%d\tpartition=%d\n",
2083 sgi_get_sysid(Index[0]), Index[0]+1);
2085 for (i = 1, start = 0; i < sortcount; i++) {
2086 int cylsize = sgi_get_nsect() * sgi_get_ntrks();
2088 if ((sgi_get_start_sector(Index[i]) % cylsize) != 0) {
2089 if (debug) /* I do not understand how some disks fulfil it */
2091 printf(_("Partition %d does not start on cylinder boundary.\n"),
2094 if (sgi_get_num_sectors(Index[i]) % cylsize != 0) {
2095 if (debug) /* I do not understand how some disks fulfil it */
2097 printf(_("Partition %d does not end on cylinder boundary.\n"),
2100 /* We cannot handle several "entire disk" entries. */
2101 if (sgi_get_sysid(Index[i]) == ENTIRE_DISK) continue;
2102 if (start > sgi_get_start_sector(Index[i])) {
2104 printf(_("The Partition %d and %d overlap by %d sectors.\n"),
2105 Index[i-1]+1, Index[i]+1,
2106 start - sgi_get_start_sector(Index[i]));
2107 if (gap > 0) gap = -gap;
2108 if (gap == 0) gap = -1;
2110 if (start < sgi_get_start_sector(Index[i])) {
2112 printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"),
2113 sgi_get_start_sector(Index[i]) - start,
2114 start, sgi_get_start_sector(Index[i])-1);
2115 gap += sgi_get_start_sector(Index[i]) - start;
2116 add2freelist(start, sgi_get_start_sector(Index[i]));
2118 start = sgi_get_start_sector(Index[i])
2119 + sgi_get_num_sectors(Index[i]);
2122 printf("%2d:%12d\t%12d\t%12d\n", Index[i],
2123 sgi_get_start_sector(Index[i]),
2124 sgi_get_num_sectors(Index[i]),
2125 sgi_get_sysid(Index[i]));
2128 if (start < lastblock) {
2130 printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"),
2131 lastblock - start, start, lastblock-1);
2132 gap += lastblock - start;
2133 add2freelist(start, lastblock);
2136 * Done with arithmetics
2137 * Go for details now
2140 if (!sgi_get_num_sectors(sgi_get_bootpartition())) {
2141 printf(_("\nThe boot partition does not exist.\n"));
2143 if (!sgi_get_num_sectors(sgi_get_swappartition())) {
2144 printf(_("\nThe swap partition does not exist.\n"));
2146 if ((sgi_get_sysid(sgi_get_swappartition()) != SGI_SWAP)
2147 && (sgi_get_sysid(sgi_get_swappartition()) != LINUX_SWAP))
2148 printf(_("\nThe swap partition has no swap type.\n"));
2150 if (sgi_check_bootfile("/unix"))
2151 printf(_("\tYou have chosen an unusual boot file name.\n"));
2153 return (gap > 0) ? 1 : (gap == 0) ? 0 : -1;
2160 * returned value is:
2161 * = 0 : disk is properly filled to the rim
2162 * < 0 : there is an overlap
2163 * > 0 : there is still some vacant space
2165 return verify_sgi(0);
2169 sgi_change_sysid(int i, int sys)
2171 if( sgi_get_num_sectors(i) == 0 ) { /* caught already before, ... */
2172 printf(_("Sorry You may change the Tag of non-empty partitions.\n"));
2175 if (((sys != ENTIRE_DISK ) && (sys != SGI_VOLHDR))
2176 && (sgi_get_start_sector(i) < 1) ) {
2178 _("It is highly recommended that the partition at offset 0\n"
2179 "is of type \"SGI volhdr\", the IRIX system will rely on it to\n"
2180 "retrieve from its directory standalone tools like sash and fx.\n"
2181 "Only the \"SGI volume\" entire disk section may violate this.\n"
2182 "Type YES if you are sure about tagging this partition differently.\n"));
2183 if (strcmp(line_ptr, _("YES\n")))
2186 sgilabel->partitions[i].id = SGI_SSWAP32(sys);
2189 /* returns partition index of first entry marked as entire disk */
2195 for (i = 0; i < 16; i++)
2196 if (sgi_get_sysid(i) == SGI_VOLUME)
2202 sgi_set_partition(int i, unsigned int start, unsigned int length, int sys)
2204 sgilabel->partitions[i].id = SGI_SSWAP32(sys);
2205 sgilabel->partitions[i].num_sectors = SGI_SSWAP32(length);
2206 sgilabel->partitions[i].start_sector = SGI_SSWAP32(start);
2208 if (sgi_gaps() < 0) /* rebuild freelist */
2209 printf(_("Do You know, You got a partition overlap on the disk?\n"));
2213 sgi_set_entire(void)
2217 for (n = 10; n < partitions; n++) {
2218 if(!sgi_get_num_sectors(n) ) {
2219 sgi_set_partition(n, 0, sgi_get_lastblock(), SGI_VOLUME);
2226 sgi_set_volhdr(void)
2230 for (n = 8; n < partitions; n++) {
2231 if (!sgi_get_num_sectors(n)) {
2233 * 5 cylinders is an arbitrary value I like
2234 * IRIX 5.3 stored files in the volume header
2235 * (like sash, symmon, fx, ide) with ca. 3200
2238 if (heads * sectors * 5 < sgi_get_lastblock())
2239 sgi_set_partition(n, 0, heads * sectors * 5, SGI_VOLHDR);
2246 sgi_delete_partition(int i)
2248 sgi_set_partition(i, 0, 0, 0);
2252 sgi_add_partition(int n, int sys)
2255 unsigned int first = 0, last = 0;
2259 } else if (n == 8) {
2262 if(sgi_get_num_sectors(n)) {
2263 printf(_("Partition %d is already defined. Delete "
2264 "it before re-adding it.\n"), n + 1);
2267 if ((sgi_entire() == -1) && (sys != SGI_VOLUME)) {
2268 printf(_("Attempting to generate entire disk entry automatically.\n"));
2272 if ((sgi_gaps() == 0) && (sys != SGI_VOLUME)) {
2273 printf(_("The entire disk is already covered with partitions.\n"));
2276 if (sgi_gaps() < 0) {
2277 printf(_("You got a partition overlap on the disk. Fix it first!\n"));
2280 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
2282 if(sys == SGI_VOLUME) {
2283 last = sgi_get_lastblock();
2284 first = read_int(0, 0, last-1, 0, mesg);
2286 printf(_("It is highly recommended that eleventh partition\n"
2287 "covers the entire disk and is of type `SGI volume'\n"));
2290 first = freelist[0].first;
2291 last = freelist[0].last;
2292 first = read_int(scround(first), scround(first), scround(last)-1,
2295 if (display_in_cyl_units)
2296 first *= units_per_sector;
2298 first = first; /* align to cylinder if you know how ... */
2300 last = isinfreelist(first);
2302 printf(_("You will get a partition overlap on the disk. "
2303 "Fix it first!\n"));
2307 snprintf(mesg, sizeof(mesg), _(" Last %s"), str_units(SINGULAR));
2308 last = read_int(scround(first), scround(last)-1, scround(last)-1,
2309 scround(first), mesg)+1;
2310 if (display_in_cyl_units)
2311 last *= units_per_sector;
2313 last = last; /* align to cylinder if You know how ... */
2314 if ( (sys == SGI_VOLUME) && (first != 0 || last != sgi_get_lastblock() ) )
2315 printf(_("It is highly recommended that eleventh partition\n"
2316 "covers the entire disk and is of type `SGI volume'\n"));
2317 sgi_set_partition(n, first, last-first, sys);
2320 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
2322 create_sgilabel(void)
2324 struct hd_geometry geometry;
2331 long longsectors; /* the number of sectors on the device */
2332 int res; /* the result from the ioctl */
2333 int sec_fac; /* the sector factor */
2335 sec_fac = sector_size / 512; /* determine the sector factor */
2338 _("Building a new SGI disklabel. Changes will remain in memory only,\n"
2339 "until you decide to write them. After that, of course, the previous\n"
2340 "content will be unrecoverably lost.\n\n"));
2342 sgi_other_endian = (BB_LITTLE_ENDIAN);
2343 res = ioctl(fd, BLKGETSIZE, &longsectors);
2344 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
2345 heads = geometry.heads;
2346 sectors = geometry.sectors;
2348 /* the get device size ioctl was successful */
2349 cylinders = longsectors / (heads * sectors);
2350 cylinders /= sec_fac;
2352 /* otherwise print error and use truncated version */
2353 cylinders = geometry.cylinders;
2355 _("Warning: BLKGETSIZE ioctl failed on %s. "
2356 "Using geometry cylinder value of %d.\n"
2357 "This value may be truncated for devices"
2358 " > 33.8 GB.\n"), disk_device, cylinders);
2361 for (i = 0; i < 4; i++) {
2363 if (valid_part_table_flag(MBRbuffer)) {
2364 if(get_part_table(i)->sys_ind) {
2365 old[i].sysid = get_part_table(i)->sys_ind;
2366 old[i].start = get_start_sect(get_part_table(i));
2367 old[i].nsect = get_nr_sects(get_part_table(i));
2368 printf(_("Trying to keep parameters of partition %d.\n"), i);
2370 printf(_("ID=%02x\tSTART=%d\tLENGTH=%d\n"),
2371 old[i].sysid, old[i].start, old[i].nsect);
2376 memset(MBRbuffer, 0, sizeof(MBRbuffer));
2377 sgilabel->magic = SGI_SSWAP32(SGI_LABEL_MAGIC);
2378 sgilabel->boot_part = SGI_SSWAP16(0);
2379 sgilabel->swap_part = SGI_SSWAP16(1);
2381 /* sizeof(sgilabel->boot_file) = 16 > 6 */
2382 memset(sgilabel->boot_file, 0, 16);
2383 strcpy((char*)sgilabel->boot_file, "/unix");
2385 sgilabel->devparam.skew = (0);
2386 sgilabel->devparam.gap1 = (0);
2387 sgilabel->devparam.gap2 = (0);
2388 sgilabel->devparam.sparecyl = (0);
2389 sgilabel->devparam.pcylcount = SGI_SSWAP16(geometry.cylinders);
2390 sgilabel->devparam.head_vol0 = SGI_SSWAP16(0);
2391 sgilabel->devparam.ntrks = SGI_SSWAP16(geometry.heads);
2392 /* tracks/cylinder (heads) */
2393 sgilabel->devparam.cmd_tag_queue_depth = (0);
2394 sgilabel->devparam.unused0 = (0);
2395 sgilabel->devparam.unused1 = SGI_SSWAP16(0);
2396 sgilabel->devparam.nsect = SGI_SSWAP16(geometry.sectors);
2398 sgilabel->devparam.bytes = SGI_SSWAP16(512);
2399 sgilabel->devparam.ilfact = SGI_SSWAP16(1);
2400 sgilabel->devparam.flags = SGI_SSWAP32(TRACK_FWD|
2401 IGNORE_ERRORS|RESEEK);
2402 sgilabel->devparam.datarate = SGI_SSWAP32(0);
2403 sgilabel->devparam.retries_on_error = SGI_SSWAP32(1);
2404 sgilabel->devparam.ms_per_word = SGI_SSWAP32(0);
2405 sgilabel->devparam.xylogics_gap1 = SGI_SSWAP16(0);
2406 sgilabel->devparam.xylogics_syncdelay = SGI_SSWAP16(0);
2407 sgilabel->devparam.xylogics_readdelay = SGI_SSWAP16(0);
2408 sgilabel->devparam.xylogics_gap2 = SGI_SSWAP16(0);
2409 sgilabel->devparam.xylogics_readgate = SGI_SSWAP16(0);
2410 sgilabel->devparam.xylogics_writecont = SGI_SSWAP16(0);
2411 memset( &(sgilabel->directory), 0, sizeof(struct volume_directory)*15 );
2412 memset( &(sgilabel->partitions), 0, sizeof(struct sgi_partition)*16 );
2413 current_label_type = label_sgi;
2418 for (i = 0; i < 4; i++) {
2420 sgi_set_partition(i, old[i].start, old[i].nsect, old[i].sysid);
2428 /* do nothing in the beginning */
2430 #endif /* CONFIG_FEATURE_FDISK_ADVANCED */
2432 /* _____________________________________________________________
2438 sgiinfo *info = calloc(1, sizeof(sgiinfo));
2440 info->magic = SGI_SSWAP32(SGI_INFO_MAGIC);
2441 info->b1 = SGI_SSWAP32(-1);
2442 info->b2 = SGI_SSWAP16(-1);
2443 info->b3 = SGI_SSWAP16(1);
2444 /* You may want to replace this string !!!!!!! */
2445 strcpy( (char*)info->scsi_string, "IBM OEM 0662S12 3 30" );
2446 strcpy( (char*)info->serial, "0000" );
2447 info->check1816 = SGI_SSWAP16(18*256 +16 );
2448 strcpy( (char*)info->installer, "Sfx version 5.3, Oct 18, 1994" );
2451 #endif /* SGI_LABEL */
2454 #ifdef CONFIG_FEATURE_SUN_LABEL
2458 * I think this is mostly, or entirely, due to
2459 * Jakub Jelinek (jj@sunsite.mff.cuni.cz), July 1996
2461 * Merged with fdisk for other architectures, aeb, June 1998.
2463 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
2464 * Internationalization
2468 static int sun_other_endian;
2469 static int scsi_disk;
2473 #define IDE0_MAJOR 3
2476 #define IDE1_MAJOR 22
2480 guess_device_type(void)
2482 struct stat bootstat;
2484 if (fstat(fd, &bootstat) < 0) {
2487 } else if (S_ISBLK(bootstat.st_mode)
2488 && (major(bootstat.st_rdev) == IDE0_MAJOR ||
2489 major(bootstat.st_rdev) == IDE1_MAJOR)) {
2492 } else if (S_ISBLK(bootstat.st_mode)
2493 && major(bootstat.st_rdev) == FLOPPY_MAJOR) {
2502 static const struct systypes sun_sys_types[] = {
2503 { "\x00" "Empty" }, /* 0 */
2504 { "\x01" "Boot" }, /* 1 */
2505 { "\x02" "SunOS root" }, /* 2 */
2506 { "\x03" "SunOS swap" }, /* SUNOS_SWAP */
2507 { "\x04" "SunOS usr" }, /* 4 */
2508 { "\x05" "Whole disk" }, /* WHOLE_DISK */
2509 { "\x06" "SunOS stand" }, /* 6 */
2510 { "\x07" "SunOS var" }, /* 7 */
2511 { "\x08" "SunOS home" }, /* 8 */
2512 { "\x82" "Linux swap" }, /* LINUX_SWAP */
2513 { "\x83" "Linux native" }, /* LINUX_NATIVE */
2514 { "\x8e" "Linux LVM" }, /* 0x8e */
2515 /* New (2.2.x) raid partition with autodetect using persistent superblock */
2516 { "\xfd" "Linux raid autodetect" }, /* 0xfd */
2522 set_sun_partition(int i, uint start, uint stop, int sysid)
2524 sunlabel->infos[i].id = sysid;
2525 sunlabel->partitions[i].start_cylinder =
2526 SUN_SSWAP32(start / (heads * sectors));
2527 sunlabel->partitions[i].num_sectors =
2528 SUN_SSWAP32(stop - start);
2533 check_sun_label(void)
2535 unsigned short *ush;
2538 if (sunlabel->magic != SUN_LABEL_MAGIC
2539 && sunlabel->magic != SUN_LABEL_MAGIC_SWAPPED) {
2540 current_label_type = label_dos;
2541 sun_other_endian = 0;
2544 sun_other_endian = (sunlabel->magic == SUN_LABEL_MAGIC_SWAPPED);
2545 ush = ((unsigned short *) (sunlabel + 1)) - 1;
2546 for (csum = 0; ush >= (unsigned short *)sunlabel;) csum ^= *ush--;
2548 fprintf(stderr,_("Detected sun disklabel with wrong checksum.\n"
2549 "Probably you'll have to set all the values,\n"
2550 "e.g. heads, sectors, cylinders and partitions\n"
2551 "or force a fresh label (s command in main menu)\n"));
2553 heads = SUN_SSWAP16(sunlabel->ntrks);
2554 cylinders = SUN_SSWAP16(sunlabel->ncyl);
2555 sectors = SUN_SSWAP16(sunlabel->nsect);
2558 current_label_type = label_sun;
2563 static const struct sun_predefined_drives {
2566 unsigned short sparecyl;
2567 unsigned short ncyl;
2568 unsigned short nacyl;
2569 unsigned short pcylcount;
2570 unsigned short ntrks;
2571 unsigned short nsect;
2572 unsigned short rspeed;
2574 { "Quantum","ProDrive 80S",1,832,2,834,6,34,3662},
2575 { "Quantum","ProDrive 105S",1,974,2,1019,6,35,3662},
2576 { "CDC","Wren IV 94171-344",3,1545,2,1549,9,46,3600},
2577 { "IBM","DPES-31080",0,4901,2,4903,4,108,5400},
2578 { "IBM","DORS-32160",0,1015,2,1017,67,62,5400},
2579 { "IBM","DNES-318350",0,11199,2,11474,10,320,7200},
2580 { "SEAGATE","ST34371",0,3880,2,3882,16,135,7228},
2581 { "","SUN0104",1,974,2,1019,6,35,3662},
2582 { "","SUN0207",4,1254,2,1272,9,36,3600},
2583 { "","SUN0327",3,1545,2,1549,9,46,3600},
2584 { "","SUN0340",0,1538,2,1544,6,72,4200},
2585 { "","SUN0424",2,1151,2,2500,9,80,4400},
2586 { "","SUN0535",0,1866,2,2500,7,80,5400},
2587 { "","SUN0669",5,1614,2,1632,15,54,3600},
2588 { "","SUN1.0G",5,1703,2,1931,15,80,3597},
2589 { "","SUN1.05",0,2036,2,2038,14,72,5400},
2590 { "","SUN1.3G",6,1965,2,3500,17,80,5400},
2591 { "","SUN2.1G",0,2733,2,3500,19,80,5400},
2592 { "IOMEGA","Jaz",0,1019,2,1021,64,32,5394},
2595 static const struct sun_predefined_drives *
2596 sun_autoconfigure_scsi(void)
2598 const struct sun_predefined_drives *p = NULL;
2600 #ifdef SCSI_IOCTL_GET_IDLUN
2610 if (!ioctl(fd, SCSI_IOCTL_GET_IDLUN, &id)) {
2612 "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n",
2614 ((id[0]>>24)&0xff)-/*PROC_SCSI_SCSI+PROC_SCSI_FILE*/33,
2616 /* This is very wrong (works only if you have one HBA),
2617 but I haven't found a way how to get hostno
2618 from the current kernel */
2625 pfd = fopen("/proc/scsi/scsi","r");
2627 while (fgets(buffer2, 2048, pfd)) {
2628 if (!strcmp(buffer, buffer2)) {
2629 if (fgets(buffer2,2048,pfd)) {
2630 q = strstr(buffer2,"Vendor: ");
2635 *q++ = 0; /* truncate vendor name */
2636 q = strstr(q,"Model: ");
2641 q = strstr(q," Rev: ");
2644 for (i = 0; i < SIZE(sun_drives); i++) {
2645 if (*sun_drives[i].vendor && strcasecmp(sun_drives[i].vendor, vendor))
2647 if (!strstr(model, sun_drives[i].model))
2649 printf(_("Autoconfigure found a %s%s%s\n"),sun_drives[i].vendor,(*sun_drives[i].vendor) ? " " : "",sun_drives[i].model);
2668 create_sunlabel(void)
2670 struct hd_geometry geometry;
2674 const struct sun_predefined_drives *p = NULL;
2677 _("Building a new sun disklabel. Changes will remain in memory only,\n"
2678 "until you decide to write them. After that, of course, the previous\n"
2679 "content won't be recoverable.\n\n"));
2680 sun_other_endian = BB_LITTLE_ENDIAN;
2681 memset(MBRbuffer, 0, sizeof(MBRbuffer));
2682 sunlabel->magic = SUN_SSWAP16(SUN_LABEL_MAGIC);
2684 puts(_("Drive type\n"
2685 " ? auto configure\n"
2686 " 0 custom (with hardware detected defaults)"));
2687 for (i = 0; i < SIZE(sun_drives); i++) {
2688 printf(" %c %s%s%s\n",
2689 i + 'a', sun_drives[i].vendor,
2690 (*sun_drives[i].vendor) ? " " : "",
2691 sun_drives[i].model);
2694 c = read_char(_("Select type (? for auto, 0 for custom): "));
2695 if (c >= 'a' && c < 'a' + SIZE(sun_drives)) {
2696 p = sun_drives + c - 'a';
2698 } else if (c >= 'A' && c < 'A' + SIZE(sun_drives)) {
2699 p = sun_drives + c - 'A';
2701 } else if (c == '0') {
2703 } else if (c == '?' && scsi_disk) {
2704 p = sun_autoconfigure_scsi();
2706 printf(_("Autoconfigure failed.\n"));
2713 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
2714 heads = geometry.heads;
2715 sectors = geometry.sectors;
2716 cylinders = geometry.cylinders;
2723 sunlabel->nacyl = 0;
2724 sunlabel->pcylcount = SUN_SSWAP16(cylinders);
2725 sunlabel->rspeed = SUN_SSWAP16(300);
2726 sunlabel->ilfact = SUN_SSWAP16(1);
2727 sunlabel->sparecyl = 0;
2729 heads = read_int(1,heads,1024,0,_("Heads"));
2730 sectors = read_int(1,sectors,1024,0,_("Sectors/track"));
2732 cylinders = read_int(1,cylinders-2,65535,0,_("Cylinders"));
2734 cylinders = read_int(1,0,65535,0,_("Cylinders"));
2735 sunlabel->nacyl = SUN_SSWAP16(read_int(0,2,65535,0, _("Alternate cylinders")));
2736 sunlabel->pcylcount = SUN_SSWAP16(read_int(0,cylinders+SUN_SSWAP16(sunlabel->nacyl), 65535,0, _("Physical cylinders")));
2737 sunlabel->rspeed = SUN_SSWAP16(read_int(1,5400,100000,0, _("Rotation speed (rpm)")));
2738 sunlabel->ilfact = SUN_SSWAP16(read_int(1,1,32,0, _("Interleave factor")));
2739 sunlabel->sparecyl = SUN_SSWAP16(read_int(0,0,sectors,0, _("Extra sectors per cylinder")));
2742 sunlabel->sparecyl = SUN_SSWAP16(p->sparecyl);
2743 sunlabel->ncyl = SUN_SSWAP16(p->ncyl);
2744 sunlabel->nacyl = SUN_SSWAP16(p->nacyl);
2745 sunlabel->pcylcount = SUN_SSWAP16(p->pcylcount);
2746 sunlabel->ntrks = SUN_SSWAP16(p->ntrks);
2747 sunlabel->nsect = SUN_SSWAP16(p->nsect);
2748 sunlabel->rspeed = SUN_SSWAP16(p->rspeed);
2749 sunlabel->ilfact = SUN_SSWAP16(1);
2750 cylinders = p->ncyl;
2753 puts(_("You may change all the disk params from the x menu"));
2756 snprintf((char *)(sunlabel->info), sizeof(sunlabel->info),
2757 "%s%s%s cyl %d alt %d hd %d sec %d",
2758 p ? p->vendor : "", (p && *p->vendor) ? " " : "",
2759 p ? p->model : (floppy ? _("3,5\" floppy") : _("Linux custom")),
2760 cylinders, SUN_SSWAP16(sunlabel->nacyl), heads, sectors);
2762 sunlabel->ntrks = SUN_SSWAP16(heads);
2763 sunlabel->nsect = SUN_SSWAP16(sectors);
2764 sunlabel->ncyl = SUN_SSWAP16(cylinders);
2766 set_sun_partition(0, 0, cylinders * heads * sectors, LINUX_NATIVE);
2768 if (cylinders * heads * sectors >= 150 * 2048) {
2769 ndiv = cylinders - (50 * 2048 / (heads * sectors)); /* 50M swap */
2771 ndiv = cylinders * 2 / 3;
2772 set_sun_partition(0, 0, ndiv * heads * sectors, LINUX_NATIVE);
2773 set_sun_partition(1, ndiv * heads * sectors, cylinders * heads * sectors, LINUX_SWAP);
2774 sunlabel->infos[1].flags |= 0x01; /* Not mountable */
2776 set_sun_partition(2, 0, cylinders * heads * sectors, WHOLE_DISK);
2778 unsigned short *ush = (unsigned short *)sunlabel;
2779 unsigned short csum = 0;
2780 while (ush < (unsigned short *)(&sunlabel->csum))
2782 sunlabel->csum = csum;
2785 set_all_unchanged();
2787 get_boot(create_empty_sun);
2791 toggle_sunflags(int i, unsigned char mask)
2793 if (sunlabel->infos[i].flags & mask)
2794 sunlabel->infos[i].flags &= ~mask;
2796 sunlabel->infos[i].flags |= mask;
2801 fetch_sun(uint *starts, uint *lens, uint *start, uint *stop)
2803 int i, continuous = 1;
2806 *stop = cylinders * heads * sectors;
2807 for (i = 0; i < partitions; i++) {
2808 if (sunlabel->partitions[i].num_sectors
2809 && sunlabel->infos[i].id
2810 && sunlabel->infos[i].id != WHOLE_DISK) {
2811 starts[i] = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
2812 lens[i] = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
2814 if (starts[i] == *start)
2816 else if (starts[i] + lens[i] >= *stop)
2820 /* There will be probably more gaps
2821 than one, so lets check afterwards */
2830 static uint *verify_sun_starts;
2833 verify_sun_cmp(int *a, int *b)
2835 if (*a == -1) return 1;
2836 if (*b == -1) return -1;
2837 if (verify_sun_starts[*a] > verify_sun_starts[*b]) return 1;
2844 uint starts[8], lens[8], start, stop;
2845 int i,j,k,starto,endo;
2848 verify_sun_starts = starts;
2849 fetch_sun(starts,lens,&start,&stop);
2850 for (k = 0; k < 7; k++) {
2851 for (i = 0; i < 8; i++) {
2852 if (k && (lens[i] % (heads * sectors))) {
2853 printf(_("Partition %d doesn't end on cylinder boundary\n"), i+1);
2856 for (j = 0; j < i; j++)
2858 if (starts[j] == starts[i]+lens[i]) {
2859 starts[j] = starts[i]; lens[j] += lens[i];
2861 } else if (starts[i] == starts[j]+lens[j]){
2865 if (starts[i] < starts[j]+lens[j]
2866 && starts[j] < starts[i]+lens[i]) {
2868 if (starts[j] > starto)
2870 endo = starts[i]+lens[i];
2871 if (starts[j]+lens[j] < endo)
2872 endo = starts[j]+lens[j];
2873 printf(_("Partition %d overlaps with others in "
2874 "sectors %d-%d\n"), i+1, starto, endo);
2881 for (i = 0; i < 8; i++) {
2887 qsort(array,SIZE(array),sizeof(array[0]),
2888 (int (*)(const void *,const void *)) verify_sun_cmp);
2889 if (array[0] == -1) {
2890 printf(_("No partitions defined\n"));
2893 stop = cylinders * heads * sectors;
2894 if (starts[array[0]])
2895 printf(_("Unused gap - sectors 0-%d\n"),starts[array[0]]);
2896 for (i = 0; i < 7 && array[i+1] != -1; i++) {
2897 printf(_("Unused gap - sectors %d-%d\n"),starts[array[i]]+lens[array[i]],starts[array[i+1]]);
2899 start = starts[array[i]] + lens[array[i]];
2901 printf(_("Unused gap - sectors %d-%d\n"),start,stop);
2905 add_sun_partition(int n, int sys)
2907 uint start, stop, stop2;
2908 uint starts[8], lens[8];
2914 if (sunlabel->partitions[n].num_sectors && sunlabel->infos[n].id) {
2915 printf(_("Partition %d is already defined. Delete "
2916 "it before re-adding it.\n"), n + 1);
2920 fetch_sun(starts,lens,&start,&stop);
2921 if (stop <= start) {
2925 printf(_("Other partitions already cover the whole disk.\nDelete "
2926 "some/shrink them before retry.\n"));
2930 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
2933 first = read_int(0, 0, 0, 0, mesg);
2935 first = read_int(scround(start), scround(stop)+1,
2936 scround(stop), 0, mesg);
2937 if (display_in_cyl_units)
2938 first *= units_per_sector;
2940 /* Starting sector has to be properly aligned */
2941 first = (first + heads * sectors - 1) / (heads * sectors);
2942 if (n == 2 && first != 0)
2944 It is highly recommended that the third partition covers the whole disk\n\
2945 and is of type `Whole disk'\n");
2946 /* ewt asks to add: "don't start a partition at cyl 0"
2947 However, edmundo@rano.demon.co.uk writes:
2948 "In addition to having a Sun partition table, to be able to
2949 boot from the disc, the first partition, /dev/sdX1, must
2950 start at cylinder 0. This means that /dev/sdX1 contains
2951 the partition table and the boot block, as these are the
2952 first two sectors of the disc. Therefore you must be
2953 careful what you use /dev/sdX1 for. In particular, you must
2954 not use a partition starting at cylinder 0 for Linux swap,
2955 as that would overwrite the partition table and the boot
2956 block. You may, however, use such a partition for a UFS
2957 or EXT2 file system, as these file systems leave the first
2958 1024 bytes undisturbed. */
2959 /* On the other hand, one should not use partitions
2960 starting at block 0 in an md, or the label will
2962 for (i = 0; i < partitions; i++)
2963 if (lens[i] && starts[i] <= first && starts[i] + lens[i] > first)
2965 if (i < partitions && !whole_disk) {
2966 if (n == 2 && !first) {
2970 printf(_("Sector %d is already allocated\n"), first);
2974 stop = cylinders * heads * sectors;
2976 for (i = 0; i < partitions; i++) {
2977 if (starts[i] > first && starts[i] < stop)
2980 snprintf(mesg, sizeof(mesg),
2981 _("Last %s or +size or +sizeM or +sizeK"),
2982 str_units(SINGULAR));
2984 last = read_int(scround(stop2), scround(stop2), scround(stop2),
2986 else if (n == 2 && !first)
2987 last = read_int(scround(first), scround(stop2), scround(stop2),
2988 scround(first), mesg);
2990 last = read_int(scround(first), scround(stop), scround(stop),
2991 scround(first), mesg);
2992 if (display_in_cyl_units)
2993 last *= units_per_sector;
2994 if (n == 2 && !first) {
2995 if (last >= stop2) {
2998 } else if (last > stop) {
2999 printf(_("You haven't covered the whole disk with "
3000 "the 3rd partition, but your value\n"
3001 "%d %s covers some other partition. "
3002 "Your entry has been changed\n"
3004 scround(last), str_units(SINGULAR),
3005 scround(stop), str_units(SINGULAR));
3008 } else if (!whole_disk && last > stop)
3013 set_sun_partition(n, first, last, sys);
3017 sun_delete_partition(int i)
3022 && sunlabel->infos[i].id == WHOLE_DISK
3023 && !sunlabel->partitions[i].start_cylinder
3024 && (nsec = SUN_SSWAP32(sunlabel->partitions[i].num_sectors)) == heads * sectors * cylinders)
3025 printf(_("If you want to maintain SunOS/Solaris compatibility, "
3026 "consider leaving this\n"
3027 "partition as Whole disk (5), starting at 0, with %u "
3028 "sectors\n"), nsec);
3029 sunlabel->infos[i].id = 0;
3030 sunlabel->partitions[i].num_sectors = 0;
3034 sun_change_sysid(int i, int sys)
3036 if (sys == LINUX_SWAP && !sunlabel->partitions[i].start_cylinder) {
3038 _("It is highly recommended that the partition at offset 0\n"
3039 "is UFS, EXT2FS filesystem or SunOS swap. Putting Linux swap\n"
3040 "there may destroy your partition table and bootblock.\n"
3041 "Type YES if you're very sure you would like that partition\n"
3042 "tagged with 82 (Linux swap): "));
3043 if (strcmp (line_ptr, _("YES\n")))
3049 /* swaps are not mountable by default */
3050 sunlabel->infos[i].flags |= 0x01;
3053 /* assume other types are mountable;
3054 user can change it anyway */
3055 sunlabel->infos[i].flags &= ~0x01;
3058 sunlabel->infos[i].id = sys;
3062 sun_list_table(int xtra)
3066 w = strlen(disk_device);
3069 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d rpm\n"
3070 "%d cylinders, %d alternate cylinders, %d physical cylinders\n"
3071 "%d extra sects/cyl, interleave %d:1\n"
3073 "Units = %s of %d * 512 bytes\n\n"),
3074 disk_device, heads, sectors, SUN_SSWAP16(sunlabel->rspeed),
3075 cylinders, SUN_SSWAP16(sunlabel->nacyl),
3076 SUN_SSWAP16(sunlabel->pcylcount),
3077 SUN_SSWAP16(sunlabel->sparecyl),
3078 SUN_SSWAP16(sunlabel->ilfact),
3080 str_units(PLURAL), units_per_sector);
3083 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d cylinders\n"
3084 "Units = %s of %d * 512 bytes\n\n"),
3085 disk_device, heads, sectors, cylinders,
3086 str_units(PLURAL), units_per_sector);
3088 printf(_("%*s Flag Start End Blocks Id System\n"),
3089 w + 1, _("Device"));
3090 for (i = 0 ; i < partitions; i++) {
3091 if (sunlabel->partitions[i].num_sectors) {
3092 uint32_t start = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
3093 uint32_t len = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
3094 printf("%s %c%c %9ld %9ld %9ld%c %2x %s\n",
3095 partname(disk_device, i+1, w), /* device */
3096 (sunlabel->infos[i].flags & 0x01) ? 'u' : ' ', /* flags */
3097 (sunlabel->infos[i].flags & 0x10) ? 'r' : ' ',
3098 (long) scround(start), /* start */
3099 (long) scround(start+len), /* end */
3100 (long) len / 2, len & 1 ? '+' : ' ', /* odd flag on end */
3101 sunlabel->infos[i].id, /* type id */
3102 partition_type(sunlabel->infos[i].id)); /* type name */
3107 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3110 sun_set_alt_cyl(void)
3113 SUN_SSWAP16(read_int(0,SUN_SSWAP16(sunlabel->nacyl), 65535, 0,
3114 _("Number of alternate cylinders")));
3118 sun_set_ncyl(int cyl)
3120 sunlabel->ncyl = SUN_SSWAP16(cyl);
3126 sunlabel->sparecyl =
3127 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->sparecyl), sectors, 0,
3128 _("Extra sectors per cylinder")));
3132 sun_set_ilfact(void)
3135 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->ilfact), 32, 0,
3136 _("Interleave factor")));
3140 sun_set_rspeed(void)
3143 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->rspeed), 100000, 0,
3144 _("Rotation speed (rpm)")));
3148 sun_set_pcylcount(void)
3150 sunlabel->pcylcount =
3151 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->pcylcount), 65535, 0,
3152 _("Number of physical cylinders")));
3154 #endif /* CONFIG_FEATURE_FDISK_ADVANCED */
3157 sun_write_table(void)
3159 unsigned short *ush = (unsigned short *)sunlabel;
3160 unsigned short csum = 0;
3162 while (ush < (unsigned short *)(&sunlabel->csum))
3164 sunlabel->csum = csum;
3165 if (lseek(fd, 0, SEEK_SET) < 0)
3166 fdisk_fatal(unable_to_seek);
3167 if (write(fd, sunlabel, SECTOR_SIZE) != SECTOR_SIZE)
3168 fdisk_fatal(unable_to_write);
3170 #endif /* SUN_LABEL */
3172 /* DOS partition types */
3174 static const struct systypes i386_sys_types[] = {
3177 { "\x04" "FAT16 <32M" },
3178 { "\x05" "Extended" }, /* DOS 3.3+ extended partition */
3179 { "\x06" "FAT16" }, /* DOS 16-bit >=32M */
3180 { "\x07" "HPFS/NTFS" }, /* OS/2 IFS, eg, HPFS or NTFS or QNX */
3181 { "\x0a" "OS/2 Boot Manager" },/* OS/2 Boot Manager */
3182 { "\x0b" "Win95 FAT32" },
3183 { "\x0c" "Win95 FAT32 (LBA)" },/* LBA really is `Extended Int 13h' */
3184 { "\x0e" "Win95 FAT16 (LBA)" },
3185 { "\x0f" "Win95 Ext'd (LBA)" },
3186 { "\x11" "Hidden FAT12" },
3187 { "\x12" "Compaq diagnostics" },
3188 { "\x14" "Hidden FAT16 <32M" },
3189 { "\x16" "Hidden FAT16" },
3190 { "\x17" "Hidden HPFS/NTFS" },
3191 { "\x1b" "Hidden Win95 FAT32" },
3192 { "\x1c" "Hidden Win95 FAT32 (LBA)" },
3193 { "\x1e" "Hidden Win95 FAT16 (LBA)" },
3194 { "\x3c" "PartitionMagic recovery" },
3195 { "\x41" "PPC PReP Boot" },
3197 { "\x63" "GNU HURD or SysV" }, /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */
3198 { "\x80" "Old Minix" }, /* Minix 1.4a and earlier */
3199 { "\x81" "Minix / old Linux" },/* Minix 1.4b and later */
3200 { "\x82" "Linux swap" }, /* also Solaris */
3202 { "\x84" "OS/2 hidden C: drive" },
3203 { "\x85" "Linux extended" },
3204 { "\x86" "NTFS volume set" },
3205 { "\x87" "NTFS volume set" },
3206 { "\x8e" "Linux LVM" },
3207 { "\x9f" "BSD/OS" }, /* BSDI */
3208 { "\xa0" "IBM Thinkpad hibernation" },
3209 { "\xa5" "FreeBSD" }, /* various BSD flavours */
3210 { "\xa6" "OpenBSD" },
3211 { "\xa8" "Darwin UFS" },
3212 { "\xa9" "NetBSD" },
3213 { "\xab" "Darwin boot" },
3214 { "\xb7" "BSDI fs" },
3215 { "\xb8" "BSDI swap" },
3216 { "\xbe" "Solaris boot" },
3217 { "\xeb" "BeOS fs" },
3218 { "\xee" "EFI GPT" }, /* Intel EFI GUID Partition Table */
3219 { "\xef" "EFI (FAT-12/16/32)" },/* Intel EFI System Partition */
3220 { "\xf0" "Linux/PA-RISC boot" },/* Linux/PA-RISC boot loader */
3221 { "\xf2" "DOS secondary" }, /* DOS 3.3+ secondary */
3222 { "\xfd" "Linux raid autodetect" },/* New (2.2.x) raid partition with
3223 autodetect using persistent
3225 #ifdef CONFIG_WEIRD_PARTITION_TYPES
3226 { "\x02" "XENIX root" },
3227 { "\x03" "XENIX usr" },
3228 { "\x08" "AIX" }, /* AIX boot (AIX -- PS/2 port) or SplitDrive */
3229 { "\x09" "AIX bootable" }, /* AIX data or Coherent */
3231 { "\x18" "AST SmartSleep" },
3232 { "\x24" "NEC DOS" },
3233 { "\x39" "Plan 9" },
3234 { "\x40" "Venix 80286" },
3235 { "\x4d" "QNX4.x" },
3236 { "\x4e" "QNX4.x 2nd part" },
3237 { "\x4f" "QNX4.x 3rd part" },
3238 { "\x50" "OnTrack DM" },
3239 { "\x51" "OnTrack DM6 Aux1" }, /* (or Novell) */
3240 { "\x52" "CP/M" }, /* CP/M or Microport SysV/AT */
3241 { "\x53" "OnTrack DM6 Aux3" },
3242 { "\x54" "OnTrackDM6" },
3243 { "\x55" "EZ-Drive" },
3244 { "\x56" "Golden Bow" },
3245 { "\x5c" "Priam Edisk" },
3246 { "\x61" "SpeedStor" },
3247 { "\x64" "Novell Netware 286" },
3248 { "\x65" "Novell Netware 386" },
3249 { "\x70" "DiskSecure Multi-Boot" },
3251 { "\x93" "Amoeba" },
3252 { "\x94" "Amoeba BBT" }, /* (bad block table) */
3253 { "\xa7" "NeXTSTEP" },
3254 { "\xbb" "Boot Wizard hidden" },
3255 { "\xc1" "DRDOS/sec (FAT-12)" },
3256 { "\xc4" "DRDOS/sec (FAT-16 < 32M)" },
3257 { "\xc6" "DRDOS/sec (FAT-16)" },
3258 { "\xc7" "Syrinx" },
3259 { "\xda" "Non-FS data" },
3260 { "\xdb" "CP/M / CTOS / ..." },/* CP/M or Concurrent CP/M or
3261 Concurrent DOS or CTOS */
3262 { "\xde" "Dell Utility" }, /* Dell PowerEdge Server utilities */
3263 { "\xdf" "BootIt" }, /* BootIt EMBRM */
3264 { "\xe1" "DOS access" }, /* DOS access or SpeedStor 12-bit FAT
3265 extended partition */
3266 { "\xe3" "DOS R/O" }, /* DOS R/O or SpeedStor */
3267 { "\xe4" "SpeedStor" }, /* SpeedStor 16-bit FAT extended
3268 partition < 1024 cyl. */
3269 { "\xf1" "SpeedStor" },
3270 { "\xf4" "SpeedStor" }, /* SpeedStor large partition */
3271 { "\xfe" "LANstep" }, /* SpeedStor >1024 cyl. or LANstep */
3272 { "\xff" "BBT" }, /* Xenix Bad Block Table */
3279 /* A valid partition table sector ends in 0x55 0xaa */
3281 part_table_flag(const char *b)
3283 return ((uint) b[510]) + (((uint) b[511]) << 8);
3287 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3289 write_part_table_flag(char *b)
3295 /* start_sect and nr_sects are stored little endian on all machines */
3296 /* moreover, they are not aligned correctly */
3298 store4_little_endian(unsigned char *cp, unsigned int val)
3300 cp[0] = (val & 0xff);
3301 cp[1] = ((val >> 8) & 0xff);
3302 cp[2] = ((val >> 16) & 0xff);
3303 cp[3] = ((val >> 24) & 0xff);
3305 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3308 read4_little_endian(const unsigned char *cp)
3310 return (uint)(cp[0]) + ((uint)(cp[1]) << 8)
3311 + ((uint)(cp[2]) << 16) + ((uint)(cp[3]) << 24);
3314 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3316 set_start_sect(struct partition *p, unsigned int start_sect)
3318 store4_little_endian(p->start4, start_sect);
3323 get_start_sect(const struct partition *p)
3325 return read4_little_endian(p->start4);
3328 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3330 set_nr_sects(struct partition *p, int32_t nr_sects)
3332 store4_little_endian(p->size4, nr_sects);
3337 get_nr_sects(const struct partition *p)
3339 return read4_little_endian(p->size4);
3342 /* normally O_RDWR, -l option gives O_RDONLY */
3343 static int type_open = O_RDWR;
3346 static int ext_index; /* the prime extended partition */
3347 static int listing; /* no aborts for fdisk -l */
3348 static int dos_compatible_flag = ~0;
3349 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3350 static int dos_changed;
3351 static int nowarn; /* no warnings for fdisk -l/-s */
3356 static uint user_cylinders, user_heads, user_sectors;
3357 static uint pt_heads, pt_sectors;
3358 static uint kern_heads, kern_sectors;
3360 static off_t extended_offset; /* offset of link pointers */
3362 static unsigned long long total_number_of_sectors;
3365 static jmp_buf listingbuf;
3367 static void fdisk_fatal(enum failure why)
3369 const char *message;
3373 longjmp(listingbuf, 1);
3377 case unable_to_open:
3378 message = "Unable to open %s\n";
3380 case unable_to_read:
3381 message = "Unable to read %s\n";
3383 case unable_to_seek:
3384 message = "Unable to seek on %s\n";
3386 case unable_to_write:
3387 message = "Unable to write %s\n";
3390 message = "BLKGETSIZE ioctl failed on %s\n";
3393 message = "Fatal error\n";
3396 fputc('\n', stderr);
3397 fprintf(stderr, message, disk_device);
3402 seek_sector(off_t secno)
3404 off_t offset = secno * sector_size;
3405 if (lseek(fd, offset, SEEK_SET) == (off_t) -1)
3406 fdisk_fatal(unable_to_seek);
3409 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3411 write_sector(off_t secno, char *buf)
3414 if (write(fd, buf, sector_size) != sector_size)
3415 fdisk_fatal(unable_to_write);
3419 /* Allocate a buffer and read a partition table sector */
3421 read_pte(struct pte *pe, off_t offset)
3423 pe->offset = offset;
3424 pe->sectorbuffer = (char *) xmalloc(sector_size);
3425 seek_sector(offset);
3426 if (read(fd, pe->sectorbuffer, sector_size) != sector_size)
3427 fdisk_fatal(unable_to_read);
3428 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3431 pe->part_table = pe->ext_pointer = NULL;
3435 get_partition_start(const struct pte *pe)
3437 return pe->offset + get_start_sect(pe->part_table);
3440 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3442 * Avoid warning about DOS partitions when no DOS partition was changed.
3443 * Here a heuristic "is probably dos partition".
3444 * We might also do the opposite and warn in all cases except
3445 * for "is probably nondos partition".
3448 is_dos_partition(int t)
3450 return (t == 1 || t == 4 || t == 6 ||
3451 t == 0x0b || t == 0x0c || t == 0x0e ||
3452 t == 0x11 || t == 0x12 || t == 0x14 || t == 0x16 ||
3453 t == 0x1b || t == 0x1c || t == 0x1e || t == 0x24 ||
3454 t == 0xc1 || t == 0xc4 || t == 0xc6);
3460 #ifdef CONFIG_FEATURE_SUN_LABEL
3461 if (label_sun == current_label_type) {
3462 puts(_("Command action"));
3463 puts(_("\ta\ttoggle a read only flag")); /* sun */
3464 puts(_("\tb\tedit bsd disklabel"));
3465 puts(_("\tc\ttoggle the mountable flag")); /* sun */
3466 puts(_("\td\tdelete a partition"));
3467 puts(_("\tl\tlist known partition types"));
3468 puts(_("\tm\tprint this menu"));
3469 puts(_("\tn\tadd a new partition"));
3470 puts(_("\to\tcreate a new empty DOS partition table"));
3471 puts(_("\tp\tprint the partition table"));
3472 puts(_("\tq\tquit without saving changes"));
3473 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3474 puts(_("\tt\tchange a partition's system id"));
3475 puts(_("\tu\tchange display/entry units"));
3476 puts(_("\tv\tverify the partition table"));
3477 puts(_("\tw\twrite table to disk and exit"));
3478 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3479 puts(_("\tx\textra functionality (experts only)"));
3483 #ifdef CONFIG_FEATURE_SGI_LABEL
3484 if (label_sgi == current_label_type) {
3485 puts(_("Command action"));
3486 puts(_("\ta\tselect bootable partition")); /* sgi flavour */
3487 puts(_("\tb\tedit bootfile entry")); /* sgi */
3488 puts(_("\tc\tselect sgi swap partition")); /* sgi flavour */
3489 puts(_("\td\tdelete a partition"));
3490 puts(_("\tl\tlist known partition types"));
3491 puts(_("\tm\tprint this menu"));
3492 puts(_("\tn\tadd a new partition"));
3493 puts(_("\to\tcreate a new empty DOS partition table"));
3494 puts(_("\tp\tprint the partition table"));
3495 puts(_("\tq\tquit without saving changes"));
3496 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3497 puts(_("\tt\tchange a partition's system id"));
3498 puts(_("\tu\tchange display/entry units"));
3499 puts(_("\tv\tverify the partition table"));
3500 puts(_("\tw\twrite table to disk and exit"));
3503 #ifdef CONFIG_FEATURE_AIX_LABEL
3504 if (label_aix == current_label_type) {
3505 puts(_("Command action"));
3506 puts(_("\tm\tprint this menu"));
3507 puts(_("\to\tcreate a new empty DOS partition table"));
3508 puts(_("\tq\tquit without saving changes"));
3509 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3513 puts(_("Command action"));
3514 puts(_("\ta\ttoggle a bootable flag"));
3515 puts(_("\tb\tedit bsd disklabel"));
3516 puts(_("\tc\ttoggle the dos compatibility flag"));
3517 puts(_("\td\tdelete a partition"));
3518 puts(_("\tl\tlist known partition types"));
3519 puts(_("\tm\tprint this menu"));
3520 puts(_("\tn\tadd a new partition"));
3521 puts(_("\to\tcreate a new empty DOS partition table"));
3522 puts(_("\tp\tprint the partition table"));
3523 puts(_("\tq\tquit without saving changes"));
3524 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3525 puts(_("\tt\tchange a partition's system id"));
3526 puts(_("\tu\tchange display/entry units"));
3527 puts(_("\tv\tverify the partition table"));
3528 puts(_("\tw\twrite table to disk and exit"));
3529 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3530 puts(_("\tx\textra functionality (experts only)"));
3534 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3537 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3541 #ifdef CONFIG_FEATURE_SUN_LABEL
3542 if (label_sun == current_label_type) {
3543 puts(_("Command action"));
3544 puts(_("\ta\tchange number of alternate cylinders")); /*sun*/
3545 puts(_("\tc\tchange number of cylinders"));
3546 puts(_("\td\tprint the raw data in the partition table"));
3547 puts(_("\te\tchange number of extra sectors per cylinder"));/*sun*/
3548 puts(_("\th\tchange number of heads"));
3549 puts(_("\ti\tchange interleave factor")); /*sun*/
3550 puts(_("\to\tchange rotation speed (rpm)")); /*sun*/
3551 puts(_("\tm\tprint this menu"));
3552 puts(_("\tp\tprint the partition table"));
3553 puts(_("\tq\tquit without saving changes"));
3554 puts(_("\tr\treturn to main menu"));
3555 puts(_("\ts\tchange number of sectors/track"));
3556 puts(_("\tv\tverify the partition table"));
3557 puts(_("\tw\twrite table to disk and exit"));
3558 puts(_("\ty\tchange number of physical cylinders")); /*sun*/
3561 #ifdef CONFIG_FEATURE_SGI_LABEL
3562 if (label_sgi == current_label_type) {
3563 puts(_("Command action"));
3564 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3565 puts(_("\tc\tchange number of cylinders"));
3566 puts(_("\td\tprint the raw data in the partition table"));
3567 puts(_("\te\tlist extended partitions")); /* !sun */
3568 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3569 puts(_("\th\tchange number of heads"));
3570 puts(_("\tm\tprint this menu"));
3571 puts(_("\tp\tprint the partition table"));
3572 puts(_("\tq\tquit without saving changes"));
3573 puts(_("\tr\treturn to main menu"));
3574 puts(_("\ts\tchange number of sectors/track"));
3575 puts(_("\tv\tverify the partition table"));
3576 puts(_("\tw\twrite table to disk and exit"));
3579 #ifdef CONFIG_FEATURE_AIX_LABEL
3580 if (label_aix == current_label_type) {
3581 puts(_("Command action"));
3582 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3583 puts(_("\tc\tchange number of cylinders"));
3584 puts(_("\td\tprint the raw data in the partition table"));
3585 puts(_("\te\tlist extended partitions")); /* !sun */
3586 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3587 puts(_("\th\tchange number of heads"));
3588 puts(_("\tm\tprint this menu"));
3589 puts(_("\tp\tprint the partition table"));
3590 puts(_("\tq\tquit without saving changes"));
3591 puts(_("\tr\treturn to main menu"));
3592 puts(_("\ts\tchange number of sectors/track"));
3593 puts(_("\tv\tverify the partition table"));
3594 puts(_("\tw\twrite table to disk and exit"));
3598 puts(_("Command action"));
3599 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3600 puts(_("\tc\tchange number of cylinders"));
3601 puts(_("\td\tprint the raw data in the partition table"));
3602 puts(_("\te\tlist extended partitions")); /* !sun */
3603 puts(_("\tf\tfix partition order")); /* !sun, !aix, !sgi */
3604 #ifdef CONFIG_FEATURE_SGI_LABEL
3605 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3607 puts(_("\th\tchange number of heads"));
3608 puts(_("\tm\tprint this menu"));
3609 puts(_("\tp\tprint the partition table"));
3610 puts(_("\tq\tquit without saving changes"));
3611 puts(_("\tr\treturn to main menu"));
3612 puts(_("\ts\tchange number of sectors/track"));
3613 puts(_("\tv\tverify the partition table"));
3614 puts(_("\tw\twrite table to disk and exit"));
3617 #endif /* ADVANCED mode */
3619 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3620 static const struct systypes *
3624 #ifdef CONFIG_FEATURE_SUN_LABEL
3625 label_sun == current_label_type ? sun_sys_types :
3627 #ifdef CONFIG_FEATURE_SGI_LABEL
3628 label_sgi == current_label_type ? sgi_sys_types :
3633 #define get_sys_types() i386_sys_types
3634 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3636 static const char *partition_type(unsigned char type)
3639 const struct systypes *types = get_sys_types();
3641 for (i = 0; types[i].name; i++)
3642 if ((unsigned char )types[i].name[0] == type)
3643 return types[i].name + 1;
3645 return _("Unknown");
3649 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3654 #ifdef CONFIG_FEATURE_SUN_LABEL
3655 label_sun == current_label_type ? sunlabel->infos[i].id :
3657 #ifdef CONFIG_FEATURE_SGI_LABEL
3658 label_sgi == current_label_type ? sgi_get_sysid(i) :
3660 ptes[i].part_table->sys_ind);
3663 void list_types(const struct systypes *sys)
3665 uint last[4], done = 0, next = 0, size;
3668 for (i = 0; sys[i].name; i++);
3671 for (i = 3; i >= 0; i--)
3672 last[3 - i] = done += (size + i - done) / (i + 1);
3676 printf("%c%2x %-15.15s", i ? ' ' : '\n',
3677 (unsigned char)sys[next].name[0],
3678 partition_type((unsigned char)sys[next].name[0]));
3679 next = last[i++] + done;
3680 if (i > 3 || next >= last[i]) {
3684 } while (done < last[0]);
3687 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3690 is_cleared_partition(const struct partition *p)
3692 return !(!p || p->boot_ind || p->head || p->sector || p->cyl ||
3693 p->sys_ind || p->end_head || p->end_sector || p->end_cyl ||
3694 get_start_sect(p) || get_nr_sects(p));
3698 clear_partition(struct partition *p)
3702 memset(p, 0, sizeof(struct partition));
3705 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3707 set_partition(int i, int doext, off_t start, off_t stop, int sysid)
3709 struct partition *p;
3713 p = ptes[i].ext_pointer;
3714 offset = extended_offset;
3716 p = ptes[i].part_table;
3717 offset = ptes[i].offset;
3721 set_start_sect(p, start - offset);
3722 set_nr_sects(p, stop - start + 1);
3723 if (dos_compatible_flag && (start/(sectors*heads) > 1023))
3724 start = heads*sectors*1024 - 1;
3725 set_hsc(p->head, p->sector, p->cyl, start);
3726 if (dos_compatible_flag && (stop/(sectors*heads) > 1023))
3727 stop = heads*sectors*1024 - 1;
3728 set_hsc(p->end_head, p->end_sector, p->end_cyl, stop);
3729 ptes[i].changed = 1;
3734 test_c(const char **m, const char *mesg)
3738 fprintf(stderr, _("You must set"));
3740 fprintf(stderr, " %s", *m);
3750 const char *m = NULL;
3754 prev = test_c(&m, _("heads"));
3756 prev = test_c(&m, _("sectors"));
3758 prev = test_c(&m, _("cylinders"));
3762 fprintf(stderr, "%s%s.\n"
3763 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3764 "You can do this from the extra functions menu.\n"
3766 , prev ? _(" and ") : " ", m);
3771 static void update_units(void)
3773 int cyl_units = heads * sectors;
3775 if (display_in_cyl_units && cyl_units)
3776 units_per_sector = cyl_units;
3778 units_per_sector = 1; /* in sectors */
3781 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3783 warn_cylinders(void)
3785 if (label_dos == current_label_type && cylinders > 1024 && !nowarn)
3786 fprintf(stderr, _("\n"
3787 "The number of cylinders for this disk is set to %d.\n"
3788 "There is nothing wrong with that, but this is larger than 1024,\n"
3789 "and could in certain setups cause problems with:\n"
3790 "1) software that runs at boot time (e.g., old versions of LILO)\n"
3791 "2) booting and partitioning software from other OSs\n"
3792 " (e.g., DOS FDISK, OS/2 FDISK)\n"),
3798 read_extended(int ext)
3802 struct partition *p, *q;
3806 pex->ext_pointer = pex->part_table;
3808 p = pex->part_table;
3809 if (!get_start_sect(p)) {
3811 _("Bad offset in primary extended partition\n"));
3815 while (IS_EXTENDED(p->sys_ind)) {
3816 struct pte *pe = &ptes[partitions];
3818 if (partitions >= MAXIMUM_PARTS) {
3819 /* This is not a Linux restriction, but
3820 this program uses arrays of size MAXIMUM_PARTS.
3821 Do not try to `improve' this test. */
3822 struct pte *pre = &ptes[partitions-1];
3823 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3825 _("Warning: deleting partitions after %d\n"),
3829 clear_partition(pre->ext_pointer);
3833 read_pte(pe, extended_offset + get_start_sect(p));
3835 if (!extended_offset)
3836 extended_offset = get_start_sect(p);
3838 q = p = pt_offset(pe->sectorbuffer, 0);
3839 for (i = 0; i < 4; i++, p++) if (get_nr_sects(p)) {
3840 if (IS_EXTENDED(p->sys_ind)) {
3841 if (pe->ext_pointer)
3843 _("Warning: extra link "
3844 "pointer in partition table"
3845 " %d\n"), partitions + 1);
3847 pe->ext_pointer = p;
3848 } else if (p->sys_ind) {
3851 _("Warning: ignoring extra "
3852 "data in partition table"
3853 " %d\n"), partitions + 1);
3859 /* very strange code here... */
3860 if (!pe->part_table) {
3861 if (q != pe->ext_pointer)
3864 pe->part_table = q + 1;
3866 if (!pe->ext_pointer) {
3867 if (q != pe->part_table)
3868 pe->ext_pointer = q;
3870 pe->ext_pointer = q + 1;
3873 p = pe->ext_pointer;
3877 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3878 /* remove empty links */
3880 for (i = 4; i < partitions; i++) {
3881 struct pte *pe = &ptes[i];
3883 if (!get_nr_sects(pe->part_table) &&
3884 (partitions > 5 || ptes[4].part_table->sys_ind)) {
3885 printf("omitting empty partition (%d)\n", i+1);
3886 delete_partition(i);
3887 goto remove; /* numbering changed */
3893 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3895 create_doslabel(void)
3900 _("Building a new DOS disklabel. Changes will remain in memory only,\n"
3901 "until you decide to write them. After that, of course, the previous\n"
3902 "content won't be recoverable.\n\n"));
3904 current_label_type = label_dos;
3906 #ifdef CONFIG_FEATURE_OSF_LABEL
3907 possibly_osf_label = 0;
3911 for (i = 510-64; i < 510; i++)
3913 write_part_table_flag(MBRbuffer);
3914 extended_offset = 0;
3915 set_all_unchanged();
3917 get_boot(create_empty_dos);
3919 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3922 get_sectorsize(void)
3924 if (!user_set_sector_size) {
3926 if (ioctl(fd, BLKSSZGET, &arg) == 0)
3928 if (sector_size != DEFAULT_SECTOR_SIZE)
3929 printf(_("Note: sector size is %d (not %d)\n"),
3930 sector_size, DEFAULT_SECTOR_SIZE);
3935 get_kernel_geometry(void)
3937 struct hd_geometry geometry;
3939 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
3940 kern_heads = geometry.heads;
3941 kern_sectors = geometry.sectors;
3942 /* never use geometry.cylinders - it is truncated */
3947 get_partition_table_geometry(void)
3949 const unsigned char *bufp = (const unsigned char *)MBRbuffer;
3950 struct partition *p;
3951 int i, h, s, hh, ss;
3955 if (!(valid_part_table_flag((char*)bufp)))
3959 for (i = 0; i < 4; i++) {
3960 p = pt_offset(bufp, i);
3961 if (p->sys_ind != 0) {
3962 h = p->end_head + 1;
3963 s = (p->end_sector & 077);
3968 } else if (hh != h || ss != s)
3973 if (!first && !bad) {
3983 unsigned long long bytes; /* really u64 */
3986 sec_fac = sector_size / 512;
3987 #ifdef CONFIG_FEATURE_SUN_LABEL
3988 guess_device_type();
3990 heads = cylinders = sectors = 0;
3991 kern_heads = kern_sectors = 0;
3992 pt_heads = pt_sectors = 0;
3994 get_kernel_geometry();
3995 get_partition_table_geometry();
3997 heads = user_heads ? user_heads :
3998 pt_heads ? pt_heads :
3999 kern_heads ? kern_heads : 255;
4000 sectors = user_sectors ? user_sectors :
4001 pt_sectors ? pt_sectors :
4002 kern_sectors ? kern_sectors : 63;
4003 if (ioctl(fd, BLKGETSIZE64, &bytes) == 0) {
4006 unsigned long longsectors;
4008 if (ioctl(fd, BLKGETSIZE, &longsectors))
4010 bytes = ((unsigned long long) longsectors) << 9;
4013 total_number_of_sectors = (bytes >> 9);
4016 if (dos_compatible_flag)
4017 sector_offset = sectors;
4019 cylinders = total_number_of_sectors / (heads * sectors * sec_fac);
4021 cylinders = user_cylinders;
4025 * Read MBR. Returns:
4026 * -1: no 0xaa55 flag present (possibly entire disk BSD)
4027 * 0: found or created label
4031 get_boot(enum action what)
4037 for (i = 0; i < 4; i++) {
4038 struct pte *pe = &ptes[i];
4040 pe->part_table = pt_offset(MBRbuffer, i);
4041 pe->ext_pointer = NULL;
4043 pe->sectorbuffer = MBRbuffer;
4044 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4045 pe->changed = (what == create_empty_dos);
4049 #ifdef CONFIG_FEATURE_SUN_LABEL
4050 if (what == create_empty_sun && check_sun_label())
4054 memset(MBRbuffer, 0, 512);
4056 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4057 if (what == create_empty_dos)
4058 goto got_dos_table; /* skip reading disk */
4060 if ((fd = open(disk_device, type_open)) < 0) {
4061 if ((fd = open(disk_device, O_RDONLY)) < 0) {
4062 if (what == try_only)
4064 fdisk_fatal(unable_to_open);
4066 printf(_("You will not be able to write "
4067 "the partition table.\n"));
4070 if (512 != read(fd, MBRbuffer, 512)) {
4071 if (what == try_only)
4073 fdisk_fatal(unable_to_read);
4076 if ((fd = open(disk_device, O_RDONLY)) < 0)
4078 if (512 != read(fd, MBRbuffer, 512))
4086 #ifdef CONFIG_FEATURE_SUN_LABEL
4087 if (check_sun_label())
4091 #ifdef CONFIG_FEATURE_SGI_LABEL
4092 if (check_sgi_label())
4096 #ifdef CONFIG_FEATURE_AIX_LABEL
4097 if (check_aix_label())
4101 #ifdef CONFIG_FEATURE_OSF_LABEL
4102 if (check_osf_label()) {
4103 possibly_osf_label = 1;
4104 if (!valid_part_table_flag(MBRbuffer)) {
4105 current_label_type = label_osf;
4108 printf(_("This disk has both DOS and BSD magic.\n"
4109 "Give the 'b' command to go to BSD mode.\n"));
4113 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4117 if (!valid_part_table_flag(MBRbuffer)) {
4118 #ifndef CONFIG_FEATURE_FDISK_WRITABLE
4124 _("Device contains neither a valid DOS "
4125 "partition table, nor Sun, SGI or OSF "
4128 #ifdef CONFIG_FEATURE_SUN_LABEL
4137 case create_empty_dos:
4138 #ifdef CONFIG_FEATURE_SUN_LABEL
4139 case create_empty_sun:
4143 fprintf(stderr, _("Internal error\n"));
4146 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
4149 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4154 for (i = 0; i < 4; i++) {
4155 struct pte *pe = &ptes[i];
4157 if (IS_EXTENDED(pe->part_table->sys_ind)) {
4158 if (partitions != 4)
4159 fprintf(stderr, _("Ignoring extra extended "
4160 "partition %d\n"), i + 1);
4166 for (i = 3; i < partitions; i++) {
4167 struct pte *pe = &ptes[i];
4169 if (!valid_part_table_flag(pe->sectorbuffer)) {
4171 _("Warning: invalid flag 0x%04x of partition "
4172 "table %d will be corrected by w(rite)\n"),
4173 part_table_flag(pe->sectorbuffer), i + 1);
4174 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4183 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4185 * Print the message MESG, then read an integer between LOW and HIGH (inclusive).
4186 * If the user hits Enter, DFLT is returned.
4187 * Answers like +10 are interpreted as offsets from BASE.
4189 * There is no default if DFLT is not between LOW and HIGH.
4192 read_int(uint low, uint dflt, uint high, uint base, char *mesg)
4196 static char *ms = NULL;
4197 static int mslen = 0;
4199 if (!ms || strlen(mesg)+100 > mslen) {
4200 mslen = strlen(mesg)+200;
4201 ms = xrealloc(ms,mslen);
4204 if (dflt < low || dflt > high)
4208 snprintf(ms, mslen, _("%s (%u-%u, default %u): "),
4209 mesg, low, high, dflt);
4211 snprintf(ms, mslen, "%s (%u-%u): ", mesg, low, high);
4214 int use_default = default_ok;
4216 /* ask question and read answer */
4217 while (read_chars(ms) != '\n' && !isdigit(*line_ptr)
4218 && *line_ptr != '-' && *line_ptr != '+')
4221 if (*line_ptr == '+' || *line_ptr == '-') {
4222 int minus = (*line_ptr == '-');
4225 i = atoi(line_ptr+1);
4227 while (isdigit(*++line_ptr))
4230 switch (*line_ptr) {
4233 if (!display_in_cyl_units)
4234 i *= heads * sectors;
4248 absolute = 1000000000;
4254 unsigned long long bytes;
4257 bytes = (unsigned long long) i * absolute;
4258 unit = sector_size * units_per_sector;
4259 bytes += unit/2; /* round */
4268 while (isdigit(*line_ptr)) {
4274 printf(_("Using default value %u\n"), i = dflt);
4275 if (i >= low && i <= high)
4278 printf(_("Value out of range.\n"));
4284 get_partition(int warn, int max)
4289 i = read_int(1, 0, max, 0, _("Partition number")) - 1;
4295 label_sun != current_label_type &&
4296 label_sgi != current_label_type &&
4297 !pe->part_table->sys_ind
4299 #ifdef CONFIG_FEATURE_SUN_LABEL
4301 label_sun == current_label_type &&
4303 !sunlabel->partitions[i].num_sectors
4304 || !sunlabel->infos[i].id
4308 #ifdef CONFIG_FEATURE_SGI_LABEL
4310 label_sgi == current_label_type &&
4311 !sgi_get_num_sectors(i)
4316 _("Warning: partition %d has empty type\n"),
4325 get_existing_partition(int warn, int max)
4330 for (i = 0; i < max; i++) {
4331 struct pte *pe = &ptes[i];
4332 struct partition *p = pe->part_table;
4334 if (p && !is_cleared_partition(p)) {
4341 printf(_("Selected partition %d\n"), pno+1);
4344 printf(_("No partition is defined yet!\n"));
4348 return get_partition(warn, max);
4352 get_nonexisting_partition(int warn, int max)
4357 for (i = 0; i < max; i++) {
4358 struct pte *pe = &ptes[i];
4359 struct partition *p = pe->part_table;
4361 if (p && is_cleared_partition(p)) {
4368 printf(_("Selected partition %d\n"), pno+1);
4371 printf(_("All primary partitions have been defined already!\n"));
4375 return get_partition(warn, max);
4379 void change_units(void)
4381 display_in_cyl_units = !display_in_cyl_units;
4383 printf(_("Changing display/entry units to %s\n"),
4388 toggle_active(int i)
4390 struct pte *pe = &ptes[i];
4391 struct partition *p = pe->part_table;
4393 if (IS_EXTENDED(p->sys_ind) && !p->boot_ind)
4395 _("WARNING: Partition %d is an extended partition\n"),
4397 p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG);
4402 toggle_dos_compatibility_flag(void)
4404 dos_compatible_flag = ~dos_compatible_flag;
4405 if (dos_compatible_flag) {
4406 sector_offset = sectors;
4407 printf(_("DOS Compatibility flag is set\n"));
4411 printf(_("DOS Compatibility flag is not set\n"));
4416 delete_partition(int i)
4418 struct pte *pe = &ptes[i];
4419 struct partition *p = pe->part_table;
4420 struct partition *q = pe->ext_pointer;
4422 /* Note that for the fifth partition (i == 4) we don't actually
4423 * decrement partitions.
4426 if (warn_geometry())
4427 return; /* C/H/S not set */
4430 #ifdef CONFIG_FEATURE_SUN_LABEL
4431 if (label_sun == current_label_type) {
4432 sun_delete_partition(i);
4436 #ifdef CONFIG_FEATURE_SGI_LABEL
4437 if (label_sgi == current_label_type) {
4438 sgi_delete_partition(i);
4444 if (IS_EXTENDED(p->sys_ind) && i == ext_index) {
4446 ptes[ext_index].ext_pointer = NULL;
4447 extended_offset = 0;
4453 if (!q->sys_ind && i > 4) {
4454 /* the last one in the chain - just delete */
4457 clear_partition(ptes[i].ext_pointer);
4458 ptes[i].changed = 1;
4460 /* not the last one - further ones will be moved down */
4462 /* delete this link in the chain */
4463 p = ptes[i-1].ext_pointer;
4465 set_start_sect(p, get_start_sect(q));
4466 set_nr_sects(p, get_nr_sects(q));
4467 ptes[i-1].changed = 1;
4468 } else if (partitions > 5) { /* 5 will be moved to 4 */
4469 /* the first logical in a longer chain */
4472 if (pe->part_table) /* prevent SEGFAULT */
4473 set_start_sect(pe->part_table,
4474 get_partition_start(pe) -
4476 pe->offset = extended_offset;
4480 if (partitions > 5) {
4482 while (i < partitions) {
4483 ptes[i] = ptes[i+1];
4487 /* the only logical: clear only */
4488 clear_partition(ptes[i].part_table);
4495 int i, sys, origsys;
4496 struct partition *p;
4498 #ifdef CONFIG_FEATURE_SGI_LABEL
4499 /* If sgi_label then don't use get_existing_partition,
4500 let the user select a partition, since get_existing_partition()
4501 only works for Linux like partition tables. */
4502 if (label_sgi != current_label_type) {
4503 i = get_existing_partition(0, partitions);
4505 i = get_partition(0, partitions);
4508 i = get_existing_partition(0, partitions);
4512 p = ptes[i].part_table;
4513 origsys = sys = get_sysid(i);
4515 /* if changing types T to 0 is allowed, then
4516 the reverse change must be allowed, too */
4517 if (!sys && label_sgi != current_label_type &&
4518 label_sun != current_label_type && !get_nr_sects(p))
4520 printf(_("Partition %d does not exist yet!\n"), i + 1);
4523 sys = read_hex (get_sys_types());
4525 if (!sys && label_sgi != current_label_type &&
4526 label_sun != current_label_type)
4528 printf(_("Type 0 means free space to many systems\n"
4529 "(but not to Linux). Having partitions of\n"
4530 "type 0 is probably unwise. You can delete\n"
4531 "a partition using the `d' command.\n"));
4535 if (label_sun != current_label_type && label_sgi != current_label_type) {
4536 if (IS_EXTENDED(sys) != IS_EXTENDED(p->sys_ind)) {
4537 printf(_("You cannot change a partition into"
4538 " an extended one or vice versa\n"
4539 "Delete it first.\n"));
4545 #ifdef CONFIG_FEATURE_SUN_LABEL
4546 if (label_sun == current_label_type && i == 2 && sys != WHOLE_DISK)
4547 printf(_("Consider leaving partition 3 "
4548 "as Whole disk (5),\n"
4549 "as SunOS/Solaris expects it and "
4550 "even Linux likes it.\n\n"));
4552 #ifdef CONFIG_FEATURE_SGI_LABEL
4553 if (label_sgi == current_label_type &&
4555 (i == 10 && sys != ENTIRE_DISK) ||
4556 (i == 8 && sys != 0)
4559 printf(_("Consider leaving partition 9 "
4560 "as volume header (0),\nand "
4561 "partition 11 as entire volume (6)"
4562 "as IRIX expects it.\n\n"));
4567 #ifdef CONFIG_FEATURE_SUN_LABEL
4568 if (label_sun == current_label_type) {
4569 sun_change_sysid(i, sys);
4572 #ifdef CONFIG_FEATURE_SGI_LABEL
4573 if (label_sgi == current_label_type) {
4574 sgi_change_sysid(i, sys);
4579 printf(_("Changed system type of partition %d "
4580 "to %x (%s)\n"), i + 1, sys,
4581 partition_type(sys));
4582 ptes[i].changed = 1;
4583 if (is_dos_partition(origsys) ||
4584 is_dos_partition(sys))
4591 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
4594 /* check_consistency() and long2chs() added Sat Mar 6 12:28:16 1993,
4595 * faith@cs.unc.edu, based on code fragments from pfdisk by Gordon W. Ross,
4596 * Jan. 1990 (version 1.2.1 by Gordon W. Ross Aug. 1990; Modified by S.
4597 * Lubkin Oct. 1991). */
4600 long2chs(ulong ls, uint *c, uint *h, uint *s)
4602 int spc = heads * sectors;
4607 *s = ls % sectors + 1; /* sectors count from 1 */
4611 check_consistency(const struct partition *p, int partition)
4613 uint pbc, pbh, pbs; /* physical beginning c, h, s */
4614 uint pec, peh, pes; /* physical ending c, h, s */
4615 uint lbc, lbh, lbs; /* logical beginning c, h, s */
4616 uint lec, leh, les; /* logical ending c, h, s */
4618 if (!heads || !sectors || (partition >= 4))
4619 return; /* do not check extended partitions */
4621 /* physical beginning c, h, s */
4622 pbc = (p->cyl & 0xff) | ((p->sector << 2) & 0x300);
4624 pbs = p->sector & 0x3f;
4626 /* physical ending c, h, s */
4627 pec = (p->end_cyl & 0xff) | ((p->end_sector << 2) & 0x300);
4629 pes = p->end_sector & 0x3f;
4631 /* compute logical beginning (c, h, s) */
4632 long2chs(get_start_sect(p), &lbc, &lbh, &lbs);
4634 /* compute logical ending (c, h, s) */
4635 long2chs(get_start_sect(p) + get_nr_sects(p) - 1, &lec, &leh, &les);
4637 /* Same physical / logical beginning? */
4638 if (cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) {
4639 printf(_("Partition %d has different physical/logical "
4640 "beginnings (non-Linux?):\n"), partition + 1);
4641 printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs);
4642 printf(_("logical=(%d, %d, %d)\n"),lbc, lbh, lbs);
4645 /* Same physical / logical ending? */
4646 if (cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) {
4647 printf(_("Partition %d has different physical/logical "
4648 "endings:\n"), partition + 1);
4649 printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
4650 printf(_("logical=(%d, %d, %d)\n"),lec, leh, les);
4654 /* Beginning on cylinder boundary? */
4655 if (pbh != !pbc || pbs != 1) {
4656 printf(_("Partition %i does not start on cylinder "
4657 "boundary:\n"), partition + 1);
4658 printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs);
4659 printf(_("should be (%d, %d, 1)\n"), pbc, !pbc);
4663 /* Ending on cylinder boundary? */
4664 if (peh != (heads - 1) || pes != sectors) {
4665 printf(_("Partition %i does not end on cylinder boundary.\n"),
4668 printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
4669 printf(_("should be (%d, %d, %d)\n"),
4670 pec, heads - 1, sectors);
4676 list_disk_geometry(void)
4678 long long bytes = (total_number_of_sectors << 9);
4679 long megabytes = bytes/1000000;
4681 if (megabytes < 10000)
4682 printf(_("\nDisk %s: %ld MB, %lld bytes\n"),
4683 disk_device, megabytes, bytes);
4685 printf(_("\nDisk %s: %ld.%ld GB, %lld bytes\n"),
4686 disk_device, megabytes/1000, (megabytes/100)%10, bytes);
4687 printf(_("%d heads, %d sectors/track, %d cylinders"),
4688 heads, sectors, cylinders);
4689 if (units_per_sector == 1)
4690 printf(_(", total %llu sectors"),
4691 total_number_of_sectors / (sector_size/512));
4692 printf(_("\nUnits = %s of %d * %d = %d bytes\n\n"),
4694 units_per_sector, sector_size, units_per_sector * sector_size);
4698 * Check whether partition entries are ordered by their starting positions.
4699 * Return 0 if OK. Return i if partition i should have been earlier.
4700 * Two separate checks: primary and logical partitions.
4703 wrong_p_order(int *prev)
4705 const struct pte *pe;
4706 const struct partition *p;
4707 off_t last_p_start_pos = 0, p_start_pos;
4710 for (i = 0 ; i < partitions; i++) {
4713 last_p_start_pos = 0;
4716 if ((p = pe->part_table)->sys_ind) {
4717 p_start_pos = get_partition_start(pe);
4719 if (last_p_start_pos > p_start_pos) {
4725 last_p_start_pos = p_start_pos;
4732 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
4734 * Fix the chain of logicals.
4735 * extended_offset is unchanged, the set of sectors used is unchanged
4736 * The chain is sorted so that sectors increase, and so that
4737 * starting sectors increase.
4739 * After this it may still be that cfdisk doesnt like the table.
4740 * (This is because cfdisk considers expanded parts, from link to
4741 * end of partition, and these may still overlap.)
4743 * sfdisk /dev/hda > ohda; sfdisk /dev/hda < ohda
4747 fix_chain_of_logicals(void)
4749 int j, oj, ojj, sj, sjj;
4750 struct partition *pj,*pjj,tmp;
4752 /* Stage 1: sort sectors but leave sector of part 4 */
4753 /* (Its sector is the global extended_offset.) */
4755 for (j = 5; j < partitions-1; j++) {
4756 oj = ptes[j].offset;
4757 ojj = ptes[j+1].offset;
4759 ptes[j].offset = ojj;
4760 ptes[j+1].offset = oj;
4761 pj = ptes[j].part_table;
4762 set_start_sect(pj, get_start_sect(pj)+oj-ojj);
4763 pjj = ptes[j+1].part_table;
4764 set_start_sect(pjj, get_start_sect(pjj)+ojj-oj);
4765 set_start_sect(ptes[j-1].ext_pointer,
4766 ojj-extended_offset);
4767 set_start_sect(ptes[j].ext_pointer,
4768 oj-extended_offset);
4773 /* Stage 2: sort starting sectors */
4775 for (j = 4; j < partitions-1; j++) {
4776 pj = ptes[j].part_table;
4777 pjj = ptes[j+1].part_table;
4778 sj = get_start_sect(pj);
4779 sjj = get_start_sect(pjj);
4780 oj = ptes[j].offset;
4781 ojj = ptes[j+1].offset;
4782 if (oj+sj > ojj+sjj) {
4786 set_start_sect(pj, ojj+sjj-oj);
4787 set_start_sect(pjj, oj+sj-ojj);
4792 /* Probably something was changed */
4793 for (j = 4; j < partitions; j++)
4794 ptes[j].changed = 1;
4799 fix_partition_table_order(void)
4801 struct pte *pei, *pek;
4804 if (!wrong_p_order(NULL)) {
4805 printf(_("Nothing to do. Ordering is correct already.\n\n"));
4809 while ((i = wrong_p_order(&k)) != 0 && i < 4) {
4810 /* partition i should have come earlier, move it */
4811 /* We have to move data in the MBR */
4812 struct partition *pi, *pk, *pe, pbuf;
4816 pe = pei->ext_pointer;
4817 pei->ext_pointer = pek->ext_pointer;
4818 pek->ext_pointer = pe;
4820 pi = pei->part_table;
4821 pk = pek->part_table;
4823 memmove(&pbuf, pi, sizeof(struct partition));
4824 memmove(pi, pk, sizeof(struct partition));
4825 memmove(pk, &pbuf, sizeof(struct partition));
4827 pei->changed = pek->changed = 1;
4831 fix_chain_of_logicals();
4839 list_table(int xtra)
4841 const struct partition *p;
4844 #ifdef CONFIG_FEATURE_SUN_LABEL
4845 if (label_sun == current_label_type) {
4846 sun_list_table(xtra);
4851 #ifdef CONFIG_FEATURE_SGI_LABEL
4852 if (label_sgi == current_label_type) {
4853 sgi_list_table(xtra);
4858 list_disk_geometry();
4860 #ifdef CONFIG_FEATURE_OSF_LABEL
4861 if (label_osf == current_label_type) {
4862 xbsd_print_disklabel(xtra);
4867 /* Heuristic: we list partition 3 of /dev/foo as /dev/foo3,
4868 but if the device name ends in a digit, say /dev/foo1,
4869 then the partition is called /dev/foo1p3. */
4870 w = strlen(disk_device);
4871 if (w && isdigit(disk_device[w-1]))
4876 printf(_("%*s Boot Start End Blocks Id System\n"),
4879 for (i = 0; i < partitions; i++) {
4880 const struct pte *pe = &ptes[i];
4883 if (p && !is_cleared_partition(p)) {
4884 off_t psects = get_nr_sects(p);
4885 off_t pblocks = psects;
4886 unsigned int podd = 0;
4888 if (sector_size < 1024) {
4889 pblocks /= (1024 / sector_size);
4890 podd = psects % (1024 / sector_size);
4892 if (sector_size > 1024)
4893 pblocks *= (sector_size / 1024);
4895 "%s %c %11llu %11llu %11llu%c %2x %s\n",
4896 partname(disk_device, i+1, w+2),
4897 /* boot flag */ !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG
4899 /* start */ (unsigned long long) cround(get_partition_start(pe)),
4900 /* end */ (unsigned long long) cround(get_partition_start(pe) + psects
4901 - (psects ? 1 : 0)),
4902 /* odd flag on end */ (unsigned long long) pblocks, podd ? '+' : ' ',
4903 /* type id */ p->sys_ind,
4904 /* type name */ partition_type(p->sys_ind));
4905 check_consistency(p, i);
4909 /* Is partition table in disk order? It need not be, but... */
4910 /* partition table entries are not checked for correct order if this
4911 is a sgi, sun or aix labeled disk... */
4912 if (label_dos == current_label_type && wrong_p_order(NULL)) {
4914 printf(_("\nPartition table entries are not in disk order\n"));
4918 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
4920 x_list_table(int extend)
4922 const struct pte *pe;
4923 const struct partition *p;
4926 printf(_("\nDisk %s: %d heads, %d sectors, %d cylinders\n\n"),
4927 disk_device, heads, sectors, cylinders);
4928 printf(_("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n"));
4929 for (i = 0 ; i < partitions; i++) {
4931 p = (extend ? pe->ext_pointer : pe->part_table);
4933 printf("%2d %02x%4d%4d%5d%4d%4d%5d%11u%11u %02x\n",
4934 i + 1, p->boot_ind, p->head,
4936 cylinder(p->sector, p->cyl), p->end_head,
4937 sector(p->end_sector),
4938 cylinder(p->end_sector, p->end_cyl),
4939 get_start_sect(p), get_nr_sects(p), p->sys_ind);
4941 check_consistency(p, i);
4947 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4949 fill_bounds(off_t *first, off_t *last)
4952 const struct pte *pe = &ptes[0];
4953 const struct partition *p;
4955 for (i = 0; i < partitions; pe++,i++) {
4957 if (!p->sys_ind || IS_EXTENDED(p->sys_ind)) {
4958 first[i] = 0xffffffff;
4961 first[i] = get_partition_start(pe);
4962 last[i] = first[i] + get_nr_sects(p) - 1;
4968 check(int n, uint h, uint s, uint c, off_t start)
4970 off_t total, real_s, real_c;
4972 real_s = sector(s) - 1;
4973 real_c = cylinder(s, c);
4974 total = (real_c * sectors + real_s) * heads + h;
4976 fprintf(stderr, _("Warning: partition %d contains sector 0\n"), n);
4979 _("Partition %d: head %d greater than maximum %d\n"),
4981 if (real_s >= sectors)
4982 fprintf(stderr, _("Partition %d: sector %d greater than "
4983 "maximum %d\n"), n, s, sectors);
4984 if (real_c >= cylinders)
4985 fprintf(stderr, _("Partitions %d: cylinder %llu greater than "
4986 "maximum %d\n"), n, (unsigned long long)real_c + 1, cylinders);
4987 if (cylinders <= 1024 && start != total)
4989 _("Partition %d: previous sectors %llu disagrees with "
4990 "total %llu\n"), n, (unsigned long long)start, (unsigned long long)total);
4998 off_t first[partitions], last[partitions];
4999 struct partition *p;
5001 if (warn_geometry())
5004 #ifdef CONFIG_FEATURE_SUN_LABEL
5005 if (label_sun == current_label_type) {
5010 #ifdef CONFIG_FEATURE_SGI_LABEL
5011 if (label_sgi == current_label_type) {
5017 fill_bounds(first, last);
5018 for (i = 0; i < partitions; i++) {
5019 struct pte *pe = &ptes[i];
5022 if (p->sys_ind && !IS_EXTENDED(p->sys_ind)) {
5023 check_consistency(p, i);
5024 if (get_partition_start(pe) < first[i])
5025 printf(_("Warning: bad start-of-data in "
5026 "partition %d\n"), i + 1);
5027 check(i + 1, p->end_head, p->end_sector, p->end_cyl,
5029 total += last[i] + 1 - first[i];
5030 for (j = 0; j < i; j++)
5031 if ((first[i] >= first[j] && first[i] <= last[j])
5032 || ((last[i] <= last[j] && last[i] >= first[j]))) {
5033 printf(_("Warning: partition %d overlaps "
5034 "partition %d.\n"), j + 1, i + 1);
5035 total += first[i] >= first[j] ?
5036 first[i] : first[j];
5037 total -= last[i] <= last[j] ?
5043 if (extended_offset) {
5044 struct pte *pex = &ptes[ext_index];
5045 off_t e_last = get_start_sect(pex->part_table) +
5046 get_nr_sects(pex->part_table) - 1;
5048 for (i = 4; i < partitions; i++) {
5050 p = ptes[i].part_table;
5052 if (i != 4 || i + 1 < partitions)
5053 printf(_("Warning: partition %d "
5054 "is empty\n"), i + 1);
5056 else if (first[i] < extended_offset ||
5058 printf(_("Logical partition %d not entirely in "
5059 "partition %d\n"), i + 1, ext_index + 1);
5063 if (total > heads * sectors * cylinders)
5064 printf(_("Total allocated sectors %d greater than the maximum "
5065 "%d\n"), total, heads * sectors * cylinders);
5066 else if ((total = heads * sectors * cylinders - total) != 0)
5067 printf(_("%d unallocated sectors\n"), total);
5071 add_partition(int n, int sys)
5073 char mesg[256]; /* 48 does not suffice in Japanese */
5074 int i, num_read = 0;
5075 struct partition *p = ptes[n].part_table;
5076 struct partition *q = ptes[ext_index].part_table;
5078 off_t start, stop = 0, limit, temp,
5079 first[partitions], last[partitions];
5081 if (p && p->sys_ind) {
5082 printf(_("Partition %d is already defined. Delete "
5083 "it before re-adding it.\n"), n + 1);
5086 fill_bounds(first, last);
5088 start = sector_offset;
5089 if (display_in_cyl_units || !total_number_of_sectors)
5090 llimit = heads * sectors * cylinders - 1;
5092 llimit = total_number_of_sectors - 1;
5094 if (limit != llimit)
5096 if (extended_offset) {
5097 first[ext_index] = extended_offset;
5098 last[ext_index] = get_start_sect(q) +
5099 get_nr_sects(q) - 1;
5102 start = extended_offset + sector_offset;
5103 limit = get_start_sect(q) + get_nr_sects(q) - 1;
5105 if (display_in_cyl_units)
5106 for (i = 0; i < partitions; i++)
5107 first[i] = (cround(first[i]) - 1) * units_per_sector;
5109 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
5112 for (i = 0; i < partitions; i++) {
5115 if (start == ptes[i].offset)
5116 start += sector_offset;
5117 lastplusoff = last[i] + ((n < 4) ? 0 : sector_offset);
5118 if (start >= first[i] && start <= lastplusoff)
5119 start = lastplusoff + 1;
5123 if (start >= temp+units_per_sector && num_read) {
5124 printf(_("Sector %llu is already allocated\n"), (unsigned long long)temp);
5128 if (!num_read && start == temp) {
5131 saved_start = start;
5132 start = read_int(cround(saved_start), cround(saved_start), cround(limit),
5134 if (display_in_cyl_units) {
5135 start = (start - 1) * units_per_sector;
5136 if (start < saved_start) start = saved_start;
5140 } while (start != temp || !num_read);
5141 if (n > 4) { /* NOT for fifth partition */
5142 struct pte *pe = &ptes[n];
5144 pe->offset = start - sector_offset;
5145 if (pe->offset == extended_offset) { /* must be corrected */
5147 if (sector_offset == 1)
5152 for (i = 0; i < partitions; i++) {
5153 struct pte *pe = &ptes[i];
5155 if (start < pe->offset && limit >= pe->offset)
5156 limit = pe->offset - 1;
5157 if (start < first[i] && limit >= first[i])
5158 limit = first[i] - 1;
5160 if (start > limit) {
5161 printf(_("No free sectors available\n"));
5166 if (cround(start) == cround(limit)) {
5169 snprintf(mesg, sizeof(mesg),
5170 _("Last %s or +size or +sizeM or +sizeK"),
5171 str_units(SINGULAR));
5172 stop = read_int(cround(start), cround(limit), cround(limit),
5173 cround(start), mesg);
5174 if (display_in_cyl_units) {
5175 stop = stop * units_per_sector - 1;
5181 set_partition(n, 0, start, stop, sys);
5183 set_partition(n - 1, 1, ptes[n].offset, stop, EXTENDED);
5185 if (IS_EXTENDED(sys)) {
5186 struct pte *pe4 = &ptes[4];
5187 struct pte *pen = &ptes[n];
5190 pen->ext_pointer = p;
5191 pe4->offset = extended_offset = start;
5192 pe4->sectorbuffer = xcalloc(1, sector_size);
5193 pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
5194 pe4->ext_pointer = pe4->part_table + 1;
5203 if (partitions > 5 || ptes[4].part_table->sys_ind) {
5204 struct pte *pe = &ptes[partitions];
5206 pe->sectorbuffer = xcalloc(1, sector_size);
5207 pe->part_table = pt_offset(pe->sectorbuffer, 0);
5208 pe->ext_pointer = pe->part_table + 1;
5213 add_partition(partitions - 1, LINUX_NATIVE);
5219 int i, free_primary = 0;
5221 if (warn_geometry())
5224 #ifdef CONFIG_FEATURE_SUN_LABEL
5225 if (label_sun == current_label_type) {
5226 add_sun_partition(get_partition(0, partitions), LINUX_NATIVE);
5230 #ifdef CONFIG_FEATURE_SGI_LABEL
5231 if (label_sgi == current_label_type) {
5232 sgi_add_partition(get_partition(0, partitions), LINUX_NATIVE);
5236 #ifdef CONFIG_FEATURE_AIX_LABEL
5237 if (label_aix == current_label_type) {
5238 printf(_("\tSorry - this fdisk cannot handle AIX disk labels."
5239 "\n\tIf you want to add DOS-type partitions, create"
5240 "\n\ta new empty DOS partition table first. (Use o.)"
5242 "This will destroy the present disk contents.\n"));
5247 for (i = 0; i < 4; i++)
5248 free_primary += !ptes[i].part_table->sys_ind;
5250 if (!free_primary && partitions >= MAXIMUM_PARTS) {
5251 printf(_("The maximum number of partitions has been created\n"));
5255 if (!free_primary) {
5256 if (extended_offset)
5259 printf(_("You must delete some partition and add "
5260 "an extended partition first\n"));
5262 char c, line[LINE_LENGTH];
5263 snprintf(line, sizeof(line), "%s\n %s\n p primary "
5264 "partition (1-4)\n",
5265 "Command action", (extended_offset ?
5266 "l logical (5 or over)" : "e extended"));
5268 if ((c = read_char(line)) == 'p' || c == 'P') {
5269 i = get_nonexisting_partition(0, 4);
5271 add_partition(i, LINUX_NATIVE);
5274 else if (c == 'l' && extended_offset) {
5278 else if (c == 'e' && !extended_offset) {
5279 i = get_nonexisting_partition(0, 4);
5281 add_partition(i, EXTENDED);
5285 printf(_("Invalid partition number "
5286 "for type `%c'\n"), c);
5296 if (label_dos == current_label_type) {
5297 for (i = 0; i < 3; i++)
5298 if (ptes[i].changed)
5299 ptes[3].changed = 1;
5300 for (i = 3; i < partitions; i++) {
5301 struct pte *pe = &ptes[i];
5304 write_part_table_flag(pe->sectorbuffer);
5305 write_sector(pe->offset, pe->sectorbuffer);
5309 #ifdef CONFIG_FEATURE_SGI_LABEL
5310 else if (label_sgi == current_label_type) {
5311 /* no test on change? the printf below might be mistaken */
5315 #ifdef CONFIG_FEATURE_SUN_LABEL
5316 else if (label_sun == current_label_type) {
5319 for (i = 0; i < 8; i++)
5320 if (ptes[i].changed)
5327 printf(_("The partition table has been altered!\n\n"));
5328 reread_partition_table(1);
5332 reread_partition_table(int leave)
5337 printf(_("Calling ioctl() to re-read partition table.\n"));
5340 if ((i = ioctl(fd, BLKRRPART)) != 0) {
5343 /* some kernel versions (1.2.x) seem to have trouble
5344 rereading the partition table, but if asked to do it
5345 twice, the second time works. - biro@yggdrasil.com */
5348 if ((i = ioctl(fd, BLKRRPART)) != 0)
5353 printf(_("\nWARNING: Re-reading the partition table "
5354 "failed with error %d: %s.\n"
5355 "The kernel still uses the old table.\n"
5356 "The new table will be used "
5357 "at the next reboot.\n"),
5358 error, strerror(error));
5363 _("\nWARNING: If you have created or modified any DOS 6.x\n"
5364 "partitions, please see the fdisk manual page for additional\n"
5370 printf(_("Syncing disks.\n"));
5372 sleep(4); /* for sync() */
5376 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
5378 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
5379 #define MAX_PER_LINE 16
5381 print_buffer(char *pbuffer)
5385 for (i = 0, l = 0; i < sector_size; i++, l++) {
5387 printf("0x%03X:", i);
5388 printf(" %02X", (unsigned char) pbuffer[i]);
5389 if (l == MAX_PER_LINE - 1) {
5405 printf(_("Device: %s\n"), disk_device);
5406 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
5407 if (label_sun == current_label_type || label_sgi == current_label_type)
5408 print_buffer(MBRbuffer);
5411 for (i = 3; i < partitions; i++)
5412 print_buffer(ptes[i].sectorbuffer);
5418 struct pte *pe = &ptes[i];
5419 struct partition *p = pe->part_table;
5422 if (warn_geometry())
5424 if (!p->sys_ind || !get_nr_sects(p) || IS_EXTENDED(p->sys_ind)) {
5425 printf(_("Partition %d has no data area\n"), i + 1);
5428 first = get_partition_start(pe);
5429 new = read_int(first, first, first + get_nr_sects(p) - 1, first,
5430 _("New beginning of data")) - pe->offset;
5432 if (new != get_nr_sects(p)) {
5433 first = get_nr_sects(p) + get_start_sect(p) - new;
5434 set_nr_sects(p, first);
5435 set_start_sect(p, new);
5447 c = tolower(read_char(_("Expert command (m for help): ")));
5450 #ifdef CONFIG_FEATURE_SUN_LABEL
5451 if (label_sun == current_label_type)
5456 if (label_dos == current_label_type)
5457 move_begin(get_partition(0, partitions));
5460 user_cylinders = cylinders =
5461 read_int(1, cylinders, 1048576, 0,
5462 _("Number of cylinders"));
5463 #ifdef CONFIG_FEATURE_SUN_LABEL
5464 if (label_sun == current_label_type)
5465 sun_set_ncyl(cylinders);
5467 if (label_dos == current_label_type)
5474 #ifdef CONFIG_FEATURE_SGI_LABEL
5475 if (label_sgi == current_label_type)
5479 #ifdef CONFIG_FEATURE_SUN_LABEL
5480 if (label_sun == current_label_type)
5484 if (label_dos == current_label_type)
5488 if (label_dos == current_label_type)
5489 fix_partition_table_order();
5492 #ifdef CONFIG_FEATURE_SGI_LABEL
5497 user_heads = heads = read_int(1, heads, 256, 0,
5498 _("Number of heads"));
5502 #ifdef CONFIG_FEATURE_SUN_LABEL
5503 if (label_sun == current_label_type)
5508 #ifdef CONFIG_FEATURE_SUN_LABEL
5509 if (label_sun == current_label_type)
5514 #ifdef CONFIG_FEATURE_SUN_LABEL
5515 if (label_sun == current_label_type)
5528 user_sectors = sectors = read_int(1, sectors, 63, 0,
5529 _("Number of sectors"));
5530 if (dos_compatible_flag) {
5531 sector_offset = sectors;
5532 fprintf(stderr, _("Warning: setting "
5533 "sector offset for DOS "
5542 write_table(); /* does not return */
5545 #ifdef CONFIG_FEATURE_SUN_LABEL
5546 if (label_sun == current_label_type)
5547 sun_set_pcylcount();
5555 #endif /* ADVANCED mode */
5558 is_ide_cdrom_or_tape(const char *device)
5562 struct stat statbuf;
5565 /* No device was given explicitly, and we are trying some
5566 likely things. But opening /dev/hdc may produce errors like
5567 "hdc: tray open or drive not ready"
5568 if it happens to be a CD-ROM drive. It even happens that
5569 the process hangs on the attempt to read a music CD.
5570 So try to be careful. This only works since 2.1.73. */
5572 if (strncmp("/dev/hd", device, 7))
5575 snprintf(buf, sizeof(buf), "/proc/ide/%s/media", device+5);
5576 procf = fopen(buf, "r");
5577 if (procf != NULL && fgets(buf, sizeof(buf), procf))
5578 is_ide = (!strncmp(buf, "cdrom", 5) ||
5579 !strncmp(buf, "tape", 4));
5581 /* Now when this proc file does not exist, skip the
5582 device when it is read-only. */
5583 if (stat(device, &statbuf) == 0)
5584 is_ide = ((statbuf.st_mode & 0222) == 0);
5593 try(const char *device, int user_specified)
5597 disk_device = device;
5598 if (setjmp(listingbuf))
5600 if (!user_specified)
5601 if (is_ide_cdrom_or_tape(device))
5603 if ((fd = open(disk_device, type_open)) >= 0) {
5604 gb = get_boot(try_only);
5605 if (gb > 0) { /* I/O error */
5607 } else if (gb < 0) { /* no DOS signature */
5608 list_disk_geometry();
5609 if (label_aix == current_label_type){
5612 #ifdef CONFIG_FEATURE_OSF_LABEL
5613 if (btrydev(device) < 0)
5616 _("Disk %s doesn't contain a valid "
5617 "partition table\n"), device);
5622 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5623 if (label_sun != current_label_type && partitions > 4){
5624 delete_partition(ext_index);
5629 /* Ignore other errors, since we try IDE
5630 and SCSI hard disks which may not be
5631 installed on the system. */
5632 if (errno == EACCES) {
5633 fprintf(stderr, _("Cannot open %s\n"), device);
5639 /* for fdisk -l: try all things in /proc/partitions
5640 that look like a partition name (do not end in a digit) */
5645 char line[100], ptname[100], devname[120], *s;
5648 procpt = bb_wfopen(PROC_PARTITIONS, "r");
5650 while (fgets(line, sizeof(line), procpt)) {
5651 if (sscanf(line, " %d %d %d %[^\n ]",
5652 &ma, &mi, &sz, ptname) != 4)
5654 for (s = ptname; *s; s++);
5657 sprintf(devname, "/dev/%s", ptname);
5660 #ifdef CONFIG_FEATURE_CLEAN_UP
5665 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5667 unknown_command(int c)
5669 printf(_("%c: unknown command\n"), c);
5673 int fdisk_main(int argc, char **argv)
5676 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5679 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5685 * fdisk -l [-b sectorsize] [-u] device ...
5686 * fdisk -s [partition] ...
5687 * fdisk [-b sectorsize] [-u] device
5689 * Options -C, -H, -S set the geometry.
5692 while ((c = getopt(argc, argv, "b:C:H:lS:uvV"
5693 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5699 /* Ugly: this sector size is really per device,
5700 so cannot be combined with multiple disks,
5701 and te same goes for the C/H/S options.
5703 sector_size = atoi(optarg);
5704 if (sector_size != 512 && sector_size != 1024 &&
5705 sector_size != 2048)
5708 user_set_sector_size = 1;
5711 user_cylinders = atoi(optarg);
5714 user_heads = atoi(optarg);
5715 if (user_heads <= 0 || user_heads >= 256)
5719 user_sectors = atoi(optarg);
5720 if (user_sectors <= 0 || user_sectors >= 64)
5724 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5728 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5734 display_in_cyl_units = 0;
5738 printf("fdisk v" UTIL_LINUX_VERSION "\n");
5746 printf(_("This kernel finds the sector size itself - "
5747 "-b option ignored\n"));
5749 if (user_set_sector_size && argc-optind != 1)
5750 printf(_("Warning: the -b (set sector size) option should"
5751 " be used with one specified device\n"));
5754 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5758 type_open = O_RDONLY;
5759 if (argc > optind) {
5762 /* avoid gcc warning:
5763 variable `k' might be clobbered by `longjmp' */
5767 for (k = optind; k < argc; k++)
5770 /* we no longer have default device names */
5771 /* but, we can use /proc/partitions instead */
5775 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5779 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5785 type_open = O_RDONLY;
5787 opts = argc - optind;
5791 for (j = optind; j < argc; j++) {
5792 disk_device = argv[j];
5793 if ((fd = open(disk_device, type_open)) < 0)
5794 fdisk_fatal(unable_to_open);
5795 if (ioctl(fd, BLKGETSIZE, &size))
5796 fdisk_fatal(ioctl_error);
5799 printf("%ld\n", size/2);
5801 printf("%s: %ld\n", argv[j], size/2);
5807 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5808 if (argc-optind == 1)
5809 disk_device = argv[optind];
5815 #ifdef CONFIG_FEATURE_OSF_LABEL
5816 if (label_osf == current_label_type) {
5817 /* OSF label, and no DOS label */
5818 printf(_("Detected an OSF/1 disklabel on %s, entering "
5819 "disklabel mode.\n"),
5822 /*Why do we do this? It seems to be counter-intuitive*/
5823 current_label_type = label_dos;
5824 /* If we return we may want to make an empty DOS label? */
5830 c = tolower(read_char(_("Command (m for help): ")));
5833 if (label_dos == current_label_type)
5834 toggle_active(get_partition(1, partitions));
5835 #ifdef CONFIG_FEATURE_SUN_LABEL
5836 else if (label_sun == current_label_type)
5837 toggle_sunflags(get_partition(1, partitions),
5840 #ifdef CONFIG_FEATURE_SGI_LABEL
5841 else if (label_sgi == current_label_type)
5842 sgi_set_bootpartition(
5843 get_partition(1, partitions));
5849 #ifdef CONFIG_FEATURE_SGI_LABEL
5850 if (label_sgi == current_label_type) {
5851 printf(_("\nThe current boot file is: %s\n"),
5852 sgi_get_bootfile());
5853 if (read_chars(_("Please enter the name of the "
5854 "new boot file: ")) == '\n')
5855 printf(_("Boot file unchanged\n"));
5857 sgi_set_bootfile(line_ptr);
5860 #ifdef CONFIG_FEATURE_OSF_LABEL
5865 if (label_dos == current_label_type)
5866 toggle_dos_compatibility_flag();
5867 #ifdef CONFIG_FEATURE_SUN_LABEL
5868 else if (label_sun == current_label_type)
5869 toggle_sunflags(get_partition(1, partitions),
5872 #ifdef CONFIG_FEATURE_SGI_LABEL
5873 else if (label_sgi == current_label_type)
5874 sgi_set_swappartition(
5875 get_partition(1, partitions));
5883 #ifdef CONFIG_FEATURE_SGI_LABEL
5884 /* If sgi_label then don't use get_existing_partition,
5885 let the user select a partition, since
5886 get_existing_partition() only works for Linux-like
5888 if (label_sgi != current_label_type) {
5889 j = get_existing_partition(1, partitions);
5891 j = get_partition(1, partitions);
5894 j = get_existing_partition(1, partitions);
5897 delete_partition(j);
5901 #ifdef CONFIG_FEATURE_SGI_LABEL
5902 if (label_sgi == current_label_type)
5908 list_types(get_sys_types());
5927 #ifdef CONFIG_FEATURE_SUN_LABEL
5941 write_table(); /* does not return */
5943 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
5945 #ifdef CONFIG_FEATURE_SGI_LABEL
5946 if (label_sgi == current_label_type) {
5948 _("\n\tSorry, no experts menu for SGI "
5949 "partition tables available.\n\n"));
5962 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */