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"
13 #define PROC_PARTITIONS "/proc/partitions"
16 #include <sys/types.h>
17 #include <sys/stat.h> /* stat */
26 #include <assert.h> /* assert */
29 #include <sys/ioctl.h>
30 #include <sys/param.h>
31 #include <sys/sysmacros.h> /* major */
33 #include <stdint.h> /* for uint32_t, uint16_t, uint8_t, int16_t, etc */
35 /* Copied from linux/major.h */
36 #define FLOPPY_MAJOR 2
38 #include <sys/utsname.h>
44 #define BLKRRPART _IO(0x12,95) /* re-read partition table */
45 #define BLKGETSIZE _IO(0x12,96) /* return device size */
46 #define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */
47 #define BLKSSZGET _IO(0x12,104) /* get block device sector size */
49 /* Avoid conflicts with the 2.6 kernel headers, which define
50 * _IOR rather differently */
52 #define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size))
53 #define BLKGETSIZE64 _IOR(0x12,114,uint64_t)
59 #define DEFAULT_SECTOR_SIZE 512
60 #define MAX_SECTOR_SIZE 2048
61 #define SECTOR_SIZE 512 /* still used in BSD code */
62 #define MAXIMUM_PARTS 60
64 #define ACTIVE_FLAG 0x80
67 #define WIN98_EXTENDED 0x0f
68 #define LINUX_PARTITION 0x81
69 #define LINUX_SWAP 0x82
70 #define LINUX_NATIVE 0x83
71 #define LINUX_EXTENDED 0x85
72 #define LINUX_LVM 0x8e
73 #define LINUX_RAID 0xfd
78 #define IS_EXTENDED(i) \
79 ((i) == EXTENDED || (i) == WIN98_EXTENDED || (i) == LINUX_EXTENDED)
81 #define SIZE(a) (sizeof(a)/sizeof((a)[0]))
83 #define cround(n) (display_in_cyl_units ? ((n)/units_per_sector)+1 : (n))
84 #define scround(x) (((x)+units_per_sector-1)/units_per_sector)
86 #ifdef CONFIG_FEATURE_SUN_LABEL
87 #define SCSI_IOCTL_GET_IDLUN 0x5382
91 /* including <linux/hdreg.h> also fails */
94 unsigned char sectors;
95 unsigned short cylinders;
99 #define HDIO_GETGEO 0x0301 /* get device geometry */
106 static uint sector_size = DEFAULT_SECTOR_SIZE;
107 static uint user_set_sector_size;
108 static uint sector_offset = 1;
111 * Raw disk label. For DOS-type partition tables the MBR,
112 * with descriptions of the primary partitions.
114 #if (MAX_SECTOR_SIZE) > (BUFSIZ+1)
115 static char MBRbuffer[MAX_SECTOR_SIZE];
117 # define MBRbuffer bb_common_bufsiz1
120 #ifdef CONFIG_FEATURE_OSF_LABEL
121 static int possibly_osf_label;
124 static uint heads, sectors, cylinders;
125 static void update_units(void);
129 * return partition name - uses static storage unless buf is supplied
132 partname(const char *dev, int pno, int lth)
134 static char buffer[80];
141 bufsiz = sizeof(buffer);
146 if (isdigit(dev[w-1]))
149 /* devfs kludge - note: fdisk partition names are not supposed
150 to equal kernel names, so there is no reason to do this */
151 if (strcmp(dev + w - 4, "disc") == 0) {
159 snprintf(bufp, bufsiz, "%*.*s%s%-2u",
160 lth-wp-2, w, dev, p, pno);
162 snprintf(bufp, bufsiz, "%.*s%s%-2u", w, dev, p, pno);
168 unsigned char boot_ind; /* 0x80 - active */
169 unsigned char head; /* starting head */
170 unsigned char sector; /* starting sector */
171 unsigned char cyl; /* starting cylinder */
172 unsigned char sys_ind; /* What partition type */
173 unsigned char end_head; /* end head */
174 unsigned char end_sector; /* end sector */
175 unsigned char end_cyl; /* end cylinder */
176 unsigned char start4[4]; /* starting sector counting from 0 */
177 unsigned char size4[4]; /* nr of sectors in partition */
181 ioctl_error, unable_to_open, unable_to_read, unable_to_seek,
186 label_dos, label_sun, label_sgi, label_aix, label_osf
189 enum action { fdisk, require, try_only, create_empty_dos, create_empty_sun };
191 static enum label_type current_label_type;
193 static const char *disk_device;
194 static int fd; /* the disk */
195 static int partitions = 4; /* maximum partition + 1 */
196 static uint display_in_cyl_units = 1;
197 static uint units_per_sector = 1;
198 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
199 static char *line_ptr;
200 static void change_units(void);
201 static void reread_partition_table(int leave);
202 static void delete_partition(int i);
203 static int get_partition(int warn, int max);
204 static void list_types(const struct systypes *sys);
205 static uint read_int(uint low, uint dflt, uint high, uint base, char *mesg);
207 static const char *partition_type(unsigned char type);
208 static void fdisk_fatal(enum failure why) ATTRIBUTE_NORETURN;
209 static void get_geometry(void);
210 static int get_boot(enum action what);
215 #define hex_val(c) ({ \
217 isdigit(_c) ? _c - '0' : \
218 tolower(_c) + 10 - 'a'; \
222 #define LINE_LENGTH 800
223 #define pt_offset(b, n) ((struct partition *)((b) + 0x1be + \
224 (n) * sizeof(struct partition)))
225 #define sector(s) ((s) & 0x3f)
226 #define cylinder(s, c) ((c) | (((s) & 0xc0) << 2))
228 #define hsc2sector(h,s,c) (sector(s) - 1 + sectors * \
229 ((h) + heads * cylinder(s,c)))
230 #define set_hsc(h,s,c,sector) { \
231 s = sector % sectors + 1; \
233 h = sector % heads; \
236 s |= (sector >> 2) & 0xc0; \
240 static int32_t get_start_sect(const struct partition *p);
241 static int32_t get_nr_sects(const struct partition *p);
244 * per partition table entry data
246 * The four primary partitions have the same sectorbuffer (MBRbuffer)
247 * and have NULL ext_pointer.
248 * Each logical partition table entry has two pointers, one for the
249 * partition and one link to the next one.
252 struct partition *part_table; /* points into sectorbuffer */
253 struct partition *ext_pointer; /* points into sectorbuffer */
254 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
255 char changed; /* boolean */
257 off_t offset; /* disk sector number */
258 char *sectorbuffer; /* disk sector contents */
259 } ptes[MAXIMUM_PARTS];
262 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
264 set_all_unchanged(void)
268 for (i = 0; i < MAXIMUM_PARTS; i++)
277 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
279 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_OSF_LABEL)
280 static struct partition *
281 get_part_table(int i)
283 return ptes[i].part_table;
289 { /* n==1: use singular */
291 return display_in_cyl_units ? _("cylinder") : _("sector");
293 return display_in_cyl_units ? _("cylinders") : _("sectors");
297 valid_part_table_flag(const char *mbuffer) {
298 const unsigned char *b = (const unsigned char *)mbuffer;
299 return (b[510] == 0x55 && b[511] == 0xaa);
302 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
303 static char line_buffer[LINE_LENGTH];
305 /* read line; return 0 or first char */
309 static int got_eof = 0;
311 fflush (stdout); /* requested by niles@scyld.com */
312 line_ptr = line_buffer;
313 if (!fgets(line_buffer, LINE_LENGTH, stdin)) {
315 got_eof++; /* user typed ^D ? */
317 fprintf(stderr, _("\ngot EOF thrice - exiting..\n"));
322 while (*line_ptr && !isgraph(*line_ptr))
328 read_char(const char *mesg)
332 } while (!read_line());
337 read_chars(const char *mesg)
348 read_hex(const struct systypes *sys)
353 read_char(_("Hex code (type L to list codes): "));
354 if (*line_ptr == 'l' || *line_ptr == 'L')
356 else if (isxdigit (*line_ptr)) {
359 hex = hex << 4 | hex_val(*line_ptr++);
360 while (isxdigit(*line_ptr));
365 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
367 #ifdef CONFIG_FEATURE_AIX_LABEL
369 * Copyright (C) Andreas Neuper, Sep 1998.
370 * This file may be redistributed under
371 * the terms of the GNU Public License.
375 unsigned int magic; /* expect AIX_LABEL_MAGIC */
376 unsigned int fillbytes1[124];
377 unsigned int physical_volume_id;
378 unsigned int fillbytes2[124];
381 #define AIX_LABEL_MAGIC 0xc9c2d4c1
382 #define AIX_LABEL_MAGIC_SWAPPED 0xc1d4c2c9
383 #define AIX_INFO_MAGIC 0x00072959
384 #define AIX_INFO_MAGIC_SWAPPED 0x59290700
386 #define aixlabel ((aix_partition *)MBRbuffer)
391 * 1999-03-20 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
392 * Internationalization
394 * 2003-03-20 Phillip Kesling <pkesling@sgi.com>
398 static int aix_other_endian;
399 static short aix_volumes = 1;
402 * only dealing with free blocks here
409 _("\n\tThere is a valid AIX label on this disk.\n"
410 "\tUnfortunately Linux cannot handle these\n"
411 "\tdisks at the moment. Nevertheless some\n"
413 "\t1. fdisk will destroy its contents on write.\n"
414 "\t2. Be sure that this disk is NOT a still vital\n"
415 "\t part of a volume group. (Otherwise you may\n"
416 "\t erase the other disks as well, if unmirrored.)\n"
417 "\t3. Before deleting this physical volume be sure\n"
418 "\t to remove the disk logically from your AIX\n"
419 "\t machine. (Otherwise you become an AIXpert).")
424 check_aix_label(void)
426 if (aixlabel->magic != AIX_LABEL_MAGIC &&
427 aixlabel->magic != AIX_LABEL_MAGIC_SWAPPED) {
428 current_label_type = 0;
429 aix_other_endian = 0;
432 aix_other_endian = (aixlabel->magic == AIX_LABEL_MAGIC_SWAPPED);
434 current_label_type = label_aix;
438 /*aix_nolabel();*/ /* %% */
439 /*aix_label = 1;*/ /* %% */
442 #endif /* AIX_LABEL */
444 #ifdef CONFIG_FEATURE_OSF_LABEL
446 * Copyright (c) 1987, 1988 Regents of the University of California.
447 * All rights reserved.
449 * Redistribution and use in source and binary forms, with or without
450 * modification, are permitted provided that the following conditions
452 * 1. Redistributions of source code must retain the above copyright
453 * notice, this list of conditions and the following disclaimer.
454 * 2. Redistributions in binary form must reproduce the above copyright
455 * notice, this list of conditions and the following disclaimer in the
456 * documentation and/or other materials provided with the distribution.
457 * 3. All advertising materials mentioning features or use of this software
458 * must display the following acknowledgment:
459 * This product includes software developed by the University of
460 * California, Berkeley and its contributors.
461 * 4. Neither the name of the University nor the names of its contributors
462 * may be used to endorse or promote products derived from this software
463 * without specific prior written permission.
465 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
466 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
467 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
468 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
469 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
470 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
471 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
472 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
473 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
474 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
479 #ifndef BSD_DISKMAGIC
480 #define BSD_DISKMAGIC ((uint32_t) 0x82564557)
483 #ifndef BSD_MAXPARTITIONS
484 #define BSD_MAXPARTITIONS 16
487 #define BSD_LINUX_BOOTDIR "/usr/ucb/mdec"
489 #if defined (i386) || defined (__sparc__) || defined (__arm__) || defined (__mips__) || defined (__s390__) || defined (__sh__) || defined(__x86_64__)
490 #define BSD_LABELSECTOR 1
491 #define BSD_LABELOFFSET 0
492 #elif defined (__alpha__) || defined (__powerpc__) || defined (__ia64__) || defined (__hppa__)
493 #define BSD_LABELSECTOR 0
494 #define BSD_LABELOFFSET 64
495 #elif defined (__s390__) || defined (__s390x__)
496 #define BSD_LABELSECTOR 1
497 #define BSD_LABELOFFSET 0
499 #error unknown architecture
502 #define BSD_BBSIZE 8192 /* size of boot area, with label */
503 #define BSD_SBSIZE 8192 /* max size of fs superblock */
505 struct xbsd_disklabel {
506 uint32_t d_magic; /* the magic number */
507 int16_t d_type; /* drive type */
508 int16_t d_subtype; /* controller/d_type specific */
509 char d_typename[16]; /* type name, e.g. "eagle" */
510 char d_packname[16]; /* pack identifier */
512 uint32_t d_secsize; /* # of bytes per sector */
513 uint32_t d_nsectors; /* # of data sectors per track */
514 uint32_t d_ntracks; /* # of tracks per cylinder */
515 uint32_t d_ncylinders; /* # of data cylinders per unit */
516 uint32_t d_secpercyl; /* # of data sectors per cylinder */
517 uint32_t d_secperunit; /* # of data sectors per unit */
519 * Spares (bad sector replacements) below
520 * are not counted in d_nsectors or d_secpercyl.
521 * Spare sectors are assumed to be physical sectors
522 * which occupy space at the end of each track and/or cylinder.
524 uint16_t d_sparespertrack; /* # of spare sectors per track */
525 uint16_t d_sparespercyl; /* # of spare sectors per cylinder */
527 * Alternate cylinders include maintenance, replacement,
528 * configuration description areas, etc.
530 uint32_t d_acylinders; /* # of alt. cylinders per unit */
532 /* hardware characteristics: */
534 * d_interleave, d_trackskew and d_cylskew describe perturbations
535 * in the media format used to compensate for a slow controller.
536 * Interleave is physical sector interleave, set up by the formatter
537 * or controller when formatting. When interleaving is in use,
538 * logically adjacent sectors are not physically contiguous,
539 * but instead are separated by some number of sectors.
540 * It is specified as the ratio of physical sectors traversed
541 * per logical sector. Thus an interleave of 1:1 implies contiguous
542 * layout, while 2:1 implies that logical sector 0 is separated
543 * by one sector from logical sector 1.
544 * d_trackskew is the offset of sector 0 on track N
545 * relative to sector 0 on track N-1 on the same cylinder.
546 * Finally, d_cylskew is the offset of sector 0 on cylinder N
547 * relative to sector 0 on cylinder N-1.
549 uint16_t d_rpm; /* rotational speed */
550 uint16_t d_interleave; /* hardware sector interleave */
551 uint16_t d_trackskew; /* sector 0 skew, per track */
552 uint16_t d_cylskew; /* sector 0 skew, per cylinder */
553 uint32_t d_headswitch; /* head switch time, usec */
554 uint32_t d_trkseek; /* track-to-track seek, usec */
555 uint32_t d_flags; /* generic flags */
557 uint32_t d_drivedata[NDDATA]; /* drive-type specific information */
559 uint32_t d_spare[NSPARE]; /* reserved for future use */
560 uint32_t d_magic2; /* the magic number (again) */
561 uint16_t d_checksum; /* xor of data incl. partitions */
562 /* filesystem and partition information: */
563 uint16_t d_npartitions; /* number of partitions in following */
564 uint32_t d_bbsize; /* size of boot area at sn0, bytes */
565 uint32_t d_sbsize; /* max size of fs superblock, bytes */
566 struct xbsd_partition { /* the partition table */
567 uint32_t p_size; /* number of sectors in partition */
568 uint32_t p_offset; /* starting sector */
569 uint32_t p_fsize; /* filesystem basic fragment size */
570 uint8_t p_fstype; /* filesystem type, see below */
571 uint8_t p_frag; /* filesystem fragments per block */
572 uint16_t p_cpg; /* filesystem cylinders per group */
573 } d_partitions[BSD_MAXPARTITIONS]; /* actually may be more */
577 #define BSD_DTYPE_SMD 1 /* SMD, XSMD; VAX hp/up */
578 #define BSD_DTYPE_MSCP 2 /* MSCP */
579 #define BSD_DTYPE_DEC 3 /* other DEC (rk, rl) */
580 #define BSD_DTYPE_SCSI 4 /* SCSI */
581 #define BSD_DTYPE_ESDI 5 /* ESDI interface */
582 #define BSD_DTYPE_ST506 6 /* ST506 etc. */
583 #define BSD_DTYPE_HPIB 7 /* CS/80 on HP-IB */
584 #define BSD_DTYPE_HPFL 8 /* HP Fiber-link */
585 #define BSD_DTYPE_FLOPPY 10 /* floppy */
587 /* d_subtype values: */
588 #define BSD_DSTYPE_INDOSPART 0x8 /* is inside dos partition */
589 #define BSD_DSTYPE_DOSPART(s) ((s) & 3) /* dos partition number */
590 #define BSD_DSTYPE_GEOMETRY 0x10 /* drive params in label */
593 static const char * const xbsd_dktypenames[] = {
607 #define BSD_DKMAXTYPES (sizeof(xbsd_dktypenames) / sizeof(xbsd_dktypenames[0]) - 1)
611 * Filesystem type and version.
612 * Used to interpret other filesystem-specific
613 * per-partition information.
615 #define BSD_FS_UNUSED 0 /* unused */
616 #define BSD_FS_SWAP 1 /* swap */
617 #define BSD_FS_V6 2 /* Sixth Edition */
618 #define BSD_FS_V7 3 /* Seventh Edition */
619 #define BSD_FS_SYSV 4 /* System V */
620 #define BSD_FS_V71K 5 /* V7 with 1K blocks (4.1, 2.9) */
621 #define BSD_FS_V8 6 /* Eighth Edition, 4K blocks */
622 #define BSD_FS_BSDFFS 7 /* 4.2BSD fast file system */
623 #define BSD_FS_BSDLFS 9 /* 4.4BSD log-structured file system */
624 #define BSD_FS_OTHER 10 /* in use, but unknown/unsupported */
625 #define BSD_FS_HPFS 11 /* OS/2 high-performance file system */
626 #define BSD_FS_ISO9660 12 /* ISO-9660 filesystem (cdrom) */
627 #define BSD_FS_ISOFS BSD_FS_ISO9660
628 #define BSD_FS_BOOT 13 /* partition contains bootstrap */
629 #define BSD_FS_ADOS 14 /* AmigaDOS fast file system */
630 #define BSD_FS_HFS 15 /* Macintosh HFS */
631 #define BSD_FS_ADVFS 16 /* Digital Unix AdvFS */
633 /* this is annoying, but it's also the way it is :-( */
635 #define BSD_FS_EXT2 8 /* ext2 file system */
637 #define BSD_FS_MSDOS 8 /* MS-DOS file system */
641 static const struct systypes xbsd_fstypes[] = {
642 { "\x00" "unused" }, /* BSD_FS_UNUSED */
643 { "\x01" "swap" }, /* BSD_FS_SWAP */
644 { "\x02" "Version 6" }, /* BSD_FS_V6 */
645 { "\x03" "Version 7" }, /* BSD_FS_V7 */
646 { "\x04" "System V" }, /* BSD_FS_SYSV */
647 { "\x05" "4.1BSD" }, /* BSD_FS_V71K */
648 { "\x06" "Eighth Edition" }, /* BSD_FS_V8 */
649 { "\x07" "4.2BSD" }, /* BSD_FS_BSDFFS */
651 { "\x08" "ext2" }, /* BSD_FS_EXT2 */
653 { "\x08" "MS-DOS" }, /* BSD_FS_MSDOS */
655 { "\x09" "4.4LFS" }, /* BSD_FS_BSDLFS */
656 { "\x0a" "unknown" }, /* BSD_FS_OTHER */
657 { "\x0b" "HPFS" }, /* BSD_FS_HPFS */
658 { "\x0c" "ISO-9660" }, /* BSD_FS_ISO9660 */
659 { "\x0d" "boot" }, /* BSD_FS_BOOT */
660 { "\x0e" "ADOS" }, /* BSD_FS_ADOS */
661 { "\x0f" "HFS" }, /* BSD_FS_HFS */
662 { "\x10" "AdvFS" }, /* BSD_FS_ADVFS */
665 #define BSD_FSMAXTYPES (SIZE(xbsd_fstypes)-1)
670 * flags shared by various drives:
672 #define BSD_D_REMOVABLE 0x01 /* removable media */
673 #define BSD_D_ECC 0x02 /* supports ECC */
674 #define BSD_D_BADSECT 0x04 /* supports bad sector forw. */
675 #define BSD_D_RAMDISK 0x08 /* disk emulator */
676 #define BSD_D_CHAIN 0x10 /* can do back-back transfers */
677 #define BSD_D_DOSPART 0x20 /* within MSDOS partition */
679 #endif /* OSF_LABEL */
682 * Copyright (C) Andreas Neuper, Sep 1998.
683 * This file may be modified and redistributed under
684 * the terms of the GNU Public License.
687 struct device_parameter { /* 48 bytes */
691 unsigned char sparecyl;
692 unsigned short pcylcount;
693 unsigned short head_vol0;
694 unsigned short ntrks; /* tracks in cyl 0 or vol 0 */
695 unsigned char cmd_tag_queue_depth;
696 unsigned char unused0;
697 unsigned short unused1;
698 unsigned short nsect; /* sectors/tracks in cyl 0 or vol 0 */
699 unsigned short bytes;
700 unsigned short ilfact;
701 unsigned int flags; /* controller flags */
702 unsigned int datarate;
703 unsigned int retries_on_error;
704 unsigned int ms_per_word;
705 unsigned short xylogics_gap1;
706 unsigned short xylogics_syncdelay;
707 unsigned short xylogics_readdelay;
708 unsigned short xylogics_gap2;
709 unsigned short xylogics_readgate;
710 unsigned short xylogics_writecont;
713 #define SGI_VOLHDR 0x00
714 /* 1 and 2 were used for drive types no longer supported by SGI */
715 #define SGI_SWAP 0x03
716 /* 4 and 5 were for filesystem types SGI haven't ever supported on MIPS CPUs */
717 #define SGI_VOLUME 0x06
719 #define SGI_LVOL 0x08
720 #define SGI_RLVOL 0x09
722 #define SGI_XFSLOG 0x0b
725 #define ENTIRE_DISK SGI_VOLUME
729 #define SECTOR_SLIP 0x01
730 #define SECTOR_FWD 0x02
731 #define TRACK_FWD 0x04
732 #define TRACK_MULTIVOL 0x08
733 #define IGNORE_ERRORS 0x10
735 #define ENABLE_CMDTAGQ 0x40
738 unsigned int magic; /* expect SGI_LABEL_MAGIC */
739 unsigned short boot_part; /* active boot partition */
740 unsigned short swap_part; /* active swap partition */
741 unsigned char boot_file[16]; /* name of the bootfile */
742 struct device_parameter devparam; /* 1 * 48 bytes */
743 struct volume_directory { /* 15 * 16 bytes */
744 unsigned char vol_file_name[8]; /* a character array */
745 unsigned int vol_file_start; /* number of logical block */
746 unsigned int vol_file_size; /* number of bytes */
748 struct sgi_partition { /* 16 * 12 bytes */
749 unsigned int num_sectors; /* number of blocks */
750 unsigned int start_sector; /* must be cylinder aligned */
754 unsigned int fillbytes;
758 unsigned int magic; /* looks like a magic number */
767 unsigned char scsi_string[50];
768 unsigned char serial[137];
769 unsigned short check1816;
770 unsigned char installer[225];
773 #define SGI_LABEL_MAGIC 0x0be5a941
774 #define SGI_LABEL_MAGIC_SWAPPED 0x41a9e50b
775 #define SGI_INFO_MAGIC 0x00072959
776 #define SGI_INFO_MAGIC_SWAPPED 0x59290700
777 #define SGI_SSWAP16(x) (sgi_other_endian ? __swap16(x) \
779 #define SGI_SSWAP32(x) (sgi_other_endian ? __swap32(x) \
782 #define sgilabel ((sgi_partition *)MBRbuffer)
783 #define sgiparam (sgilabel->devparam)
786 unsigned char info[128]; /* Informative text string */
787 unsigned char spare0[14];
789 unsigned char spare1;
791 unsigned char spare2;
794 unsigned char spare1[246]; /* Boot information etc. */
795 unsigned short rspeed; /* Disk rotational speed */
796 unsigned short pcylcount; /* Physical cylinder count */
797 unsigned short sparecyl; /* extra sects per cylinder */
798 unsigned char spare2[4]; /* More magic... */
799 unsigned short ilfact; /* Interleave factor */
800 unsigned short ncyl; /* Data cylinder count */
801 unsigned short nacyl; /* Alt. cylinder count */
802 unsigned short ntrks; /* Tracks per cylinder */
803 unsigned short nsect; /* Sectors per track */
804 unsigned char spare3[4]; /* Even more magic... */
805 struct sun_partition {
806 uint32_t start_cylinder;
807 uint32_t num_sectors;
809 unsigned short magic; /* Magic number */
810 unsigned short csum; /* Label xor'd checksum */
814 #define SUN_LABEL_MAGIC 0xDABE
815 #define SUN_LABEL_MAGIC_SWAPPED 0xBEDA
816 #define sunlabel ((sun_partition *)MBRbuffer)
817 #define SUN_SSWAP16(x) (sun_other_endian ? __swap16(x) \
819 #define SUN_SSWAP32(x) (sun_other_endian ? __swap32(x) \
823 #ifdef CONFIG_FEATURE_OSF_LABEL
826 19990319 - Arnaldo Carvalho de Melo <acme@conectiva.com.br> - i18n/nls
828 20000101 - David Huggins-Daines <dhuggins@linuxcare.com> - Better
829 support for OSF/1 disklabels on Alpha.
830 Also fixed unaligned accesses in alpha_bootblock_checksum()
833 #define FREEBSD_PARTITION 0xa5
834 #define NETBSD_PARTITION 0xa9
836 static void xbsd_delete_part(void);
837 static void xbsd_new_part(void);
838 static void xbsd_write_disklabel(void);
839 static int xbsd_create_disklabel(void);
840 static void xbsd_edit_disklabel(void);
841 static void xbsd_write_bootstrap(void);
842 static void xbsd_change_fstype(void);
843 static int xbsd_get_part_index(int max);
844 static int xbsd_check_new_partition(int *i);
845 static void xbsd_list_types(void);
846 static u_short xbsd_dkcksum(struct xbsd_disklabel *lp);
847 static int xbsd_initlabel(struct partition *p, struct xbsd_disklabel *d);
848 static int xbsd_readlabel(struct partition *p, struct xbsd_disklabel *d);
849 static int xbsd_writelabel(struct partition *p, struct xbsd_disklabel *d);
851 #if defined (__alpha__)
852 static void alpha_bootblock_checksum(char *boot);
855 #if !defined (__alpha__)
856 static int xbsd_translate_fstype(int linux_type);
857 static void xbsd_link_part(void);
858 static struct partition *xbsd_part;
859 static int xbsd_part_index;
862 #if defined (__alpha__)
863 /* We access this through a uint64_t * when checksumming */
864 static char disklabelbuffer[BSD_BBSIZE] ATTRIBUTE_ALIGNED(8);
866 static char disklabelbuffer[BSD_BBSIZE];
869 static struct xbsd_disklabel xbsd_dlabel;
871 #define bsd_cround(n) \
872 (display_in_cyl_units ? ((n)/xbsd_dlabel.d_secpercyl) + 1 : (n))
875 * Test whether the whole disk has BSD disk label magic.
877 * Note: often reformatting with DOS-type label leaves the BSD magic,
878 * so this does not mean that there is a BSD disk label.
881 check_osf_label(void)
883 if (xbsd_readlabel(NULL, &xbsd_dlabel) == 0)
888 static void xbsd_print_disklabel(int);
891 btrydev(const char * dev)
893 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
895 printf(_("\nBSD label for device: %s\n"), dev);
896 xbsd_print_disklabel (0);
903 puts (_("Command action"));
904 puts (_("\td\tdelete a BSD partition"));
905 puts (_("\te\tedit drive data"));
906 puts (_("\ti\tinstall bootstrap"));
907 puts (_("\tl\tlist known filesystem types"));
908 puts (_("\tm\tprint this menu"));
909 puts (_("\tn\tadd a new BSD partition"));
910 puts (_("\tp\tprint BSD partition table"));
911 puts (_("\tq\tquit without saving changes"));
912 puts (_("\tr\treturn to main menu"));
913 puts (_("\ts\tshow complete disklabel"));
914 puts (_("\tt\tchange a partition's filesystem id"));
915 puts (_("\tu\tchange units (cylinders/sectors)"));
916 puts (_("\tw\twrite disklabel to disk"));
917 #if !defined (__alpha__)
918 puts (_("\tx\tlink BSD partition to non-BSD partition"));
922 #if !defined (__alpha__)
930 is_bsd_partition_type(int type)
932 return (type == FREEBSD_PARTITION ||
933 type == hidden(FREEBSD_PARTITION) ||
934 type == NETBSD_PARTITION ||
935 type == hidden(NETBSD_PARTITION));
942 #if !defined (__alpha__)
946 for (t = 0; t < 4; t++) {
947 p = get_part_table(t);
948 if (p && is_bsd_partition_type(p->sys_ind)) {
951 ss = get_start_sect(xbsd_part);
953 fprintf(stderr, _("Partition %s has invalid starting sector 0.\n"),
954 partname(disk_device, t+1, 0));
957 printf(_("Reading disklabel of %s at sector %d.\n"),
958 partname(disk_device, t+1, 0), ss + BSD_LABELSECTOR);
959 if (xbsd_readlabel(xbsd_part, &xbsd_dlabel) == 0)
960 if (xbsd_create_disklabel() == 0)
967 printf(_("There is no *BSD partition on %s.\n"), disk_device);
971 #elif defined (__alpha__)
973 if (xbsd_readlabel(NULL, &xbsd_dlabel) == 0)
974 if (xbsd_create_disklabel() == 0)
981 switch (tolower(read_char(_("BSD disklabel command (m for help): ")))) {
986 xbsd_edit_disklabel();
989 xbsd_write_bootstrap();
998 xbsd_print_disklabel(0);
1006 xbsd_print_disklabel(1);
1009 xbsd_change_fstype();
1015 xbsd_write_disklabel();
1017 #if !defined (__alpha__)
1030 xbsd_delete_part(void)
1034 i = xbsd_get_part_index(xbsd_dlabel.d_npartitions);
1035 xbsd_dlabel.d_partitions[i].p_size = 0;
1036 xbsd_dlabel.d_partitions[i].p_offset = 0;
1037 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
1038 if (xbsd_dlabel.d_npartitions == i + 1)
1039 while (xbsd_dlabel.d_partitions[xbsd_dlabel.d_npartitions-1].p_size == 0)
1040 xbsd_dlabel.d_npartitions--;
1050 if (!xbsd_check_new_partition(&i))
1053 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
1054 begin = get_start_sect(xbsd_part);
1055 end = begin + get_nr_sects(xbsd_part) - 1;
1058 end = xbsd_dlabel.d_secperunit - 1;
1061 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
1062 begin = read_int(bsd_cround(begin), bsd_cround(begin), bsd_cround(end),
1065 if (display_in_cyl_units)
1066 begin = (begin - 1) * xbsd_dlabel.d_secpercyl;
1068 snprintf(mesg, sizeof(mesg), _("Last %s or +size or +sizeM or +sizeK"),
1069 str_units(SINGULAR));
1070 end = read_int(bsd_cround (begin), bsd_cround (end), bsd_cround (end),
1071 bsd_cround (begin), mesg);
1073 if (display_in_cyl_units)
1074 end = end * xbsd_dlabel.d_secpercyl - 1;
1076 xbsd_dlabel.d_partitions[i].p_size = end - begin + 1;
1077 xbsd_dlabel.d_partitions[i].p_offset = begin;
1078 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
1082 xbsd_print_disklabel(int show_all)
1084 struct xbsd_disklabel *lp = &xbsd_dlabel;
1085 struct xbsd_partition *pp;
1089 #if defined (__alpha__)
1090 printf("# %s:\n", disk_device);
1092 printf("# %s:\n", partname(disk_device, xbsd_part_index+1, 0));
1094 if ((unsigned) lp->d_type < BSD_DKMAXTYPES)
1095 printf(_("type: %s\n"), xbsd_dktypenames[lp->d_type]);
1097 printf(_("type: %d\n"), lp->d_type);
1098 printf(_("disk: %.*s\n"), (int) sizeof(lp->d_typename), lp->d_typename);
1099 printf(_("label: %.*s\n"), (int) sizeof(lp->d_packname), lp->d_packname);
1100 printf(_("flags:"));
1101 if (lp->d_flags & BSD_D_REMOVABLE)
1102 printf(_(" removable"));
1103 if (lp->d_flags & BSD_D_ECC)
1105 if (lp->d_flags & BSD_D_BADSECT)
1106 printf(_(" badsect"));
1108 /* On various machines the fields of *lp are short/int/long */
1109 /* In order to avoid problems, we cast them all to long. */
1110 printf(_("bytes/sector: %ld\n"), (long) lp->d_secsize);
1111 printf(_("sectors/track: %ld\n"), (long) lp->d_nsectors);
1112 printf(_("tracks/cylinder: %ld\n"), (long) lp->d_ntracks);
1113 printf(_("sectors/cylinder: %ld\n"), (long) lp->d_secpercyl);
1114 printf(_("cylinders: %ld\n"), (long) lp->d_ncylinders);
1115 printf(_("rpm: %d\n"), lp->d_rpm);
1116 printf(_("interleave: %d\n"), lp->d_interleave);
1117 printf(_("trackskew: %d\n"), lp->d_trackskew);
1118 printf(_("cylinderskew: %d\n"), lp->d_cylskew);
1119 printf(_("headswitch: %ld\t\t# milliseconds\n"),
1120 (long) lp->d_headswitch);
1121 printf(_("track-to-track seek: %ld\t# milliseconds\n"),
1122 (long) lp->d_trkseek);
1123 printf(_("drivedata: "));
1124 for (i = NDDATA - 1; i >= 0; i--)
1125 if (lp->d_drivedata[i])
1129 for (j = 0; j <= i; j++)
1130 printf("%ld ", (long) lp->d_drivedata[j]);
1132 printf(_("\n%d partitions:\n"), lp->d_npartitions);
1133 printf(_("# start end size fstype [fsize bsize cpg]\n"));
1134 pp = lp->d_partitions;
1135 for (i = 0; i < lp->d_npartitions; i++, pp++) {
1137 if (display_in_cyl_units && lp->d_secpercyl) {
1138 printf(" %c: %8ld%c %8ld%c %8ld%c ",
1140 (long) pp->p_offset / lp->d_secpercyl + 1,
1141 (pp->p_offset % lp->d_secpercyl) ? '*' : ' ',
1142 (long) (pp->p_offset + pp->p_size + lp->d_secpercyl - 1) / lp->d_secpercyl,
1143 ((pp->p_offset + pp->p_size) % lp->d_secpercyl) ? '*' : ' ',
1144 (long) pp->p_size / lp->d_secpercyl,
1145 (pp->p_size % lp->d_secpercyl) ? '*' : ' '
1148 printf(" %c: %8ld %8ld %8ld ",
1150 (long) pp->p_offset,
1151 (long) pp->p_offset + pp->p_size - 1,
1156 if ((unsigned) pp->p_fstype < BSD_FSMAXTYPES)
1157 printf("%8.8s", xbsd_fstypes[pp->p_fstype].name);
1159 printf("%8x", pp->p_fstype);
1161 switch (pp->p_fstype) {
1163 printf(" %5ld %5ld %5.5s ",
1164 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, "");
1167 printf(" %5ld %5ld %5d ",
1168 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, pp->p_cpg);
1171 printf("%22.22s", "");
1180 xbsd_write_disklabel(void)
1182 #if defined (__alpha__)
1183 printf(_("Writing disklabel to %s.\n"), disk_device);
1184 xbsd_writelabel(NULL, &xbsd_dlabel);
1186 printf(_("Writing disklabel to %s.\n"),
1187 partname(disk_device, xbsd_part_index + 1, 0));
1188 xbsd_writelabel(xbsd_part, &xbsd_dlabel);
1190 reread_partition_table(0); /* no exit yet */
1194 xbsd_create_disklabel(void)
1198 #if defined (__alpha__)
1199 fprintf(stderr, _("%s contains no disklabel.\n"), disk_device);
1201 fprintf(stderr, _("%s contains no disklabel.\n"),
1202 partname(disk_device, xbsd_part_index + 1, 0));
1206 c = read_char(_("Do you want to create a disklabel? (y/n) "));
1207 if (c == 'y' || c == 'Y') {
1209 #if defined (__alpha__) || defined (__powerpc__) || defined (__hppa__) || \
1210 defined (__s390__) || defined (__s390x__)
1213 xbsd_part, &xbsd_dlabel/* not used, xbsd_part_index*/
1216 xbsd_print_disklabel (1);
1220 } else if (c == 'n')
1226 edit_int(int def, char *mesg)
1229 fputs(mesg, stdout);
1230 printf(" (%d): ", def);
1234 while (!isdigit(*line_ptr)); /* FIXME: ?!! */
1235 return atoi(line_ptr);
1239 xbsd_edit_disklabel(void)
1241 struct xbsd_disklabel *d;
1245 #if defined (__alpha__) || defined (__ia64__)
1246 d->d_secsize = (u_long) edit_int((u_long) d->d_secsize ,_("bytes/sector"));
1247 d->d_nsectors = (u_long) edit_int((u_long) d->d_nsectors ,_("sectors/track"));
1248 d->d_ntracks = (u_long) edit_int((u_long) d->d_ntracks ,_("tracks/cylinder"));
1249 d->d_ncylinders = (u_long) edit_int((u_long) d->d_ncylinders ,_("cylinders"));
1252 /* d->d_secpercyl can be != d->d_nsectors * d->d_ntracks */
1254 d->d_secpercyl = (u_long) edit_int((u_long) d->d_nsectors * d->d_ntracks,
1255 _("sectors/cylinder"));
1256 if (d->d_secpercyl <= d->d_nsectors * d->d_ntracks)
1259 printf(_("Must be <= sectors/track * tracks/cylinder (default).\n"));
1261 d->d_rpm = (u_short) edit_int((u_short) d->d_rpm ,_("rpm"));
1262 d->d_interleave = (u_short) edit_int((u_short) d->d_interleave,_("interleave"));
1263 d->d_trackskew = (u_short) edit_int((u_short) d->d_trackskew ,_("trackskew"));
1264 d->d_cylskew = (u_short) edit_int((u_short) d->d_cylskew ,_("cylinderskew"));
1265 d->d_headswitch = (u_long) edit_int((u_long) d->d_headswitch ,_("headswitch"));
1266 d->d_trkseek = (u_long) edit_int((u_long) d->d_trkseek ,_("track-to-track seek"));
1268 d->d_secperunit = d->d_secpercyl * d->d_ncylinders;
1272 xbsd_get_bootstrap (char *path, void *ptr, int size)
1276 if ((fdb = open (path, O_RDONLY)) < 0) {
1280 if (read(fdb, ptr, size) < 0) {
1285 printf(" ... %s\n", path);
1293 printf(_("\nSyncing disks.\n"));
1295 sleep(4); /* What? */
1299 xbsd_write_bootstrap(void)
1301 char *bootdir = BSD_LINUX_BOOTDIR;
1302 char path[MAXPATHLEN];
1304 struct xbsd_disklabel dl;
1308 if (xbsd_dlabel.d_type == BSD_DTYPE_SCSI)
1313 printf(_("Bootstrap: %sboot -> boot%s (%s): "),
1314 dkbasename, dkbasename, dkbasename);
1316 line_ptr[strlen(line_ptr)-1] = '\0';
1317 dkbasename = line_ptr;
1319 snprintf(path, sizeof(path), "%s/%sboot", bootdir, dkbasename);
1320 if (!xbsd_get_bootstrap(path, disklabelbuffer, (int) xbsd_dlabel.d_secsize))
1323 /* We need a backup of the disklabel (xbsd_dlabel might have changed). */
1324 d = &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE];
1325 memmove(&dl, d, sizeof(struct xbsd_disklabel));
1327 /* The disklabel will be overwritten by 0's from bootxx anyway */
1328 memset(d, 0, sizeof(struct xbsd_disklabel));
1330 snprintf(path, sizeof(path), "%s/boot%s", bootdir, dkbasename);
1331 if (!xbsd_get_bootstrap (path, &disklabelbuffer[xbsd_dlabel.d_secsize],
1332 (int) xbsd_dlabel.d_bbsize - xbsd_dlabel.d_secsize))
1335 e = d + sizeof(struct xbsd_disklabel);
1336 for (p = d; p < e; p++)
1338 fprintf(stderr, _("Bootstrap overlaps with disk label!\n"));
1342 memmove(d, &dl, sizeof(struct xbsd_disklabel));
1344 #if defined (__powerpc__) || defined (__hppa__)
1346 #elif defined (__alpha__)
1348 alpha_bootblock_checksum(disklabelbuffer);
1350 sector = get_start_sect(xbsd_part);
1353 if (lseek(fd, sector * SECTOR_SIZE, SEEK_SET) == -1)
1354 fdisk_fatal(unable_to_seek);
1355 if (BSD_BBSIZE != write(fd, disklabelbuffer, BSD_BBSIZE))
1356 fdisk_fatal(unable_to_write);
1358 #if defined (__alpha__)
1359 printf(_("Bootstrap installed on %s.\n"), disk_device);
1361 printf(_("Bootstrap installed on %s.\n"),
1362 partname (disk_device, xbsd_part_index+1, 0));
1369 xbsd_change_fstype(void)
1373 i = xbsd_get_part_index(xbsd_dlabel.d_npartitions);
1374 xbsd_dlabel.d_partitions[i].p_fstype = read_hex(xbsd_fstypes);
1378 xbsd_get_part_index(int max)
1383 snprintf(prompt, sizeof(prompt), _("Partition (a-%c): "), 'a' + max - 1);
1385 l = tolower(read_char(prompt));
1386 while (l < 'a' || l > 'a' + max - 1);
1391 xbsd_check_new_partition(int *i)
1393 /* room for more? various BSD flavours have different maxima */
1394 if (xbsd_dlabel.d_npartitions == BSD_MAXPARTITIONS) {
1397 for (t = 0; t < BSD_MAXPARTITIONS; t++)
1398 if (xbsd_dlabel.d_partitions[t].p_size == 0)
1401 if (t == BSD_MAXPARTITIONS) {
1402 fprintf(stderr, _("The maximum number of partitions "
1403 "has been created\n"));
1408 *i = xbsd_get_part_index (BSD_MAXPARTITIONS);
1410 if (*i >= xbsd_dlabel.d_npartitions)
1411 xbsd_dlabel.d_npartitions = (*i) + 1;
1413 if (xbsd_dlabel.d_partitions[*i].p_size != 0) {
1414 fprintf(stderr, _("This partition already exists.\n"));
1422 xbsd_list_types(void)
1424 list_types(xbsd_fstypes);
1428 xbsd_dkcksum(struct xbsd_disklabel *lp)
1430 u_short *start, *end;
1433 start = (u_short *) lp;
1434 end = (u_short *) &lp->d_partitions[lp->d_npartitions];
1441 xbsd_initlabel(struct partition *p, struct xbsd_disklabel *d)
1443 struct xbsd_partition *pp;
1446 memset(d, 0, sizeof(struct xbsd_disklabel));
1448 d->d_magic = BSD_DISKMAGIC;
1450 if (strncmp(disk_device, "/dev/sd", 7) == 0)
1451 d->d_type = BSD_DTYPE_SCSI;
1453 d->d_type = BSD_DTYPE_ST506;
1455 #if 0 /* not used (at least not written to disk) by NetBSD/i386 1.0 */
1456 d->d_subtype = BSD_DSTYPE_INDOSPART & pindex;
1459 #if !defined (__alpha__)
1460 d->d_flags = BSD_D_DOSPART;
1464 d->d_secsize = SECTOR_SIZE; /* bytes/sector */
1465 d->d_nsectors = sectors; /* sectors/track */
1466 d->d_ntracks = heads; /* tracks/cylinder (heads) */
1467 d->d_ncylinders = cylinders;
1468 d->d_secpercyl = sectors * heads;/* sectors/cylinder */
1469 if (d->d_secpercyl == 0)
1470 d->d_secpercyl = 1; /* avoid segfaults */
1471 d->d_secperunit = d->d_secpercyl * d->d_ncylinders;
1474 d->d_interleave = 1;
1477 d->d_headswitch = 0;
1480 d->d_magic2 = BSD_DISKMAGIC;
1481 d->d_bbsize = BSD_BBSIZE;
1482 d->d_sbsize = BSD_SBSIZE;
1484 #if !defined (__alpha__)
1485 d->d_npartitions = 4;
1486 pp = &d->d_partitions[2]; /* Partition C should be
1487 the NetBSD partition */
1488 pp->p_offset = get_start_sect(p);
1489 pp->p_size = get_nr_sects(p);
1490 pp->p_fstype = BSD_FS_UNUSED;
1491 pp = &d->d_partitions[3]; /* Partition D should be
1494 pp->p_size = d->d_secperunit;
1495 pp->p_fstype = BSD_FS_UNUSED;
1496 #elif defined (__alpha__)
1497 d->d_npartitions = 3;
1498 pp = &d->d_partitions[2]; /* Partition C should be
1501 pp->p_size = d->d_secperunit;
1502 pp->p_fstype = BSD_FS_UNUSED;
1509 * Read a xbsd_disklabel from sector 0 or from the starting sector of p.
1510 * If it has the right magic, return 1.
1513 xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d)
1517 /* p is used only to get the starting sector */
1518 #if !defined (__alpha__)
1519 sector = (p ? get_start_sect(p) : 0);
1520 #elif defined (__alpha__)
1524 if (lseek(fd, sector * SECTOR_SIZE, SEEK_SET) == -1)
1525 fdisk_fatal(unable_to_seek);
1526 if (BSD_BBSIZE != read(fd, disklabelbuffer, BSD_BBSIZE))
1527 fdisk_fatal(unable_to_read);
1529 memmove(d, &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
1530 sizeof(struct xbsd_disklabel));
1532 if (d->d_magic != BSD_DISKMAGIC || d->d_magic2 != BSD_DISKMAGIC)
1535 for (t = d->d_npartitions; t < BSD_MAXPARTITIONS; t++) {
1536 d->d_partitions[t].p_size = 0;
1537 d->d_partitions[t].p_offset = 0;
1538 d->d_partitions[t].p_fstype = BSD_FS_UNUSED;
1541 if (d->d_npartitions > BSD_MAXPARTITIONS)
1542 fprintf(stderr, _("Warning: too many partitions "
1543 "(%d, maximum is %d).\n"),
1544 d->d_npartitions, BSD_MAXPARTITIONS);
1549 xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d)
1551 unsigned int sector;
1553 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
1554 sector = get_start_sect(p) + BSD_LABELSECTOR;
1556 sector = BSD_LABELSECTOR;
1560 d->d_checksum = xbsd_dkcksum (d);
1562 /* This is necessary if we want to write the bootstrap later,
1563 otherwise we'd write the old disklabel with the bootstrap.
1565 memmove(&disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
1566 d, sizeof(struct xbsd_disklabel));
1568 #if defined (__alpha__) && BSD_LABELSECTOR == 0
1569 alpha_bootblock_checksum (disklabelbuffer);
1570 if (lseek(fd, 0, SEEK_SET) == -1)
1571 fdisk_fatal(unable_to_seek);
1572 if (BSD_BBSIZE != write(fd, disklabelbuffer, BSD_BBSIZE))
1573 fdisk_fatal(unable_to_write);
1575 if (lseek(fd, sector * SECTOR_SIZE + BSD_LABELOFFSET, SEEK_SET) == -1)
1576 fdisk_fatal(unable_to_seek);
1577 if (sizeof(struct xbsd_disklabel) != write(fd, d, sizeof(struct xbsd_disklabel)))
1578 fdisk_fatal(unable_to_write);
1585 #if !defined (__alpha__)
1587 xbsd_translate_fstype(int linux_type)
1589 switch (linux_type) {
1590 case 0x01: /* DOS 12-bit FAT */
1591 case 0x04: /* DOS 16-bit <32M */
1592 case 0x06: /* DOS 16-bit >=32M */
1593 case 0xe1: /* DOS access */
1594 case 0xe3: /* DOS R/O */
1595 case 0xf2: /* DOS secondary */
1596 return BSD_FS_MSDOS;
1597 case 0x07: /* OS/2 HPFS */
1600 return BSD_FS_OTHER;
1605 xbsd_link_part(void)
1608 struct partition *p;
1610 k = get_partition(1, partitions);
1612 if (!xbsd_check_new_partition(&i))
1615 p = get_part_table(k);
1617 xbsd_dlabel.d_partitions[i].p_size = get_nr_sects(p);
1618 xbsd_dlabel.d_partitions[i].p_offset = get_start_sect(p);
1619 xbsd_dlabel.d_partitions[i].p_fstype = xbsd_translate_fstype(p->sys_ind);
1623 #if defined (__alpha__)
1625 #if !defined(__GLIBC__)
1626 typedef unsigned long long uint64_t;
1630 alpha_bootblock_checksum(char *boot)
1635 dp = (uint64_t *)boot;
1637 for (i = 0; i < 63; i++)
1641 #endif /* __alpha__ */
1643 #endif /* OSF_LABEL */
1645 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
1646 static inline unsigned short
1647 __swap16(unsigned short x)
1649 return (((uint16_t)(x) & 0xFF) << 8) | (((uint16_t)(x) & 0xFF00) >> 8);
1652 static inline uint32_t
1653 __swap32(uint32_t x)
1655 return (((x & 0xFF) << 24) |
1656 ((x & 0xFF00) << 8) |
1657 ((x & 0xFF0000) >> 8) |
1658 ((x & 0xFF000000) >> 24));
1662 #ifdef CONFIG_FEATURE_SGI_LABEL
1667 * Copyright (C) Andreas Neuper, Sep 1998.
1668 * This file may be modified and redistributed under
1669 * the terms of the GNU Public License.
1671 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
1672 * Internationalization
1676 static int sgi_other_endian;
1678 static short sgi_volumes = 1;
1681 * only dealing with free blocks here
1688 static freeblocks freelist[17]; /* 16 partitions can produce 17 vacant slots */
1691 setfreelist(int i, unsigned int f, unsigned int l)
1693 freelist[i].first = f;
1694 freelist[i].last = l;
1698 add2freelist(unsigned int f, unsigned int l)
1701 for (i = 0; i < 17 ; i++)
1702 if (freelist[i].last == 0)
1704 setfreelist(i, f, l);
1712 for (i = 0; i < 17 ; i++)
1713 setfreelist(i, 0, 0);
1717 isinfreelist(unsigned int b)
1721 for (i = 0; i < 17 ; i++)
1722 if (freelist[i].first <= b && freelist[i].last >= b)
1723 return freelist[i].last;
1726 /* return last vacant block of this stride (never 0). */
1727 /* the '>=' is not quite correct, but simplifies the code */
1729 * end of free blocks section
1732 static const struct systypes sgi_sys_types[] = {
1733 /* SGI_VOLHDR */ { "\x00" "SGI volhdr" },
1734 /* 0x01 */ { "\x01" "SGI trkrepl" },
1735 /* 0x02 */ { "\x02" "SGI secrepl" },
1736 /* SGI_SWAP */ { "\x03" "SGI raw" },
1737 /* 0x04 */ { "\x04" "SGI bsd" },
1738 /* 0x05 */ { "\x05" "SGI sysv" },
1739 /* ENTIRE_DISK */ { "\x06" "SGI volume" },
1740 /* SGI_EFS */ { "\x07" "SGI efs" },
1741 /* 0x08 */ { "\x08" "SGI lvol" },
1742 /* 0x09 */ { "\x09" "SGI rlvol" },
1743 /* SGI_XFS */ { "\x0a" "SGI xfs" },
1744 /* SGI_XFSLOG */ { "\x0b" "SGI xfslog" },
1745 /* SGI_XLV */ { "\x0c" "SGI xlv" },
1746 /* SGI_XVM */ { "\x0d" "SGI xvm" },
1747 /* LINUX_SWAP */ { "\x82" "Linux swap" },
1748 /* LINUX_NATIVE */ { "\x83" "Linux native" },
1749 /* LINUX_LVM */ { "\x8d" "Linux LVM" },
1750 /* LINUX_RAID */ { "\xfd" "Linux RAID" },
1758 return SGI_SSWAP16(sgilabel->devparam.nsect);
1764 return SGI_SSWAP16(sgilabel->devparam.ntrks);
1768 two_s_complement_32bit_sum(unsigned int* base, int size /* in bytes */)
1771 unsigned int sum = 0;
1773 size /= sizeof(unsigned int);
1774 for (i = 0; i < size; i++)
1775 sum -= SGI_SSWAP32(base[i]);
1780 check_sgi_label(void)
1782 if (sizeof(sgilabel) > 512) {
1784 _("According to MIPS Computer Systems, Inc the "
1785 "Label must not contain more than 512 bytes\n"));
1789 if (sgilabel->magic != SGI_LABEL_MAGIC
1790 && sgilabel->magic != SGI_LABEL_MAGIC_SWAPPED) {
1791 current_label_type = label_dos;
1795 sgi_other_endian = (sgilabel->magic == SGI_LABEL_MAGIC_SWAPPED);
1797 * test for correct checksum
1799 if (two_s_complement_32bit_sum((unsigned int*)sgilabel,
1800 sizeof(*sgilabel))) {
1802 _("Detected sgi disklabel with wrong checksum.\n"));
1805 current_label_type = label_sgi;
1812 sgi_get_start_sector(int i)
1814 return SGI_SSWAP32(sgilabel->partitions[i].start_sector);
1818 sgi_get_num_sectors(int i)
1820 return SGI_SSWAP32(sgilabel->partitions[i].num_sectors);
1824 sgi_get_sysid(int i)
1826 return SGI_SSWAP32(sgilabel->partitions[i].id);
1830 sgi_get_bootpartition(void)
1832 return SGI_SSWAP16(sgilabel->boot_part);
1836 sgi_get_swappartition(void)
1838 return SGI_SSWAP16(sgilabel->swap_part);
1842 sgi_list_table(int xtra)
1845 int kpi = 0; /* kernel partition ID */
1848 printf(_("\nDisk %s (SGI disk label): %d heads, %d sectors\n"
1849 "%d cylinders, %d physical cylinders\n"
1850 "%d extra sects/cyl, interleave %d:1\n"
1852 "Units = %s of %d * 512 bytes\n\n"),
1853 disk_device, heads, sectors, cylinders,
1854 SGI_SSWAP16(sgiparam.pcylcount),
1855 SGI_SSWAP16(sgiparam.sparecyl),
1856 SGI_SSWAP16(sgiparam.ilfact),
1858 str_units(PLURAL), units_per_sector);
1860 printf( _("\nDisk %s (SGI disk label): "
1861 "%d heads, %d sectors, %d cylinders\n"
1862 "Units = %s of %d * 512 bytes\n\n"),
1863 disk_device, heads, sectors, cylinders,
1864 str_units(PLURAL), units_per_sector );
1867 w = strlen(disk_device);
1868 wd = strlen(_("Device"));
1872 printf(_("----- partitions -----\n"
1873 "Pt# %*s Info Start End Sectors Id System\n"),
1874 w + 2, _("Device"));
1875 for (i = 0 ; i < partitions; i++) {
1876 if( sgi_get_num_sectors(i) || debug ) {
1877 uint32_t start = sgi_get_start_sector(i);
1878 uint32_t len = sgi_get_num_sectors(i);
1879 kpi++; /* only count nonempty partitions */
1881 "%2d: %s %4s %9ld %9ld %9ld %2x %s\n",
1882 /* fdisk part number */ i+1,
1883 /* device */ partname(disk_device, kpi, w+3),
1884 /* flags */ (sgi_get_swappartition() == i) ? "swap" :
1885 /* flags */ (sgi_get_bootpartition() == i) ? "boot" : " ",
1886 /* start */ (long) scround(start),
1887 /* end */ (long) scround(start+len)-1,
1888 /* no odd flag on end */(long) len,
1889 /* type id */ sgi_get_sysid(i),
1890 /* type name */ partition_type(sgi_get_sysid(i)));
1893 printf(_("----- Bootinfo -----\nBootfile: %s\n"
1894 "----- Directory Entries -----\n"),
1895 sgilabel->boot_file);
1896 for (i = 0 ; i < sgi_volumes; i++) {
1897 if (sgilabel->directory[i].vol_file_size) {
1898 uint32_t start = SGI_SSWAP32(sgilabel->directory[i].vol_file_start);
1899 uint32_t len = SGI_SSWAP32(sgilabel->directory[i].vol_file_size);
1900 unsigned char *name = sgilabel->directory[i].vol_file_name;
1902 printf(_("%2d: %-10s sector%5u size%8u\n"),
1903 i, (char*)name, (unsigned int) start, (unsigned int) len);
1909 sgi_set_bootpartition(int i)
1911 sgilabel->boot_part = SGI_SSWAP16(((short)i));
1915 sgi_get_lastblock(void)
1917 return heads * sectors * cylinders;
1921 sgi_set_swappartition(int i)
1923 sgilabel->swap_part = SGI_SSWAP16(((short)i));
1927 sgi_check_bootfile(const char* aFile)
1929 if (strlen(aFile) < 3) /* "/a\n" is minimum */ {
1930 printf(_("\nInvalid Bootfile!\n"
1931 "\tThe bootfile must be an absolute non-zero pathname,\n"
1932 "\te.g. \"/unix\" or \"/unix.save\".\n"));
1935 if (strlen(aFile) > 16) {
1936 printf(_("\n\tName of Bootfile too long: "
1937 "16 bytes maximum.\n"));
1940 if (aFile[0] != '/') {
1941 printf(_("\n\tBootfile must have a "
1942 "fully qualified pathname.\n"));
1947 if (strncmp(aFile, (char*)sgilabel->boot_file, 16)) {
1948 printf(_("\n\tBe aware, that the bootfile is not checked for existence.\n\t"
1949 "SGI's default is \"/unix\" and for backup \"/unix.save\".\n"));
1950 /* filename is correct and did change */
1953 return 0; /* filename did not change */
1957 sgi_get_bootfile(void)
1959 return (char*)sgilabel->boot_file;
1963 sgi_set_bootfile(const char* aFile)
1967 if (sgi_check_bootfile(aFile)) {
1969 if ((aFile[i] != '\n') /* in principle caught again by next line */
1970 && (strlen(aFile) > i))
1971 sgilabel->boot_file[i] = aFile[i];
1973 sgilabel->boot_file[i] = 0;
1976 printf(_("\n\tBootfile is changed to \"%s\".\n"), sgilabel->boot_file);
1981 create_sgiinfo(void)
1983 /* I keep SGI's habit to write the sgilabel to the second block */
1984 sgilabel->directory[0].vol_file_start = SGI_SSWAP32(2);
1985 sgilabel->directory[0].vol_file_size = SGI_SSWAP32(sizeof(sgiinfo));
1986 strncpy((char*)sgilabel->directory[0].vol_file_name, "sgilabel", 8);
1989 static sgiinfo *fill_sgiinfo(void);
1992 sgi_write_table(void)
1995 sgilabel->csum = SGI_SSWAP32(two_s_complement_32bit_sum(
1996 (unsigned int*)sgilabel, sizeof(*sgilabel)));
1997 assert(two_s_complement_32bit_sum(
1998 (unsigned int*)sgilabel, sizeof(*sgilabel)) == 0);
2000 if (lseek(fd, 0, SEEK_SET) < 0)
2001 fdisk_fatal(unable_to_seek);
2002 if (write(fd, sgilabel, SECTOR_SIZE) != SECTOR_SIZE)
2003 fdisk_fatal(unable_to_write);
2004 if (!strncmp((char*)sgilabel->directory[0].vol_file_name, "sgilabel", 8)) {
2006 * keep this habit of first writing the "sgilabel".
2007 * I never tested whether it works without (AN 981002).
2009 sgiinfo *info = fill_sgiinfo();
2010 int infostartblock = SGI_SSWAP32(sgilabel->directory[0].vol_file_start);
2011 if (lseek(fd, infostartblock*SECTOR_SIZE, SEEK_SET) < 0)
2012 fdisk_fatal(unable_to_seek);
2013 if (write(fd, info, SECTOR_SIZE) != SECTOR_SIZE)
2014 fdisk_fatal(unable_to_write);
2020 compare_start(int *x, int *y)
2023 * sort according to start sectors
2024 * and prefers largest partition:
2025 * entry zero is entire disk entry
2027 unsigned int i = *x;
2028 unsigned int j = *y;
2029 unsigned int a = sgi_get_start_sector(i);
2030 unsigned int b = sgi_get_start_sector(j);
2031 unsigned int c = sgi_get_num_sectors(i);
2032 unsigned int d = sgi_get_num_sectors(j);
2035 return (d > c) ? 1 : (d == c) ? 0 : -1;
2036 return (a > b) ? 1 : -1;
2041 verify_sgi(int verbose)
2043 int Index[16]; /* list of valid partitions */
2044 int sortcount = 0; /* number of used partitions, i.e. non-zero lengths */
2045 int entire = 0, i = 0;
2046 unsigned int start = 0;
2047 long long gap = 0; /* count unused blocks */
2048 unsigned int lastblock = sgi_get_lastblock();
2051 for (i = 0; i < 16; i++) {
2052 if (sgi_get_num_sectors(i) != 0) {
2053 Index[sortcount++] = i;
2054 if (sgi_get_sysid(i) == ENTIRE_DISK) {
2055 if (entire++ == 1) {
2057 printf(_("More than one entire disk entry present.\n"));
2062 if (sortcount == 0) {
2064 printf(_("No partitions defined\n"));
2065 return (lastblock > 0) ? 1 : (lastblock == 0) ? 0 : -1;
2067 qsort(Index, sortcount, sizeof(Index[0]), (void*)compare_start);
2068 if (sgi_get_sysid(Index[0]) == ENTIRE_DISK) {
2069 if ((Index[0] != 10) && verbose)
2070 printf(_("IRIX likes when Partition 11 covers the entire disk.\n"));
2071 if ((sgi_get_start_sector(Index[0]) != 0) && verbose)
2072 printf(_("The entire disk partition should start "
2074 "not at diskblock %d.\n"),
2075 sgi_get_start_sector(Index[0]));
2076 if (debug) /* I do not understand how some disks fulfil it */
2077 if ((sgi_get_num_sectors(Index[0]) != lastblock) && verbose)
2078 printf(_("The entire disk partition is only %d diskblock large,\n"
2079 "but the disk is %d diskblocks long.\n"),
2080 sgi_get_num_sectors(Index[0]), lastblock);
2081 lastblock = sgi_get_num_sectors(Index[0]);
2084 printf(_("One Partition (#11) should cover the entire disk.\n"));
2086 printf("sysid=%d\tpartition=%d\n",
2087 sgi_get_sysid(Index[0]), Index[0]+1);
2089 for (i = 1, start = 0; i < sortcount; i++) {
2090 int cylsize = sgi_get_nsect() * sgi_get_ntrks();
2092 if ((sgi_get_start_sector(Index[i]) % cylsize) != 0) {
2093 if (debug) /* I do not understand how some disks fulfil it */
2095 printf(_("Partition %d does not start on cylinder boundary.\n"),
2098 if (sgi_get_num_sectors(Index[i]) % cylsize != 0) {
2099 if (debug) /* I do not understand how some disks fulfil it */
2101 printf(_("Partition %d does not end on cylinder boundary.\n"),
2104 /* We cannot handle several "entire disk" entries. */
2105 if (sgi_get_sysid(Index[i]) == ENTIRE_DISK) continue;
2106 if (start > sgi_get_start_sector(Index[i])) {
2108 printf(_("The Partition %d and %d overlap by %d sectors.\n"),
2109 Index[i-1]+1, Index[i]+1,
2110 start - sgi_get_start_sector(Index[i]));
2111 if (gap > 0) gap = -gap;
2112 if (gap == 0) gap = -1;
2114 if (start < sgi_get_start_sector(Index[i])) {
2116 printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"),
2117 sgi_get_start_sector(Index[i]) - start,
2118 start, sgi_get_start_sector(Index[i])-1);
2119 gap += sgi_get_start_sector(Index[i]) - start;
2120 add2freelist(start, sgi_get_start_sector(Index[i]));
2122 start = sgi_get_start_sector(Index[i])
2123 + sgi_get_num_sectors(Index[i]);
2126 printf("%2d:%12d\t%12d\t%12d\n", Index[i],
2127 sgi_get_start_sector(Index[i]),
2128 sgi_get_num_sectors(Index[i]),
2129 sgi_get_sysid(Index[i]));
2132 if (start < lastblock) {
2134 printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"),
2135 lastblock - start, start, lastblock-1);
2136 gap += lastblock - start;
2137 add2freelist(start, lastblock);
2140 * Done with arithmetics
2141 * Go for details now
2144 if (!sgi_get_num_sectors(sgi_get_bootpartition())) {
2145 printf(_("\nThe boot partition does not exist.\n"));
2147 if (!sgi_get_num_sectors(sgi_get_swappartition())) {
2148 printf(_("\nThe swap partition does not exist.\n"));
2150 if ((sgi_get_sysid(sgi_get_swappartition()) != SGI_SWAP)
2151 && (sgi_get_sysid(sgi_get_swappartition()) != LINUX_SWAP))
2152 printf(_("\nThe swap partition has no swap type.\n"));
2154 if (sgi_check_bootfile("/unix"))
2155 printf(_("\tYou have chosen an unusual boot file name.\n"));
2157 return (gap > 0) ? 1 : (gap == 0) ? 0 : -1;
2164 * returned value is:
2165 * = 0 : disk is properly filled to the rim
2166 * < 0 : there is an overlap
2167 * > 0 : there is still some vacant space
2169 return verify_sgi(0);
2173 sgi_change_sysid(int i, int sys)
2175 if( sgi_get_num_sectors(i) == 0 ) { /* caught already before, ... */
2176 printf(_("Sorry You may change the Tag of non-empty partitions.\n"));
2179 if (((sys != ENTIRE_DISK ) && (sys != SGI_VOLHDR))
2180 && (sgi_get_start_sector(i) < 1) ) {
2182 _("It is highly recommended that the partition at offset 0\n"
2183 "is of type \"SGI volhdr\", the IRIX system will rely on it to\n"
2184 "retrieve from its directory standalone tools like sash and fx.\n"
2185 "Only the \"SGI volume\" entire disk section may violate this.\n"
2186 "Type YES if you are sure about tagging this partition differently.\n"));
2187 if (strcmp(line_ptr, _("YES\n")))
2190 sgilabel->partitions[i].id = SGI_SSWAP32(sys);
2193 /* returns partition index of first entry marked as entire disk */
2199 for (i = 0; i < 16; i++)
2200 if (sgi_get_sysid(i) == SGI_VOLUME)
2206 sgi_set_partition(int i, unsigned int start, unsigned int length, int sys)
2208 sgilabel->partitions[i].id = SGI_SSWAP32(sys);
2209 sgilabel->partitions[i].num_sectors = SGI_SSWAP32(length);
2210 sgilabel->partitions[i].start_sector = SGI_SSWAP32(start);
2212 if (sgi_gaps() < 0) /* rebuild freelist */
2213 printf(_("Do You know, You got a partition overlap on the disk?\n"));
2217 sgi_set_entire(void)
2221 for (n = 10; n < partitions; n++) {
2222 if(!sgi_get_num_sectors(n) ) {
2223 sgi_set_partition(n, 0, sgi_get_lastblock(), SGI_VOLUME);
2230 sgi_set_volhdr(void)
2234 for (n = 8; n < partitions; n++) {
2235 if (!sgi_get_num_sectors(n)) {
2237 * 5 cylinders is an arbitrary value I like
2238 * IRIX 5.3 stored files in the volume header
2239 * (like sash, symmon, fx, ide) with ca. 3200
2242 if (heads * sectors * 5 < sgi_get_lastblock())
2243 sgi_set_partition(n, 0, heads * sectors * 5, SGI_VOLHDR);
2250 sgi_delete_partition(int i)
2252 sgi_set_partition(i, 0, 0, 0);
2256 sgi_add_partition(int n, int sys)
2259 unsigned int first = 0, last = 0;
2263 } else if (n == 8) {
2266 if(sgi_get_num_sectors(n)) {
2267 printf(_("Partition %d is already defined. Delete "
2268 "it before re-adding it.\n"), n + 1);
2271 if ((sgi_entire() == -1) && (sys != SGI_VOLUME)) {
2272 printf(_("Attempting to generate entire disk entry automatically.\n"));
2276 if ((sgi_gaps() == 0) && (sys != SGI_VOLUME)) {
2277 printf(_("The entire disk is already covered with partitions.\n"));
2280 if (sgi_gaps() < 0) {
2281 printf(_("You got a partition overlap on the disk. Fix it first!\n"));
2284 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
2286 if(sys == SGI_VOLUME) {
2287 last = sgi_get_lastblock();
2288 first = read_int(0, 0, last-1, 0, mesg);
2290 printf(_("It is highly recommended that eleventh partition\n"
2291 "covers the entire disk and is of type `SGI volume'\n"));
2294 first = freelist[0].first;
2295 last = freelist[0].last;
2296 first = read_int(scround(first), scround(first), scround(last)-1,
2299 if (display_in_cyl_units)
2300 first *= units_per_sector;
2302 first = first; /* align to cylinder if you know how ... */
2304 last = isinfreelist(first);
2306 printf(_("You will get a partition overlap on the disk. "
2307 "Fix it first!\n"));
2311 snprintf(mesg, sizeof(mesg), _(" Last %s"), str_units(SINGULAR));
2312 last = read_int(scround(first), scround(last)-1, scround(last)-1,
2313 scround(first), mesg)+1;
2314 if (display_in_cyl_units)
2315 last *= units_per_sector;
2317 last = last; /* align to cylinder if You know how ... */
2318 if ( (sys == SGI_VOLUME) && (first != 0 || last != sgi_get_lastblock() ) )
2319 printf(_("It is highly recommended that eleventh partition\n"
2320 "covers the entire disk and is of type `SGI volume'\n"));
2321 sgi_set_partition(n, first, last-first, sys);
2324 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
2326 create_sgilabel(void)
2328 struct hd_geometry geometry;
2335 long longsectors; /* the number of sectors on the device */
2336 int res; /* the result from the ioctl */
2337 int sec_fac; /* the sector factor */
2339 sec_fac = sector_size / 512; /* determine the sector factor */
2342 _("Building a new SGI disklabel. Changes will remain in memory only,\n"
2343 "until you decide to write them. After that, of course, the previous\n"
2344 "content will be unrecoverably lost.\n\n"));
2346 sgi_other_endian = (BYTE_ORDER == LITTLE_ENDIAN);
2347 res = ioctl(fd, BLKGETSIZE, &longsectors);
2348 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
2349 heads = geometry.heads;
2350 sectors = geometry.sectors;
2352 /* the get device size ioctl was successful */
2353 cylinders = longsectors / (heads * sectors);
2354 cylinders /= sec_fac;
2356 /* otherwise print error and use truncated version */
2357 cylinders = geometry.cylinders;
2359 _("Warning: BLKGETSIZE ioctl failed on %s. "
2360 "Using geometry cylinder value of %d.\n"
2361 "This value may be truncated for devices"
2362 " > 33.8 GB.\n"), disk_device, cylinders);
2365 for (i = 0; i < 4; i++) {
2367 if (valid_part_table_flag(MBRbuffer)) {
2368 if(get_part_table(i)->sys_ind) {
2369 old[i].sysid = get_part_table(i)->sys_ind;
2370 old[i].start = get_start_sect(get_part_table(i));
2371 old[i].nsect = get_nr_sects(get_part_table(i));
2372 printf(_("Trying to keep parameters of partition %d.\n"), i);
2374 printf(_("ID=%02x\tSTART=%d\tLENGTH=%d\n"),
2375 old[i].sysid, old[i].start, old[i].nsect);
2380 memset(MBRbuffer, 0, sizeof(MBRbuffer));
2381 sgilabel->magic = SGI_SSWAP32(SGI_LABEL_MAGIC);
2382 sgilabel->boot_part = SGI_SSWAP16(0);
2383 sgilabel->swap_part = SGI_SSWAP16(1);
2385 /* sizeof(sgilabel->boot_file) = 16 > 6 */
2386 memset(sgilabel->boot_file, 0, 16);
2387 strcpy((char*)sgilabel->boot_file, "/unix");
2389 sgilabel->devparam.skew = (0);
2390 sgilabel->devparam.gap1 = (0);
2391 sgilabel->devparam.gap2 = (0);
2392 sgilabel->devparam.sparecyl = (0);
2393 sgilabel->devparam.pcylcount = SGI_SSWAP16(geometry.cylinders);
2394 sgilabel->devparam.head_vol0 = SGI_SSWAP16(0);
2395 sgilabel->devparam.ntrks = SGI_SSWAP16(geometry.heads);
2396 /* tracks/cylinder (heads) */
2397 sgilabel->devparam.cmd_tag_queue_depth = (0);
2398 sgilabel->devparam.unused0 = (0);
2399 sgilabel->devparam.unused1 = SGI_SSWAP16(0);
2400 sgilabel->devparam.nsect = SGI_SSWAP16(geometry.sectors);
2402 sgilabel->devparam.bytes = SGI_SSWAP16(512);
2403 sgilabel->devparam.ilfact = SGI_SSWAP16(1);
2404 sgilabel->devparam.flags = SGI_SSWAP32(TRACK_FWD|
2405 IGNORE_ERRORS|RESEEK);
2406 sgilabel->devparam.datarate = SGI_SSWAP32(0);
2407 sgilabel->devparam.retries_on_error = SGI_SSWAP32(1);
2408 sgilabel->devparam.ms_per_word = SGI_SSWAP32(0);
2409 sgilabel->devparam.xylogics_gap1 = SGI_SSWAP16(0);
2410 sgilabel->devparam.xylogics_syncdelay = SGI_SSWAP16(0);
2411 sgilabel->devparam.xylogics_readdelay = SGI_SSWAP16(0);
2412 sgilabel->devparam.xylogics_gap2 = SGI_SSWAP16(0);
2413 sgilabel->devparam.xylogics_readgate = SGI_SSWAP16(0);
2414 sgilabel->devparam.xylogics_writecont = SGI_SSWAP16(0);
2415 memset( &(sgilabel->directory), 0, sizeof(struct volume_directory)*15 );
2416 memset( &(sgilabel->partitions), 0, sizeof(struct sgi_partition)*16 );
2417 current_label_type = label_sgi;
2422 for (i = 0; i < 4; i++) {
2424 sgi_set_partition(i, old[i].start, old[i].nsect, old[i].sysid);
2432 /* do nothing in the beginning */
2434 #endif /* CONFIG_FEATURE_FDISK_ADVANCED */
2436 /* _____________________________________________________________
2442 sgiinfo *info = calloc(1, sizeof(sgiinfo));
2444 info->magic = SGI_SSWAP32(SGI_INFO_MAGIC);
2445 info->b1 = SGI_SSWAP32(-1);
2446 info->b2 = SGI_SSWAP16(-1);
2447 info->b3 = SGI_SSWAP16(1);
2448 /* You may want to replace this string !!!!!!! */
2449 strcpy( (char*)info->scsi_string, "IBM OEM 0662S12 3 30" );
2450 strcpy( (char*)info->serial, "0000" );
2451 info->check1816 = SGI_SSWAP16(18*256 +16 );
2452 strcpy( (char*)info->installer, "Sfx version 5.3, Oct 18, 1994" );
2455 #endif /* SGI_LABEL */
2458 #ifdef CONFIG_FEATURE_SUN_LABEL
2462 * I think this is mostly, or entirely, due to
2463 * Jakub Jelinek (jj@sunsite.mff.cuni.cz), July 1996
2465 * Merged with fdisk for other architectures, aeb, June 1998.
2467 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
2468 * Internationalization
2472 static int sun_other_endian;
2473 static int scsi_disk;
2477 #define IDE0_MAJOR 3
2480 #define IDE1_MAJOR 22
2484 guess_device_type(void)
2486 struct stat bootstat;
2488 if (fstat(fd, &bootstat) < 0) {
2491 } else if (S_ISBLK(bootstat.st_mode)
2492 && (major(bootstat.st_rdev) == IDE0_MAJOR ||
2493 major(bootstat.st_rdev) == IDE1_MAJOR)) {
2496 } else if (S_ISBLK(bootstat.st_mode)
2497 && major(bootstat.st_rdev) == FLOPPY_MAJOR) {
2506 static const struct systypes sun_sys_types[] = {
2507 { "\x00" "Empty" }, /* 0 */
2508 { "\x01" "Boot" }, /* 1 */
2509 { "\x02" "SunOS root" }, /* 2 */
2510 { "\x03" "SunOS swap" }, /* SUNOS_SWAP */
2511 { "\x04" "SunOS usr" }, /* 4 */
2512 { "\x05" "Whole disk" }, /* WHOLE_DISK */
2513 { "\x06" "SunOS stand" }, /* 6 */
2514 { "\x07" "SunOS var" }, /* 7 */
2515 { "\x08" "SunOS home" }, /* 8 */
2516 { "\x82" "Linux swap" }, /* LINUX_SWAP */
2517 { "\x83" "Linux native" }, /* LINUX_NATIVE */
2518 { "\x8e" "Linux LVM" }, /* 0x8e */
2519 /* New (2.2.x) raid partition with autodetect using persistent superblock */
2520 { "\xfd" "Linux raid autodetect" }, /* 0xfd */
2526 set_sun_partition(int i, uint start, uint stop, int sysid)
2528 sunlabel->infos[i].id = sysid;
2529 sunlabel->partitions[i].start_cylinder =
2530 SUN_SSWAP32(start / (heads * sectors));
2531 sunlabel->partitions[i].num_sectors =
2532 SUN_SSWAP32(stop - start);
2537 check_sun_label(void)
2539 unsigned short *ush;
2542 if (sunlabel->magic != SUN_LABEL_MAGIC
2543 && sunlabel->magic != SUN_LABEL_MAGIC_SWAPPED) {
2544 current_label_type = label_dos;
2545 sun_other_endian = 0;
2548 sun_other_endian = (sunlabel->magic == SUN_LABEL_MAGIC_SWAPPED);
2549 ush = ((unsigned short *) (sunlabel + 1)) - 1;
2550 for (csum = 0; ush >= (unsigned short *)sunlabel;) csum ^= *ush--;
2552 fprintf(stderr,_("Detected sun disklabel with wrong checksum.\n"
2553 "Probably you'll have to set all the values,\n"
2554 "e.g. heads, sectors, cylinders and partitions\n"
2555 "or force a fresh label (s command in main menu)\n"));
2557 heads = SUN_SSWAP16(sunlabel->ntrks);
2558 cylinders = SUN_SSWAP16(sunlabel->ncyl);
2559 sectors = SUN_SSWAP16(sunlabel->nsect);
2562 current_label_type = label_sun;
2567 static const struct sun_predefined_drives {
2570 unsigned short sparecyl;
2571 unsigned short ncyl;
2572 unsigned short nacyl;
2573 unsigned short pcylcount;
2574 unsigned short ntrks;
2575 unsigned short nsect;
2576 unsigned short rspeed;
2578 { "Quantum","ProDrive 80S",1,832,2,834,6,34,3662},
2579 { "Quantum","ProDrive 105S",1,974,2,1019,6,35,3662},
2580 { "CDC","Wren IV 94171-344",3,1545,2,1549,9,46,3600},
2581 { "IBM","DPES-31080",0,4901,2,4903,4,108,5400},
2582 { "IBM","DORS-32160",0,1015,2,1017,67,62,5400},
2583 { "IBM","DNES-318350",0,11199,2,11474,10,320,7200},
2584 { "SEAGATE","ST34371",0,3880,2,3882,16,135,7228},
2585 { "","SUN0104",1,974,2,1019,6,35,3662},
2586 { "","SUN0207",4,1254,2,1272,9,36,3600},
2587 { "","SUN0327",3,1545,2,1549,9,46,3600},
2588 { "","SUN0340",0,1538,2,1544,6,72,4200},
2589 { "","SUN0424",2,1151,2,2500,9,80,4400},
2590 { "","SUN0535",0,1866,2,2500,7,80,5400},
2591 { "","SUN0669",5,1614,2,1632,15,54,3600},
2592 { "","SUN1.0G",5,1703,2,1931,15,80,3597},
2593 { "","SUN1.05",0,2036,2,2038,14,72,5400},
2594 { "","SUN1.3G",6,1965,2,3500,17,80,5400},
2595 { "","SUN2.1G",0,2733,2,3500,19,80,5400},
2596 { "IOMEGA","Jaz",0,1019,2,1021,64,32,5394},
2599 static const struct sun_predefined_drives *
2600 sun_autoconfigure_scsi(void)
2602 const struct sun_predefined_drives *p = NULL;
2604 #ifdef SCSI_IOCTL_GET_IDLUN
2614 if (!ioctl(fd, SCSI_IOCTL_GET_IDLUN, &id)) {
2616 "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n",
2618 ((id[0]>>24)&0xff)-/*PROC_SCSI_SCSI+PROC_SCSI_FILE*/33,
2620 /* This is very wrong (works only if you have one HBA),
2621 but I haven't found a way how to get hostno
2622 from the current kernel */
2629 pfd = fopen("/proc/scsi/scsi","r");
2631 while (fgets(buffer2, 2048, pfd)) {
2632 if (!strcmp(buffer, buffer2)) {
2633 if (fgets(buffer2,2048,pfd)) {
2634 q = strstr(buffer2,"Vendor: ");
2639 *q++ = 0; /* truncate vendor name */
2640 q = strstr(q,"Model: ");
2645 q = strstr(q," Rev: ");
2648 for (i = 0; i < SIZE(sun_drives); i++) {
2649 if (*sun_drives[i].vendor && strcasecmp(sun_drives[i].vendor, vendor))
2651 if (!strstr(model, sun_drives[i].model))
2653 printf(_("Autoconfigure found a %s%s%s\n"),sun_drives[i].vendor,(*sun_drives[i].vendor) ? " " : "",sun_drives[i].model);
2672 create_sunlabel(void)
2674 struct hd_geometry geometry;
2678 const struct sun_predefined_drives *p = NULL;
2681 _("Building a new sun disklabel. Changes will remain in memory only,\n"
2682 "until you decide to write them. After that, of course, the previous\n"
2683 "content won't be recoverable.\n\n"));
2684 #if BYTE_ORDER == LITTLE_ENDIAN
2685 sun_other_endian = 1;
2687 sun_other_endian = 0;
2689 memset(MBRbuffer, 0, sizeof(MBRbuffer));
2690 sunlabel->magic = SUN_SSWAP16(SUN_LABEL_MAGIC);
2692 puts(_("Drive type\n"
2693 " ? auto configure\n"
2694 " 0 custom (with hardware detected defaults)"));
2695 for (i = 0; i < SIZE(sun_drives); i++) {
2696 printf(" %c %s%s%s\n",
2697 i + 'a', sun_drives[i].vendor,
2698 (*sun_drives[i].vendor) ? " " : "",
2699 sun_drives[i].model);
2702 c = read_char(_("Select type (? for auto, 0 for custom): "));
2703 if (c >= 'a' && c < 'a' + SIZE(sun_drives)) {
2704 p = sun_drives + c - 'a';
2706 } else if (c >= 'A' && c < 'A' + SIZE(sun_drives)) {
2707 p = sun_drives + c - 'A';
2709 } else if (c == '0') {
2711 } else if (c == '?' && scsi_disk) {
2712 p = sun_autoconfigure_scsi();
2714 printf(_("Autoconfigure failed.\n"));
2721 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
2722 heads = geometry.heads;
2723 sectors = geometry.sectors;
2724 cylinders = geometry.cylinders;
2731 sunlabel->nacyl = 0;
2732 sunlabel->pcylcount = SUN_SSWAP16(cylinders);
2733 sunlabel->rspeed = SUN_SSWAP16(300);
2734 sunlabel->ilfact = SUN_SSWAP16(1);
2735 sunlabel->sparecyl = 0;
2737 heads = read_int(1,heads,1024,0,_("Heads"));
2738 sectors = read_int(1,sectors,1024,0,_("Sectors/track"));
2740 cylinders = read_int(1,cylinders-2,65535,0,_("Cylinders"));
2742 cylinders = read_int(1,0,65535,0,_("Cylinders"));
2743 sunlabel->nacyl = SUN_SSWAP16(read_int(0,2,65535,0, _("Alternate cylinders")));
2744 sunlabel->pcylcount = SUN_SSWAP16(read_int(0,cylinders+SUN_SSWAP16(sunlabel->nacyl), 65535,0, _("Physical cylinders")));
2745 sunlabel->rspeed = SUN_SSWAP16(read_int(1,5400,100000,0, _("Rotation speed (rpm)")));
2746 sunlabel->ilfact = SUN_SSWAP16(read_int(1,1,32,0, _("Interleave factor")));
2747 sunlabel->sparecyl = SUN_SSWAP16(read_int(0,0,sectors,0, _("Extra sectors per cylinder")));
2750 sunlabel->sparecyl = SUN_SSWAP16(p->sparecyl);
2751 sunlabel->ncyl = SUN_SSWAP16(p->ncyl);
2752 sunlabel->nacyl = SUN_SSWAP16(p->nacyl);
2753 sunlabel->pcylcount = SUN_SSWAP16(p->pcylcount);
2754 sunlabel->ntrks = SUN_SSWAP16(p->ntrks);
2755 sunlabel->nsect = SUN_SSWAP16(p->nsect);
2756 sunlabel->rspeed = SUN_SSWAP16(p->rspeed);
2757 sunlabel->ilfact = SUN_SSWAP16(1);
2758 cylinders = p->ncyl;
2761 puts(_("You may change all the disk params from the x menu"));
2764 snprintf((char *)(sunlabel->info), sizeof(sunlabel->info),
2765 "%s%s%s cyl %d alt %d hd %d sec %d",
2766 p ? p->vendor : "", (p && *p->vendor) ? " " : "",
2767 p ? p->model : (floppy ? _("3,5\" floppy") : _("Linux custom")),
2768 cylinders, SUN_SSWAP16(sunlabel->nacyl), heads, sectors);
2770 sunlabel->ntrks = SUN_SSWAP16(heads);
2771 sunlabel->nsect = SUN_SSWAP16(sectors);
2772 sunlabel->ncyl = SUN_SSWAP16(cylinders);
2774 set_sun_partition(0, 0, cylinders * heads * sectors, LINUX_NATIVE);
2776 if (cylinders * heads * sectors >= 150 * 2048) {
2777 ndiv = cylinders - (50 * 2048 / (heads * sectors)); /* 50M swap */
2779 ndiv = cylinders * 2 / 3;
2780 set_sun_partition(0, 0, ndiv * heads * sectors, LINUX_NATIVE);
2781 set_sun_partition(1, ndiv * heads * sectors, cylinders * heads * sectors, LINUX_SWAP);
2782 sunlabel->infos[1].flags |= 0x01; /* Not mountable */
2784 set_sun_partition(2, 0, cylinders * heads * sectors, WHOLE_DISK);
2786 unsigned short *ush = (unsigned short *)sunlabel;
2787 unsigned short csum = 0;
2788 while (ush < (unsigned short *)(&sunlabel->csum))
2790 sunlabel->csum = csum;
2793 set_all_unchanged();
2795 get_boot(create_empty_sun);
2799 toggle_sunflags(int i, unsigned char mask)
2801 if (sunlabel->infos[i].flags & mask)
2802 sunlabel->infos[i].flags &= ~mask;
2804 sunlabel->infos[i].flags |= mask;
2809 fetch_sun(uint *starts, uint *lens, uint *start, uint *stop)
2811 int i, continuous = 1;
2814 *stop = cylinders * heads * sectors;
2815 for (i = 0; i < partitions; i++) {
2816 if (sunlabel->partitions[i].num_sectors
2817 && sunlabel->infos[i].id
2818 && sunlabel->infos[i].id != WHOLE_DISK) {
2819 starts[i] = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
2820 lens[i] = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
2822 if (starts[i] == *start)
2824 else if (starts[i] + lens[i] >= *stop)
2828 /* There will be probably more gaps
2829 than one, so lets check afterwards */
2838 static uint *verify_sun_starts;
2841 verify_sun_cmp(int *a, int *b)
2843 if (*a == -1) return 1;
2844 if (*b == -1) return -1;
2845 if (verify_sun_starts[*a] > verify_sun_starts[*b]) return 1;
2852 uint starts[8], lens[8], start, stop;
2853 int i,j,k,starto,endo;
2856 verify_sun_starts = starts;
2857 fetch_sun(starts,lens,&start,&stop);
2858 for (k = 0; k < 7; k++) {
2859 for (i = 0; i < 8; i++) {
2860 if (k && (lens[i] % (heads * sectors))) {
2861 printf(_("Partition %d doesn't end on cylinder boundary\n"), i+1);
2864 for (j = 0; j < i; j++)
2866 if (starts[j] == starts[i]+lens[i]) {
2867 starts[j] = starts[i]; lens[j] += lens[i];
2869 } else if (starts[i] == starts[j]+lens[j]){
2873 if (starts[i] < starts[j]+lens[j]
2874 && starts[j] < starts[i]+lens[i]) {
2876 if (starts[j] > starto)
2878 endo = starts[i]+lens[i];
2879 if (starts[j]+lens[j] < endo)
2880 endo = starts[j]+lens[j];
2881 printf(_("Partition %d overlaps with others in "
2882 "sectors %d-%d\n"), i+1, starto, endo);
2889 for (i = 0; i < 8; i++) {
2895 qsort(array,SIZE(array),sizeof(array[0]),
2896 (int (*)(const void *,const void *)) verify_sun_cmp);
2897 if (array[0] == -1) {
2898 printf(_("No partitions defined\n"));
2901 stop = cylinders * heads * sectors;
2902 if (starts[array[0]])
2903 printf(_("Unused gap - sectors 0-%d\n"),starts[array[0]]);
2904 for (i = 0; i < 7 && array[i+1] != -1; i++) {
2905 printf(_("Unused gap - sectors %d-%d\n"),starts[array[i]]+lens[array[i]],starts[array[i+1]]);
2907 start = starts[array[i]] + lens[array[i]];
2909 printf(_("Unused gap - sectors %d-%d\n"),start,stop);
2913 add_sun_partition(int n, int sys)
2915 uint start, stop, stop2;
2916 uint starts[8], lens[8];
2922 if (sunlabel->partitions[n].num_sectors && sunlabel->infos[n].id) {
2923 printf(_("Partition %d is already defined. Delete "
2924 "it before re-adding it.\n"), n + 1);
2928 fetch_sun(starts,lens,&start,&stop);
2929 if (stop <= start) {
2933 printf(_("Other partitions already cover the whole disk.\nDelete "
2934 "some/shrink them before retry.\n"));
2938 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
2941 first = read_int(0, 0, 0, 0, mesg);
2943 first = read_int(scround(start), scround(stop)+1,
2944 scround(stop), 0, mesg);
2945 if (display_in_cyl_units)
2946 first *= units_per_sector;
2948 /* Starting sector has to be properly aligned */
2949 first = (first + heads * sectors - 1) / (heads * sectors);
2950 if (n == 2 && first != 0)
2952 It is highly recommended that the third partition covers the whole disk\n\
2953 and is of type `Whole disk'\n");
2954 /* ewt asks to add: "don't start a partition at cyl 0"
2955 However, edmundo@rano.demon.co.uk writes:
2956 "In addition to having a Sun partition table, to be able to
2957 boot from the disc, the first partition, /dev/sdX1, must
2958 start at cylinder 0. This means that /dev/sdX1 contains
2959 the partition table and the boot block, as these are the
2960 first two sectors of the disc. Therefore you must be
2961 careful what you use /dev/sdX1 for. In particular, you must
2962 not use a partition starting at cylinder 0 for Linux swap,
2963 as that would overwrite the partition table and the boot
2964 block. You may, however, use such a partition for a UFS
2965 or EXT2 file system, as these file systems leave the first
2966 1024 bytes undisturbed. */
2967 /* On the other hand, one should not use partitions
2968 starting at block 0 in an md, or the label will
2970 for (i = 0; i < partitions; i++)
2971 if (lens[i] && starts[i] <= first && starts[i] + lens[i] > first)
2973 if (i < partitions && !whole_disk) {
2974 if (n == 2 && !first) {
2978 printf(_("Sector %d is already allocated\n"), first);
2982 stop = cylinders * heads * sectors;
2984 for (i = 0; i < partitions; i++) {
2985 if (starts[i] > first && starts[i] < stop)
2988 snprintf(mesg, sizeof(mesg),
2989 _("Last %s or +size or +sizeM or +sizeK"),
2990 str_units(SINGULAR));
2992 last = read_int(scround(stop2), scround(stop2), scround(stop2),
2994 else if (n == 2 && !first)
2995 last = read_int(scround(first), scround(stop2), scround(stop2),
2996 scround(first), mesg);
2998 last = read_int(scround(first), scround(stop), scround(stop),
2999 scround(first), mesg);
3000 if (display_in_cyl_units)
3001 last *= units_per_sector;
3002 if (n == 2 && !first) {
3003 if (last >= stop2) {
3006 } else if (last > stop) {
3007 printf(_("You haven't covered the whole disk with "
3008 "the 3rd partition, but your value\n"
3009 "%d %s covers some other partition. "
3010 "Your entry has been changed\n"
3012 scround(last), str_units(SINGULAR),
3013 scround(stop), str_units(SINGULAR));
3016 } else if (!whole_disk && last > stop)
3021 set_sun_partition(n, first, last, sys);
3025 sun_delete_partition(int i)
3030 && sunlabel->infos[i].id == WHOLE_DISK
3031 && !sunlabel->partitions[i].start_cylinder
3032 && (nsec = SUN_SSWAP32(sunlabel->partitions[i].num_sectors)) == heads * sectors * cylinders)
3033 printf(_("If you want to maintain SunOS/Solaris compatibility, "
3034 "consider leaving this\n"
3035 "partition as Whole disk (5), starting at 0, with %u "
3036 "sectors\n"), nsec);
3037 sunlabel->infos[i].id = 0;
3038 sunlabel->partitions[i].num_sectors = 0;
3042 sun_change_sysid(int i, int sys)
3044 if (sys == LINUX_SWAP && !sunlabel->partitions[i].start_cylinder) {
3046 _("It is highly recommended that the partition at offset 0\n"
3047 "is UFS, EXT2FS filesystem or SunOS swap. Putting Linux swap\n"
3048 "there may destroy your partition table and bootblock.\n"
3049 "Type YES if you're very sure you would like that partition\n"
3050 "tagged with 82 (Linux swap): "));
3051 if (strcmp (line_ptr, _("YES\n")))
3057 /* swaps are not mountable by default */
3058 sunlabel->infos[i].flags |= 0x01;
3061 /* assume other types are mountable;
3062 user can change it anyway */
3063 sunlabel->infos[i].flags &= ~0x01;
3066 sunlabel->infos[i].id = sys;
3070 sun_list_table(int xtra)
3074 w = strlen(disk_device);
3077 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d rpm\n"
3078 "%d cylinders, %d alternate cylinders, %d physical cylinders\n"
3079 "%d extra sects/cyl, interleave %d:1\n"
3081 "Units = %s of %d * 512 bytes\n\n"),
3082 disk_device, heads, sectors, SUN_SSWAP16(sunlabel->rspeed),
3083 cylinders, SUN_SSWAP16(sunlabel->nacyl),
3084 SUN_SSWAP16(sunlabel->pcylcount),
3085 SUN_SSWAP16(sunlabel->sparecyl),
3086 SUN_SSWAP16(sunlabel->ilfact),
3088 str_units(PLURAL), units_per_sector);
3091 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d cylinders\n"
3092 "Units = %s of %d * 512 bytes\n\n"),
3093 disk_device, heads, sectors, cylinders,
3094 str_units(PLURAL), units_per_sector);
3096 printf(_("%*s Flag Start End Blocks Id System\n"),
3097 w + 1, _("Device"));
3098 for (i = 0 ; i < partitions; i++) {
3099 if (sunlabel->partitions[i].num_sectors) {
3100 uint32_t start = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
3101 uint32_t len = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
3102 printf("%s %c%c %9ld %9ld %9ld%c %2x %s\n",
3103 partname(disk_device, i+1, w), /* device */
3104 (sunlabel->infos[i].flags & 0x01) ? 'u' : ' ', /* flags */
3105 (sunlabel->infos[i].flags & 0x10) ? 'r' : ' ',
3106 (long) scround(start), /* start */
3107 (long) scround(start+len), /* end */
3108 (long) len / 2, len & 1 ? '+' : ' ', /* odd flag on end */
3109 sunlabel->infos[i].id, /* type id */
3110 partition_type(sunlabel->infos[i].id)); /* type name */
3115 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3118 sun_set_alt_cyl(void)
3121 SUN_SSWAP16(read_int(0,SUN_SSWAP16(sunlabel->nacyl), 65535, 0,
3122 _("Number of alternate cylinders")));
3126 sun_set_ncyl(int cyl)
3128 sunlabel->ncyl = SUN_SSWAP16(cyl);
3134 sunlabel->sparecyl =
3135 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->sparecyl), sectors, 0,
3136 _("Extra sectors per cylinder")));
3140 sun_set_ilfact(void)
3143 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->ilfact), 32, 0,
3144 _("Interleave factor")));
3148 sun_set_rspeed(void)
3151 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->rspeed), 100000, 0,
3152 _("Rotation speed (rpm)")));
3156 sun_set_pcylcount(void)
3158 sunlabel->pcylcount =
3159 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->pcylcount), 65535, 0,
3160 _("Number of physical cylinders")));
3162 #endif /* CONFIG_FEATURE_FDISK_ADVANCED */
3165 sun_write_table(void)
3167 unsigned short *ush = (unsigned short *)sunlabel;
3168 unsigned short csum = 0;
3170 while (ush < (unsigned short *)(&sunlabel->csum))
3172 sunlabel->csum = csum;
3173 if (lseek(fd, 0, SEEK_SET) < 0)
3174 fdisk_fatal(unable_to_seek);
3175 if (write(fd, sunlabel, SECTOR_SIZE) != SECTOR_SIZE)
3176 fdisk_fatal(unable_to_write);
3178 #endif /* SUN_LABEL */
3180 /* DOS partition types */
3182 static const struct systypes i386_sys_types[] = {
3185 { "\x04" "FAT16 <32M" },
3186 { "\x05" "Extended" }, /* DOS 3.3+ extended partition */
3187 { "\x06" "FAT16" }, /* DOS 16-bit >=32M */
3188 { "\x07" "HPFS/NTFS" }, /* OS/2 IFS, eg, HPFS or NTFS or QNX */
3189 { "\x0a" "OS/2 Boot Manager" },/* OS/2 Boot Manager */
3190 { "\x0b" "Win95 FAT32" },
3191 { "\x0c" "Win95 FAT32 (LBA)" },/* LBA really is `Extended Int 13h' */
3192 { "\x0e" "Win95 FAT16 (LBA)" },
3193 { "\x0f" "Win95 Ext'd (LBA)" },
3194 { "\x11" "Hidden FAT12" },
3195 { "\x12" "Compaq diagnostics" },
3196 { "\x14" "Hidden FAT16 <32M" },
3197 { "\x16" "Hidden FAT16" },
3198 { "\x17" "Hidden HPFS/NTFS" },
3199 { "\x1b" "Hidden Win95 FAT32" },
3200 { "\x1c" "Hidden Win95 FAT32 (LBA)" },
3201 { "\x1e" "Hidden Win95 FAT16 (LBA)" },
3202 { "\x3c" "PartitionMagic recovery" },
3203 { "\x41" "PPC PReP Boot" },
3205 { "\x63" "GNU HURD or SysV" }, /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */
3206 { "\x80" "Old Minix" }, /* Minix 1.4a and earlier */
3207 { "\x81" "Minix / old Linux" },/* Minix 1.4b and later */
3208 { "\x82" "Linux swap" }, /* also Solaris */
3210 { "\x84" "OS/2 hidden C: drive" },
3211 { "\x85" "Linux extended" },
3212 { "\x86" "NTFS volume set" },
3213 { "\x87" "NTFS volume set" },
3214 { "\x8e" "Linux LVM" },
3215 { "\x9f" "BSD/OS" }, /* BSDI */
3216 { "\xa0" "IBM Thinkpad hibernation" },
3217 { "\xa5" "FreeBSD" }, /* various BSD flavours */
3218 { "\xa6" "OpenBSD" },
3219 { "\xa8" "Darwin UFS" },
3220 { "\xa9" "NetBSD" },
3221 { "\xab" "Darwin boot" },
3222 { "\xb7" "BSDI fs" },
3223 { "\xb8" "BSDI swap" },
3224 { "\xbe" "Solaris boot" },
3225 { "\xeb" "BeOS fs" },
3226 { "\xee" "EFI GPT" }, /* Intel EFI GUID Partition Table */
3227 { "\xef" "EFI (FAT-12/16/32)" },/* Intel EFI System Partition */
3228 { "\xf0" "Linux/PA-RISC boot" },/* Linux/PA-RISC boot loader */
3229 { "\xf2" "DOS secondary" }, /* DOS 3.3+ secondary */
3230 { "\xfd" "Linux raid autodetect" },/* New (2.2.x) raid partition with
3231 autodetect using persistent
3233 #ifdef CONFIG_WEIRD_PARTITION_TYPES
3234 { "\x02" "XENIX root" },
3235 { "\x03" "XENIX usr" },
3236 { "\x08" "AIX" }, /* AIX boot (AIX -- PS/2 port) or SplitDrive */
3237 { "\x09" "AIX bootable" }, /* AIX data or Coherent */
3239 { "\x18" "AST SmartSleep" },
3240 { "\x24" "NEC DOS" },
3241 { "\x39" "Plan 9" },
3242 { "\x40" "Venix 80286" },
3243 { "\x4d" "QNX4.x" },
3244 { "\x4e" "QNX4.x 2nd part" },
3245 { "\x4f" "QNX4.x 3rd part" },
3246 { "\x50" "OnTrack DM" },
3247 { "\x51" "OnTrack DM6 Aux1" }, /* (or Novell) */
3248 { "\x52" "CP/M" }, /* CP/M or Microport SysV/AT */
3249 { "\x53" "OnTrack DM6 Aux3" },
3250 { "\x54" "OnTrackDM6" },
3251 { "\x55" "EZ-Drive" },
3252 { "\x56" "Golden Bow" },
3253 { "\x5c" "Priam Edisk" },
3254 { "\x61" "SpeedStor" },
3255 { "\x64" "Novell Netware 286" },
3256 { "\x65" "Novell Netware 386" },
3257 { "\x70" "DiskSecure Multi-Boot" },
3259 { "\x93" "Amoeba" },
3260 { "\x94" "Amoeba BBT" }, /* (bad block table) */
3261 { "\xa7" "NeXTSTEP" },
3262 { "\xbb" "Boot Wizard hidden" },
3263 { "\xc1" "DRDOS/sec (FAT-12)" },
3264 { "\xc4" "DRDOS/sec (FAT-16 < 32M)" },
3265 { "\xc6" "DRDOS/sec (FAT-16)" },
3266 { "\xc7" "Syrinx" },
3267 { "\xda" "Non-FS data" },
3268 { "\xdb" "CP/M / CTOS / ..." },/* CP/M or Concurrent CP/M or
3269 Concurrent DOS or CTOS */
3270 { "\xde" "Dell Utility" }, /* Dell PowerEdge Server utilities */
3271 { "\xdf" "BootIt" }, /* BootIt EMBRM */
3272 { "\xe1" "DOS access" }, /* DOS access or SpeedStor 12-bit FAT
3273 extended partition */
3274 { "\xe3" "DOS R/O" }, /* DOS R/O or SpeedStor */
3275 { "\xe4" "SpeedStor" }, /* SpeedStor 16-bit FAT extended
3276 partition < 1024 cyl. */
3277 { "\xf1" "SpeedStor" },
3278 { "\xf4" "SpeedStor" }, /* SpeedStor large partition */
3279 { "\xfe" "LANstep" }, /* SpeedStor >1024 cyl. or LANstep */
3280 { "\xff" "BBT" }, /* Xenix Bad Block Table */
3287 /* A valid partition table sector ends in 0x55 0xaa */
3289 part_table_flag(const char *b)
3291 return ((uint) b[510]) + (((uint) b[511]) << 8);
3295 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3297 write_part_table_flag(char *b)
3303 /* start_sect and nr_sects are stored little endian on all machines */
3304 /* moreover, they are not aligned correctly */
3306 store4_little_endian(unsigned char *cp, unsigned int val)
3308 cp[0] = (val & 0xff);
3309 cp[1] = ((val >> 8) & 0xff);
3310 cp[2] = ((val >> 16) & 0xff);
3311 cp[3] = ((val >> 24) & 0xff);
3313 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3316 read4_little_endian(const unsigned char *cp)
3318 return (uint)(cp[0]) + ((uint)(cp[1]) << 8)
3319 + ((uint)(cp[2]) << 16) + ((uint)(cp[3]) << 24);
3322 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3324 set_start_sect(struct partition *p, unsigned int start_sect)
3326 store4_little_endian(p->start4, start_sect);
3331 get_start_sect(const struct partition *p)
3333 return read4_little_endian(p->start4);
3336 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3338 set_nr_sects(struct partition *p, int32_t nr_sects)
3340 store4_little_endian(p->size4, nr_sects);
3345 get_nr_sects(const struct partition *p)
3347 return read4_little_endian(p->size4);
3350 /* normally O_RDWR, -l option gives O_RDONLY */
3351 static int type_open = O_RDWR;
3354 static int ext_index; /* the prime extended partition */
3355 static int listing; /* no aborts for fdisk -l */
3356 static int dos_compatible_flag = ~0;
3357 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3358 static int dos_changed;
3359 static int nowarn; /* no warnings for fdisk -l/-s */
3364 static uint user_cylinders, user_heads, user_sectors;
3365 static uint pt_heads, pt_sectors;
3366 static uint kern_heads, kern_sectors;
3368 static off_t extended_offset; /* offset of link pointers */
3370 static unsigned long long total_number_of_sectors;
3373 static jmp_buf listingbuf;
3375 static void fdisk_fatal(enum failure why)
3377 const char *message;
3381 longjmp(listingbuf, 1);
3385 case unable_to_open:
3386 message = "Unable to open %s\n";
3388 case unable_to_read:
3389 message = "Unable to read %s\n";
3391 case unable_to_seek:
3392 message = "Unable to seek on %s\n";
3394 case unable_to_write:
3395 message = "Unable to write %s\n";
3398 message = "BLKGETSIZE ioctl failed on %s\n";
3401 message = "Fatal error\n";
3404 fputc('\n', stderr);
3405 fprintf(stderr, message, disk_device);
3410 seek_sector(off_t secno)
3412 off_t offset = secno * sector_size;
3413 if (lseek(fd, offset, SEEK_SET) == (off_t) -1)
3414 fdisk_fatal(unable_to_seek);
3417 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3419 write_sector(off_t secno, char *buf)
3422 if (write(fd, buf, sector_size) != sector_size)
3423 fdisk_fatal(unable_to_write);
3427 /* Allocate a buffer and read a partition table sector */
3429 read_pte(struct pte *pe, off_t offset)
3431 pe->offset = offset;
3432 pe->sectorbuffer = (char *) xmalloc(sector_size);
3433 seek_sector(offset);
3434 if (read(fd, pe->sectorbuffer, sector_size) != sector_size)
3435 fdisk_fatal(unable_to_read);
3436 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3439 pe->part_table = pe->ext_pointer = NULL;
3443 get_partition_start(const struct pte *pe)
3445 return pe->offset + get_start_sect(pe->part_table);
3448 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3450 * Avoid warning about DOS partitions when no DOS partition was changed.
3451 * Here a heuristic "is probably dos partition".
3452 * We might also do the opposite and warn in all cases except
3453 * for "is probably nondos partition".
3456 is_dos_partition(int t)
3458 return (t == 1 || t == 4 || t == 6 ||
3459 t == 0x0b || t == 0x0c || t == 0x0e ||
3460 t == 0x11 || t == 0x12 || t == 0x14 || t == 0x16 ||
3461 t == 0x1b || t == 0x1c || t == 0x1e || t == 0x24 ||
3462 t == 0xc1 || t == 0xc4 || t == 0xc6);
3468 #ifdef CONFIG_FEATURE_SUN_LABEL
3469 if (label_sun == current_label_type) {
3470 puts(_("Command action"));
3471 puts(_("\ta\ttoggle a read only flag")); /* sun */
3472 puts(_("\tb\tedit bsd disklabel"));
3473 puts(_("\tc\ttoggle the mountable flag")); /* sun */
3474 puts(_("\td\tdelete a partition"));
3475 puts(_("\tl\tlist known partition types"));
3476 puts(_("\tm\tprint this menu"));
3477 puts(_("\tn\tadd a new partition"));
3478 puts(_("\to\tcreate a new empty DOS partition table"));
3479 puts(_("\tp\tprint the partition table"));
3480 puts(_("\tq\tquit without saving changes"));
3481 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3482 puts(_("\tt\tchange a partition's system id"));
3483 puts(_("\tu\tchange display/entry units"));
3484 puts(_("\tv\tverify the partition table"));
3485 puts(_("\tw\twrite table to disk and exit"));
3486 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3487 puts(_("\tx\textra functionality (experts only)"));
3491 #ifdef CONFIG_FEATURE_SGI_LABEL
3492 if (label_sgi == current_label_type) {
3493 puts(_("Command action"));
3494 puts(_("\ta\tselect bootable partition")); /* sgi flavour */
3495 puts(_("\tb\tedit bootfile entry")); /* sgi */
3496 puts(_("\tc\tselect sgi swap partition")); /* sgi flavour */
3497 puts(_("\td\tdelete a partition"));
3498 puts(_("\tl\tlist known partition types"));
3499 puts(_("\tm\tprint this menu"));
3500 puts(_("\tn\tadd a new partition"));
3501 puts(_("\to\tcreate a new empty DOS partition table"));
3502 puts(_("\tp\tprint the partition table"));
3503 puts(_("\tq\tquit without saving changes"));
3504 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3505 puts(_("\tt\tchange a partition's system id"));
3506 puts(_("\tu\tchange display/entry units"));
3507 puts(_("\tv\tverify the partition table"));
3508 puts(_("\tw\twrite table to disk and exit"));
3511 #ifdef CONFIG_FEATURE_AIX_LABEL
3512 if (label_aix == current_label_type) {
3513 puts(_("Command action"));
3514 puts(_("\tm\tprint this menu"));
3515 puts(_("\to\tcreate a new empty DOS partition table"));
3516 puts(_("\tq\tquit without saving changes"));
3517 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3521 puts(_("Command action"));
3522 puts(_("\ta\ttoggle a bootable flag"));
3523 puts(_("\tb\tedit bsd disklabel"));
3524 puts(_("\tc\ttoggle the dos compatibility flag"));
3525 puts(_("\td\tdelete a partition"));
3526 puts(_("\tl\tlist known partition types"));
3527 puts(_("\tm\tprint this menu"));
3528 puts(_("\tn\tadd a new partition"));
3529 puts(_("\to\tcreate a new empty DOS partition table"));
3530 puts(_("\tp\tprint the partition table"));
3531 puts(_("\tq\tquit without saving changes"));
3532 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3533 puts(_("\tt\tchange a partition's system id"));
3534 puts(_("\tu\tchange display/entry units"));
3535 puts(_("\tv\tverify the partition table"));
3536 puts(_("\tw\twrite table to disk and exit"));
3537 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3538 puts(_("\tx\textra functionality (experts only)"));
3542 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3545 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3549 #ifdef CONFIG_FEATURE_SUN_LABEL
3550 if (label_sun == current_label_type) {
3551 puts(_("Command action"));
3552 puts(_("\ta\tchange number of alternate cylinders")); /*sun*/
3553 puts(_("\tc\tchange number of cylinders"));
3554 puts(_("\td\tprint the raw data in the partition table"));
3555 puts(_("\te\tchange number of extra sectors per cylinder"));/*sun*/
3556 puts(_("\th\tchange number of heads"));
3557 puts(_("\ti\tchange interleave factor")); /*sun*/
3558 puts(_("\to\tchange rotation speed (rpm)")); /*sun*/
3559 puts(_("\tm\tprint this menu"));
3560 puts(_("\tp\tprint the partition table"));
3561 puts(_("\tq\tquit without saving changes"));
3562 puts(_("\tr\treturn to main menu"));
3563 puts(_("\ts\tchange number of sectors/track"));
3564 puts(_("\tv\tverify the partition table"));
3565 puts(_("\tw\twrite table to disk and exit"));
3566 puts(_("\ty\tchange number of physical cylinders")); /*sun*/
3569 #ifdef CONFIG_FEATURE_SGI_LABEL
3570 if (label_sgi == current_label_type) {
3571 puts(_("Command action"));
3572 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3573 puts(_("\tc\tchange number of cylinders"));
3574 puts(_("\td\tprint the raw data in the partition table"));
3575 puts(_("\te\tlist extended partitions")); /* !sun */
3576 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3577 puts(_("\th\tchange number of heads"));
3578 puts(_("\tm\tprint this menu"));
3579 puts(_("\tp\tprint the partition table"));
3580 puts(_("\tq\tquit without saving changes"));
3581 puts(_("\tr\treturn to main menu"));
3582 puts(_("\ts\tchange number of sectors/track"));
3583 puts(_("\tv\tverify the partition table"));
3584 puts(_("\tw\twrite table to disk and exit"));
3587 #ifdef CONFIG_FEATURE_AIX_LABEL
3588 if (label_aix == current_label_type) {
3589 puts(_("Command action"));
3590 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3591 puts(_("\tc\tchange number of cylinders"));
3592 puts(_("\td\tprint the raw data in the partition table"));
3593 puts(_("\te\tlist extended partitions")); /* !sun */
3594 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3595 puts(_("\th\tchange number of heads"));
3596 puts(_("\tm\tprint this menu"));
3597 puts(_("\tp\tprint the partition table"));
3598 puts(_("\tq\tquit without saving changes"));
3599 puts(_("\tr\treturn to main menu"));
3600 puts(_("\ts\tchange number of sectors/track"));
3601 puts(_("\tv\tverify the partition table"));
3602 puts(_("\tw\twrite table to disk and exit"));
3606 puts(_("Command action"));
3607 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3608 puts(_("\tc\tchange number of cylinders"));
3609 puts(_("\td\tprint the raw data in the partition table"));
3610 puts(_("\te\tlist extended partitions")); /* !sun */
3611 puts(_("\tf\tfix partition order")); /* !sun, !aix, !sgi */
3612 #ifdef CONFIG_FEATURE_SGI_LABEL
3613 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3615 puts(_("\th\tchange number of heads"));
3616 puts(_("\tm\tprint this menu"));
3617 puts(_("\tp\tprint the partition table"));
3618 puts(_("\tq\tquit without saving changes"));
3619 puts(_("\tr\treturn to main menu"));
3620 puts(_("\ts\tchange number of sectors/track"));
3621 puts(_("\tv\tverify the partition table"));
3622 puts(_("\tw\twrite table to disk and exit"));
3625 #endif /* ADVANCED mode */
3627 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3628 static const struct systypes *
3632 #ifdef CONFIG_FEATURE_SUN_LABEL
3633 label_sun == current_label_type ? sun_sys_types :
3635 #ifdef CONFIG_FEATURE_SGI_LABEL
3636 label_sgi == current_label_type ? sgi_sys_types :
3641 #define get_sys_types() i386_sys_types
3642 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3644 static const char *partition_type(unsigned char type)
3647 const struct systypes *types = get_sys_types();
3649 for (i = 0; types[i].name; i++)
3650 if ((unsigned char )types[i].name[0] == type)
3651 return types[i].name + 1;
3653 return _("Unknown");
3657 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3662 #ifdef CONFIG_FEATURE_SUN_LABEL
3663 label_sun == current_label_type ? sunlabel->infos[i].id :
3665 #ifdef CONFIG_FEATURE_SGI_LABEL
3666 label_sgi == current_label_type ? sgi_get_sysid(i) :
3668 ptes[i].part_table->sys_ind);
3671 void list_types(const struct systypes *sys)
3673 uint last[4], done = 0, next = 0, size;
3676 for (i = 0; sys[i].name; i++);
3679 for (i = 3; i >= 0; i--)
3680 last[3 - i] = done += (size + i - done) / (i + 1);
3684 printf("%c%2x %-15.15s", i ? ' ' : '\n',
3685 (unsigned char)sys[next].name[0],
3686 partition_type((unsigned char)sys[next].name[0]));
3687 next = last[i++] + done;
3688 if (i > 3 || next >= last[i]) {
3692 } while (done < last[0]);
3695 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3698 is_cleared_partition(const struct partition *p)
3700 return !(!p || p->boot_ind || p->head || p->sector || p->cyl ||
3701 p->sys_ind || p->end_head || p->end_sector || p->end_cyl ||
3702 get_start_sect(p) || get_nr_sects(p));
3706 clear_partition(struct partition *p)
3710 memset(p, 0, sizeof(struct partition));
3713 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3715 set_partition(int i, int doext, off_t start, off_t stop, int sysid)
3717 struct partition *p;
3721 p = ptes[i].ext_pointer;
3722 offset = extended_offset;
3724 p = ptes[i].part_table;
3725 offset = ptes[i].offset;
3729 set_start_sect(p, start - offset);
3730 set_nr_sects(p, stop - start + 1);
3731 if (dos_compatible_flag && (start/(sectors*heads) > 1023))
3732 start = heads*sectors*1024 - 1;
3733 set_hsc(p->head, p->sector, p->cyl, start);
3734 if (dos_compatible_flag && (stop/(sectors*heads) > 1023))
3735 stop = heads*sectors*1024 - 1;
3736 set_hsc(p->end_head, p->end_sector, p->end_cyl, stop);
3737 ptes[i].changed = 1;
3742 test_c(const char **m, const char *mesg)
3746 fprintf(stderr, _("You must set"));
3748 fprintf(stderr, " %s", *m);
3758 const char *m = NULL;
3762 prev = test_c(&m, _("heads"));
3764 prev = test_c(&m, _("sectors"));
3766 prev = test_c(&m, _("cylinders"));
3770 fprintf(stderr, "%s%s.\n"
3771 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3772 "You can do this from the extra functions menu.\n"
3774 , prev ? _(" and ") : " ", m);
3779 static void update_units(void)
3781 int cyl_units = heads * sectors;
3783 if (display_in_cyl_units && cyl_units)
3784 units_per_sector = cyl_units;
3786 units_per_sector = 1; /* in sectors */
3789 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3791 warn_cylinders(void)
3793 if (label_dos == current_label_type && cylinders > 1024 && !nowarn)
3794 fprintf(stderr, _("\n"
3795 "The number of cylinders for this disk is set to %d.\n"
3796 "There is nothing wrong with that, but this is larger than 1024,\n"
3797 "and could in certain setups cause problems with:\n"
3798 "1) software that runs at boot time (e.g., old versions of LILO)\n"
3799 "2) booting and partitioning software from other OSs\n"
3800 " (e.g., DOS FDISK, OS/2 FDISK)\n"),
3806 read_extended(int ext)
3810 struct partition *p, *q;
3814 pex->ext_pointer = pex->part_table;
3816 p = pex->part_table;
3817 if (!get_start_sect(p)) {
3819 _("Bad offset in primary extended partition\n"));
3823 while (IS_EXTENDED(p->sys_ind)) {
3824 struct pte *pe = &ptes[partitions];
3826 if (partitions >= MAXIMUM_PARTS) {
3827 /* This is not a Linux restriction, but
3828 this program uses arrays of size MAXIMUM_PARTS.
3829 Do not try to `improve' this test. */
3830 struct pte *pre = &ptes[partitions-1];
3831 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3833 _("Warning: deleting partitions after %d\n"),
3837 clear_partition(pre->ext_pointer);
3841 read_pte(pe, extended_offset + get_start_sect(p));
3843 if (!extended_offset)
3844 extended_offset = get_start_sect(p);
3846 q = p = pt_offset(pe->sectorbuffer, 0);
3847 for (i = 0; i < 4; i++, p++) if (get_nr_sects(p)) {
3848 if (IS_EXTENDED(p->sys_ind)) {
3849 if (pe->ext_pointer)
3851 _("Warning: extra link "
3852 "pointer in partition table"
3853 " %d\n"), partitions + 1);
3855 pe->ext_pointer = p;
3856 } else if (p->sys_ind) {
3859 _("Warning: ignoring extra "
3860 "data in partition table"
3861 " %d\n"), partitions + 1);
3867 /* very strange code here... */
3868 if (!pe->part_table) {
3869 if (q != pe->ext_pointer)
3872 pe->part_table = q + 1;
3874 if (!pe->ext_pointer) {
3875 if (q != pe->part_table)
3876 pe->ext_pointer = q;
3878 pe->ext_pointer = q + 1;
3881 p = pe->ext_pointer;
3885 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3886 /* remove empty links */
3888 for (i = 4; i < partitions; i++) {
3889 struct pte *pe = &ptes[i];
3891 if (!get_nr_sects(pe->part_table) &&
3892 (partitions > 5 || ptes[4].part_table->sys_ind)) {
3893 printf("omitting empty partition (%d)\n", i+1);
3894 delete_partition(i);
3895 goto remove; /* numbering changed */
3901 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3903 create_doslabel(void)
3908 _("Building a new DOS disklabel. Changes will remain in memory only,\n"
3909 "until you decide to write them. After that, of course, the previous\n"
3910 "content won't be recoverable.\n\n"));
3912 current_label_type = label_dos;
3914 #ifdef CONFIG_FEATURE_OSF_LABEL
3915 possibly_osf_label = 0;
3919 for (i = 510-64; i < 510; i++)
3921 write_part_table_flag(MBRbuffer);
3922 extended_offset = 0;
3923 set_all_unchanged();
3925 get_boot(create_empty_dos);
3927 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3930 get_sectorsize(void)
3932 if (!user_set_sector_size) {
3934 if (ioctl(fd, BLKSSZGET, &arg) == 0)
3936 if (sector_size != DEFAULT_SECTOR_SIZE)
3937 printf(_("Note: sector size is %d (not %d)\n"),
3938 sector_size, DEFAULT_SECTOR_SIZE);
3943 get_kernel_geometry(void)
3945 struct hd_geometry geometry;
3947 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
3948 kern_heads = geometry.heads;
3949 kern_sectors = geometry.sectors;
3950 /* never use geometry.cylinders - it is truncated */
3955 get_partition_table_geometry(void)
3957 const unsigned char *bufp = (const unsigned char *)MBRbuffer;
3958 struct partition *p;
3959 int i, h, s, hh, ss;
3963 if (!(valid_part_table_flag((char*)bufp)))
3967 for (i = 0; i < 4; i++) {
3968 p = pt_offset(bufp, i);
3969 if (p->sys_ind != 0) {
3970 h = p->end_head + 1;
3971 s = (p->end_sector & 077);
3976 } else if (hh != h || ss != s)
3981 if (!first && !bad) {
3991 unsigned long long bytes; /* really u64 */
3994 sec_fac = sector_size / 512;
3995 #ifdef CONFIG_FEATURE_SUN_LABEL
3996 guess_device_type();
3998 heads = cylinders = sectors = 0;
3999 kern_heads = kern_sectors = 0;
4000 pt_heads = pt_sectors = 0;
4002 get_kernel_geometry();
4003 get_partition_table_geometry();
4005 heads = user_heads ? user_heads :
4006 pt_heads ? pt_heads :
4007 kern_heads ? kern_heads : 255;
4008 sectors = user_sectors ? user_sectors :
4009 pt_sectors ? pt_sectors :
4010 kern_sectors ? kern_sectors : 63;
4011 if (ioctl(fd, BLKGETSIZE64, &bytes) == 0) {
4014 unsigned long longsectors;
4016 if (ioctl(fd, BLKGETSIZE, &longsectors))
4018 bytes = ((unsigned long long) longsectors) << 9;
4021 total_number_of_sectors = (bytes >> 9);
4024 if (dos_compatible_flag)
4025 sector_offset = sectors;
4027 cylinders = total_number_of_sectors / (heads * sectors * sec_fac);
4029 cylinders = user_cylinders;
4033 * Read MBR. Returns:
4034 * -1: no 0xaa55 flag present (possibly entire disk BSD)
4035 * 0: found or created label
4039 get_boot(enum action what)
4045 for (i = 0; i < 4; i++) {
4046 struct pte *pe = &ptes[i];
4048 pe->part_table = pt_offset(MBRbuffer, i);
4049 pe->ext_pointer = NULL;
4051 pe->sectorbuffer = MBRbuffer;
4052 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4053 pe->changed = (what == create_empty_dos);
4057 #ifdef CONFIG_FEATURE_SUN_LABEL
4058 if (what == create_empty_sun && check_sun_label())
4062 memset(MBRbuffer, 0, 512);
4064 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4065 if (what == create_empty_dos)
4066 goto got_dos_table; /* skip reading disk */
4068 if ((fd = open(disk_device, type_open)) < 0) {
4069 if ((fd = open(disk_device, O_RDONLY)) < 0) {
4070 if (what == try_only)
4072 fdisk_fatal(unable_to_open);
4074 printf(_("You will not be able to write "
4075 "the partition table.\n"));
4078 if (512 != read(fd, MBRbuffer, 512)) {
4079 if (what == try_only)
4081 fdisk_fatal(unable_to_read);
4084 if ((fd = open(disk_device, O_RDONLY)) < 0)
4086 if (512 != read(fd, MBRbuffer, 512))
4094 #ifdef CONFIG_FEATURE_SUN_LABEL
4095 if (check_sun_label())
4099 #ifdef CONFIG_FEATURE_SGI_LABEL
4100 if (check_sgi_label())
4104 #ifdef CONFIG_FEATURE_AIX_LABEL
4105 if (check_aix_label())
4109 #ifdef CONFIG_FEATURE_OSF_LABEL
4110 if (check_osf_label()) {
4111 possibly_osf_label = 1;
4112 if (!valid_part_table_flag(MBRbuffer)) {
4113 current_label_type = label_osf;
4116 printf(_("This disk has both DOS and BSD magic.\n"
4117 "Give the 'b' command to go to BSD mode.\n"));
4121 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4125 if (!valid_part_table_flag(MBRbuffer)) {
4126 #ifndef CONFIG_FEATURE_FDISK_WRITABLE
4132 _("Device contains neither a valid DOS "
4133 "partition table, nor Sun, SGI or OSF "
4136 #ifdef CONFIG_FEATURE_SUN_LABEL
4145 case create_empty_dos:
4146 #ifdef CONFIG_FEATURE_SUN_LABEL
4147 case create_empty_sun:
4151 fprintf(stderr, _("Internal error\n"));
4154 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
4157 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4162 for (i = 0; i < 4; i++) {
4163 struct pte *pe = &ptes[i];
4165 if (IS_EXTENDED(pe->part_table->sys_ind)) {
4166 if (partitions != 4)
4167 fprintf(stderr, _("Ignoring extra extended "
4168 "partition %d\n"), i + 1);
4174 for (i = 3; i < partitions; i++) {
4175 struct pte *pe = &ptes[i];
4177 if (!valid_part_table_flag(pe->sectorbuffer)) {
4179 _("Warning: invalid flag 0x%04x of partition "
4180 "table %d will be corrected by w(rite)\n"),
4181 part_table_flag(pe->sectorbuffer), i + 1);
4182 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4191 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4193 * Print the message MESG, then read an integer between LOW and HIGH (inclusive).
4194 * If the user hits Enter, DFLT is returned.
4195 * Answers like +10 are interpreted as offsets from BASE.
4197 * There is no default if DFLT is not between LOW and HIGH.
4200 read_int(uint low, uint dflt, uint high, uint base, char *mesg)
4204 static char *ms = NULL;
4205 static int mslen = 0;
4207 if (!ms || strlen(mesg)+100 > mslen) {
4208 mslen = strlen(mesg)+200;
4209 ms = xrealloc(ms,mslen);
4212 if (dflt < low || dflt > high)
4216 snprintf(ms, mslen, _("%s (%u-%u, default %u): "),
4217 mesg, low, high, dflt);
4219 snprintf(ms, mslen, "%s (%u-%u): ", mesg, low, high);
4222 int use_default = default_ok;
4224 /* ask question and read answer */
4225 while (read_chars(ms) != '\n' && !isdigit(*line_ptr)
4226 && *line_ptr != '-' && *line_ptr != '+')
4229 if (*line_ptr == '+' || *line_ptr == '-') {
4230 int minus = (*line_ptr == '-');
4233 i = atoi(line_ptr+1);
4235 while (isdigit(*++line_ptr))
4238 switch (*line_ptr) {
4241 if (!display_in_cyl_units)
4242 i *= heads * sectors;
4256 absolute = 1000000000;
4262 unsigned long long bytes;
4265 bytes = (unsigned long long) i * absolute;
4266 unit = sector_size * units_per_sector;
4267 bytes += unit/2; /* round */
4276 while (isdigit(*line_ptr)) {
4282 printf(_("Using default value %u\n"), i = dflt);
4283 if (i >= low && i <= high)
4286 printf(_("Value out of range.\n"));
4292 get_partition(int warn, int max)
4297 i = read_int(1, 0, max, 0, _("Partition number")) - 1;
4303 label_sun != current_label_type &&
4304 label_sgi != current_label_type &&
4305 !pe->part_table->sys_ind
4307 #ifdef CONFIG_FEATURE_SUN_LABEL
4309 label_sun == current_label_type &&
4311 !sunlabel->partitions[i].num_sectors
4312 || !sunlabel->infos[i].id
4316 #ifdef CONFIG_FEATURE_SGI_LABEL
4318 label_sgi == current_label_type &&
4319 !sgi_get_num_sectors(i)
4324 _("Warning: partition %d has empty type\n"),
4333 get_existing_partition(int warn, int max)
4338 for (i = 0; i < max; i++) {
4339 struct pte *pe = &ptes[i];
4340 struct partition *p = pe->part_table;
4342 if (p && !is_cleared_partition(p)) {
4349 printf(_("Selected partition %d\n"), pno+1);
4352 printf(_("No partition is defined yet!\n"));
4356 return get_partition(warn, max);
4360 get_nonexisting_partition(int warn, int max)
4365 for (i = 0; i < max; i++) {
4366 struct pte *pe = &ptes[i];
4367 struct partition *p = pe->part_table;
4369 if (p && is_cleared_partition(p)) {
4376 printf(_("Selected partition %d\n"), pno+1);
4379 printf(_("All primary partitions have been defined already!\n"));
4383 return get_partition(warn, max);
4387 void change_units(void)
4389 display_in_cyl_units = !display_in_cyl_units;
4391 printf(_("Changing display/entry units to %s\n"),
4396 toggle_active(int i)
4398 struct pte *pe = &ptes[i];
4399 struct partition *p = pe->part_table;
4401 if (IS_EXTENDED(p->sys_ind) && !p->boot_ind)
4403 _("WARNING: Partition %d is an extended partition\n"),
4405 p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG);
4410 toggle_dos_compatibility_flag(void)
4412 dos_compatible_flag = ~dos_compatible_flag;
4413 if (dos_compatible_flag) {
4414 sector_offset = sectors;
4415 printf(_("DOS Compatibility flag is set\n"));
4419 printf(_("DOS Compatibility flag is not set\n"));
4424 delete_partition(int i)
4426 struct pte *pe = &ptes[i];
4427 struct partition *p = pe->part_table;
4428 struct partition *q = pe->ext_pointer;
4430 /* Note that for the fifth partition (i == 4) we don't actually
4431 * decrement partitions.
4434 if (warn_geometry())
4435 return; /* C/H/S not set */
4438 #ifdef CONFIG_FEATURE_SUN_LABEL
4439 if (label_sun == current_label_type) {
4440 sun_delete_partition(i);
4444 #ifdef CONFIG_FEATURE_SGI_LABEL
4445 if (label_sgi == current_label_type) {
4446 sgi_delete_partition(i);
4452 if (IS_EXTENDED(p->sys_ind) && i == ext_index) {
4454 ptes[ext_index].ext_pointer = NULL;
4455 extended_offset = 0;
4461 if (!q->sys_ind && i > 4) {
4462 /* the last one in the chain - just delete */
4465 clear_partition(ptes[i].ext_pointer);
4466 ptes[i].changed = 1;
4468 /* not the last one - further ones will be moved down */
4470 /* delete this link in the chain */
4471 p = ptes[i-1].ext_pointer;
4473 set_start_sect(p, get_start_sect(q));
4474 set_nr_sects(p, get_nr_sects(q));
4475 ptes[i-1].changed = 1;
4476 } else if (partitions > 5) { /* 5 will be moved to 4 */
4477 /* the first logical in a longer chain */
4480 if (pe->part_table) /* prevent SEGFAULT */
4481 set_start_sect(pe->part_table,
4482 get_partition_start(pe) -
4484 pe->offset = extended_offset;
4488 if (partitions > 5) {
4490 while (i < partitions) {
4491 ptes[i] = ptes[i+1];
4495 /* the only logical: clear only */
4496 clear_partition(ptes[i].part_table);
4503 int i, sys, origsys;
4504 struct partition *p;
4506 #ifdef CONFIG_FEATURE_SGI_LABEL
4507 /* If sgi_label then don't use get_existing_partition,
4508 let the user select a partition, since get_existing_partition()
4509 only works for Linux like partition tables. */
4510 if (label_sgi != current_label_type) {
4511 i = get_existing_partition(0, partitions);
4513 i = get_partition(0, partitions);
4516 i = get_existing_partition(0, partitions);
4520 p = ptes[i].part_table;
4521 origsys = sys = get_sysid(i);
4523 /* if changing types T to 0 is allowed, then
4524 the reverse change must be allowed, too */
4525 if (!sys && label_sgi != current_label_type &&
4526 label_sun != current_label_type && !get_nr_sects(p))
4528 printf(_("Partition %d does not exist yet!\n"), i + 1);
4531 sys = read_hex (get_sys_types());
4533 if (!sys && label_sgi != current_label_type &&
4534 label_sun != current_label_type)
4536 printf(_("Type 0 means free space to many systems\n"
4537 "(but not to Linux). Having partitions of\n"
4538 "type 0 is probably unwise. You can delete\n"
4539 "a partition using the `d' command.\n"));
4543 if (label_sun != current_label_type && label_sgi != current_label_type) {
4544 if (IS_EXTENDED(sys) != IS_EXTENDED(p->sys_ind)) {
4545 printf(_("You cannot change a partition into"
4546 " an extended one or vice versa\n"
4547 "Delete it first.\n"));
4553 #ifdef CONFIG_FEATURE_SUN_LABEL
4554 if (label_sun == current_label_type && i == 2 && sys != WHOLE_DISK)
4555 printf(_("Consider leaving partition 3 "
4556 "as Whole disk (5),\n"
4557 "as SunOS/Solaris expects it and "
4558 "even Linux likes it.\n\n"));
4560 #ifdef CONFIG_FEATURE_SGI_LABEL
4561 if (label_sgi == current_label_type &&
4563 (i == 10 && sys != ENTIRE_DISK) ||
4564 (i == 8 && sys != 0)
4567 printf(_("Consider leaving partition 9 "
4568 "as volume header (0),\nand "
4569 "partition 11 as entire volume (6)"
4570 "as IRIX expects it.\n\n"));
4575 #ifdef CONFIG_FEATURE_SUN_LABEL
4576 if (label_sun == current_label_type) {
4577 sun_change_sysid(i, sys);
4580 #ifdef CONFIG_FEATURE_SGI_LABEL
4581 if (label_sgi == current_label_type) {
4582 sgi_change_sysid(i, sys);
4587 printf(_("Changed system type of partition %d "
4588 "to %x (%s)\n"), i + 1, sys,
4589 partition_type(sys));
4590 ptes[i].changed = 1;
4591 if (is_dos_partition(origsys) ||
4592 is_dos_partition(sys))
4599 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
4602 /* check_consistency() and long2chs() added Sat Mar 6 12:28:16 1993,
4603 * faith@cs.unc.edu, based on code fragments from pfdisk by Gordon W. Ross,
4604 * Jan. 1990 (version 1.2.1 by Gordon W. Ross Aug. 1990; Modified by S.
4605 * Lubkin Oct. 1991). */
4608 long2chs(ulong ls, uint *c, uint *h, uint *s)
4610 int spc = heads * sectors;
4615 *s = ls % sectors + 1; /* sectors count from 1 */
4619 check_consistency(const struct partition *p, int partition)
4621 uint pbc, pbh, pbs; /* physical beginning c, h, s */
4622 uint pec, peh, pes; /* physical ending c, h, s */
4623 uint lbc, lbh, lbs; /* logical beginning c, h, s */
4624 uint lec, leh, les; /* logical ending c, h, s */
4626 if (!heads || !sectors || (partition >= 4))
4627 return; /* do not check extended partitions */
4629 /* physical beginning c, h, s */
4630 pbc = (p->cyl & 0xff) | ((p->sector << 2) & 0x300);
4632 pbs = p->sector & 0x3f;
4634 /* physical ending c, h, s */
4635 pec = (p->end_cyl & 0xff) | ((p->end_sector << 2) & 0x300);
4637 pes = p->end_sector & 0x3f;
4639 /* compute logical beginning (c, h, s) */
4640 long2chs(get_start_sect(p), &lbc, &lbh, &lbs);
4642 /* compute logical ending (c, h, s) */
4643 long2chs(get_start_sect(p) + get_nr_sects(p) - 1, &lec, &leh, &les);
4645 /* Same physical / logical beginning? */
4646 if (cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) {
4647 printf(_("Partition %d has different physical/logical "
4648 "beginnings (non-Linux?):\n"), partition + 1);
4649 printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs);
4650 printf(_("logical=(%d, %d, %d)\n"),lbc, lbh, lbs);
4653 /* Same physical / logical ending? */
4654 if (cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) {
4655 printf(_("Partition %d has different physical/logical "
4656 "endings:\n"), partition + 1);
4657 printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
4658 printf(_("logical=(%d, %d, %d)\n"),lec, leh, les);
4662 /* Beginning on cylinder boundary? */
4663 if (pbh != !pbc || pbs != 1) {
4664 printf(_("Partition %i does not start on cylinder "
4665 "boundary:\n"), partition + 1);
4666 printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs);
4667 printf(_("should be (%d, %d, 1)\n"), pbc, !pbc);
4671 /* Ending on cylinder boundary? */
4672 if (peh != (heads - 1) || pes != sectors) {
4673 printf(_("Partition %i does not end on cylinder boundary.\n"),
4676 printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
4677 printf(_("should be (%d, %d, %d)\n"),
4678 pec, heads - 1, sectors);
4684 list_disk_geometry(void)
4686 long long bytes = (total_number_of_sectors << 9);
4687 long megabytes = bytes/1000000;
4689 if (megabytes < 10000)
4690 printf(_("\nDisk %s: %ld MB, %lld bytes\n"),
4691 disk_device, megabytes, bytes);
4693 printf(_("\nDisk %s: %ld.%ld GB, %lld bytes\n"),
4694 disk_device, megabytes/1000, (megabytes/100)%10, bytes);
4695 printf(_("%d heads, %d sectors/track, %d cylinders"),
4696 heads, sectors, cylinders);
4697 if (units_per_sector == 1)
4698 printf(_(", total %llu sectors"),
4699 total_number_of_sectors / (sector_size/512));
4700 printf(_("\nUnits = %s of %d * %d = %d bytes\n\n"),
4702 units_per_sector, sector_size, units_per_sector * sector_size);
4706 * Check whether partition entries are ordered by their starting positions.
4707 * Return 0 if OK. Return i if partition i should have been earlier.
4708 * Two separate checks: primary and logical partitions.
4711 wrong_p_order(int *prev)
4713 const struct pte *pe;
4714 const struct partition *p;
4715 off_t last_p_start_pos = 0, p_start_pos;
4718 for (i = 0 ; i < partitions; i++) {
4721 last_p_start_pos = 0;
4724 if ((p = pe->part_table)->sys_ind) {
4725 p_start_pos = get_partition_start(pe);
4727 if (last_p_start_pos > p_start_pos) {
4733 last_p_start_pos = p_start_pos;
4740 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
4742 * Fix the chain of logicals.
4743 * extended_offset is unchanged, the set of sectors used is unchanged
4744 * The chain is sorted so that sectors increase, and so that
4745 * starting sectors increase.
4747 * After this it may still be that cfdisk doesnt like the table.
4748 * (This is because cfdisk considers expanded parts, from link to
4749 * end of partition, and these may still overlap.)
4751 * sfdisk /dev/hda > ohda; sfdisk /dev/hda < ohda
4755 fix_chain_of_logicals(void)
4757 int j, oj, ojj, sj, sjj;
4758 struct partition *pj,*pjj,tmp;
4760 /* Stage 1: sort sectors but leave sector of part 4 */
4761 /* (Its sector is the global extended_offset.) */
4763 for (j = 5; j < partitions-1; j++) {
4764 oj = ptes[j].offset;
4765 ojj = ptes[j+1].offset;
4767 ptes[j].offset = ojj;
4768 ptes[j+1].offset = oj;
4769 pj = ptes[j].part_table;
4770 set_start_sect(pj, get_start_sect(pj)+oj-ojj);
4771 pjj = ptes[j+1].part_table;
4772 set_start_sect(pjj, get_start_sect(pjj)+ojj-oj);
4773 set_start_sect(ptes[j-1].ext_pointer,
4774 ojj-extended_offset);
4775 set_start_sect(ptes[j].ext_pointer,
4776 oj-extended_offset);
4781 /* Stage 2: sort starting sectors */
4783 for (j = 4; j < partitions-1; j++) {
4784 pj = ptes[j].part_table;
4785 pjj = ptes[j+1].part_table;
4786 sj = get_start_sect(pj);
4787 sjj = get_start_sect(pjj);
4788 oj = ptes[j].offset;
4789 ojj = ptes[j+1].offset;
4790 if (oj+sj > ojj+sjj) {
4794 set_start_sect(pj, ojj+sjj-oj);
4795 set_start_sect(pjj, oj+sj-ojj);
4800 /* Probably something was changed */
4801 for (j = 4; j < partitions; j++)
4802 ptes[j].changed = 1;
4807 fix_partition_table_order(void)
4809 struct pte *pei, *pek;
4812 if (!wrong_p_order(NULL)) {
4813 printf(_("Nothing to do. Ordering is correct already.\n\n"));
4817 while ((i = wrong_p_order(&k)) != 0 && i < 4) {
4818 /* partition i should have come earlier, move it */
4819 /* We have to move data in the MBR */
4820 struct partition *pi, *pk, *pe, pbuf;
4824 pe = pei->ext_pointer;
4825 pei->ext_pointer = pek->ext_pointer;
4826 pek->ext_pointer = pe;
4828 pi = pei->part_table;
4829 pk = pek->part_table;
4831 memmove(&pbuf, pi, sizeof(struct partition));
4832 memmove(pi, pk, sizeof(struct partition));
4833 memmove(pk, &pbuf, sizeof(struct partition));
4835 pei->changed = pek->changed = 1;
4839 fix_chain_of_logicals();
4847 list_table(int xtra)
4849 const struct partition *p;
4852 #ifdef CONFIG_FEATURE_SUN_LABEL
4853 if (label_sun == current_label_type) {
4854 sun_list_table(xtra);
4859 #ifdef CONFIG_FEATURE_SGI_LABEL
4860 if (label_sgi == current_label_type) {
4861 sgi_list_table(xtra);
4866 list_disk_geometry();
4868 #ifdef CONFIG_FEATURE_OSF_LABEL
4869 if (label_osf == current_label_type) {
4870 xbsd_print_disklabel(xtra);
4875 /* Heuristic: we list partition 3 of /dev/foo as /dev/foo3,
4876 but if the device name ends in a digit, say /dev/foo1,
4877 then the partition is called /dev/foo1p3. */
4878 w = strlen(disk_device);
4879 if (w && isdigit(disk_device[w-1]))
4884 printf(_("%*s Boot Start End Blocks Id System\n"),
4887 for (i = 0; i < partitions; i++) {
4888 const struct pte *pe = &ptes[i];
4891 if (p && !is_cleared_partition(p)) {
4892 off_t psects = get_nr_sects(p);
4893 off_t pblocks = psects;
4894 unsigned int podd = 0;
4896 if (sector_size < 1024) {
4897 pblocks /= (1024 / sector_size);
4898 podd = psects % (1024 / sector_size);
4900 if (sector_size > 1024)
4901 pblocks *= (sector_size / 1024);
4903 "%s %c %11llu %11llu %11llu%c %2x %s\n",
4904 partname(disk_device, i+1, w+2),
4905 /* boot flag */ !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG
4907 /* start */ (unsigned long long) cround(get_partition_start(pe)),
4908 /* end */ (unsigned long long) cround(get_partition_start(pe) + psects
4909 - (psects ? 1 : 0)),
4910 /* odd flag on end */ (unsigned long long) pblocks, podd ? '+' : ' ',
4911 /* type id */ p->sys_ind,
4912 /* type name */ partition_type(p->sys_ind));
4913 check_consistency(p, i);
4917 /* Is partition table in disk order? It need not be, but... */
4918 /* partition table entries are not checked for correct order if this
4919 is a sgi, sun or aix labeled disk... */
4920 if (label_dos == current_label_type && wrong_p_order(NULL)) {
4922 printf(_("\nPartition table entries are not in disk order\n"));
4926 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
4928 x_list_table(int extend)
4930 const struct pte *pe;
4931 const struct partition *p;
4934 printf(_("\nDisk %s: %d heads, %d sectors, %d cylinders\n\n"),
4935 disk_device, heads, sectors, cylinders);
4936 printf(_("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n"));
4937 for (i = 0 ; i < partitions; i++) {
4939 p = (extend ? pe->ext_pointer : pe->part_table);
4941 printf("%2d %02x%4d%4d%5d%4d%4d%5d%11u%11u %02x\n",
4942 i + 1, p->boot_ind, p->head,
4944 cylinder(p->sector, p->cyl), p->end_head,
4945 sector(p->end_sector),
4946 cylinder(p->end_sector, p->end_cyl),
4947 get_start_sect(p), get_nr_sects(p), p->sys_ind);
4949 check_consistency(p, i);
4955 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4957 fill_bounds(off_t *first, off_t *last)
4960 const struct pte *pe = &ptes[0];
4961 const struct partition *p;
4963 for (i = 0; i < partitions; pe++,i++) {
4965 if (!p->sys_ind || IS_EXTENDED(p->sys_ind)) {
4966 first[i] = 0xffffffff;
4969 first[i] = get_partition_start(pe);
4970 last[i] = first[i] + get_nr_sects(p) - 1;
4976 check(int n, uint h, uint s, uint c, off_t start)
4978 off_t total, real_s, real_c;
4980 real_s = sector(s) - 1;
4981 real_c = cylinder(s, c);
4982 total = (real_c * sectors + real_s) * heads + h;
4984 fprintf(stderr, _("Warning: partition %d contains sector 0\n"), n);
4987 _("Partition %d: head %d greater than maximum %d\n"),
4989 if (real_s >= sectors)
4990 fprintf(stderr, _("Partition %d: sector %d greater than "
4991 "maximum %d\n"), n, s, sectors);
4992 if (real_c >= cylinders)
4993 fprintf(stderr, _("Partitions %d: cylinder %llu greater than "
4994 "maximum %d\n"), n, (unsigned long long)real_c + 1, cylinders);
4995 if (cylinders <= 1024 && start != total)
4997 _("Partition %d: previous sectors %llu disagrees with "
4998 "total %llu\n"), n, (unsigned long long)start, (unsigned long long)total);
5006 off_t first[partitions], last[partitions];
5007 struct partition *p;
5009 if (warn_geometry())
5012 #ifdef CONFIG_FEATURE_SUN_LABEL
5013 if (label_sun == current_label_type) {
5018 #ifdef CONFIG_FEATURE_SGI_LABEL
5019 if (label_sgi == current_label_type) {
5025 fill_bounds(first, last);
5026 for (i = 0; i < partitions; i++) {
5027 struct pte *pe = &ptes[i];
5030 if (p->sys_ind && !IS_EXTENDED(p->sys_ind)) {
5031 check_consistency(p, i);
5032 if (get_partition_start(pe) < first[i])
5033 printf(_("Warning: bad start-of-data in "
5034 "partition %d\n"), i + 1);
5035 check(i + 1, p->end_head, p->end_sector, p->end_cyl,
5037 total += last[i] + 1 - first[i];
5038 for (j = 0; j < i; j++)
5039 if ((first[i] >= first[j] && first[i] <= last[j])
5040 || ((last[i] <= last[j] && last[i] >= first[j]))) {
5041 printf(_("Warning: partition %d overlaps "
5042 "partition %d.\n"), j + 1, i + 1);
5043 total += first[i] >= first[j] ?
5044 first[i] : first[j];
5045 total -= last[i] <= last[j] ?
5051 if (extended_offset) {
5052 struct pte *pex = &ptes[ext_index];
5053 off_t e_last = get_start_sect(pex->part_table) +
5054 get_nr_sects(pex->part_table) - 1;
5056 for (i = 4; i < partitions; i++) {
5058 p = ptes[i].part_table;
5060 if (i != 4 || i + 1 < partitions)
5061 printf(_("Warning: partition %d "
5062 "is empty\n"), i + 1);
5064 else if (first[i] < extended_offset ||
5066 printf(_("Logical partition %d not entirely in "
5067 "partition %d\n"), i + 1, ext_index + 1);
5071 if (total > heads * sectors * cylinders)
5072 printf(_("Total allocated sectors %d greater than the maximum "
5073 "%d\n"), total, heads * sectors * cylinders);
5074 else if ((total = heads * sectors * cylinders - total) != 0)
5075 printf(_("%d unallocated sectors\n"), total);
5079 add_partition(int n, int sys)
5081 char mesg[256]; /* 48 does not suffice in Japanese */
5083 struct partition *p = ptes[n].part_table;
5084 struct partition *q = ptes[ext_index].part_table;
5086 off_t start, stop = 0, limit, temp,
5087 first[partitions], last[partitions];
5089 if (p && p->sys_ind) {
5090 printf(_("Partition %d is already defined. Delete "
5091 "it before re-adding it.\n"), n + 1);
5094 fill_bounds(first, last);
5096 start = sector_offset;
5097 if (display_in_cyl_units || !total_number_of_sectors)
5098 llimit = heads * sectors * cylinders - 1;
5100 llimit = total_number_of_sectors - 1;
5102 if (limit != llimit)
5104 if (extended_offset) {
5105 first[ext_index] = extended_offset;
5106 last[ext_index] = get_start_sect(q) +
5107 get_nr_sects(q) - 1;
5110 start = extended_offset + sector_offset;
5111 limit = get_start_sect(q) + get_nr_sects(q) - 1;
5113 if (display_in_cyl_units)
5114 for (i = 0; i < partitions; i++)
5115 first[i] = (cround(first[i]) - 1) * units_per_sector;
5117 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
5120 for (i = 0; i < partitions; i++) {
5123 if (start == ptes[i].offset)
5124 start += sector_offset;
5125 lastplusoff = last[i] + ((n < 4) ? 0 : sector_offset);
5126 if (start >= first[i] && start <= lastplusoff)
5127 start = lastplusoff + 1;
5131 if (start >= temp+units_per_sector && readed) {
5132 printf(_("Sector %llu is already allocated\n"), (unsigned long long)temp);
5136 if (!readed && start == temp) {
5139 saved_start = start;
5140 start = read_int(cround(saved_start), cround(saved_start), cround(limit),
5142 if (display_in_cyl_units) {
5143 start = (start - 1) * units_per_sector;
5144 if (start < saved_start) start = saved_start;
5148 } while (start != temp || !readed);
5149 if (n > 4) { /* NOT for fifth partition */
5150 struct pte *pe = &ptes[n];
5152 pe->offset = start - sector_offset;
5153 if (pe->offset == extended_offset) { /* must be corrected */
5155 if (sector_offset == 1)
5160 for (i = 0; i < partitions; i++) {
5161 struct pte *pe = &ptes[i];
5163 if (start < pe->offset && limit >= pe->offset)
5164 limit = pe->offset - 1;
5165 if (start < first[i] && limit >= first[i])
5166 limit = first[i] - 1;
5168 if (start > limit) {
5169 printf(_("No free sectors available\n"));
5174 if (cround(start) == cround(limit)) {
5177 snprintf(mesg, sizeof(mesg),
5178 _("Last %s or +size or +sizeM or +sizeK"),
5179 str_units(SINGULAR));
5180 stop = read_int(cround(start), cround(limit), cround(limit),
5181 cround(start), mesg);
5182 if (display_in_cyl_units) {
5183 stop = stop * units_per_sector - 1;
5189 set_partition(n, 0, start, stop, sys);
5191 set_partition(n - 1, 1, ptes[n].offset, stop, EXTENDED);
5193 if (IS_EXTENDED(sys)) {
5194 struct pte *pe4 = &ptes[4];
5195 struct pte *pen = &ptes[n];
5198 pen->ext_pointer = p;
5199 pe4->offset = extended_offset = start;
5200 pe4->sectorbuffer = xcalloc(1, sector_size);
5201 pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
5202 pe4->ext_pointer = pe4->part_table + 1;
5211 if (partitions > 5 || ptes[4].part_table->sys_ind) {
5212 struct pte *pe = &ptes[partitions];
5214 pe->sectorbuffer = xcalloc(1, sector_size);
5215 pe->part_table = pt_offset(pe->sectorbuffer, 0);
5216 pe->ext_pointer = pe->part_table + 1;
5221 add_partition(partitions - 1, LINUX_NATIVE);
5227 int i, free_primary = 0;
5229 if (warn_geometry())
5232 #ifdef CONFIG_FEATURE_SUN_LABEL
5233 if (label_sun == current_label_type) {
5234 add_sun_partition(get_partition(0, partitions), LINUX_NATIVE);
5238 #ifdef CONFIG_FEATURE_SGI_LABEL
5239 if (label_sgi == current_label_type) {
5240 sgi_add_partition(get_partition(0, partitions), LINUX_NATIVE);
5244 #ifdef CONFIG_FEATURE_AIX_LABEL
5245 if (label_aix == current_label_type) {
5246 printf(_("\tSorry - this fdisk cannot handle AIX disk labels."
5247 "\n\tIf you want to add DOS-type partitions, create"
5248 "\n\ta new empty DOS partition table first. (Use o.)"
5250 "This will destroy the present disk contents.\n"));
5255 for (i = 0; i < 4; i++)
5256 free_primary += !ptes[i].part_table->sys_ind;
5258 if (!free_primary && partitions >= MAXIMUM_PARTS) {
5259 printf(_("The maximum number of partitions has been created\n"));
5263 if (!free_primary) {
5264 if (extended_offset)
5267 printf(_("You must delete some partition and add "
5268 "an extended partition first\n"));
5270 char c, line[LINE_LENGTH];
5271 snprintf(line, sizeof(line), "%s\n %s\n p primary "
5272 "partition (1-4)\n",
5273 "Command action", (extended_offset ?
5274 "l logical (5 or over)" : "e extended"));
5276 if ((c = read_char(line)) == 'p' || c == 'P') {
5277 i = get_nonexisting_partition(0, 4);
5279 add_partition(i, LINUX_NATIVE);
5282 else if (c == 'l' && extended_offset) {
5286 else if (c == 'e' && !extended_offset) {
5287 i = get_nonexisting_partition(0, 4);
5289 add_partition(i, EXTENDED);
5293 printf(_("Invalid partition number "
5294 "for type `%c'\n"), c);
5304 if (label_dos == current_label_type) {
5305 for (i = 0; i < 3; i++)
5306 if (ptes[i].changed)
5307 ptes[3].changed = 1;
5308 for (i = 3; i < partitions; i++) {
5309 struct pte *pe = &ptes[i];
5312 write_part_table_flag(pe->sectorbuffer);
5313 write_sector(pe->offset, pe->sectorbuffer);
5317 #ifdef CONFIG_FEATURE_SGI_LABEL
5318 else if (label_sgi == current_label_type) {
5319 /* no test on change? the printf below might be mistaken */
5323 #ifdef CONFIG_FEATURE_SUN_LABEL
5324 else if (label_sun == current_label_type) {
5327 for (i = 0; i < 8; i++)
5328 if (ptes[i].changed)
5335 printf(_("The partition table has been altered!\n\n"));
5336 reread_partition_table(1);
5340 reread_partition_table(int leave)
5345 printf(_("Calling ioctl() to re-read partition table.\n"));
5348 if ((i = ioctl(fd, BLKRRPART)) != 0) {
5351 /* some kernel versions (1.2.x) seem to have trouble
5352 rereading the partition table, but if asked to do it
5353 twice, the second time works. - biro@yggdrasil.com */
5356 if ((i = ioctl(fd, BLKRRPART)) != 0)
5361 printf(_("\nWARNING: Re-reading the partition table "
5362 "failed with error %d: %s.\n"
5363 "The kernel still uses the old table.\n"
5364 "The new table will be used "
5365 "at the next reboot.\n"),
5366 error, strerror(error));
5371 _("\nWARNING: If you have created or modified any DOS 6.x\n"
5372 "partitions, please see the fdisk manual page for additional\n"
5378 printf(_("Syncing disks.\n"));
5380 sleep(4); /* for sync() */
5384 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
5386 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
5387 #define MAX_PER_LINE 16
5389 print_buffer(char *pbuffer)
5393 for (i = 0, l = 0; i < sector_size; i++, l++) {
5395 printf("0x%03X:", i);
5396 printf(" %02X", (unsigned char) pbuffer[i]);
5397 if (l == MAX_PER_LINE - 1) {
5413 printf(_("Device: %s\n"), disk_device);
5414 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
5415 if (label_sun == current_label_type || label_sgi == current_label_type)
5416 print_buffer(MBRbuffer);
5419 for (i = 3; i < partitions; i++)
5420 print_buffer(ptes[i].sectorbuffer);
5426 struct pte *pe = &ptes[i];
5427 struct partition *p = pe->part_table;
5430 if (warn_geometry())
5432 if (!p->sys_ind || !get_nr_sects(p) || IS_EXTENDED(p->sys_ind)) {
5433 printf(_("Partition %d has no data area\n"), i + 1);
5436 first = get_partition_start(pe);
5437 new = read_int(first, first, first + get_nr_sects(p) - 1, first,
5438 _("New beginning of data")) - pe->offset;
5440 if (new != get_nr_sects(p)) {
5441 first = get_nr_sects(p) + get_start_sect(p) - new;
5442 set_nr_sects(p, first);
5443 set_start_sect(p, new);
5455 c = tolower(read_char(_("Expert command (m for help): ")));
5458 #ifdef CONFIG_FEATURE_SUN_LABEL
5459 if (label_sun == current_label_type)
5464 if (label_dos == current_label_type)
5465 move_begin(get_partition(0, partitions));
5468 user_cylinders = cylinders =
5469 read_int(1, cylinders, 1048576, 0,
5470 _("Number of cylinders"));
5471 #ifdef CONFIG_FEATURE_SUN_LABEL
5472 if (label_sun == current_label_type)
5473 sun_set_ncyl(cylinders);
5475 if (label_dos == current_label_type)
5482 #ifdef CONFIG_FEATURE_SGI_LABEL
5483 if (label_sgi == current_label_type)
5487 #ifdef CONFIG_FEATURE_SUN_LABEL
5488 if (label_sun == current_label_type)
5492 if (label_dos == current_label_type)
5496 if (label_dos == current_label_type)
5497 fix_partition_table_order();
5500 #ifdef CONFIG_FEATURE_SGI_LABEL
5505 user_heads = heads = read_int(1, heads, 256, 0,
5506 _("Number of heads"));
5510 #ifdef CONFIG_FEATURE_SUN_LABEL
5511 if (label_sun == current_label_type)
5516 #ifdef CONFIG_FEATURE_SUN_LABEL
5517 if (label_sun == current_label_type)
5522 #ifdef CONFIG_FEATURE_SUN_LABEL
5523 if (label_sun == current_label_type)
5536 user_sectors = sectors = read_int(1, sectors, 63, 0,
5537 _("Number of sectors"));
5538 if (dos_compatible_flag) {
5539 sector_offset = sectors;
5540 fprintf(stderr, _("Warning: setting "
5541 "sector offset for DOS "
5550 write_table(); /* does not return */
5553 #ifdef CONFIG_FEATURE_SUN_LABEL
5554 if (label_sun == current_label_type)
5555 sun_set_pcylcount();
5563 #endif /* ADVANCED mode */
5566 is_ide_cdrom_or_tape(const char *device)
5570 struct stat statbuf;
5573 /* No device was given explicitly, and we are trying some
5574 likely things. But opening /dev/hdc may produce errors like
5575 "hdc: tray open or drive not ready"
5576 if it happens to be a CD-ROM drive. It even happens that
5577 the process hangs on the attempt to read a music CD.
5578 So try to be careful. This only works since 2.1.73. */
5580 if (strncmp("/dev/hd", device, 7))
5583 snprintf(buf, sizeof(buf), "/proc/ide/%s/media", device+5);
5584 procf = fopen(buf, "r");
5585 if (procf != NULL && fgets(buf, sizeof(buf), procf))
5586 is_ide = (!strncmp(buf, "cdrom", 5) ||
5587 !strncmp(buf, "tape", 4));
5589 /* Now when this proc file does not exist, skip the
5590 device when it is read-only. */
5591 if (stat(device, &statbuf) == 0)
5592 is_ide = ((statbuf.st_mode & 0222) == 0);
5601 try(const char *device, int user_specified)
5605 disk_device = device;
5606 if (setjmp(listingbuf))
5608 if (!user_specified)
5609 if (is_ide_cdrom_or_tape(device))
5611 if ((fd = open(disk_device, type_open)) >= 0) {
5612 gb = get_boot(try_only);
5613 if (gb > 0) { /* I/O error */
5615 } else if (gb < 0) { /* no DOS signature */
5616 list_disk_geometry();
5617 if (label_aix == current_label_type){
5620 #ifdef CONFIG_FEATURE_OSF_LABEL
5621 if (btrydev(device) < 0)
5624 _("Disk %s doesn't contain a valid "
5625 "partition table\n"), device);
5630 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5631 if (label_sun != current_label_type && partitions > 4){
5632 delete_partition(ext_index);
5637 /* Ignore other errors, since we try IDE
5638 and SCSI hard disks which may not be
5639 installed on the system. */
5640 if (errno == EACCES) {
5641 fprintf(stderr, _("Cannot open %s\n"), device);
5647 /* for fdisk -l: try all things in /proc/partitions
5648 that look like a partition name (do not end in a digit) */
5653 char line[100], ptname[100], devname[120], *s;
5656 procpt = bb_wfopen(PROC_PARTITIONS, "r");
5658 while (fgets(line, sizeof(line), procpt)) {
5659 if (sscanf(line, " %d %d %d %[^\n ]",
5660 &ma, &mi, &sz, ptname) != 4)
5662 for (s = ptname; *s; s++);
5665 sprintf(devname, "/dev/%s", ptname);
5668 #ifdef CONFIG_FEATURE_CLEAN_UP
5673 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5675 unknown_command(int c)
5677 printf(_("%c: unknown command\n"), c);
5681 int fdisk_main(int argc, char **argv)
5684 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5687 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5693 * fdisk -l [-b sectorsize] [-u] device ...
5694 * fdisk -s [partition] ...
5695 * fdisk [-b sectorsize] [-u] device
5697 * Options -C, -H, -S set the geometry.
5700 while ((c = getopt(argc, argv, "b:C:H:lS:uvV"
5701 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5707 /* Ugly: this sector size is really per device,
5708 so cannot be combined with multiple disks,
5709 and te same goes for the C/H/S options.
5711 sector_size = atoi(optarg);
5712 if (sector_size != 512 && sector_size != 1024 &&
5713 sector_size != 2048)
5716 user_set_sector_size = 1;
5719 user_cylinders = atoi(optarg);
5722 user_heads = atoi(optarg);
5723 if (user_heads <= 0 || user_heads >= 256)
5727 user_sectors = atoi(optarg);
5728 if (user_sectors <= 0 || user_sectors >= 64)
5732 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5736 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5742 display_in_cyl_units = 0;
5746 printf("fdisk v" UTIL_LINUX_VERSION "\n");
5754 printf(_("This kernel finds the sector size itself - "
5755 "-b option ignored\n"));
5757 if (user_set_sector_size && argc-optind != 1)
5758 printf(_("Warning: the -b (set sector size) option should"
5759 " be used with one specified device\n"));
5762 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5766 type_open = O_RDONLY;
5767 if (argc > optind) {
5770 /* avoid gcc warning:
5771 variable `k' might be clobbered by `longjmp' */
5775 for (k = optind; k < argc; k++)
5778 /* we no longer have default device names */
5779 /* but, we can use /proc/partitions instead */
5783 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5787 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5793 type_open = O_RDONLY;
5795 opts = argc - optind;
5799 for (j = optind; j < argc; j++) {
5800 disk_device = argv[j];
5801 if ((fd = open(disk_device, type_open)) < 0)
5802 fdisk_fatal(unable_to_open);
5803 if (ioctl(fd, BLKGETSIZE, &size))
5804 fdisk_fatal(ioctl_error);
5807 printf("%ld\n", size/2);
5809 printf("%s: %ld\n", argv[j], size/2);
5815 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5816 if (argc-optind == 1)
5817 disk_device = argv[optind];
5823 #ifdef CONFIG_FEATURE_OSF_LABEL
5824 if (label_osf == current_label_type) {
5825 /* OSF label, and no DOS label */
5826 printf(_("Detected an OSF/1 disklabel on %s, entering "
5827 "disklabel mode.\n"),
5830 /*Why do we do this? It seems to be counter-intuitive*/
5831 current_label_type = label_dos;
5832 /* If we return we may want to make an empty DOS label? */
5838 c = tolower(read_char(_("Command (m for help): ")));
5841 if (label_dos == current_label_type)
5842 toggle_active(get_partition(1, partitions));
5843 #ifdef CONFIG_FEATURE_SUN_LABEL
5844 else if (label_sun == current_label_type)
5845 toggle_sunflags(get_partition(1, partitions),
5848 #ifdef CONFIG_FEATURE_SGI_LABEL
5849 else if (label_sgi == current_label_type)
5850 sgi_set_bootpartition(
5851 get_partition(1, partitions));
5857 #ifdef CONFIG_FEATURE_SGI_LABEL
5858 if (label_sgi == current_label_type) {
5859 printf(_("\nThe current boot file is: %s\n"),
5860 sgi_get_bootfile());
5861 if (read_chars(_("Please enter the name of the "
5862 "new boot file: ")) == '\n')
5863 printf(_("Boot file unchanged\n"));
5865 sgi_set_bootfile(line_ptr);
5868 #ifdef CONFIG_FEATURE_OSF_LABEL
5873 if (label_dos == current_label_type)
5874 toggle_dos_compatibility_flag();
5875 #ifdef CONFIG_FEATURE_SUN_LABEL
5876 else if (label_sun == current_label_type)
5877 toggle_sunflags(get_partition(1, partitions),
5880 #ifdef CONFIG_FEATURE_SGI_LABEL
5881 else if (label_sgi == current_label_type)
5882 sgi_set_swappartition(
5883 get_partition(1, partitions));
5891 #ifdef CONFIG_FEATURE_SGI_LABEL
5892 /* If sgi_label then don't use get_existing_partition,
5893 let the user select a partition, since
5894 get_existing_partition() only works for Linux-like
5896 if (label_sgi != current_label_type) {
5897 j = get_existing_partition(1, partitions);
5899 j = get_partition(1, partitions);
5902 j = get_existing_partition(1, partitions);
5905 delete_partition(j);
5909 #ifdef CONFIG_FEATURE_SGI_LABEL
5910 if (label_sgi == current_label_type)
5916 list_types(get_sys_types());
5935 #ifdef CONFIG_FEATURE_SUN_LABEL
5949 write_table(); /* does not return */
5951 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
5953 #ifdef CONFIG_FEATURE_SGI_LABEL
5954 if (label_sgi == current_label_type) {
5956 _("\n\tSorry, no experts menu for SGI "
5957 "partition tables available.\n\n"));
5970 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */