1 /* fdisk.c -- Partition table manipulator for Linux.
3 * Copyright (C) 1992 A. V. Le Blanc (LeBlanc@mcc.ac.uk)
4 * Copyright (C) 2001,2002 Vladimir Oleynik <dzo@simtreas.ru> (initial bb port)
6 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
9 /* Current changes have not compatibility with this version */
10 #define UTIL_LINUX_VERSION "2.12"
15 #define PROC_PARTITIONS "/proc/partitions"
18 #include <sys/types.h>
19 #include <sys/stat.h> /* stat */
28 #include <assert.h> /* assert */
31 #include <sys/ioctl.h>
32 #include <sys/param.h>
33 #include <sys/sysmacros.h> /* major */
35 #include <stdint.h> /* for uint32_t, uint16_t, uint8_t, int16_t, etc */
37 /* Copied from linux/major.h */
38 #define FLOPPY_MAJOR 2
40 #include <sys/utsname.h>
46 #define BLKRRPART _IO(0x12,95) /* re-read partition table */
47 #define BLKGETSIZE _IO(0x12,96) /* return device size */
48 #define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */
49 #define BLKSSZGET _IO(0x12,104) /* get block device sector size */
51 /* Avoid conflicts with the 2.6 kernel headers, which define
52 * _IOR rather differently */
54 #define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size))
55 #define BLKGETSIZE64 _IOR(0x12,114,uint64_t)
61 #define DEFAULT_SECTOR_SIZE 512
62 #define MAX_SECTOR_SIZE 2048
63 #define SECTOR_SIZE 512 /* still used in BSD code */
64 #define MAXIMUM_PARTS 60
66 #define ACTIVE_FLAG 0x80
69 #define WIN98_EXTENDED 0x0f
70 #define LINUX_PARTITION 0x81
71 #define LINUX_SWAP 0x82
72 #define LINUX_NATIVE 0x83
73 #define LINUX_EXTENDED 0x85
74 #define LINUX_LVM 0x8e
75 #define LINUX_RAID 0xfd
80 #define IS_EXTENDED(i) \
81 ((i) == EXTENDED || (i) == WIN98_EXTENDED || (i) == LINUX_EXTENDED)
83 #define SIZE(a) (sizeof(a)/sizeof((a)[0]))
85 #define cround(n) (display_in_cyl_units ? ((n)/units_per_sector)+1 : (n))
86 #define scround(x) (((x)+units_per_sector-1)/units_per_sector)
88 #ifdef CONFIG_FEATURE_SUN_LABEL
89 #define SCSI_IOCTL_GET_IDLUN 0x5382
93 /* including <linux/hdreg.h> also fails */
96 unsigned char sectors;
97 unsigned short cylinders;
101 #define HDIO_GETGEO 0x0301 /* get device geometry */
108 static uint sector_size = DEFAULT_SECTOR_SIZE;
109 static uint user_set_sector_size;
110 static uint sector_offset = 1;
113 * Raw disk label. For DOS-type partition tables the MBR,
114 * with descriptions of the primary partitions.
116 #if (MAX_SECTOR_SIZE) > (BUFSIZ+1)
117 static char MBRbuffer[MAX_SECTOR_SIZE];
119 # define MBRbuffer bb_common_bufsiz1
122 #ifdef CONFIG_FEATURE_OSF_LABEL
123 static int possibly_osf_label;
126 static uint heads, sectors, cylinders;
127 static void update_units(void);
131 * return partition name - uses static storage unless buf is supplied
134 partname(const char *dev, int pno, int lth)
136 static char buffer[80];
143 bufsiz = sizeof(buffer);
148 if (isdigit(dev[w-1]))
151 /* devfs kludge - note: fdisk partition names are not supposed
152 to equal kernel names, so there is no reason to do this */
153 if (strcmp(dev + w - 4, "disc") == 0) {
161 snprintf(bufp, bufsiz, "%*.*s%s%-2u",
162 lth-wp-2, w, dev, p, pno);
164 snprintf(bufp, bufsiz, "%.*s%s%-2u", w, dev, p, pno);
170 unsigned char boot_ind; /* 0x80 - active */
171 unsigned char head; /* starting head */
172 unsigned char sector; /* starting sector */
173 unsigned char cyl; /* starting cylinder */
174 unsigned char sys_ind; /* What partition type */
175 unsigned char end_head; /* end head */
176 unsigned char end_sector; /* end sector */
177 unsigned char end_cyl; /* end cylinder */
178 unsigned char start4[4]; /* starting sector counting from 0 */
179 unsigned char size4[4]; /* nr of sectors in partition */
183 ioctl_error, unable_to_open, unable_to_read, unable_to_seek,
188 label_dos, label_sun, label_sgi, label_aix, label_osf
191 enum action { fdisk, require, try_only, create_empty_dos, create_empty_sun };
193 static enum label_type current_label_type;
195 static const char *disk_device;
196 static int fd; /* the disk */
197 static int partitions = 4; /* maximum partition + 1 */
198 static uint display_in_cyl_units = 1;
199 static uint units_per_sector = 1;
200 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
201 static char *line_ptr;
202 static void change_units(void);
203 static void reread_partition_table(int leave);
204 static void delete_partition(int i);
205 static int get_partition(int warn, int max);
206 static void list_types(const struct systypes *sys);
207 static uint read_int(uint low, uint dflt, uint high, uint base, char *mesg);
209 static const char *partition_type(unsigned char type);
210 static void fdisk_fatal(enum failure why) ATTRIBUTE_NORETURN;
211 static void get_geometry(void);
212 static int get_boot(enum action what);
217 #define hex_val(c) ({ \
219 isdigit(_c) ? _c - '0' : \
220 tolower(_c) + 10 - 'a'; \
224 #define LINE_LENGTH 800
225 #define pt_offset(b, n) ((struct partition *)((b) + 0x1be + \
226 (n) * sizeof(struct partition)))
227 #define sector(s) ((s) & 0x3f)
228 #define cylinder(s, c) ((c) | (((s) & 0xc0) << 2))
230 #define hsc2sector(h,s,c) (sector(s) - 1 + sectors * \
231 ((h) + heads * cylinder(s,c)))
232 #define set_hsc(h,s,c,sector) { \
233 s = sector % sectors + 1; \
235 h = sector % heads; \
238 s |= (sector >> 2) & 0xc0; \
242 static int32_t get_start_sect(const struct partition *p);
243 static int32_t get_nr_sects(const struct partition *p);
246 * per partition table entry data
248 * The four primary partitions have the same sectorbuffer (MBRbuffer)
249 * and have NULL ext_pointer.
250 * Each logical partition table entry has two pointers, one for the
251 * partition and one link to the next one.
254 struct partition *part_table; /* points into sectorbuffer */
255 struct partition *ext_pointer; /* points into sectorbuffer */
256 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
257 char changed; /* boolean */
259 off_t offset; /* disk sector number */
260 char *sectorbuffer; /* disk sector contents */
261 } ptes[MAXIMUM_PARTS];
264 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
266 set_all_unchanged(void)
270 for (i = 0; i < MAXIMUM_PARTS; i++)
279 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
281 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_OSF_LABEL)
282 static struct partition *
283 get_part_table(int i)
285 return ptes[i].part_table;
291 { /* n==1: use singular */
293 return display_in_cyl_units ? _("cylinder") : _("sector");
295 return display_in_cyl_units ? _("cylinders") : _("sectors");
299 valid_part_table_flag(const char *mbuffer) {
300 const unsigned char *b = (const unsigned char *)mbuffer;
301 return (b[510] == 0x55 && b[511] == 0xaa);
304 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
305 static char line_buffer[LINE_LENGTH];
307 /* read line; return 0 or first char */
311 static int got_eof = 0;
313 fflush (stdout); /* requested by niles@scyld.com */
314 line_ptr = line_buffer;
315 if (!fgets(line_buffer, LINE_LENGTH, stdin)) {
317 got_eof++; /* user typed ^D ? */
319 fprintf(stderr, _("\ngot EOF thrice - exiting..\n"));
324 while (*line_ptr && !isgraph(*line_ptr))
330 read_char(const char *mesg)
334 } while (!read_line());
339 read_chars(const char *mesg)
350 read_hex(const struct systypes *sys)
355 read_char(_("Hex code (type L to list codes): "));
356 if (*line_ptr == 'l' || *line_ptr == 'L')
358 else if (isxdigit (*line_ptr)) {
361 hex = hex << 4 | hex_val(*line_ptr++);
362 while (isxdigit(*line_ptr));
367 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
369 #ifdef CONFIG_FEATURE_AIX_LABEL
371 * Copyright (C) Andreas Neuper, Sep 1998.
372 * This file may be redistributed under
373 * the terms of the GNU Public License.
377 unsigned int magic; /* expect AIX_LABEL_MAGIC */
378 unsigned int fillbytes1[124];
379 unsigned int physical_volume_id;
380 unsigned int fillbytes2[124];
383 #define AIX_LABEL_MAGIC 0xc9c2d4c1
384 #define AIX_LABEL_MAGIC_SWAPPED 0xc1d4c2c9
385 #define AIX_INFO_MAGIC 0x00072959
386 #define AIX_INFO_MAGIC_SWAPPED 0x59290700
388 #define aixlabel ((aix_partition *)MBRbuffer)
393 * 1999-03-20 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
394 * Internationalization
396 * 2003-03-20 Phillip Kesling <pkesling@sgi.com>
400 static int aix_other_endian;
401 static short aix_volumes = 1;
404 * only dealing with free blocks here
411 _("\n\tThere is a valid AIX label on this disk.\n"
412 "\tUnfortunately Linux cannot handle these\n"
413 "\tdisks at the moment. Nevertheless some\n"
415 "\t1. fdisk will destroy its contents on write.\n"
416 "\t2. Be sure that this disk is NOT a still vital\n"
417 "\t part of a volume group. (Otherwise you may\n"
418 "\t erase the other disks as well, if unmirrored.)\n"
419 "\t3. Before deleting this physical volume be sure\n"
420 "\t to remove the disk logically from your AIX\n"
421 "\t machine. (Otherwise you become an AIXpert).")
426 check_aix_label(void)
428 if (aixlabel->magic != AIX_LABEL_MAGIC &&
429 aixlabel->magic != AIX_LABEL_MAGIC_SWAPPED) {
430 current_label_type = 0;
431 aix_other_endian = 0;
434 aix_other_endian = (aixlabel->magic == AIX_LABEL_MAGIC_SWAPPED);
436 current_label_type = label_aix;
440 /*aix_nolabel();*/ /* %% */
441 /*aix_label = 1;*/ /* %% */
444 #endif /* AIX_LABEL */
446 #ifdef CONFIG_FEATURE_OSF_LABEL
448 * Copyright (c) 1987, 1988 Regents of the University of California.
449 * All rights reserved.
451 * Redistribution and use in source and binary forms, with or without
452 * modification, are permitted provided that the following conditions
454 * 1. Redistributions of source code must retain the above copyright
455 * notice, this list of conditions and the following disclaimer.
456 * 2. Redistributions in binary form must reproduce the above copyright
457 * notice, this list of conditions and the following disclaimer in the
458 * documentation and/or other materials provided with the distribution.
459 * 3. All advertising materials mentioning features or use of this software
460 * must display the following acknowledgment:
461 * This product includes software developed by the University of
462 * California, Berkeley and its contributors.
463 * 4. Neither the name of the University nor the names of its contributors
464 * may be used to endorse or promote products derived from this software
465 * without specific prior written permission.
467 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
468 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
469 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
470 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
471 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
472 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
473 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
474 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
475 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
476 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
481 #ifndef BSD_DISKMAGIC
482 #define BSD_DISKMAGIC ((uint32_t) 0x82564557)
485 #ifndef BSD_MAXPARTITIONS
486 #define BSD_MAXPARTITIONS 16
489 #define BSD_LINUX_BOOTDIR "/usr/ucb/mdec"
491 #if defined (i386) || defined (__sparc__) || defined (__arm__) || defined (__mips__) || defined (__s390__) || defined (__sh__) || defined(__x86_64__)
492 #define BSD_LABELSECTOR 1
493 #define BSD_LABELOFFSET 0
494 #elif defined (__alpha__) || defined (__powerpc__) || defined (__ia64__) || defined (__hppa__)
495 #define BSD_LABELSECTOR 0
496 #define BSD_LABELOFFSET 64
497 #elif defined (__s390__) || defined (__s390x__)
498 #define BSD_LABELSECTOR 1
499 #define BSD_LABELOFFSET 0
501 #error unknown architecture
504 #define BSD_BBSIZE 8192 /* size of boot area, with label */
505 #define BSD_SBSIZE 8192 /* max size of fs superblock */
507 struct xbsd_disklabel {
508 uint32_t d_magic; /* the magic number */
509 int16_t d_type; /* drive type */
510 int16_t d_subtype; /* controller/d_type specific */
511 char d_typename[16]; /* type name, e.g. "eagle" */
512 char d_packname[16]; /* pack identifier */
514 uint32_t d_secsize; /* # of bytes per sector */
515 uint32_t d_nsectors; /* # of data sectors per track */
516 uint32_t d_ntracks; /* # of tracks per cylinder */
517 uint32_t d_ncylinders; /* # of data cylinders per unit */
518 uint32_t d_secpercyl; /* # of data sectors per cylinder */
519 uint32_t d_secperunit; /* # of data sectors per unit */
521 * Spares (bad sector replacements) below
522 * are not counted in d_nsectors or d_secpercyl.
523 * Spare sectors are assumed to be physical sectors
524 * which occupy space at the end of each track and/or cylinder.
526 uint16_t d_sparespertrack; /* # of spare sectors per track */
527 uint16_t d_sparespercyl; /* # of spare sectors per cylinder */
529 * Alternate cylinders include maintenance, replacement,
530 * configuration description areas, etc.
532 uint32_t d_acylinders; /* # of alt. cylinders per unit */
534 /* hardware characteristics: */
536 * d_interleave, d_trackskew and d_cylskew describe perturbations
537 * in the media format used to compensate for a slow controller.
538 * Interleave is physical sector interleave, set up by the formatter
539 * or controller when formatting. When interleaving is in use,
540 * logically adjacent sectors are not physically contiguous,
541 * but instead are separated by some number of sectors.
542 * It is specified as the ratio of physical sectors traversed
543 * per logical sector. Thus an interleave of 1:1 implies contiguous
544 * layout, while 2:1 implies that logical sector 0 is separated
545 * by one sector from logical sector 1.
546 * d_trackskew is the offset of sector 0 on track N
547 * relative to sector 0 on track N-1 on the same cylinder.
548 * Finally, d_cylskew is the offset of sector 0 on cylinder N
549 * relative to sector 0 on cylinder N-1.
551 uint16_t d_rpm; /* rotational speed */
552 uint16_t d_interleave; /* hardware sector interleave */
553 uint16_t d_trackskew; /* sector 0 skew, per track */
554 uint16_t d_cylskew; /* sector 0 skew, per cylinder */
555 uint32_t d_headswitch; /* head switch time, usec */
556 uint32_t d_trkseek; /* track-to-track seek, usec */
557 uint32_t d_flags; /* generic flags */
559 uint32_t d_drivedata[NDDATA]; /* drive-type specific information */
561 uint32_t d_spare[NSPARE]; /* reserved for future use */
562 uint32_t d_magic2; /* the magic number (again) */
563 uint16_t d_checksum; /* xor of data incl. partitions */
564 /* filesystem and partition information: */
565 uint16_t d_npartitions; /* number of partitions in following */
566 uint32_t d_bbsize; /* size of boot area at sn0, bytes */
567 uint32_t d_sbsize; /* max size of fs superblock, bytes */
568 struct xbsd_partition { /* the partition table */
569 uint32_t p_size; /* number of sectors in partition */
570 uint32_t p_offset; /* starting sector */
571 uint32_t p_fsize; /* filesystem basic fragment size */
572 uint8_t p_fstype; /* filesystem type, see below */
573 uint8_t p_frag; /* filesystem fragments per block */
574 uint16_t p_cpg; /* filesystem cylinders per group */
575 } d_partitions[BSD_MAXPARTITIONS]; /* actually may be more */
579 #define BSD_DTYPE_SMD 1 /* SMD, XSMD; VAX hp/up */
580 #define BSD_DTYPE_MSCP 2 /* MSCP */
581 #define BSD_DTYPE_DEC 3 /* other DEC (rk, rl) */
582 #define BSD_DTYPE_SCSI 4 /* SCSI */
583 #define BSD_DTYPE_ESDI 5 /* ESDI interface */
584 #define BSD_DTYPE_ST506 6 /* ST506 etc. */
585 #define BSD_DTYPE_HPIB 7 /* CS/80 on HP-IB */
586 #define BSD_DTYPE_HPFL 8 /* HP Fiber-link */
587 #define BSD_DTYPE_FLOPPY 10 /* floppy */
589 /* d_subtype values: */
590 #define BSD_DSTYPE_INDOSPART 0x8 /* is inside dos partition */
591 #define BSD_DSTYPE_DOSPART(s) ((s) & 3) /* dos partition number */
592 #define BSD_DSTYPE_GEOMETRY 0x10 /* drive params in label */
595 static const char * const xbsd_dktypenames[] = {
609 #define BSD_DKMAXTYPES (sizeof(xbsd_dktypenames) / sizeof(xbsd_dktypenames[0]) - 1)
613 * Filesystem type and version.
614 * Used to interpret other filesystem-specific
615 * per-partition information.
617 #define BSD_FS_UNUSED 0 /* unused */
618 #define BSD_FS_SWAP 1 /* swap */
619 #define BSD_FS_V6 2 /* Sixth Edition */
620 #define BSD_FS_V7 3 /* Seventh Edition */
621 #define BSD_FS_SYSV 4 /* System V */
622 #define BSD_FS_V71K 5 /* V7 with 1K blocks (4.1, 2.9) */
623 #define BSD_FS_V8 6 /* Eighth Edition, 4K blocks */
624 #define BSD_FS_BSDFFS 7 /* 4.2BSD fast file system */
625 #define BSD_FS_BSDLFS 9 /* 4.4BSD log-structured file system */
626 #define BSD_FS_OTHER 10 /* in use, but unknown/unsupported */
627 #define BSD_FS_HPFS 11 /* OS/2 high-performance file system */
628 #define BSD_FS_ISO9660 12 /* ISO-9660 filesystem (cdrom) */
629 #define BSD_FS_ISOFS BSD_FS_ISO9660
630 #define BSD_FS_BOOT 13 /* partition contains bootstrap */
631 #define BSD_FS_ADOS 14 /* AmigaDOS fast file system */
632 #define BSD_FS_HFS 15 /* Macintosh HFS */
633 #define BSD_FS_ADVFS 16 /* Digital Unix AdvFS */
635 /* this is annoying, but it's also the way it is :-( */
637 #define BSD_FS_EXT2 8 /* ext2 file system */
639 #define BSD_FS_MSDOS 8 /* MS-DOS file system */
643 static const struct systypes xbsd_fstypes[] = {
644 { "\x00" "unused" }, /* BSD_FS_UNUSED */
645 { "\x01" "swap" }, /* BSD_FS_SWAP */
646 { "\x02" "Version 6" }, /* BSD_FS_V6 */
647 { "\x03" "Version 7" }, /* BSD_FS_V7 */
648 { "\x04" "System V" }, /* BSD_FS_SYSV */
649 { "\x05" "4.1BSD" }, /* BSD_FS_V71K */
650 { "\x06" "Eighth Edition" }, /* BSD_FS_V8 */
651 { "\x07" "4.2BSD" }, /* BSD_FS_BSDFFS */
653 { "\x08" "ext2" }, /* BSD_FS_EXT2 */
655 { "\x08" "MS-DOS" }, /* BSD_FS_MSDOS */
657 { "\x09" "4.4LFS" }, /* BSD_FS_BSDLFS */
658 { "\x0a" "unknown" }, /* BSD_FS_OTHER */
659 { "\x0b" "HPFS" }, /* BSD_FS_HPFS */
660 { "\x0c" "ISO-9660" }, /* BSD_FS_ISO9660 */
661 { "\x0d" "boot" }, /* BSD_FS_BOOT */
662 { "\x0e" "ADOS" }, /* BSD_FS_ADOS */
663 { "\x0f" "HFS" }, /* BSD_FS_HFS */
664 { "\x10" "AdvFS" }, /* BSD_FS_ADVFS */
667 #define BSD_FSMAXTYPES (SIZE(xbsd_fstypes)-1)
672 * flags shared by various drives:
674 #define BSD_D_REMOVABLE 0x01 /* removable media */
675 #define BSD_D_ECC 0x02 /* supports ECC */
676 #define BSD_D_BADSECT 0x04 /* supports bad sector forw. */
677 #define BSD_D_RAMDISK 0x08 /* disk emulator */
678 #define BSD_D_CHAIN 0x10 /* can do back-back transfers */
679 #define BSD_D_DOSPART 0x20 /* within MSDOS partition */
681 #endif /* OSF_LABEL */
684 * Copyright (C) Andreas Neuper, Sep 1998.
685 * This file may be modified and redistributed under
686 * the terms of the GNU Public License.
689 struct device_parameter { /* 48 bytes */
693 unsigned char sparecyl;
694 unsigned short pcylcount;
695 unsigned short head_vol0;
696 unsigned short ntrks; /* tracks in cyl 0 or vol 0 */
697 unsigned char cmd_tag_queue_depth;
698 unsigned char unused0;
699 unsigned short unused1;
700 unsigned short nsect; /* sectors/tracks in cyl 0 or vol 0 */
701 unsigned short bytes;
702 unsigned short ilfact;
703 unsigned int flags; /* controller flags */
704 unsigned int datarate;
705 unsigned int retries_on_error;
706 unsigned int ms_per_word;
707 unsigned short xylogics_gap1;
708 unsigned short xylogics_syncdelay;
709 unsigned short xylogics_readdelay;
710 unsigned short xylogics_gap2;
711 unsigned short xylogics_readgate;
712 unsigned short xylogics_writecont;
715 #define SGI_VOLHDR 0x00
716 /* 1 and 2 were used for drive types no longer supported by SGI */
717 #define SGI_SWAP 0x03
718 /* 4 and 5 were for filesystem types SGI haven't ever supported on MIPS CPUs */
719 #define SGI_VOLUME 0x06
721 #define SGI_LVOL 0x08
722 #define SGI_RLVOL 0x09
724 #define SGI_XFSLOG 0x0b
727 #define ENTIRE_DISK SGI_VOLUME
731 #define SECTOR_SLIP 0x01
732 #define SECTOR_FWD 0x02
733 #define TRACK_FWD 0x04
734 #define TRACK_MULTIVOL 0x08
735 #define IGNORE_ERRORS 0x10
737 #define ENABLE_CMDTAGQ 0x40
740 unsigned int magic; /* expect SGI_LABEL_MAGIC */
741 unsigned short boot_part; /* active boot partition */
742 unsigned short swap_part; /* active swap partition */
743 unsigned char boot_file[16]; /* name of the bootfile */
744 struct device_parameter devparam; /* 1 * 48 bytes */
745 struct volume_directory { /* 15 * 16 bytes */
746 unsigned char vol_file_name[8]; /* a character array */
747 unsigned int vol_file_start; /* number of logical block */
748 unsigned int vol_file_size; /* number of bytes */
750 struct sgi_partition { /* 16 * 12 bytes */
751 unsigned int num_sectors; /* number of blocks */
752 unsigned int start_sector; /* must be cylinder aligned */
756 unsigned int fillbytes;
760 unsigned int magic; /* looks like a magic number */
769 unsigned char scsi_string[50];
770 unsigned char serial[137];
771 unsigned short check1816;
772 unsigned char installer[225];
775 #define SGI_LABEL_MAGIC 0x0be5a941
776 #define SGI_LABEL_MAGIC_SWAPPED 0x41a9e50b
777 #define SGI_INFO_MAGIC 0x00072959
778 #define SGI_INFO_MAGIC_SWAPPED 0x59290700
779 #define SGI_SSWAP16(x) (sgi_other_endian ? __swap16(x) \
781 #define SGI_SSWAP32(x) (sgi_other_endian ? __swap32(x) \
784 #define sgilabel ((sgi_partition *)MBRbuffer)
785 #define sgiparam (sgilabel->devparam)
788 unsigned char info[128]; /* Informative text string */
789 unsigned char spare0[14];
791 unsigned char spare1;
793 unsigned char spare2;
796 unsigned char spare1[246]; /* Boot information etc. */
797 unsigned short rspeed; /* Disk rotational speed */
798 unsigned short pcylcount; /* Physical cylinder count */
799 unsigned short sparecyl; /* extra sects per cylinder */
800 unsigned char spare2[4]; /* More magic... */
801 unsigned short ilfact; /* Interleave factor */
802 unsigned short ncyl; /* Data cylinder count */
803 unsigned short nacyl; /* Alt. cylinder count */
804 unsigned short ntrks; /* Tracks per cylinder */
805 unsigned short nsect; /* Sectors per track */
806 unsigned char spare3[4]; /* Even more magic... */
807 struct sun_partition {
808 uint32_t start_cylinder;
809 uint32_t num_sectors;
811 unsigned short magic; /* Magic number */
812 unsigned short csum; /* Label xor'd checksum */
816 #define SUN_LABEL_MAGIC 0xDABE
817 #define SUN_LABEL_MAGIC_SWAPPED 0xBEDA
818 #define sunlabel ((sun_partition *)MBRbuffer)
819 #define SUN_SSWAP16(x) (sun_other_endian ? __swap16(x) \
821 #define SUN_SSWAP32(x) (sun_other_endian ? __swap32(x) \
825 #ifdef CONFIG_FEATURE_OSF_LABEL
828 19990319 - Arnaldo Carvalho de Melo <acme@conectiva.com.br> - i18n/nls
830 20000101 - David Huggins-Daines <dhuggins@linuxcare.com> - Better
831 support for OSF/1 disklabels on Alpha.
832 Also fixed unaligned accesses in alpha_bootblock_checksum()
835 #define FREEBSD_PARTITION 0xa5
836 #define NETBSD_PARTITION 0xa9
838 static void xbsd_delete_part(void);
839 static void xbsd_new_part(void);
840 static void xbsd_write_disklabel(void);
841 static int xbsd_create_disklabel(void);
842 static void xbsd_edit_disklabel(void);
843 static void xbsd_write_bootstrap(void);
844 static void xbsd_change_fstype(void);
845 static int xbsd_get_part_index(int max);
846 static int xbsd_check_new_partition(int *i);
847 static void xbsd_list_types(void);
848 static u_short xbsd_dkcksum(struct xbsd_disklabel *lp);
849 static int xbsd_initlabel(struct partition *p, struct xbsd_disklabel *d);
850 static int xbsd_readlabel(struct partition *p, struct xbsd_disklabel *d);
851 static int xbsd_writelabel(struct partition *p, struct xbsd_disklabel *d);
853 #if defined (__alpha__)
854 static void alpha_bootblock_checksum(char *boot);
857 #if !defined (__alpha__)
858 static int xbsd_translate_fstype(int linux_type);
859 static void xbsd_link_part(void);
860 static struct partition *xbsd_part;
861 static int xbsd_part_index;
864 #if defined (__alpha__)
865 /* We access this through a uint64_t * when checksumming */
866 static char disklabelbuffer[BSD_BBSIZE] ATTRIBUTE_ALIGNED(8);
868 static char disklabelbuffer[BSD_BBSIZE];
871 static struct xbsd_disklabel xbsd_dlabel;
873 #define bsd_cround(n) \
874 (display_in_cyl_units ? ((n)/xbsd_dlabel.d_secpercyl) + 1 : (n))
877 * Test whether the whole disk has BSD disk label magic.
879 * Note: often reformatting with DOS-type label leaves the BSD magic,
880 * so this does not mean that there is a BSD disk label.
883 check_osf_label(void)
885 if (xbsd_readlabel(NULL, &xbsd_dlabel) == 0)
890 static void xbsd_print_disklabel(int);
893 btrydev(const char * dev)
895 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
897 printf(_("\nBSD label for device: %s\n"), dev);
898 xbsd_print_disklabel (0);
905 puts (_("Command action"));
906 puts (_("\td\tdelete a BSD partition"));
907 puts (_("\te\tedit drive data"));
908 puts (_("\ti\tinstall bootstrap"));
909 puts (_("\tl\tlist known filesystem types"));
910 puts (_("\tm\tprint this menu"));
911 puts (_("\tn\tadd a new BSD partition"));
912 puts (_("\tp\tprint BSD partition table"));
913 puts (_("\tq\tquit without saving changes"));
914 puts (_("\tr\treturn to main menu"));
915 puts (_("\ts\tshow complete disklabel"));
916 puts (_("\tt\tchange a partition's filesystem id"));
917 puts (_("\tu\tchange units (cylinders/sectors)"));
918 puts (_("\tw\twrite disklabel to disk"));
919 #if !defined (__alpha__)
920 puts (_("\tx\tlink BSD partition to non-BSD partition"));
924 #if !defined (__alpha__)
932 is_bsd_partition_type(int type)
934 return (type == FREEBSD_PARTITION ||
935 type == hidden(FREEBSD_PARTITION) ||
936 type == NETBSD_PARTITION ||
937 type == hidden(NETBSD_PARTITION));
944 #if !defined (__alpha__)
948 for (t = 0; t < 4; t++) {
949 p = get_part_table(t);
950 if (p && is_bsd_partition_type(p->sys_ind)) {
953 ss = get_start_sect(xbsd_part);
955 fprintf(stderr, _("Partition %s has invalid starting sector 0.\n"),
956 partname(disk_device, t+1, 0));
959 printf(_("Reading disklabel of %s at sector %d.\n"),
960 partname(disk_device, t+1, 0), ss + BSD_LABELSECTOR);
961 if (xbsd_readlabel(xbsd_part, &xbsd_dlabel) == 0)
962 if (xbsd_create_disklabel() == 0)
969 printf(_("There is no *BSD partition on %s.\n"), disk_device);
973 #elif defined (__alpha__)
975 if (xbsd_readlabel(NULL, &xbsd_dlabel) == 0)
976 if (xbsd_create_disklabel() == 0)
983 switch (tolower(read_char(_("BSD disklabel command (m for help): ")))) {
988 xbsd_edit_disklabel();
991 xbsd_write_bootstrap();
1000 xbsd_print_disklabel(0);
1008 xbsd_print_disklabel(1);
1011 xbsd_change_fstype();
1017 xbsd_write_disklabel();
1019 #if !defined (__alpha__)
1032 xbsd_delete_part(void)
1036 i = xbsd_get_part_index(xbsd_dlabel.d_npartitions);
1037 xbsd_dlabel.d_partitions[i].p_size = 0;
1038 xbsd_dlabel.d_partitions[i].p_offset = 0;
1039 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
1040 if (xbsd_dlabel.d_npartitions == i + 1)
1041 while (xbsd_dlabel.d_partitions[xbsd_dlabel.d_npartitions-1].p_size == 0)
1042 xbsd_dlabel.d_npartitions--;
1052 if (!xbsd_check_new_partition(&i))
1055 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
1056 begin = get_start_sect(xbsd_part);
1057 end = begin + get_nr_sects(xbsd_part) - 1;
1060 end = xbsd_dlabel.d_secperunit - 1;
1063 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
1064 begin = read_int(bsd_cround(begin), bsd_cround(begin), bsd_cround(end),
1067 if (display_in_cyl_units)
1068 begin = (begin - 1) * xbsd_dlabel.d_secpercyl;
1070 snprintf(mesg, sizeof(mesg), _("Last %s or +size or +sizeM or +sizeK"),
1071 str_units(SINGULAR));
1072 end = read_int(bsd_cround (begin), bsd_cround (end), bsd_cround (end),
1073 bsd_cround (begin), mesg);
1075 if (display_in_cyl_units)
1076 end = end * xbsd_dlabel.d_secpercyl - 1;
1078 xbsd_dlabel.d_partitions[i].p_size = end - begin + 1;
1079 xbsd_dlabel.d_partitions[i].p_offset = begin;
1080 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
1084 xbsd_print_disklabel(int show_all)
1086 struct xbsd_disklabel *lp = &xbsd_dlabel;
1087 struct xbsd_partition *pp;
1091 #if defined (__alpha__)
1092 printf("# %s:\n", disk_device);
1094 printf("# %s:\n", partname(disk_device, xbsd_part_index+1, 0));
1096 if ((unsigned) lp->d_type < BSD_DKMAXTYPES)
1097 printf(_("type: %s\n"), xbsd_dktypenames[lp->d_type]);
1099 printf(_("type: %d\n"), lp->d_type);
1100 printf(_("disk: %.*s\n"), (int) sizeof(lp->d_typename), lp->d_typename);
1101 printf(_("label: %.*s\n"), (int) sizeof(lp->d_packname), lp->d_packname);
1102 printf(_("flags:"));
1103 if (lp->d_flags & BSD_D_REMOVABLE)
1104 printf(_(" removable"));
1105 if (lp->d_flags & BSD_D_ECC)
1107 if (lp->d_flags & BSD_D_BADSECT)
1108 printf(_(" badsect"));
1110 /* On various machines the fields of *lp are short/int/long */
1111 /* In order to avoid problems, we cast them all to long. */
1112 printf(_("bytes/sector: %ld\n"), (long) lp->d_secsize);
1113 printf(_("sectors/track: %ld\n"), (long) lp->d_nsectors);
1114 printf(_("tracks/cylinder: %ld\n"), (long) lp->d_ntracks);
1115 printf(_("sectors/cylinder: %ld\n"), (long) lp->d_secpercyl);
1116 printf(_("cylinders: %ld\n"), (long) lp->d_ncylinders);
1117 printf(_("rpm: %d\n"), lp->d_rpm);
1118 printf(_("interleave: %d\n"), lp->d_interleave);
1119 printf(_("trackskew: %d\n"), lp->d_trackskew);
1120 printf(_("cylinderskew: %d\n"), lp->d_cylskew);
1121 printf(_("headswitch: %ld\t\t# milliseconds\n"),
1122 (long) lp->d_headswitch);
1123 printf(_("track-to-track seek: %ld\t# milliseconds\n"),
1124 (long) lp->d_trkseek);
1125 printf(_("drivedata: "));
1126 for (i = NDDATA - 1; i >= 0; i--)
1127 if (lp->d_drivedata[i])
1131 for (j = 0; j <= i; j++)
1132 printf("%ld ", (long) lp->d_drivedata[j]);
1134 printf(_("\n%d partitions:\n"), lp->d_npartitions);
1135 printf(_("# start end size fstype [fsize bsize cpg]\n"));
1136 pp = lp->d_partitions;
1137 for (i = 0; i < lp->d_npartitions; i++, pp++) {
1139 if (display_in_cyl_units && lp->d_secpercyl) {
1140 printf(" %c: %8ld%c %8ld%c %8ld%c ",
1142 (long) pp->p_offset / lp->d_secpercyl + 1,
1143 (pp->p_offset % lp->d_secpercyl) ? '*' : ' ',
1144 (long) (pp->p_offset + pp->p_size + lp->d_secpercyl - 1) / lp->d_secpercyl,
1145 ((pp->p_offset + pp->p_size) % lp->d_secpercyl) ? '*' : ' ',
1146 (long) pp->p_size / lp->d_secpercyl,
1147 (pp->p_size % lp->d_secpercyl) ? '*' : ' '
1150 printf(" %c: %8ld %8ld %8ld ",
1152 (long) pp->p_offset,
1153 (long) pp->p_offset + pp->p_size - 1,
1158 if ((unsigned) pp->p_fstype < BSD_FSMAXTYPES)
1159 printf("%8.8s", xbsd_fstypes[pp->p_fstype].name);
1161 printf("%8x", pp->p_fstype);
1163 switch (pp->p_fstype) {
1165 printf(" %5ld %5ld %5.5s ",
1166 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, "");
1169 printf(" %5ld %5ld %5d ",
1170 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, pp->p_cpg);
1173 printf("%22.22s", "");
1182 xbsd_write_disklabel(void)
1184 #if defined (__alpha__)
1185 printf(_("Writing disklabel to %s.\n"), disk_device);
1186 xbsd_writelabel(NULL, &xbsd_dlabel);
1188 printf(_("Writing disklabel to %s.\n"),
1189 partname(disk_device, xbsd_part_index + 1, 0));
1190 xbsd_writelabel(xbsd_part, &xbsd_dlabel);
1192 reread_partition_table(0); /* no exit yet */
1196 xbsd_create_disklabel(void)
1200 #if defined (__alpha__)
1201 fprintf(stderr, _("%s contains no disklabel.\n"), disk_device);
1203 fprintf(stderr, _("%s contains no disklabel.\n"),
1204 partname(disk_device, xbsd_part_index + 1, 0));
1208 c = read_char(_("Do you want to create a disklabel? (y/n) "));
1209 if (c == 'y' || c == 'Y') {
1211 #if defined (__alpha__) || defined (__powerpc__) || defined (__hppa__) || \
1212 defined (__s390__) || defined (__s390x__)
1215 xbsd_part, &xbsd_dlabel/* not used, xbsd_part_index*/
1218 xbsd_print_disklabel (1);
1222 } else if (c == 'n')
1228 edit_int(int def, char *mesg)
1231 fputs(mesg, stdout);
1232 printf(" (%d): ", def);
1236 while (!isdigit(*line_ptr)); /* FIXME: ?!! */
1237 return atoi(line_ptr);
1241 xbsd_edit_disklabel(void)
1243 struct xbsd_disklabel *d;
1247 #if defined (__alpha__) || defined (__ia64__)
1248 d->d_secsize = (u_long) edit_int((u_long) d->d_secsize ,_("bytes/sector"));
1249 d->d_nsectors = (u_long) edit_int((u_long) d->d_nsectors ,_("sectors/track"));
1250 d->d_ntracks = (u_long) edit_int((u_long) d->d_ntracks ,_("tracks/cylinder"));
1251 d->d_ncylinders = (u_long) edit_int((u_long) d->d_ncylinders ,_("cylinders"));
1254 /* d->d_secpercyl can be != d->d_nsectors * d->d_ntracks */
1256 d->d_secpercyl = (u_long) edit_int((u_long) d->d_nsectors * d->d_ntracks,
1257 _("sectors/cylinder"));
1258 if (d->d_secpercyl <= d->d_nsectors * d->d_ntracks)
1261 printf(_("Must be <= sectors/track * tracks/cylinder (default).\n"));
1263 d->d_rpm = (u_short) edit_int((u_short) d->d_rpm ,_("rpm"));
1264 d->d_interleave = (u_short) edit_int((u_short) d->d_interleave,_("interleave"));
1265 d->d_trackskew = (u_short) edit_int((u_short) d->d_trackskew ,_("trackskew"));
1266 d->d_cylskew = (u_short) edit_int((u_short) d->d_cylskew ,_("cylinderskew"));
1267 d->d_headswitch = (u_long) edit_int((u_long) d->d_headswitch ,_("headswitch"));
1268 d->d_trkseek = (u_long) edit_int((u_long) d->d_trkseek ,_("track-to-track seek"));
1270 d->d_secperunit = d->d_secpercyl * d->d_ncylinders;
1274 xbsd_get_bootstrap (char *path, void *ptr, int size)
1278 if ((fdb = open (path, O_RDONLY)) < 0) {
1282 if (read(fdb, ptr, size) < 0) {
1287 printf(" ... %s\n", path);
1295 printf(_("\nSyncing disks.\n"));
1297 sleep(4); /* What? */
1301 xbsd_write_bootstrap(void)
1303 char *bootdir = BSD_LINUX_BOOTDIR;
1304 char path[MAXPATHLEN];
1306 struct xbsd_disklabel dl;
1310 if (xbsd_dlabel.d_type == BSD_DTYPE_SCSI)
1315 printf(_("Bootstrap: %sboot -> boot%s (%s): "),
1316 dkbasename, dkbasename, dkbasename);
1318 line_ptr[strlen(line_ptr)-1] = '\0';
1319 dkbasename = line_ptr;
1321 snprintf(path, sizeof(path), "%s/%sboot", bootdir, dkbasename);
1322 if (!xbsd_get_bootstrap(path, disklabelbuffer, (int) xbsd_dlabel.d_secsize))
1325 /* We need a backup of the disklabel (xbsd_dlabel might have changed). */
1326 d = &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE];
1327 memmove(&dl, d, sizeof(struct xbsd_disklabel));
1329 /* The disklabel will be overwritten by 0's from bootxx anyway */
1330 memset(d, 0, sizeof(struct xbsd_disklabel));
1332 snprintf(path, sizeof(path), "%s/boot%s", bootdir, dkbasename);
1333 if (!xbsd_get_bootstrap (path, &disklabelbuffer[xbsd_dlabel.d_secsize],
1334 (int) xbsd_dlabel.d_bbsize - xbsd_dlabel.d_secsize))
1337 e = d + sizeof(struct xbsd_disklabel);
1338 for (p = d; p < e; p++)
1340 fprintf(stderr, _("Bootstrap overlaps with disk label!\n"));
1344 memmove(d, &dl, sizeof(struct xbsd_disklabel));
1346 #if defined (__powerpc__) || defined (__hppa__)
1348 #elif defined (__alpha__)
1350 alpha_bootblock_checksum(disklabelbuffer);
1352 sector = get_start_sect(xbsd_part);
1355 if (lseek(fd, sector * SECTOR_SIZE, SEEK_SET) == -1)
1356 fdisk_fatal(unable_to_seek);
1357 if (BSD_BBSIZE != write(fd, disklabelbuffer, BSD_BBSIZE))
1358 fdisk_fatal(unable_to_write);
1360 #if defined (__alpha__)
1361 printf(_("Bootstrap installed on %s.\n"), disk_device);
1363 printf(_("Bootstrap installed on %s.\n"),
1364 partname (disk_device, xbsd_part_index+1, 0));
1371 xbsd_change_fstype(void)
1375 i = xbsd_get_part_index(xbsd_dlabel.d_npartitions);
1376 xbsd_dlabel.d_partitions[i].p_fstype = read_hex(xbsd_fstypes);
1380 xbsd_get_part_index(int max)
1385 snprintf(prompt, sizeof(prompt), _("Partition (a-%c): "), 'a' + max - 1);
1387 l = tolower(read_char(prompt));
1388 while (l < 'a' || l > 'a' + max - 1);
1393 xbsd_check_new_partition(int *i)
1395 /* room for more? various BSD flavours have different maxima */
1396 if (xbsd_dlabel.d_npartitions == BSD_MAXPARTITIONS) {
1399 for (t = 0; t < BSD_MAXPARTITIONS; t++)
1400 if (xbsd_dlabel.d_partitions[t].p_size == 0)
1403 if (t == BSD_MAXPARTITIONS) {
1404 fprintf(stderr, _("The maximum number of partitions "
1405 "has been created\n"));
1410 *i = xbsd_get_part_index (BSD_MAXPARTITIONS);
1412 if (*i >= xbsd_dlabel.d_npartitions)
1413 xbsd_dlabel.d_npartitions = (*i) + 1;
1415 if (xbsd_dlabel.d_partitions[*i].p_size != 0) {
1416 fprintf(stderr, _("This partition already exists.\n"));
1424 xbsd_list_types(void)
1426 list_types(xbsd_fstypes);
1430 xbsd_dkcksum(struct xbsd_disklabel *lp)
1432 u_short *start, *end;
1435 start = (u_short *) lp;
1436 end = (u_short *) &lp->d_partitions[lp->d_npartitions];
1443 xbsd_initlabel(struct partition *p, struct xbsd_disklabel *d)
1445 struct xbsd_partition *pp;
1448 memset(d, 0, sizeof(struct xbsd_disklabel));
1450 d->d_magic = BSD_DISKMAGIC;
1452 if (strncmp(disk_device, "/dev/sd", 7) == 0)
1453 d->d_type = BSD_DTYPE_SCSI;
1455 d->d_type = BSD_DTYPE_ST506;
1457 #if 0 /* not used (at least not written to disk) by NetBSD/i386 1.0 */
1458 d->d_subtype = BSD_DSTYPE_INDOSPART & pindex;
1461 #if !defined (__alpha__)
1462 d->d_flags = BSD_D_DOSPART;
1466 d->d_secsize = SECTOR_SIZE; /* bytes/sector */
1467 d->d_nsectors = sectors; /* sectors/track */
1468 d->d_ntracks = heads; /* tracks/cylinder (heads) */
1469 d->d_ncylinders = cylinders;
1470 d->d_secpercyl = sectors * heads;/* sectors/cylinder */
1471 if (d->d_secpercyl == 0)
1472 d->d_secpercyl = 1; /* avoid segfaults */
1473 d->d_secperunit = d->d_secpercyl * d->d_ncylinders;
1476 d->d_interleave = 1;
1479 d->d_headswitch = 0;
1482 d->d_magic2 = BSD_DISKMAGIC;
1483 d->d_bbsize = BSD_BBSIZE;
1484 d->d_sbsize = BSD_SBSIZE;
1486 #if !defined (__alpha__)
1487 d->d_npartitions = 4;
1488 pp = &d->d_partitions[2]; /* Partition C should be
1489 the NetBSD partition */
1490 pp->p_offset = get_start_sect(p);
1491 pp->p_size = get_nr_sects(p);
1492 pp->p_fstype = BSD_FS_UNUSED;
1493 pp = &d->d_partitions[3]; /* Partition D should be
1496 pp->p_size = d->d_secperunit;
1497 pp->p_fstype = BSD_FS_UNUSED;
1498 #elif defined (__alpha__)
1499 d->d_npartitions = 3;
1500 pp = &d->d_partitions[2]; /* Partition C should be
1503 pp->p_size = d->d_secperunit;
1504 pp->p_fstype = BSD_FS_UNUSED;
1511 * Read a xbsd_disklabel from sector 0 or from the starting sector of p.
1512 * If it has the right magic, return 1.
1515 xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d)
1519 /* p is used only to get the starting sector */
1520 #if !defined (__alpha__)
1521 sector = (p ? get_start_sect(p) : 0);
1522 #elif defined (__alpha__)
1526 if (lseek(fd, sector * SECTOR_SIZE, SEEK_SET) == -1)
1527 fdisk_fatal(unable_to_seek);
1528 if (BSD_BBSIZE != read(fd, disklabelbuffer, BSD_BBSIZE))
1529 fdisk_fatal(unable_to_read);
1531 memmove(d, &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
1532 sizeof(struct xbsd_disklabel));
1534 if (d->d_magic != BSD_DISKMAGIC || d->d_magic2 != BSD_DISKMAGIC)
1537 for (t = d->d_npartitions; t < BSD_MAXPARTITIONS; t++) {
1538 d->d_partitions[t].p_size = 0;
1539 d->d_partitions[t].p_offset = 0;
1540 d->d_partitions[t].p_fstype = BSD_FS_UNUSED;
1543 if (d->d_npartitions > BSD_MAXPARTITIONS)
1544 fprintf(stderr, _("Warning: too many partitions "
1545 "(%d, maximum is %d).\n"),
1546 d->d_npartitions, BSD_MAXPARTITIONS);
1551 xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d)
1553 unsigned int sector;
1555 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
1556 sector = get_start_sect(p) + BSD_LABELSECTOR;
1558 sector = BSD_LABELSECTOR;
1562 d->d_checksum = xbsd_dkcksum (d);
1564 /* This is necessary if we want to write the bootstrap later,
1565 otherwise we'd write the old disklabel with the bootstrap.
1567 memmove(&disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
1568 d, sizeof(struct xbsd_disklabel));
1570 #if defined (__alpha__) && BSD_LABELSECTOR == 0
1571 alpha_bootblock_checksum (disklabelbuffer);
1572 if (lseek(fd, 0, SEEK_SET) == -1)
1573 fdisk_fatal(unable_to_seek);
1574 if (BSD_BBSIZE != write(fd, disklabelbuffer, BSD_BBSIZE))
1575 fdisk_fatal(unable_to_write);
1577 if (lseek(fd, sector * SECTOR_SIZE + BSD_LABELOFFSET, SEEK_SET) == -1)
1578 fdisk_fatal(unable_to_seek);
1579 if (sizeof(struct xbsd_disklabel) != write(fd, d, sizeof(struct xbsd_disklabel)))
1580 fdisk_fatal(unable_to_write);
1587 #if !defined (__alpha__)
1589 xbsd_translate_fstype(int linux_type)
1591 switch (linux_type) {
1592 case 0x01: /* DOS 12-bit FAT */
1593 case 0x04: /* DOS 16-bit <32M */
1594 case 0x06: /* DOS 16-bit >=32M */
1595 case 0xe1: /* DOS access */
1596 case 0xe3: /* DOS R/O */
1597 case 0xf2: /* DOS secondary */
1598 return BSD_FS_MSDOS;
1599 case 0x07: /* OS/2 HPFS */
1602 return BSD_FS_OTHER;
1607 xbsd_link_part(void)
1610 struct partition *p;
1612 k = get_partition(1, partitions);
1614 if (!xbsd_check_new_partition(&i))
1617 p = get_part_table(k);
1619 xbsd_dlabel.d_partitions[i].p_size = get_nr_sects(p);
1620 xbsd_dlabel.d_partitions[i].p_offset = get_start_sect(p);
1621 xbsd_dlabel.d_partitions[i].p_fstype = xbsd_translate_fstype(p->sys_ind);
1625 #if defined (__alpha__)
1627 #if !defined(__GLIBC__)
1628 typedef unsigned long long uint64_t;
1632 alpha_bootblock_checksum(char *boot)
1637 dp = (uint64_t *)boot;
1639 for (i = 0; i < 63; i++)
1643 #endif /* __alpha__ */
1645 #endif /* OSF_LABEL */
1647 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
1648 static inline unsigned short
1649 __swap16(unsigned short x)
1651 return (((uint16_t)(x) & 0xFF) << 8) | (((uint16_t)(x) & 0xFF00) >> 8);
1654 static inline uint32_t
1655 __swap32(uint32_t x)
1657 return (((x & 0xFF) << 24) |
1658 ((x & 0xFF00) << 8) |
1659 ((x & 0xFF0000) >> 8) |
1660 ((x & 0xFF000000) >> 24));
1664 #ifdef CONFIG_FEATURE_SGI_LABEL
1669 * Copyright (C) Andreas Neuper, Sep 1998.
1670 * This file may be modified and redistributed under
1671 * the terms of the GNU Public License.
1673 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
1674 * Internationalization
1678 static int sgi_other_endian;
1680 static short sgi_volumes = 1;
1683 * only dealing with free blocks here
1690 static freeblocks freelist[17]; /* 16 partitions can produce 17 vacant slots */
1693 setfreelist(int i, unsigned int f, unsigned int l)
1695 freelist[i].first = f;
1696 freelist[i].last = l;
1700 add2freelist(unsigned int f, unsigned int l)
1703 for (i = 0; i < 17 ; i++)
1704 if (freelist[i].last == 0)
1706 setfreelist(i, f, l);
1714 for (i = 0; i < 17 ; i++)
1715 setfreelist(i, 0, 0);
1719 isinfreelist(unsigned int b)
1723 for (i = 0; i < 17 ; i++)
1724 if (freelist[i].first <= b && freelist[i].last >= b)
1725 return freelist[i].last;
1728 /* return last vacant block of this stride (never 0). */
1729 /* the '>=' is not quite correct, but simplifies the code */
1731 * end of free blocks section
1734 static const struct systypes sgi_sys_types[] = {
1735 /* SGI_VOLHDR */ { "\x00" "SGI volhdr" },
1736 /* 0x01 */ { "\x01" "SGI trkrepl" },
1737 /* 0x02 */ { "\x02" "SGI secrepl" },
1738 /* SGI_SWAP */ { "\x03" "SGI raw" },
1739 /* 0x04 */ { "\x04" "SGI bsd" },
1740 /* 0x05 */ { "\x05" "SGI sysv" },
1741 /* ENTIRE_DISK */ { "\x06" "SGI volume" },
1742 /* SGI_EFS */ { "\x07" "SGI efs" },
1743 /* 0x08 */ { "\x08" "SGI lvol" },
1744 /* 0x09 */ { "\x09" "SGI rlvol" },
1745 /* SGI_XFS */ { "\x0a" "SGI xfs" },
1746 /* SGI_XFSLOG */ { "\x0b" "SGI xfslog" },
1747 /* SGI_XLV */ { "\x0c" "SGI xlv" },
1748 /* SGI_XVM */ { "\x0d" "SGI xvm" },
1749 /* LINUX_SWAP */ { "\x82" "Linux swap" },
1750 /* LINUX_NATIVE */ { "\x83" "Linux native" },
1751 /* LINUX_LVM */ { "\x8d" "Linux LVM" },
1752 /* LINUX_RAID */ { "\xfd" "Linux RAID" },
1760 return SGI_SSWAP16(sgilabel->devparam.nsect);
1766 return SGI_SSWAP16(sgilabel->devparam.ntrks);
1770 two_s_complement_32bit_sum(unsigned int* base, int size /* in bytes */)
1773 unsigned int sum = 0;
1775 size /= sizeof(unsigned int);
1776 for (i = 0; i < size; i++)
1777 sum -= SGI_SSWAP32(base[i]);
1782 check_sgi_label(void)
1784 if (sizeof(sgilabel) > 512) {
1786 _("According to MIPS Computer Systems, Inc the "
1787 "Label must not contain more than 512 bytes\n"));
1791 if (sgilabel->magic != SGI_LABEL_MAGIC
1792 && sgilabel->magic != SGI_LABEL_MAGIC_SWAPPED) {
1793 current_label_type = label_dos;
1797 sgi_other_endian = (sgilabel->magic == SGI_LABEL_MAGIC_SWAPPED);
1799 * test for correct checksum
1801 if (two_s_complement_32bit_sum((unsigned int*)sgilabel,
1802 sizeof(*sgilabel))) {
1804 _("Detected sgi disklabel with wrong checksum.\n"));
1807 current_label_type = label_sgi;
1814 sgi_get_start_sector(int i)
1816 return SGI_SSWAP32(sgilabel->partitions[i].start_sector);
1820 sgi_get_num_sectors(int i)
1822 return SGI_SSWAP32(sgilabel->partitions[i].num_sectors);
1826 sgi_get_sysid(int i)
1828 return SGI_SSWAP32(sgilabel->partitions[i].id);
1832 sgi_get_bootpartition(void)
1834 return SGI_SSWAP16(sgilabel->boot_part);
1838 sgi_get_swappartition(void)
1840 return SGI_SSWAP16(sgilabel->swap_part);
1844 sgi_list_table(int xtra)
1847 int kpi = 0; /* kernel partition ID */
1850 printf(_("\nDisk %s (SGI disk label): %d heads, %d sectors\n"
1851 "%d cylinders, %d physical cylinders\n"
1852 "%d extra sects/cyl, interleave %d:1\n"
1854 "Units = %s of %d * 512 bytes\n\n"),
1855 disk_device, heads, sectors, cylinders,
1856 SGI_SSWAP16(sgiparam.pcylcount),
1857 SGI_SSWAP16(sgiparam.sparecyl),
1858 SGI_SSWAP16(sgiparam.ilfact),
1860 str_units(PLURAL), units_per_sector);
1862 printf( _("\nDisk %s (SGI disk label): "
1863 "%d heads, %d sectors, %d cylinders\n"
1864 "Units = %s of %d * 512 bytes\n\n"),
1865 disk_device, heads, sectors, cylinders,
1866 str_units(PLURAL), units_per_sector );
1869 w = strlen(disk_device);
1870 wd = strlen(_("Device"));
1874 printf(_("----- partitions -----\n"
1875 "Pt# %*s Info Start End Sectors Id System\n"),
1876 w + 2, _("Device"));
1877 for (i = 0 ; i < partitions; i++) {
1878 if( sgi_get_num_sectors(i) || debug ) {
1879 uint32_t start = sgi_get_start_sector(i);
1880 uint32_t len = sgi_get_num_sectors(i);
1881 kpi++; /* only count nonempty partitions */
1883 "%2d: %s %4s %9ld %9ld %9ld %2x %s\n",
1884 /* fdisk part number */ i+1,
1885 /* device */ partname(disk_device, kpi, w+3),
1886 /* flags */ (sgi_get_swappartition() == i) ? "swap" :
1887 /* flags */ (sgi_get_bootpartition() == i) ? "boot" : " ",
1888 /* start */ (long) scround(start),
1889 /* end */ (long) scround(start+len)-1,
1890 /* no odd flag on end */(long) len,
1891 /* type id */ sgi_get_sysid(i),
1892 /* type name */ partition_type(sgi_get_sysid(i)));
1895 printf(_("----- Bootinfo -----\nBootfile: %s\n"
1896 "----- Directory Entries -----\n"),
1897 sgilabel->boot_file);
1898 for (i = 0 ; i < sgi_volumes; i++) {
1899 if (sgilabel->directory[i].vol_file_size) {
1900 uint32_t start = SGI_SSWAP32(sgilabel->directory[i].vol_file_start);
1901 uint32_t len = SGI_SSWAP32(sgilabel->directory[i].vol_file_size);
1902 unsigned char *name = sgilabel->directory[i].vol_file_name;
1904 printf(_("%2d: %-10s sector%5u size%8u\n"),
1905 i, (char*)name, (unsigned int) start, (unsigned int) len);
1911 sgi_set_bootpartition(int i)
1913 sgilabel->boot_part = SGI_SSWAP16(((short)i));
1917 sgi_get_lastblock(void)
1919 return heads * sectors * cylinders;
1923 sgi_set_swappartition(int i)
1925 sgilabel->swap_part = SGI_SSWAP16(((short)i));
1929 sgi_check_bootfile(const char* aFile)
1931 if (strlen(aFile) < 3) /* "/a\n" is minimum */ {
1932 printf(_("\nInvalid Bootfile!\n"
1933 "\tThe bootfile must be an absolute non-zero pathname,\n"
1934 "\te.g. \"/unix\" or \"/unix.save\".\n"));
1937 if (strlen(aFile) > 16) {
1938 printf(_("\n\tName of Bootfile too long: "
1939 "16 bytes maximum.\n"));
1942 if (aFile[0] != '/') {
1943 printf(_("\n\tBootfile must have a "
1944 "fully qualified pathname.\n"));
1949 if (strncmp(aFile, (char*)sgilabel->boot_file, 16)) {
1950 printf(_("\n\tBe aware, that the bootfile is not checked for existence.\n\t"
1951 "SGI's default is \"/unix\" and for backup \"/unix.save\".\n"));
1952 /* filename is correct and did change */
1955 return 0; /* filename did not change */
1959 sgi_get_bootfile(void)
1961 return (char*)sgilabel->boot_file;
1965 sgi_set_bootfile(const char* aFile)
1969 if (sgi_check_bootfile(aFile)) {
1971 if ((aFile[i] != '\n') /* in principle caught again by next line */
1972 && (strlen(aFile) > i))
1973 sgilabel->boot_file[i] = aFile[i];
1975 sgilabel->boot_file[i] = 0;
1978 printf(_("\n\tBootfile is changed to \"%s\".\n"), sgilabel->boot_file);
1983 create_sgiinfo(void)
1985 /* I keep SGI's habit to write the sgilabel to the second block */
1986 sgilabel->directory[0].vol_file_start = SGI_SSWAP32(2);
1987 sgilabel->directory[0].vol_file_size = SGI_SSWAP32(sizeof(sgiinfo));
1988 strncpy((char*)sgilabel->directory[0].vol_file_name, "sgilabel", 8);
1991 static sgiinfo *fill_sgiinfo(void);
1994 sgi_write_table(void)
1997 sgilabel->csum = SGI_SSWAP32(two_s_complement_32bit_sum(
1998 (unsigned int*)sgilabel, sizeof(*sgilabel)));
1999 assert(two_s_complement_32bit_sum(
2000 (unsigned int*)sgilabel, sizeof(*sgilabel)) == 0);
2002 if (lseek(fd, 0, SEEK_SET) < 0)
2003 fdisk_fatal(unable_to_seek);
2004 if (write(fd, sgilabel, SECTOR_SIZE) != SECTOR_SIZE)
2005 fdisk_fatal(unable_to_write);
2006 if (!strncmp((char*)sgilabel->directory[0].vol_file_name, "sgilabel", 8)) {
2008 * keep this habit of first writing the "sgilabel".
2009 * I never tested whether it works without (AN 981002).
2011 sgiinfo *info = fill_sgiinfo();
2012 int infostartblock = SGI_SSWAP32(sgilabel->directory[0].vol_file_start);
2013 if (lseek(fd, infostartblock*SECTOR_SIZE, SEEK_SET) < 0)
2014 fdisk_fatal(unable_to_seek);
2015 if (write(fd, info, SECTOR_SIZE) != SECTOR_SIZE)
2016 fdisk_fatal(unable_to_write);
2022 compare_start(int *x, int *y)
2025 * sort according to start sectors
2026 * and prefers largest partition:
2027 * entry zero is entire disk entry
2029 unsigned int i = *x;
2030 unsigned int j = *y;
2031 unsigned int a = sgi_get_start_sector(i);
2032 unsigned int b = sgi_get_start_sector(j);
2033 unsigned int c = sgi_get_num_sectors(i);
2034 unsigned int d = sgi_get_num_sectors(j);
2037 return (d > c) ? 1 : (d == c) ? 0 : -1;
2038 return (a > b) ? 1 : -1;
2043 verify_sgi(int verbose)
2045 int Index[16]; /* list of valid partitions */
2046 int sortcount = 0; /* number of used partitions, i.e. non-zero lengths */
2047 int entire = 0, i = 0;
2048 unsigned int start = 0;
2049 long long gap = 0; /* count unused blocks */
2050 unsigned int lastblock = sgi_get_lastblock();
2053 for (i = 0; i < 16; i++) {
2054 if (sgi_get_num_sectors(i) != 0) {
2055 Index[sortcount++] = i;
2056 if (sgi_get_sysid(i) == ENTIRE_DISK) {
2057 if (entire++ == 1) {
2059 printf(_("More than one entire disk entry present.\n"));
2064 if (sortcount == 0) {
2066 printf(_("No partitions defined\n"));
2067 return (lastblock > 0) ? 1 : (lastblock == 0) ? 0 : -1;
2069 qsort(Index, sortcount, sizeof(Index[0]), (void*)compare_start);
2070 if (sgi_get_sysid(Index[0]) == ENTIRE_DISK) {
2071 if ((Index[0] != 10) && verbose)
2072 printf(_("IRIX likes when Partition 11 covers the entire disk.\n"));
2073 if ((sgi_get_start_sector(Index[0]) != 0) && verbose)
2074 printf(_("The entire disk partition should start "
2076 "not at diskblock %d.\n"),
2077 sgi_get_start_sector(Index[0]));
2078 if (debug) /* I do not understand how some disks fulfil it */
2079 if ((sgi_get_num_sectors(Index[0]) != lastblock) && verbose)
2080 printf(_("The entire disk partition is only %d diskblock large,\n"
2081 "but the disk is %d diskblocks long.\n"),
2082 sgi_get_num_sectors(Index[0]), lastblock);
2083 lastblock = sgi_get_num_sectors(Index[0]);
2086 printf(_("One Partition (#11) should cover the entire disk.\n"));
2088 printf("sysid=%d\tpartition=%d\n",
2089 sgi_get_sysid(Index[0]), Index[0]+1);
2091 for (i = 1, start = 0; i < sortcount; i++) {
2092 int cylsize = sgi_get_nsect() * sgi_get_ntrks();
2094 if ((sgi_get_start_sector(Index[i]) % cylsize) != 0) {
2095 if (debug) /* I do not understand how some disks fulfil it */
2097 printf(_("Partition %d does not start on cylinder boundary.\n"),
2100 if (sgi_get_num_sectors(Index[i]) % cylsize != 0) {
2101 if (debug) /* I do not understand how some disks fulfil it */
2103 printf(_("Partition %d does not end on cylinder boundary.\n"),
2106 /* We cannot handle several "entire disk" entries. */
2107 if (sgi_get_sysid(Index[i]) == ENTIRE_DISK) continue;
2108 if (start > sgi_get_start_sector(Index[i])) {
2110 printf(_("The Partition %d and %d overlap by %d sectors.\n"),
2111 Index[i-1]+1, Index[i]+1,
2112 start - sgi_get_start_sector(Index[i]));
2113 if (gap > 0) gap = -gap;
2114 if (gap == 0) gap = -1;
2116 if (start < sgi_get_start_sector(Index[i])) {
2118 printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"),
2119 sgi_get_start_sector(Index[i]) - start,
2120 start, sgi_get_start_sector(Index[i])-1);
2121 gap += sgi_get_start_sector(Index[i]) - start;
2122 add2freelist(start, sgi_get_start_sector(Index[i]));
2124 start = sgi_get_start_sector(Index[i])
2125 + sgi_get_num_sectors(Index[i]);
2128 printf("%2d:%12d\t%12d\t%12d\n", Index[i],
2129 sgi_get_start_sector(Index[i]),
2130 sgi_get_num_sectors(Index[i]),
2131 sgi_get_sysid(Index[i]));
2134 if (start < lastblock) {
2136 printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"),
2137 lastblock - start, start, lastblock-1);
2138 gap += lastblock - start;
2139 add2freelist(start, lastblock);
2142 * Done with arithmetics
2143 * Go for details now
2146 if (!sgi_get_num_sectors(sgi_get_bootpartition())) {
2147 printf(_("\nThe boot partition does not exist.\n"));
2149 if (!sgi_get_num_sectors(sgi_get_swappartition())) {
2150 printf(_("\nThe swap partition does not exist.\n"));
2152 if ((sgi_get_sysid(sgi_get_swappartition()) != SGI_SWAP)
2153 && (sgi_get_sysid(sgi_get_swappartition()) != LINUX_SWAP))
2154 printf(_("\nThe swap partition has no swap type.\n"));
2156 if (sgi_check_bootfile("/unix"))
2157 printf(_("\tYou have chosen an unusual boot file name.\n"));
2159 return (gap > 0) ? 1 : (gap == 0) ? 0 : -1;
2166 * returned value is:
2167 * = 0 : disk is properly filled to the rim
2168 * < 0 : there is an overlap
2169 * > 0 : there is still some vacant space
2171 return verify_sgi(0);
2175 sgi_change_sysid(int i, int sys)
2177 if( sgi_get_num_sectors(i) == 0 ) { /* caught already before, ... */
2178 printf(_("Sorry You may change the Tag of non-empty partitions.\n"));
2181 if (((sys != ENTIRE_DISK ) && (sys != SGI_VOLHDR))
2182 && (sgi_get_start_sector(i) < 1) ) {
2184 _("It is highly recommended that the partition at offset 0\n"
2185 "is of type \"SGI volhdr\", the IRIX system will rely on it to\n"
2186 "retrieve from its directory standalone tools like sash and fx.\n"
2187 "Only the \"SGI volume\" entire disk section may violate this.\n"
2188 "Type YES if you are sure about tagging this partition differently.\n"));
2189 if (strcmp(line_ptr, _("YES\n")))
2192 sgilabel->partitions[i].id = SGI_SSWAP32(sys);
2195 /* returns partition index of first entry marked as entire disk */
2201 for (i = 0; i < 16; i++)
2202 if (sgi_get_sysid(i) == SGI_VOLUME)
2208 sgi_set_partition(int i, unsigned int start, unsigned int length, int sys)
2210 sgilabel->partitions[i].id = SGI_SSWAP32(sys);
2211 sgilabel->partitions[i].num_sectors = SGI_SSWAP32(length);
2212 sgilabel->partitions[i].start_sector = SGI_SSWAP32(start);
2214 if (sgi_gaps() < 0) /* rebuild freelist */
2215 printf(_("Do You know, You got a partition overlap on the disk?\n"));
2219 sgi_set_entire(void)
2223 for (n = 10; n < partitions; n++) {
2224 if(!sgi_get_num_sectors(n) ) {
2225 sgi_set_partition(n, 0, sgi_get_lastblock(), SGI_VOLUME);
2232 sgi_set_volhdr(void)
2236 for (n = 8; n < partitions; n++) {
2237 if (!sgi_get_num_sectors(n)) {
2239 * 5 cylinders is an arbitrary value I like
2240 * IRIX 5.3 stored files in the volume header
2241 * (like sash, symmon, fx, ide) with ca. 3200
2244 if (heads * sectors * 5 < sgi_get_lastblock())
2245 sgi_set_partition(n, 0, heads * sectors * 5, SGI_VOLHDR);
2252 sgi_delete_partition(int i)
2254 sgi_set_partition(i, 0, 0, 0);
2258 sgi_add_partition(int n, int sys)
2261 unsigned int first = 0, last = 0;
2265 } else if (n == 8) {
2268 if(sgi_get_num_sectors(n)) {
2269 printf(_("Partition %d is already defined. Delete "
2270 "it before re-adding it.\n"), n + 1);
2273 if ((sgi_entire() == -1) && (sys != SGI_VOLUME)) {
2274 printf(_("Attempting to generate entire disk entry automatically.\n"));
2278 if ((sgi_gaps() == 0) && (sys != SGI_VOLUME)) {
2279 printf(_("The entire disk is already covered with partitions.\n"));
2282 if (sgi_gaps() < 0) {
2283 printf(_("You got a partition overlap on the disk. Fix it first!\n"));
2286 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
2288 if(sys == SGI_VOLUME) {
2289 last = sgi_get_lastblock();
2290 first = read_int(0, 0, last-1, 0, mesg);
2292 printf(_("It is highly recommended that eleventh partition\n"
2293 "covers the entire disk and is of type `SGI volume'\n"));
2296 first = freelist[0].first;
2297 last = freelist[0].last;
2298 first = read_int(scround(first), scround(first), scround(last)-1,
2301 if (display_in_cyl_units)
2302 first *= units_per_sector;
2304 first = first; /* align to cylinder if you know how ... */
2306 last = isinfreelist(first);
2308 printf(_("You will get a partition overlap on the disk. "
2309 "Fix it first!\n"));
2313 snprintf(mesg, sizeof(mesg), _(" Last %s"), str_units(SINGULAR));
2314 last = read_int(scround(first), scround(last)-1, scround(last)-1,
2315 scround(first), mesg)+1;
2316 if (display_in_cyl_units)
2317 last *= units_per_sector;
2319 last = last; /* align to cylinder if You know how ... */
2320 if ( (sys == SGI_VOLUME) && (first != 0 || last != sgi_get_lastblock() ) )
2321 printf(_("It is highly recommended that eleventh partition\n"
2322 "covers the entire disk and is of type `SGI volume'\n"));
2323 sgi_set_partition(n, first, last-first, sys);
2326 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
2328 create_sgilabel(void)
2330 struct hd_geometry geometry;
2337 long longsectors; /* the number of sectors on the device */
2338 int res; /* the result from the ioctl */
2339 int sec_fac; /* the sector factor */
2341 sec_fac = sector_size / 512; /* determine the sector factor */
2344 _("Building a new SGI disklabel. Changes will remain in memory only,\n"
2345 "until you decide to write them. After that, of course, the previous\n"
2346 "content will be unrecoverably lost.\n\n"));
2348 sgi_other_endian = (BB_LITTLE_ENDIAN);
2349 res = ioctl(fd, BLKGETSIZE, &longsectors);
2350 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
2351 heads = geometry.heads;
2352 sectors = geometry.sectors;
2354 /* the get device size ioctl was successful */
2355 cylinders = longsectors / (heads * sectors);
2356 cylinders /= sec_fac;
2358 /* otherwise print error and use truncated version */
2359 cylinders = geometry.cylinders;
2361 _("Warning: BLKGETSIZE ioctl failed on %s. "
2362 "Using geometry cylinder value of %d.\n"
2363 "This value may be truncated for devices"
2364 " > 33.8 GB.\n"), disk_device, cylinders);
2367 for (i = 0; i < 4; i++) {
2369 if (valid_part_table_flag(MBRbuffer)) {
2370 if(get_part_table(i)->sys_ind) {
2371 old[i].sysid = get_part_table(i)->sys_ind;
2372 old[i].start = get_start_sect(get_part_table(i));
2373 old[i].nsect = get_nr_sects(get_part_table(i));
2374 printf(_("Trying to keep parameters of partition %d.\n"), i);
2376 printf(_("ID=%02x\tSTART=%d\tLENGTH=%d\n"),
2377 old[i].sysid, old[i].start, old[i].nsect);
2382 memset(MBRbuffer, 0, sizeof(MBRbuffer));
2383 sgilabel->magic = SGI_SSWAP32(SGI_LABEL_MAGIC);
2384 sgilabel->boot_part = SGI_SSWAP16(0);
2385 sgilabel->swap_part = SGI_SSWAP16(1);
2387 /* sizeof(sgilabel->boot_file) = 16 > 6 */
2388 memset(sgilabel->boot_file, 0, 16);
2389 strcpy((char*)sgilabel->boot_file, "/unix");
2391 sgilabel->devparam.skew = (0);
2392 sgilabel->devparam.gap1 = (0);
2393 sgilabel->devparam.gap2 = (0);
2394 sgilabel->devparam.sparecyl = (0);
2395 sgilabel->devparam.pcylcount = SGI_SSWAP16(geometry.cylinders);
2396 sgilabel->devparam.head_vol0 = SGI_SSWAP16(0);
2397 sgilabel->devparam.ntrks = SGI_SSWAP16(geometry.heads);
2398 /* tracks/cylinder (heads) */
2399 sgilabel->devparam.cmd_tag_queue_depth = (0);
2400 sgilabel->devparam.unused0 = (0);
2401 sgilabel->devparam.unused1 = SGI_SSWAP16(0);
2402 sgilabel->devparam.nsect = SGI_SSWAP16(geometry.sectors);
2404 sgilabel->devparam.bytes = SGI_SSWAP16(512);
2405 sgilabel->devparam.ilfact = SGI_SSWAP16(1);
2406 sgilabel->devparam.flags = SGI_SSWAP32(TRACK_FWD|
2407 IGNORE_ERRORS|RESEEK);
2408 sgilabel->devparam.datarate = SGI_SSWAP32(0);
2409 sgilabel->devparam.retries_on_error = SGI_SSWAP32(1);
2410 sgilabel->devparam.ms_per_word = SGI_SSWAP32(0);
2411 sgilabel->devparam.xylogics_gap1 = SGI_SSWAP16(0);
2412 sgilabel->devparam.xylogics_syncdelay = SGI_SSWAP16(0);
2413 sgilabel->devparam.xylogics_readdelay = SGI_SSWAP16(0);
2414 sgilabel->devparam.xylogics_gap2 = SGI_SSWAP16(0);
2415 sgilabel->devparam.xylogics_readgate = SGI_SSWAP16(0);
2416 sgilabel->devparam.xylogics_writecont = SGI_SSWAP16(0);
2417 memset( &(sgilabel->directory), 0, sizeof(struct volume_directory)*15 );
2418 memset( &(sgilabel->partitions), 0, sizeof(struct sgi_partition)*16 );
2419 current_label_type = label_sgi;
2424 for (i = 0; i < 4; i++) {
2426 sgi_set_partition(i, old[i].start, old[i].nsect, old[i].sysid);
2434 /* do nothing in the beginning */
2436 #endif /* CONFIG_FEATURE_FDISK_ADVANCED */
2438 /* _____________________________________________________________
2444 sgiinfo *info = calloc(1, sizeof(sgiinfo));
2446 info->magic = SGI_SSWAP32(SGI_INFO_MAGIC);
2447 info->b1 = SGI_SSWAP32(-1);
2448 info->b2 = SGI_SSWAP16(-1);
2449 info->b3 = SGI_SSWAP16(1);
2450 /* You may want to replace this string !!!!!!! */
2451 strcpy( (char*)info->scsi_string, "IBM OEM 0662S12 3 30" );
2452 strcpy( (char*)info->serial, "0000" );
2453 info->check1816 = SGI_SSWAP16(18*256 +16 );
2454 strcpy( (char*)info->installer, "Sfx version 5.3, Oct 18, 1994" );
2457 #endif /* SGI_LABEL */
2460 #ifdef CONFIG_FEATURE_SUN_LABEL
2464 * I think this is mostly, or entirely, due to
2465 * Jakub Jelinek (jj@sunsite.mff.cuni.cz), July 1996
2467 * Merged with fdisk for other architectures, aeb, June 1998.
2469 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
2470 * Internationalization
2474 static int sun_other_endian;
2475 static int scsi_disk;
2479 #define IDE0_MAJOR 3
2482 #define IDE1_MAJOR 22
2486 guess_device_type(void)
2488 struct stat bootstat;
2490 if (fstat(fd, &bootstat) < 0) {
2493 } else if (S_ISBLK(bootstat.st_mode)
2494 && (major(bootstat.st_rdev) == IDE0_MAJOR ||
2495 major(bootstat.st_rdev) == IDE1_MAJOR)) {
2498 } else if (S_ISBLK(bootstat.st_mode)
2499 && major(bootstat.st_rdev) == FLOPPY_MAJOR) {
2508 static const struct systypes sun_sys_types[] = {
2509 { "\x00" "Empty" }, /* 0 */
2510 { "\x01" "Boot" }, /* 1 */
2511 { "\x02" "SunOS root" }, /* 2 */
2512 { "\x03" "SunOS swap" }, /* SUNOS_SWAP */
2513 { "\x04" "SunOS usr" }, /* 4 */
2514 { "\x05" "Whole disk" }, /* WHOLE_DISK */
2515 { "\x06" "SunOS stand" }, /* 6 */
2516 { "\x07" "SunOS var" }, /* 7 */
2517 { "\x08" "SunOS home" }, /* 8 */
2518 { "\x82" "Linux swap" }, /* LINUX_SWAP */
2519 { "\x83" "Linux native" }, /* LINUX_NATIVE */
2520 { "\x8e" "Linux LVM" }, /* 0x8e */
2521 /* New (2.2.x) raid partition with autodetect using persistent superblock */
2522 { "\xfd" "Linux raid autodetect" }, /* 0xfd */
2528 set_sun_partition(int i, uint start, uint stop, int sysid)
2530 sunlabel->infos[i].id = sysid;
2531 sunlabel->partitions[i].start_cylinder =
2532 SUN_SSWAP32(start / (heads * sectors));
2533 sunlabel->partitions[i].num_sectors =
2534 SUN_SSWAP32(stop - start);
2539 check_sun_label(void)
2541 unsigned short *ush;
2544 if (sunlabel->magic != SUN_LABEL_MAGIC
2545 && sunlabel->magic != SUN_LABEL_MAGIC_SWAPPED) {
2546 current_label_type = label_dos;
2547 sun_other_endian = 0;
2550 sun_other_endian = (sunlabel->magic == SUN_LABEL_MAGIC_SWAPPED);
2551 ush = ((unsigned short *) (sunlabel + 1)) - 1;
2552 for (csum = 0; ush >= (unsigned short *)sunlabel;) csum ^= *ush--;
2554 fprintf(stderr,_("Detected sun disklabel with wrong checksum.\n"
2555 "Probably you'll have to set all the values,\n"
2556 "e.g. heads, sectors, cylinders and partitions\n"
2557 "or force a fresh label (s command in main menu)\n"));
2559 heads = SUN_SSWAP16(sunlabel->ntrks);
2560 cylinders = SUN_SSWAP16(sunlabel->ncyl);
2561 sectors = SUN_SSWAP16(sunlabel->nsect);
2564 current_label_type = label_sun;
2569 static const struct sun_predefined_drives {
2572 unsigned short sparecyl;
2573 unsigned short ncyl;
2574 unsigned short nacyl;
2575 unsigned short pcylcount;
2576 unsigned short ntrks;
2577 unsigned short nsect;
2578 unsigned short rspeed;
2580 { "Quantum","ProDrive 80S",1,832,2,834,6,34,3662},
2581 { "Quantum","ProDrive 105S",1,974,2,1019,6,35,3662},
2582 { "CDC","Wren IV 94171-344",3,1545,2,1549,9,46,3600},
2583 { "IBM","DPES-31080",0,4901,2,4903,4,108,5400},
2584 { "IBM","DORS-32160",0,1015,2,1017,67,62,5400},
2585 { "IBM","DNES-318350",0,11199,2,11474,10,320,7200},
2586 { "SEAGATE","ST34371",0,3880,2,3882,16,135,7228},
2587 { "","SUN0104",1,974,2,1019,6,35,3662},
2588 { "","SUN0207",4,1254,2,1272,9,36,3600},
2589 { "","SUN0327",3,1545,2,1549,9,46,3600},
2590 { "","SUN0340",0,1538,2,1544,6,72,4200},
2591 { "","SUN0424",2,1151,2,2500,9,80,4400},
2592 { "","SUN0535",0,1866,2,2500,7,80,5400},
2593 { "","SUN0669",5,1614,2,1632,15,54,3600},
2594 { "","SUN1.0G",5,1703,2,1931,15,80,3597},
2595 { "","SUN1.05",0,2036,2,2038,14,72,5400},
2596 { "","SUN1.3G",6,1965,2,3500,17,80,5400},
2597 { "","SUN2.1G",0,2733,2,3500,19,80,5400},
2598 { "IOMEGA","Jaz",0,1019,2,1021,64,32,5394},
2601 static const struct sun_predefined_drives *
2602 sun_autoconfigure_scsi(void)
2604 const struct sun_predefined_drives *p = NULL;
2606 #ifdef SCSI_IOCTL_GET_IDLUN
2616 if (!ioctl(fd, SCSI_IOCTL_GET_IDLUN, &id)) {
2618 "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n",
2620 ((id[0]>>24)&0xff)-/*PROC_SCSI_SCSI+PROC_SCSI_FILE*/33,
2622 /* This is very wrong (works only if you have one HBA),
2623 but I haven't found a way how to get hostno
2624 from the current kernel */
2631 pfd = fopen("/proc/scsi/scsi","r");
2633 while (fgets(buffer2, 2048, pfd)) {
2634 if (!strcmp(buffer, buffer2)) {
2635 if (fgets(buffer2,2048,pfd)) {
2636 q = strstr(buffer2,"Vendor: ");
2641 *q++ = 0; /* truncate vendor name */
2642 q = strstr(q,"Model: ");
2647 q = strstr(q," Rev: ");
2650 for (i = 0; i < SIZE(sun_drives); i++) {
2651 if (*sun_drives[i].vendor && strcasecmp(sun_drives[i].vendor, vendor))
2653 if (!strstr(model, sun_drives[i].model))
2655 printf(_("Autoconfigure found a %s%s%s\n"),sun_drives[i].vendor,(*sun_drives[i].vendor) ? " " : "",sun_drives[i].model);
2674 create_sunlabel(void)
2676 struct hd_geometry geometry;
2680 const struct sun_predefined_drives *p = NULL;
2683 _("Building a new sun disklabel. Changes will remain in memory only,\n"
2684 "until you decide to write them. After that, of course, the previous\n"
2685 "content won't be recoverable.\n\n"));
2686 sun_other_endian = BB_LITTLE_ENDIAN;
2687 memset(MBRbuffer, 0, sizeof(MBRbuffer));
2688 sunlabel->magic = SUN_SSWAP16(SUN_LABEL_MAGIC);
2690 puts(_("Drive type\n"
2691 " ? auto configure\n"
2692 " 0 custom (with hardware detected defaults)"));
2693 for (i = 0; i < SIZE(sun_drives); i++) {
2694 printf(" %c %s%s%s\n",
2695 i + 'a', sun_drives[i].vendor,
2696 (*sun_drives[i].vendor) ? " " : "",
2697 sun_drives[i].model);
2700 c = read_char(_("Select type (? for auto, 0 for custom): "));
2701 if (c >= 'a' && c < 'a' + SIZE(sun_drives)) {
2702 p = sun_drives + c - 'a';
2704 } else if (c >= 'A' && c < 'A' + SIZE(sun_drives)) {
2705 p = sun_drives + c - 'A';
2707 } else if (c == '0') {
2709 } else if (c == '?' && scsi_disk) {
2710 p = sun_autoconfigure_scsi();
2712 printf(_("Autoconfigure failed.\n"));
2719 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
2720 heads = geometry.heads;
2721 sectors = geometry.sectors;
2722 cylinders = geometry.cylinders;
2729 sunlabel->nacyl = 0;
2730 sunlabel->pcylcount = SUN_SSWAP16(cylinders);
2731 sunlabel->rspeed = SUN_SSWAP16(300);
2732 sunlabel->ilfact = SUN_SSWAP16(1);
2733 sunlabel->sparecyl = 0;
2735 heads = read_int(1,heads,1024,0,_("Heads"));
2736 sectors = read_int(1,sectors,1024,0,_("Sectors/track"));
2738 cylinders = read_int(1,cylinders-2,65535,0,_("Cylinders"));
2740 cylinders = read_int(1,0,65535,0,_("Cylinders"));
2741 sunlabel->nacyl = SUN_SSWAP16(read_int(0,2,65535,0, _("Alternate cylinders")));
2742 sunlabel->pcylcount = SUN_SSWAP16(read_int(0,cylinders+SUN_SSWAP16(sunlabel->nacyl), 65535,0, _("Physical cylinders")));
2743 sunlabel->rspeed = SUN_SSWAP16(read_int(1,5400,100000,0, _("Rotation speed (rpm)")));
2744 sunlabel->ilfact = SUN_SSWAP16(read_int(1,1,32,0, _("Interleave factor")));
2745 sunlabel->sparecyl = SUN_SSWAP16(read_int(0,0,sectors,0, _("Extra sectors per cylinder")));
2748 sunlabel->sparecyl = SUN_SSWAP16(p->sparecyl);
2749 sunlabel->ncyl = SUN_SSWAP16(p->ncyl);
2750 sunlabel->nacyl = SUN_SSWAP16(p->nacyl);
2751 sunlabel->pcylcount = SUN_SSWAP16(p->pcylcount);
2752 sunlabel->ntrks = SUN_SSWAP16(p->ntrks);
2753 sunlabel->nsect = SUN_SSWAP16(p->nsect);
2754 sunlabel->rspeed = SUN_SSWAP16(p->rspeed);
2755 sunlabel->ilfact = SUN_SSWAP16(1);
2756 cylinders = p->ncyl;
2759 puts(_("You may change all the disk params from the x menu"));
2762 snprintf((char *)(sunlabel->info), sizeof(sunlabel->info),
2763 "%s%s%s cyl %d alt %d hd %d sec %d",
2764 p ? p->vendor : "", (p && *p->vendor) ? " " : "",
2765 p ? p->model : (floppy ? _("3,5\" floppy") : _("Linux custom")),
2766 cylinders, SUN_SSWAP16(sunlabel->nacyl), heads, sectors);
2768 sunlabel->ntrks = SUN_SSWAP16(heads);
2769 sunlabel->nsect = SUN_SSWAP16(sectors);
2770 sunlabel->ncyl = SUN_SSWAP16(cylinders);
2772 set_sun_partition(0, 0, cylinders * heads * sectors, LINUX_NATIVE);
2774 if (cylinders * heads * sectors >= 150 * 2048) {
2775 ndiv = cylinders - (50 * 2048 / (heads * sectors)); /* 50M swap */
2777 ndiv = cylinders * 2 / 3;
2778 set_sun_partition(0, 0, ndiv * heads * sectors, LINUX_NATIVE);
2779 set_sun_partition(1, ndiv * heads * sectors, cylinders * heads * sectors, LINUX_SWAP);
2780 sunlabel->infos[1].flags |= 0x01; /* Not mountable */
2782 set_sun_partition(2, 0, cylinders * heads * sectors, WHOLE_DISK);
2784 unsigned short *ush = (unsigned short *)sunlabel;
2785 unsigned short csum = 0;
2786 while (ush < (unsigned short *)(&sunlabel->csum))
2788 sunlabel->csum = csum;
2791 set_all_unchanged();
2793 get_boot(create_empty_sun);
2797 toggle_sunflags(int i, unsigned char mask)
2799 if (sunlabel->infos[i].flags & mask)
2800 sunlabel->infos[i].flags &= ~mask;
2802 sunlabel->infos[i].flags |= mask;
2807 fetch_sun(uint *starts, uint *lens, uint *start, uint *stop)
2809 int i, continuous = 1;
2812 *stop = cylinders * heads * sectors;
2813 for (i = 0; i < partitions; i++) {
2814 if (sunlabel->partitions[i].num_sectors
2815 && sunlabel->infos[i].id
2816 && sunlabel->infos[i].id != WHOLE_DISK) {
2817 starts[i] = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
2818 lens[i] = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
2820 if (starts[i] == *start)
2822 else if (starts[i] + lens[i] >= *stop)
2826 /* There will be probably more gaps
2827 than one, so lets check afterwards */
2836 static uint *verify_sun_starts;
2839 verify_sun_cmp(int *a, int *b)
2841 if (*a == -1) return 1;
2842 if (*b == -1) return -1;
2843 if (verify_sun_starts[*a] > verify_sun_starts[*b]) return 1;
2850 uint starts[8], lens[8], start, stop;
2851 int i,j,k,starto,endo;
2854 verify_sun_starts = starts;
2855 fetch_sun(starts,lens,&start,&stop);
2856 for (k = 0; k < 7; k++) {
2857 for (i = 0; i < 8; i++) {
2858 if (k && (lens[i] % (heads * sectors))) {
2859 printf(_("Partition %d doesn't end on cylinder boundary\n"), i+1);
2862 for (j = 0; j < i; j++)
2864 if (starts[j] == starts[i]+lens[i]) {
2865 starts[j] = starts[i]; lens[j] += lens[i];
2867 } else if (starts[i] == starts[j]+lens[j]){
2871 if (starts[i] < starts[j]+lens[j]
2872 && starts[j] < starts[i]+lens[i]) {
2874 if (starts[j] > starto)
2876 endo = starts[i]+lens[i];
2877 if (starts[j]+lens[j] < endo)
2878 endo = starts[j]+lens[j];
2879 printf(_("Partition %d overlaps with others in "
2880 "sectors %d-%d\n"), i+1, starto, endo);
2887 for (i = 0; i < 8; i++) {
2893 qsort(array,SIZE(array),sizeof(array[0]),
2894 (int (*)(const void *,const void *)) verify_sun_cmp);
2895 if (array[0] == -1) {
2896 printf(_("No partitions defined\n"));
2899 stop = cylinders * heads * sectors;
2900 if (starts[array[0]])
2901 printf(_("Unused gap - sectors 0-%d\n"),starts[array[0]]);
2902 for (i = 0; i < 7 && array[i+1] != -1; i++) {
2903 printf(_("Unused gap - sectors %d-%d\n"),starts[array[i]]+lens[array[i]],starts[array[i+1]]);
2905 start = starts[array[i]] + lens[array[i]];
2907 printf(_("Unused gap - sectors %d-%d\n"),start,stop);
2911 add_sun_partition(int n, int sys)
2913 uint start, stop, stop2;
2914 uint starts[8], lens[8];
2920 if (sunlabel->partitions[n].num_sectors && sunlabel->infos[n].id) {
2921 printf(_("Partition %d is already defined. Delete "
2922 "it before re-adding it.\n"), n + 1);
2926 fetch_sun(starts,lens,&start,&stop);
2927 if (stop <= start) {
2931 printf(_("Other partitions already cover the whole disk.\nDelete "
2932 "some/shrink them before retry.\n"));
2936 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
2939 first = read_int(0, 0, 0, 0, mesg);
2941 first = read_int(scround(start), scround(stop)+1,
2942 scround(stop), 0, mesg);
2943 if (display_in_cyl_units)
2944 first *= units_per_sector;
2946 /* Starting sector has to be properly aligned */
2947 first = (first + heads * sectors - 1) / (heads * sectors);
2948 if (n == 2 && first != 0)
2950 It is highly recommended that the third partition covers the whole disk\n\
2951 and is of type `Whole disk'\n");
2952 /* ewt asks to add: "don't start a partition at cyl 0"
2953 However, edmundo@rano.demon.co.uk writes:
2954 "In addition to having a Sun partition table, to be able to
2955 boot from the disc, the first partition, /dev/sdX1, must
2956 start at cylinder 0. This means that /dev/sdX1 contains
2957 the partition table and the boot block, as these are the
2958 first two sectors of the disc. Therefore you must be
2959 careful what you use /dev/sdX1 for. In particular, you must
2960 not use a partition starting at cylinder 0 for Linux swap,
2961 as that would overwrite the partition table and the boot
2962 block. You may, however, use such a partition for a UFS
2963 or EXT2 file system, as these file systems leave the first
2964 1024 bytes undisturbed. */
2965 /* On the other hand, one should not use partitions
2966 starting at block 0 in an md, or the label will
2968 for (i = 0; i < partitions; i++)
2969 if (lens[i] && starts[i] <= first && starts[i] + lens[i] > first)
2971 if (i < partitions && !whole_disk) {
2972 if (n == 2 && !first) {
2976 printf(_("Sector %d is already allocated\n"), first);
2980 stop = cylinders * heads * sectors;
2982 for (i = 0; i < partitions; i++) {
2983 if (starts[i] > first && starts[i] < stop)
2986 snprintf(mesg, sizeof(mesg),
2987 _("Last %s or +size or +sizeM or +sizeK"),
2988 str_units(SINGULAR));
2990 last = read_int(scround(stop2), scround(stop2), scround(stop2),
2992 else if (n == 2 && !first)
2993 last = read_int(scround(first), scround(stop2), scround(stop2),
2994 scround(first), mesg);
2996 last = read_int(scround(first), scround(stop), scround(stop),
2997 scround(first), mesg);
2998 if (display_in_cyl_units)
2999 last *= units_per_sector;
3000 if (n == 2 && !first) {
3001 if (last >= stop2) {
3004 } else if (last > stop) {
3005 printf(_("You haven't covered the whole disk with "
3006 "the 3rd partition, but your value\n"
3007 "%d %s covers some other partition. "
3008 "Your entry has been changed\n"
3010 scround(last), str_units(SINGULAR),
3011 scround(stop), str_units(SINGULAR));
3014 } else if (!whole_disk && last > stop)
3019 set_sun_partition(n, first, last, sys);
3023 sun_delete_partition(int i)
3028 && sunlabel->infos[i].id == WHOLE_DISK
3029 && !sunlabel->partitions[i].start_cylinder
3030 && (nsec = SUN_SSWAP32(sunlabel->partitions[i].num_sectors)) == heads * sectors * cylinders)
3031 printf(_("If you want to maintain SunOS/Solaris compatibility, "
3032 "consider leaving this\n"
3033 "partition as Whole disk (5), starting at 0, with %u "
3034 "sectors\n"), nsec);
3035 sunlabel->infos[i].id = 0;
3036 sunlabel->partitions[i].num_sectors = 0;
3040 sun_change_sysid(int i, int sys)
3042 if (sys == LINUX_SWAP && !sunlabel->partitions[i].start_cylinder) {
3044 _("It is highly recommended that the partition at offset 0\n"
3045 "is UFS, EXT2FS filesystem or SunOS swap. Putting Linux swap\n"
3046 "there may destroy your partition table and bootblock.\n"
3047 "Type YES if you're very sure you would like that partition\n"
3048 "tagged with 82 (Linux swap): "));
3049 if (strcmp (line_ptr, _("YES\n")))
3055 /* swaps are not mountable by default */
3056 sunlabel->infos[i].flags |= 0x01;
3059 /* assume other types are mountable;
3060 user can change it anyway */
3061 sunlabel->infos[i].flags &= ~0x01;
3064 sunlabel->infos[i].id = sys;
3068 sun_list_table(int xtra)
3072 w = strlen(disk_device);
3075 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d rpm\n"
3076 "%d cylinders, %d alternate cylinders, %d physical cylinders\n"
3077 "%d extra sects/cyl, interleave %d:1\n"
3079 "Units = %s of %d * 512 bytes\n\n"),
3080 disk_device, heads, sectors, SUN_SSWAP16(sunlabel->rspeed),
3081 cylinders, SUN_SSWAP16(sunlabel->nacyl),
3082 SUN_SSWAP16(sunlabel->pcylcount),
3083 SUN_SSWAP16(sunlabel->sparecyl),
3084 SUN_SSWAP16(sunlabel->ilfact),
3086 str_units(PLURAL), units_per_sector);
3089 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d cylinders\n"
3090 "Units = %s of %d * 512 bytes\n\n"),
3091 disk_device, heads, sectors, cylinders,
3092 str_units(PLURAL), units_per_sector);
3094 printf(_("%*s Flag Start End Blocks Id System\n"),
3095 w + 1, _("Device"));
3096 for (i = 0 ; i < partitions; i++) {
3097 if (sunlabel->partitions[i].num_sectors) {
3098 uint32_t start = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
3099 uint32_t len = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
3100 printf("%s %c%c %9ld %9ld %9ld%c %2x %s\n",
3101 partname(disk_device, i+1, w), /* device */
3102 (sunlabel->infos[i].flags & 0x01) ? 'u' : ' ', /* flags */
3103 (sunlabel->infos[i].flags & 0x10) ? 'r' : ' ',
3104 (long) scround(start), /* start */
3105 (long) scround(start+len), /* end */
3106 (long) len / 2, len & 1 ? '+' : ' ', /* odd flag on end */
3107 sunlabel->infos[i].id, /* type id */
3108 partition_type(sunlabel->infos[i].id)); /* type name */
3113 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3116 sun_set_alt_cyl(void)
3119 SUN_SSWAP16(read_int(0,SUN_SSWAP16(sunlabel->nacyl), 65535, 0,
3120 _("Number of alternate cylinders")));
3124 sun_set_ncyl(int cyl)
3126 sunlabel->ncyl = SUN_SSWAP16(cyl);
3132 sunlabel->sparecyl =
3133 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->sparecyl), sectors, 0,
3134 _("Extra sectors per cylinder")));
3138 sun_set_ilfact(void)
3141 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->ilfact), 32, 0,
3142 _("Interleave factor")));
3146 sun_set_rspeed(void)
3149 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->rspeed), 100000, 0,
3150 _("Rotation speed (rpm)")));
3154 sun_set_pcylcount(void)
3156 sunlabel->pcylcount =
3157 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->pcylcount), 65535, 0,
3158 _("Number of physical cylinders")));
3160 #endif /* CONFIG_FEATURE_FDISK_ADVANCED */
3163 sun_write_table(void)
3165 unsigned short *ush = (unsigned short *)sunlabel;
3166 unsigned short csum = 0;
3168 while (ush < (unsigned short *)(&sunlabel->csum))
3170 sunlabel->csum = csum;
3171 if (lseek(fd, 0, SEEK_SET) < 0)
3172 fdisk_fatal(unable_to_seek);
3173 if (write(fd, sunlabel, SECTOR_SIZE) != SECTOR_SIZE)
3174 fdisk_fatal(unable_to_write);
3176 #endif /* SUN_LABEL */
3178 /* DOS partition types */
3180 static const struct systypes i386_sys_types[] = {
3183 { "\x04" "FAT16 <32M" },
3184 { "\x05" "Extended" }, /* DOS 3.3+ extended partition */
3185 { "\x06" "FAT16" }, /* DOS 16-bit >=32M */
3186 { "\x07" "HPFS/NTFS" }, /* OS/2 IFS, eg, HPFS or NTFS or QNX */
3187 { "\x0a" "OS/2 Boot Manager" },/* OS/2 Boot Manager */
3188 { "\x0b" "Win95 FAT32" },
3189 { "\x0c" "Win95 FAT32 (LBA)" },/* LBA really is `Extended Int 13h' */
3190 { "\x0e" "Win95 FAT16 (LBA)" },
3191 { "\x0f" "Win95 Ext'd (LBA)" },
3192 { "\x11" "Hidden FAT12" },
3193 { "\x12" "Compaq diagnostics" },
3194 { "\x14" "Hidden FAT16 <32M" },
3195 { "\x16" "Hidden FAT16" },
3196 { "\x17" "Hidden HPFS/NTFS" },
3197 { "\x1b" "Hidden Win95 FAT32" },
3198 { "\x1c" "Hidden Win95 FAT32 (LBA)" },
3199 { "\x1e" "Hidden Win95 FAT16 (LBA)" },
3200 { "\x3c" "PartitionMagic recovery" },
3201 { "\x41" "PPC PReP Boot" },
3203 { "\x63" "GNU HURD or SysV" }, /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */
3204 { "\x80" "Old Minix" }, /* Minix 1.4a and earlier */
3205 { "\x81" "Minix / old Linux" },/* Minix 1.4b and later */
3206 { "\x82" "Linux swap" }, /* also Solaris */
3208 { "\x84" "OS/2 hidden C: drive" },
3209 { "\x85" "Linux extended" },
3210 { "\x86" "NTFS volume set" },
3211 { "\x87" "NTFS volume set" },
3212 { "\x8e" "Linux LVM" },
3213 { "\x9f" "BSD/OS" }, /* BSDI */
3214 { "\xa0" "IBM Thinkpad hibernation" },
3215 { "\xa5" "FreeBSD" }, /* various BSD flavours */
3216 { "\xa6" "OpenBSD" },
3217 { "\xa8" "Darwin UFS" },
3218 { "\xa9" "NetBSD" },
3219 { "\xab" "Darwin boot" },
3220 { "\xb7" "BSDI fs" },
3221 { "\xb8" "BSDI swap" },
3222 { "\xbe" "Solaris boot" },
3223 { "\xeb" "BeOS fs" },
3224 { "\xee" "EFI GPT" }, /* Intel EFI GUID Partition Table */
3225 { "\xef" "EFI (FAT-12/16/32)" },/* Intel EFI System Partition */
3226 { "\xf0" "Linux/PA-RISC boot" },/* Linux/PA-RISC boot loader */
3227 { "\xf2" "DOS secondary" }, /* DOS 3.3+ secondary */
3228 { "\xfd" "Linux raid autodetect" },/* New (2.2.x) raid partition with
3229 autodetect using persistent
3231 #ifdef CONFIG_WEIRD_PARTITION_TYPES
3232 { "\x02" "XENIX root" },
3233 { "\x03" "XENIX usr" },
3234 { "\x08" "AIX" }, /* AIX boot (AIX -- PS/2 port) or SplitDrive */
3235 { "\x09" "AIX bootable" }, /* AIX data or Coherent */
3237 { "\x18" "AST SmartSleep" },
3238 { "\x24" "NEC DOS" },
3239 { "\x39" "Plan 9" },
3240 { "\x40" "Venix 80286" },
3241 { "\x4d" "QNX4.x" },
3242 { "\x4e" "QNX4.x 2nd part" },
3243 { "\x4f" "QNX4.x 3rd part" },
3244 { "\x50" "OnTrack DM" },
3245 { "\x51" "OnTrack DM6 Aux1" }, /* (or Novell) */
3246 { "\x52" "CP/M" }, /* CP/M or Microport SysV/AT */
3247 { "\x53" "OnTrack DM6 Aux3" },
3248 { "\x54" "OnTrackDM6" },
3249 { "\x55" "EZ-Drive" },
3250 { "\x56" "Golden Bow" },
3251 { "\x5c" "Priam Edisk" },
3252 { "\x61" "SpeedStor" },
3253 { "\x64" "Novell Netware 286" },
3254 { "\x65" "Novell Netware 386" },
3255 { "\x70" "DiskSecure Multi-Boot" },
3257 { "\x93" "Amoeba" },
3258 { "\x94" "Amoeba BBT" }, /* (bad block table) */
3259 { "\xa7" "NeXTSTEP" },
3260 { "\xbb" "Boot Wizard hidden" },
3261 { "\xc1" "DRDOS/sec (FAT-12)" },
3262 { "\xc4" "DRDOS/sec (FAT-16 < 32M)" },
3263 { "\xc6" "DRDOS/sec (FAT-16)" },
3264 { "\xc7" "Syrinx" },
3265 { "\xda" "Non-FS data" },
3266 { "\xdb" "CP/M / CTOS / ..." },/* CP/M or Concurrent CP/M or
3267 Concurrent DOS or CTOS */
3268 { "\xde" "Dell Utility" }, /* Dell PowerEdge Server utilities */
3269 { "\xdf" "BootIt" }, /* BootIt EMBRM */
3270 { "\xe1" "DOS access" }, /* DOS access or SpeedStor 12-bit FAT
3271 extended partition */
3272 { "\xe3" "DOS R/O" }, /* DOS R/O or SpeedStor */
3273 { "\xe4" "SpeedStor" }, /* SpeedStor 16-bit FAT extended
3274 partition < 1024 cyl. */
3275 { "\xf1" "SpeedStor" },
3276 { "\xf4" "SpeedStor" }, /* SpeedStor large partition */
3277 { "\xfe" "LANstep" }, /* SpeedStor >1024 cyl. or LANstep */
3278 { "\xff" "BBT" }, /* Xenix Bad Block Table */
3285 /* A valid partition table sector ends in 0x55 0xaa */
3287 part_table_flag(const char *b)
3289 return ((uint) b[510]) + (((uint) b[511]) << 8);
3293 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3295 write_part_table_flag(char *b)
3301 /* start_sect and nr_sects are stored little endian on all machines */
3302 /* moreover, they are not aligned correctly */
3304 store4_little_endian(unsigned char *cp, unsigned int val)
3306 cp[0] = (val & 0xff);
3307 cp[1] = ((val >> 8) & 0xff);
3308 cp[2] = ((val >> 16) & 0xff);
3309 cp[3] = ((val >> 24) & 0xff);
3311 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3314 read4_little_endian(const unsigned char *cp)
3316 return (uint)(cp[0]) + ((uint)(cp[1]) << 8)
3317 + ((uint)(cp[2]) << 16) + ((uint)(cp[3]) << 24);
3320 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3322 set_start_sect(struct partition *p, unsigned int start_sect)
3324 store4_little_endian(p->start4, start_sect);
3329 get_start_sect(const struct partition *p)
3331 return read4_little_endian(p->start4);
3334 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3336 set_nr_sects(struct partition *p, int32_t nr_sects)
3338 store4_little_endian(p->size4, nr_sects);
3343 get_nr_sects(const struct partition *p)
3345 return read4_little_endian(p->size4);
3348 /* normally O_RDWR, -l option gives O_RDONLY */
3349 static int type_open = O_RDWR;
3352 static int ext_index; /* the prime extended partition */
3353 static int listing; /* no aborts for fdisk -l */
3354 static int dos_compatible_flag = ~0;
3355 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3356 static int dos_changed;
3357 static int nowarn; /* no warnings for fdisk -l/-s */
3362 static uint user_cylinders, user_heads, user_sectors;
3363 static uint pt_heads, pt_sectors;
3364 static uint kern_heads, kern_sectors;
3366 static off_t extended_offset; /* offset of link pointers */
3368 static unsigned long long total_number_of_sectors;
3371 static jmp_buf listingbuf;
3373 static void fdisk_fatal(enum failure why)
3375 const char *message;
3379 longjmp(listingbuf, 1);
3383 case unable_to_open:
3384 message = "Unable to open %s\n";
3386 case unable_to_read:
3387 message = "Unable to read %s\n";
3389 case unable_to_seek:
3390 message = "Unable to seek on %s\n";
3392 case unable_to_write:
3393 message = "Unable to write %s\n";
3396 message = "BLKGETSIZE ioctl failed on %s\n";
3399 message = "Fatal error\n";
3402 fputc('\n', stderr);
3403 fprintf(stderr, message, disk_device);
3408 seek_sector(off_t secno)
3410 off_t offset = secno * sector_size;
3411 if (lseek(fd, offset, SEEK_SET) == (off_t) -1)
3412 fdisk_fatal(unable_to_seek);
3415 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3417 write_sector(off_t secno, char *buf)
3420 if (write(fd, buf, sector_size) != sector_size)
3421 fdisk_fatal(unable_to_write);
3425 /* Allocate a buffer and read a partition table sector */
3427 read_pte(struct pte *pe, off_t offset)
3429 pe->offset = offset;
3430 pe->sectorbuffer = (char *) xmalloc(sector_size);
3431 seek_sector(offset);
3432 if (read(fd, pe->sectorbuffer, sector_size) != sector_size)
3433 fdisk_fatal(unable_to_read);
3434 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3437 pe->part_table = pe->ext_pointer = NULL;
3441 get_partition_start(const struct pte *pe)
3443 return pe->offset + get_start_sect(pe->part_table);
3446 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3448 * Avoid warning about DOS partitions when no DOS partition was changed.
3449 * Here a heuristic "is probably dos partition".
3450 * We might also do the opposite and warn in all cases except
3451 * for "is probably nondos partition".
3454 is_dos_partition(int t)
3456 return (t == 1 || t == 4 || t == 6 ||
3457 t == 0x0b || t == 0x0c || t == 0x0e ||
3458 t == 0x11 || t == 0x12 || t == 0x14 || t == 0x16 ||
3459 t == 0x1b || t == 0x1c || t == 0x1e || t == 0x24 ||
3460 t == 0xc1 || t == 0xc4 || t == 0xc6);
3466 #ifdef CONFIG_FEATURE_SUN_LABEL
3467 if (label_sun == current_label_type) {
3468 puts(_("Command action"));
3469 puts(_("\ta\ttoggle a read only flag")); /* sun */
3470 puts(_("\tb\tedit bsd disklabel"));
3471 puts(_("\tc\ttoggle the mountable flag")); /* sun */
3472 puts(_("\td\tdelete a partition"));
3473 puts(_("\tl\tlist known partition types"));
3474 puts(_("\tm\tprint this menu"));
3475 puts(_("\tn\tadd a new partition"));
3476 puts(_("\to\tcreate a new empty DOS partition table"));
3477 puts(_("\tp\tprint the partition table"));
3478 puts(_("\tq\tquit without saving changes"));
3479 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3480 puts(_("\tt\tchange a partition's system id"));
3481 puts(_("\tu\tchange display/entry units"));
3482 puts(_("\tv\tverify the partition table"));
3483 puts(_("\tw\twrite table to disk and exit"));
3484 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3485 puts(_("\tx\textra functionality (experts only)"));
3489 #ifdef CONFIG_FEATURE_SGI_LABEL
3490 if (label_sgi == current_label_type) {
3491 puts(_("Command action"));
3492 puts(_("\ta\tselect bootable partition")); /* sgi flavour */
3493 puts(_("\tb\tedit bootfile entry")); /* sgi */
3494 puts(_("\tc\tselect sgi swap partition")); /* sgi flavour */
3495 puts(_("\td\tdelete a partition"));
3496 puts(_("\tl\tlist known partition types"));
3497 puts(_("\tm\tprint this menu"));
3498 puts(_("\tn\tadd a new partition"));
3499 puts(_("\to\tcreate a new empty DOS partition table"));
3500 puts(_("\tp\tprint the partition table"));
3501 puts(_("\tq\tquit without saving changes"));
3502 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3503 puts(_("\tt\tchange a partition's system id"));
3504 puts(_("\tu\tchange display/entry units"));
3505 puts(_("\tv\tverify the partition table"));
3506 puts(_("\tw\twrite table to disk and exit"));
3509 #ifdef CONFIG_FEATURE_AIX_LABEL
3510 if (label_aix == current_label_type) {
3511 puts(_("Command action"));
3512 puts(_("\tm\tprint this menu"));
3513 puts(_("\to\tcreate a new empty DOS partition table"));
3514 puts(_("\tq\tquit without saving changes"));
3515 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3519 puts(_("Command action"));
3520 puts(_("\ta\ttoggle a bootable flag"));
3521 puts(_("\tb\tedit bsd disklabel"));
3522 puts(_("\tc\ttoggle the dos compatibility flag"));
3523 puts(_("\td\tdelete a partition"));
3524 puts(_("\tl\tlist known partition types"));
3525 puts(_("\tm\tprint this menu"));
3526 puts(_("\tn\tadd a new partition"));
3527 puts(_("\to\tcreate a new empty DOS partition table"));
3528 puts(_("\tp\tprint the partition table"));
3529 puts(_("\tq\tquit without saving changes"));
3530 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3531 puts(_("\tt\tchange a partition's system id"));
3532 puts(_("\tu\tchange display/entry units"));
3533 puts(_("\tv\tverify the partition table"));
3534 puts(_("\tw\twrite table to disk and exit"));
3535 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3536 puts(_("\tx\textra functionality (experts only)"));
3540 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3543 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3547 #ifdef CONFIG_FEATURE_SUN_LABEL
3548 if (label_sun == current_label_type) {
3549 puts(_("Command action"));
3550 puts(_("\ta\tchange number of alternate cylinders")); /*sun*/
3551 puts(_("\tc\tchange number of cylinders"));
3552 puts(_("\td\tprint the raw data in the partition table"));
3553 puts(_("\te\tchange number of extra sectors per cylinder"));/*sun*/
3554 puts(_("\th\tchange number of heads"));
3555 puts(_("\ti\tchange interleave factor")); /*sun*/
3556 puts(_("\to\tchange rotation speed (rpm)")); /*sun*/
3557 puts(_("\tm\tprint this menu"));
3558 puts(_("\tp\tprint the partition table"));
3559 puts(_("\tq\tquit without saving changes"));
3560 puts(_("\tr\treturn to main menu"));
3561 puts(_("\ts\tchange number of sectors/track"));
3562 puts(_("\tv\tverify the partition table"));
3563 puts(_("\tw\twrite table to disk and exit"));
3564 puts(_("\ty\tchange number of physical cylinders")); /*sun*/
3567 #ifdef CONFIG_FEATURE_SGI_LABEL
3568 if (label_sgi == current_label_type) {
3569 puts(_("Command action"));
3570 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3571 puts(_("\tc\tchange number of cylinders"));
3572 puts(_("\td\tprint the raw data in the partition table"));
3573 puts(_("\te\tlist extended partitions")); /* !sun */
3574 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3575 puts(_("\th\tchange number of heads"));
3576 puts(_("\tm\tprint this menu"));
3577 puts(_("\tp\tprint the partition table"));
3578 puts(_("\tq\tquit without saving changes"));
3579 puts(_("\tr\treturn to main menu"));
3580 puts(_("\ts\tchange number of sectors/track"));
3581 puts(_("\tv\tverify the partition table"));
3582 puts(_("\tw\twrite table to disk and exit"));
3585 #ifdef CONFIG_FEATURE_AIX_LABEL
3586 if (label_aix == current_label_type) {
3587 puts(_("Command action"));
3588 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3589 puts(_("\tc\tchange number of cylinders"));
3590 puts(_("\td\tprint the raw data in the partition table"));
3591 puts(_("\te\tlist extended partitions")); /* !sun */
3592 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3593 puts(_("\th\tchange number of heads"));
3594 puts(_("\tm\tprint this menu"));
3595 puts(_("\tp\tprint the partition table"));
3596 puts(_("\tq\tquit without saving changes"));
3597 puts(_("\tr\treturn to main menu"));
3598 puts(_("\ts\tchange number of sectors/track"));
3599 puts(_("\tv\tverify the partition table"));
3600 puts(_("\tw\twrite table to disk and exit"));
3604 puts(_("Command action"));
3605 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3606 puts(_("\tc\tchange number of cylinders"));
3607 puts(_("\td\tprint the raw data in the partition table"));
3608 puts(_("\te\tlist extended partitions")); /* !sun */
3609 puts(_("\tf\tfix partition order")); /* !sun, !aix, !sgi */
3610 #ifdef CONFIG_FEATURE_SGI_LABEL
3611 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3613 puts(_("\th\tchange number of heads"));
3614 puts(_("\tm\tprint this menu"));
3615 puts(_("\tp\tprint the partition table"));
3616 puts(_("\tq\tquit without saving changes"));
3617 puts(_("\tr\treturn to main menu"));
3618 puts(_("\ts\tchange number of sectors/track"));
3619 puts(_("\tv\tverify the partition table"));
3620 puts(_("\tw\twrite table to disk and exit"));
3623 #endif /* ADVANCED mode */
3625 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3626 static const struct systypes *
3630 #ifdef CONFIG_FEATURE_SUN_LABEL
3631 label_sun == current_label_type ? sun_sys_types :
3633 #ifdef CONFIG_FEATURE_SGI_LABEL
3634 label_sgi == current_label_type ? sgi_sys_types :
3639 #define get_sys_types() i386_sys_types
3640 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3642 static const char *partition_type(unsigned char type)
3645 const struct systypes *types = get_sys_types();
3647 for (i = 0; types[i].name; i++)
3648 if ((unsigned char )types[i].name[0] == type)
3649 return types[i].name + 1;
3651 return _("Unknown");
3655 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3660 #ifdef CONFIG_FEATURE_SUN_LABEL
3661 label_sun == current_label_type ? sunlabel->infos[i].id :
3663 #ifdef CONFIG_FEATURE_SGI_LABEL
3664 label_sgi == current_label_type ? sgi_get_sysid(i) :
3666 ptes[i].part_table->sys_ind);
3669 void list_types(const struct systypes *sys)
3671 uint last[4], done = 0, next = 0, size;
3674 for (i = 0; sys[i].name; i++);
3677 for (i = 3; i >= 0; i--)
3678 last[3 - i] = done += (size + i - done) / (i + 1);
3682 printf("%c%2x %-15.15s", i ? ' ' : '\n',
3683 (unsigned char)sys[next].name[0],
3684 partition_type((unsigned char)sys[next].name[0]));
3685 next = last[i++] + done;
3686 if (i > 3 || next >= last[i]) {
3690 } while (done < last[0]);
3693 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3696 is_cleared_partition(const struct partition *p)
3698 return !(!p || p->boot_ind || p->head || p->sector || p->cyl ||
3699 p->sys_ind || p->end_head || p->end_sector || p->end_cyl ||
3700 get_start_sect(p) || get_nr_sects(p));
3704 clear_partition(struct partition *p)
3708 memset(p, 0, sizeof(struct partition));
3711 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3713 set_partition(int i, int doext, off_t start, off_t stop, int sysid)
3715 struct partition *p;
3719 p = ptes[i].ext_pointer;
3720 offset = extended_offset;
3722 p = ptes[i].part_table;
3723 offset = ptes[i].offset;
3727 set_start_sect(p, start - offset);
3728 set_nr_sects(p, stop - start + 1);
3729 if (dos_compatible_flag && (start/(sectors*heads) > 1023))
3730 start = heads*sectors*1024 - 1;
3731 set_hsc(p->head, p->sector, p->cyl, start);
3732 if (dos_compatible_flag && (stop/(sectors*heads) > 1023))
3733 stop = heads*sectors*1024 - 1;
3734 set_hsc(p->end_head, p->end_sector, p->end_cyl, stop);
3735 ptes[i].changed = 1;
3740 test_c(const char **m, const char *mesg)
3744 fprintf(stderr, _("You must set"));
3746 fprintf(stderr, " %s", *m);
3756 const char *m = NULL;
3760 prev = test_c(&m, _("heads"));
3762 prev = test_c(&m, _("sectors"));
3764 prev = test_c(&m, _("cylinders"));
3768 fprintf(stderr, "%s%s.\n"
3769 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3770 "You can do this from the extra functions menu.\n"
3772 , prev ? _(" and ") : " ", m);
3777 static void update_units(void)
3779 int cyl_units = heads * sectors;
3781 if (display_in_cyl_units && cyl_units)
3782 units_per_sector = cyl_units;
3784 units_per_sector = 1; /* in sectors */
3787 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3789 warn_cylinders(void)
3791 if (label_dos == current_label_type && cylinders > 1024 && !nowarn)
3792 fprintf(stderr, _("\n"
3793 "The number of cylinders for this disk is set to %d.\n"
3794 "There is nothing wrong with that, but this is larger than 1024,\n"
3795 "and could in certain setups cause problems with:\n"
3796 "1) software that runs at boot time (e.g., old versions of LILO)\n"
3797 "2) booting and partitioning software from other OSs\n"
3798 " (e.g., DOS FDISK, OS/2 FDISK)\n"),
3804 read_extended(int ext)
3808 struct partition *p, *q;
3812 pex->ext_pointer = pex->part_table;
3814 p = pex->part_table;
3815 if (!get_start_sect(p)) {
3817 _("Bad offset in primary extended partition\n"));
3821 while (IS_EXTENDED(p->sys_ind)) {
3822 struct pte *pe = &ptes[partitions];
3824 if (partitions >= MAXIMUM_PARTS) {
3825 /* This is not a Linux restriction, but
3826 this program uses arrays of size MAXIMUM_PARTS.
3827 Do not try to `improve' this test. */
3828 struct pte *pre = &ptes[partitions-1];
3829 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3831 _("Warning: deleting partitions after %d\n"),
3835 clear_partition(pre->ext_pointer);
3839 read_pte(pe, extended_offset + get_start_sect(p));
3841 if (!extended_offset)
3842 extended_offset = get_start_sect(p);
3844 q = p = pt_offset(pe->sectorbuffer, 0);
3845 for (i = 0; i < 4; i++, p++) if (get_nr_sects(p)) {
3846 if (IS_EXTENDED(p->sys_ind)) {
3847 if (pe->ext_pointer)
3849 _("Warning: extra link "
3850 "pointer in partition table"
3851 " %d\n"), partitions + 1);
3853 pe->ext_pointer = p;
3854 } else if (p->sys_ind) {
3857 _("Warning: ignoring extra "
3858 "data in partition table"
3859 " %d\n"), partitions + 1);
3865 /* very strange code here... */
3866 if (!pe->part_table) {
3867 if (q != pe->ext_pointer)
3870 pe->part_table = q + 1;
3872 if (!pe->ext_pointer) {
3873 if (q != pe->part_table)
3874 pe->ext_pointer = q;
3876 pe->ext_pointer = q + 1;
3879 p = pe->ext_pointer;
3883 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3884 /* remove empty links */
3886 for (i = 4; i < partitions; i++) {
3887 struct pte *pe = &ptes[i];
3889 if (!get_nr_sects(pe->part_table) &&
3890 (partitions > 5 || ptes[4].part_table->sys_ind)) {
3891 printf("omitting empty partition (%d)\n", i+1);
3892 delete_partition(i);
3893 goto remove; /* numbering changed */
3899 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3901 create_doslabel(void)
3906 _("Building a new DOS disklabel. Changes will remain in memory only,\n"
3907 "until you decide to write them. After that, of course, the previous\n"
3908 "content won't be recoverable.\n\n"));
3910 current_label_type = label_dos;
3912 #ifdef CONFIG_FEATURE_OSF_LABEL
3913 possibly_osf_label = 0;
3917 for (i = 510-64; i < 510; i++)
3919 write_part_table_flag(MBRbuffer);
3920 extended_offset = 0;
3921 set_all_unchanged();
3923 get_boot(create_empty_dos);
3925 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3928 get_sectorsize(void)
3930 if (!user_set_sector_size) {
3932 if (ioctl(fd, BLKSSZGET, &arg) == 0)
3934 if (sector_size != DEFAULT_SECTOR_SIZE)
3935 printf(_("Note: sector size is %d (not %d)\n"),
3936 sector_size, DEFAULT_SECTOR_SIZE);
3941 get_kernel_geometry(void)
3943 struct hd_geometry geometry;
3945 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
3946 kern_heads = geometry.heads;
3947 kern_sectors = geometry.sectors;
3948 /* never use geometry.cylinders - it is truncated */
3953 get_partition_table_geometry(void)
3955 const unsigned char *bufp = (const unsigned char *)MBRbuffer;
3956 struct partition *p;
3957 int i, h, s, hh, ss;
3961 if (!(valid_part_table_flag((char*)bufp)))
3965 for (i = 0; i < 4; i++) {
3966 p = pt_offset(bufp, i);
3967 if (p->sys_ind != 0) {
3968 h = p->end_head + 1;
3969 s = (p->end_sector & 077);
3974 } else if (hh != h || ss != s)
3979 if (!first && !bad) {
3989 unsigned long long bytes; /* really u64 */
3992 sec_fac = sector_size / 512;
3993 #ifdef CONFIG_FEATURE_SUN_LABEL
3994 guess_device_type();
3996 heads = cylinders = sectors = 0;
3997 kern_heads = kern_sectors = 0;
3998 pt_heads = pt_sectors = 0;
4000 get_kernel_geometry();
4001 get_partition_table_geometry();
4003 heads = user_heads ? user_heads :
4004 pt_heads ? pt_heads :
4005 kern_heads ? kern_heads : 255;
4006 sectors = user_sectors ? user_sectors :
4007 pt_sectors ? pt_sectors :
4008 kern_sectors ? kern_sectors : 63;
4009 if (ioctl(fd, BLKGETSIZE64, &bytes) == 0) {
4012 unsigned long longsectors;
4014 if (ioctl(fd, BLKGETSIZE, &longsectors))
4016 bytes = ((unsigned long long) longsectors) << 9;
4019 total_number_of_sectors = (bytes >> 9);
4022 if (dos_compatible_flag)
4023 sector_offset = sectors;
4025 cylinders = total_number_of_sectors / (heads * sectors * sec_fac);
4027 cylinders = user_cylinders;
4031 * Read MBR. Returns:
4032 * -1: no 0xaa55 flag present (possibly entire disk BSD)
4033 * 0: found or created label
4037 get_boot(enum action what)
4043 for (i = 0; i < 4; i++) {
4044 struct pte *pe = &ptes[i];
4046 pe->part_table = pt_offset(MBRbuffer, i);
4047 pe->ext_pointer = NULL;
4049 pe->sectorbuffer = MBRbuffer;
4050 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4051 pe->changed = (what == create_empty_dos);
4055 #ifdef CONFIG_FEATURE_SUN_LABEL
4056 if (what == create_empty_sun && check_sun_label())
4060 memset(MBRbuffer, 0, 512);
4062 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4063 if (what == create_empty_dos)
4064 goto got_dos_table; /* skip reading disk */
4066 if ((fd = open(disk_device, type_open)) < 0) {
4067 if ((fd = open(disk_device, O_RDONLY)) < 0) {
4068 if (what == try_only)
4070 fdisk_fatal(unable_to_open);
4072 printf(_("You will not be able to write "
4073 "the partition table.\n"));
4076 if (512 != read(fd, MBRbuffer, 512)) {
4077 if (what == try_only)
4079 fdisk_fatal(unable_to_read);
4082 if ((fd = open(disk_device, O_RDONLY)) < 0)
4084 if (512 != read(fd, MBRbuffer, 512))
4092 #ifdef CONFIG_FEATURE_SUN_LABEL
4093 if (check_sun_label())
4097 #ifdef CONFIG_FEATURE_SGI_LABEL
4098 if (check_sgi_label())
4102 #ifdef CONFIG_FEATURE_AIX_LABEL
4103 if (check_aix_label())
4107 #ifdef CONFIG_FEATURE_OSF_LABEL
4108 if (check_osf_label()) {
4109 possibly_osf_label = 1;
4110 if (!valid_part_table_flag(MBRbuffer)) {
4111 current_label_type = label_osf;
4114 printf(_("This disk has both DOS and BSD magic.\n"
4115 "Give the 'b' command to go to BSD mode.\n"));
4119 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4123 if (!valid_part_table_flag(MBRbuffer)) {
4124 #ifndef CONFIG_FEATURE_FDISK_WRITABLE
4130 _("Device contains neither a valid DOS "
4131 "partition table, nor Sun, SGI or OSF "
4134 #ifdef CONFIG_FEATURE_SUN_LABEL
4143 case create_empty_dos:
4144 #ifdef CONFIG_FEATURE_SUN_LABEL
4145 case create_empty_sun:
4149 fprintf(stderr, _("Internal error\n"));
4152 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
4155 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4160 for (i = 0; i < 4; i++) {
4161 struct pte *pe = &ptes[i];
4163 if (IS_EXTENDED(pe->part_table->sys_ind)) {
4164 if (partitions != 4)
4165 fprintf(stderr, _("Ignoring extra extended "
4166 "partition %d\n"), i + 1);
4172 for (i = 3; i < partitions; i++) {
4173 struct pte *pe = &ptes[i];
4175 if (!valid_part_table_flag(pe->sectorbuffer)) {
4177 _("Warning: invalid flag 0x%04x of partition "
4178 "table %d will be corrected by w(rite)\n"),
4179 part_table_flag(pe->sectorbuffer), i + 1);
4180 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4189 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4191 * Print the message MESG, then read an integer between LOW and HIGH (inclusive).
4192 * If the user hits Enter, DFLT is returned.
4193 * Answers like +10 are interpreted as offsets from BASE.
4195 * There is no default if DFLT is not between LOW and HIGH.
4198 read_int(uint low, uint dflt, uint high, uint base, char *mesg)
4202 static char *ms = NULL;
4203 static int mslen = 0;
4205 if (!ms || strlen(mesg)+100 > mslen) {
4206 mslen = strlen(mesg)+200;
4207 ms = xrealloc(ms,mslen);
4210 if (dflt < low || dflt > high)
4214 snprintf(ms, mslen, _("%s (%u-%u, default %u): "),
4215 mesg, low, high, dflt);
4217 snprintf(ms, mslen, "%s (%u-%u): ", mesg, low, high);
4220 int use_default = default_ok;
4222 /* ask question and read answer */
4223 while (read_chars(ms) != '\n' && !isdigit(*line_ptr)
4224 && *line_ptr != '-' && *line_ptr != '+')
4227 if (*line_ptr == '+' || *line_ptr == '-') {
4228 int minus = (*line_ptr == '-');
4231 i = atoi(line_ptr+1);
4233 while (isdigit(*++line_ptr))
4236 switch (*line_ptr) {
4239 if (!display_in_cyl_units)
4240 i *= heads * sectors;
4254 absolute = 1000000000;
4260 unsigned long long bytes;
4263 bytes = (unsigned long long) i * absolute;
4264 unit = sector_size * units_per_sector;
4265 bytes += unit/2; /* round */
4274 while (isdigit(*line_ptr)) {
4280 printf(_("Using default value %u\n"), i = dflt);
4281 if (i >= low && i <= high)
4284 printf(_("Value out of range.\n"));
4290 get_partition(int warn, int max)
4295 i = read_int(1, 0, max, 0, _("Partition number")) - 1;
4301 label_sun != current_label_type &&
4302 label_sgi != current_label_type &&
4303 !pe->part_table->sys_ind
4305 #ifdef CONFIG_FEATURE_SUN_LABEL
4307 label_sun == current_label_type &&
4309 !sunlabel->partitions[i].num_sectors
4310 || !sunlabel->infos[i].id
4314 #ifdef CONFIG_FEATURE_SGI_LABEL
4316 label_sgi == current_label_type &&
4317 !sgi_get_num_sectors(i)
4322 _("Warning: partition %d has empty type\n"),
4331 get_existing_partition(int warn, int max)
4336 for (i = 0; i < max; i++) {
4337 struct pte *pe = &ptes[i];
4338 struct partition *p = pe->part_table;
4340 if (p && !is_cleared_partition(p)) {
4347 printf(_("Selected partition %d\n"), pno+1);
4350 printf(_("No partition is defined yet!\n"));
4354 return get_partition(warn, max);
4358 get_nonexisting_partition(int warn, int max)
4363 for (i = 0; i < max; i++) {
4364 struct pte *pe = &ptes[i];
4365 struct partition *p = pe->part_table;
4367 if (p && is_cleared_partition(p)) {
4374 printf(_("Selected partition %d\n"), pno+1);
4377 printf(_("All primary partitions have been defined already!\n"));
4381 return get_partition(warn, max);
4385 void change_units(void)
4387 display_in_cyl_units = !display_in_cyl_units;
4389 printf(_("Changing display/entry units to %s\n"),
4394 toggle_active(int i)
4396 struct pte *pe = &ptes[i];
4397 struct partition *p = pe->part_table;
4399 if (IS_EXTENDED(p->sys_ind) && !p->boot_ind)
4401 _("WARNING: Partition %d is an extended partition\n"),
4403 p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG);
4408 toggle_dos_compatibility_flag(void)
4410 dos_compatible_flag = ~dos_compatible_flag;
4411 if (dos_compatible_flag) {
4412 sector_offset = sectors;
4413 printf(_("DOS Compatibility flag is set\n"));
4417 printf(_("DOS Compatibility flag is not set\n"));
4422 delete_partition(int i)
4424 struct pte *pe = &ptes[i];
4425 struct partition *p = pe->part_table;
4426 struct partition *q = pe->ext_pointer;
4428 /* Note that for the fifth partition (i == 4) we don't actually
4429 * decrement partitions.
4432 if (warn_geometry())
4433 return; /* C/H/S not set */
4436 #ifdef CONFIG_FEATURE_SUN_LABEL
4437 if (label_sun == current_label_type) {
4438 sun_delete_partition(i);
4442 #ifdef CONFIG_FEATURE_SGI_LABEL
4443 if (label_sgi == current_label_type) {
4444 sgi_delete_partition(i);
4450 if (IS_EXTENDED(p->sys_ind) && i == ext_index) {
4452 ptes[ext_index].ext_pointer = NULL;
4453 extended_offset = 0;
4459 if (!q->sys_ind && i > 4) {
4460 /* the last one in the chain - just delete */
4463 clear_partition(ptes[i].ext_pointer);
4464 ptes[i].changed = 1;
4466 /* not the last one - further ones will be moved down */
4468 /* delete this link in the chain */
4469 p = ptes[i-1].ext_pointer;
4471 set_start_sect(p, get_start_sect(q));
4472 set_nr_sects(p, get_nr_sects(q));
4473 ptes[i-1].changed = 1;
4474 } else if (partitions > 5) { /* 5 will be moved to 4 */
4475 /* the first logical in a longer chain */
4478 if (pe->part_table) /* prevent SEGFAULT */
4479 set_start_sect(pe->part_table,
4480 get_partition_start(pe) -
4482 pe->offset = extended_offset;
4486 if (partitions > 5) {
4488 while (i < partitions) {
4489 ptes[i] = ptes[i+1];
4493 /* the only logical: clear only */
4494 clear_partition(ptes[i].part_table);
4501 int i, sys, origsys;
4502 struct partition *p;
4504 #ifdef CONFIG_FEATURE_SGI_LABEL
4505 /* If sgi_label then don't use get_existing_partition,
4506 let the user select a partition, since get_existing_partition()
4507 only works for Linux like partition tables. */
4508 if (label_sgi != current_label_type) {
4509 i = get_existing_partition(0, partitions);
4511 i = get_partition(0, partitions);
4514 i = get_existing_partition(0, partitions);
4518 p = ptes[i].part_table;
4519 origsys = sys = get_sysid(i);
4521 /* if changing types T to 0 is allowed, then
4522 the reverse change must be allowed, too */
4523 if (!sys && label_sgi != current_label_type &&
4524 label_sun != current_label_type && !get_nr_sects(p))
4526 printf(_("Partition %d does not exist yet!\n"), i + 1);
4529 sys = read_hex (get_sys_types());
4531 if (!sys && label_sgi != current_label_type &&
4532 label_sun != current_label_type)
4534 printf(_("Type 0 means free space to many systems\n"
4535 "(but not to Linux). Having partitions of\n"
4536 "type 0 is probably unwise. You can delete\n"
4537 "a partition using the `d' command.\n"));
4541 if (label_sun != current_label_type && label_sgi != current_label_type) {
4542 if (IS_EXTENDED(sys) != IS_EXTENDED(p->sys_ind)) {
4543 printf(_("You cannot change a partition into"
4544 " an extended one or vice versa\n"
4545 "Delete it first.\n"));
4551 #ifdef CONFIG_FEATURE_SUN_LABEL
4552 if (label_sun == current_label_type && i == 2 && sys != WHOLE_DISK)
4553 printf(_("Consider leaving partition 3 "
4554 "as Whole disk (5),\n"
4555 "as SunOS/Solaris expects it and "
4556 "even Linux likes it.\n\n"));
4558 #ifdef CONFIG_FEATURE_SGI_LABEL
4559 if (label_sgi == current_label_type &&
4561 (i == 10 && sys != ENTIRE_DISK) ||
4562 (i == 8 && sys != 0)
4565 printf(_("Consider leaving partition 9 "
4566 "as volume header (0),\nand "
4567 "partition 11 as entire volume (6)"
4568 "as IRIX expects it.\n\n"));
4573 #ifdef CONFIG_FEATURE_SUN_LABEL
4574 if (label_sun == current_label_type) {
4575 sun_change_sysid(i, sys);
4578 #ifdef CONFIG_FEATURE_SGI_LABEL
4579 if (label_sgi == current_label_type) {
4580 sgi_change_sysid(i, sys);
4585 printf(_("Changed system type of partition %d "
4586 "to %x (%s)\n"), i + 1, sys,
4587 partition_type(sys));
4588 ptes[i].changed = 1;
4589 if (is_dos_partition(origsys) ||
4590 is_dos_partition(sys))
4597 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
4600 /* check_consistency() and long2chs() added Sat Mar 6 12:28:16 1993,
4601 * faith@cs.unc.edu, based on code fragments from pfdisk by Gordon W. Ross,
4602 * Jan. 1990 (version 1.2.1 by Gordon W. Ross Aug. 1990; Modified by S.
4603 * Lubkin Oct. 1991). */
4606 long2chs(ulong ls, uint *c, uint *h, uint *s)
4608 int spc = heads * sectors;
4613 *s = ls % sectors + 1; /* sectors count from 1 */
4617 check_consistency(const struct partition *p, int partition)
4619 uint pbc, pbh, pbs; /* physical beginning c, h, s */
4620 uint pec, peh, pes; /* physical ending c, h, s */
4621 uint lbc, lbh, lbs; /* logical beginning c, h, s */
4622 uint lec, leh, les; /* logical ending c, h, s */
4624 if (!heads || !sectors || (partition >= 4))
4625 return; /* do not check extended partitions */
4627 /* physical beginning c, h, s */
4628 pbc = (p->cyl & 0xff) | ((p->sector << 2) & 0x300);
4630 pbs = p->sector & 0x3f;
4632 /* physical ending c, h, s */
4633 pec = (p->end_cyl & 0xff) | ((p->end_sector << 2) & 0x300);
4635 pes = p->end_sector & 0x3f;
4637 /* compute logical beginning (c, h, s) */
4638 long2chs(get_start_sect(p), &lbc, &lbh, &lbs);
4640 /* compute logical ending (c, h, s) */
4641 long2chs(get_start_sect(p) + get_nr_sects(p) - 1, &lec, &leh, &les);
4643 /* Same physical / logical beginning? */
4644 if (cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) {
4645 printf(_("Partition %d has different physical/logical "
4646 "beginnings (non-Linux?):\n"), partition + 1);
4647 printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs);
4648 printf(_("logical=(%d, %d, %d)\n"),lbc, lbh, lbs);
4651 /* Same physical / logical ending? */
4652 if (cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) {
4653 printf(_("Partition %d has different physical/logical "
4654 "endings:\n"), partition + 1);
4655 printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
4656 printf(_("logical=(%d, %d, %d)\n"),lec, leh, les);
4660 /* Beginning on cylinder boundary? */
4661 if (pbh != !pbc || pbs != 1) {
4662 printf(_("Partition %i does not start on cylinder "
4663 "boundary:\n"), partition + 1);
4664 printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs);
4665 printf(_("should be (%d, %d, 1)\n"), pbc, !pbc);
4669 /* Ending on cylinder boundary? */
4670 if (peh != (heads - 1) || pes != sectors) {
4671 printf(_("Partition %i does not end on cylinder boundary.\n"),
4674 printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
4675 printf(_("should be (%d, %d, %d)\n"),
4676 pec, heads - 1, sectors);
4682 list_disk_geometry(void)
4684 long long bytes = (total_number_of_sectors << 9);
4685 long megabytes = bytes/1000000;
4687 if (megabytes < 10000)
4688 printf(_("\nDisk %s: %ld MB, %lld bytes\n"),
4689 disk_device, megabytes, bytes);
4691 printf(_("\nDisk %s: %ld.%ld GB, %lld bytes\n"),
4692 disk_device, megabytes/1000, (megabytes/100)%10, bytes);
4693 printf(_("%d heads, %d sectors/track, %d cylinders"),
4694 heads, sectors, cylinders);
4695 if (units_per_sector == 1)
4696 printf(_(", total %llu sectors"),
4697 total_number_of_sectors / (sector_size/512));
4698 printf(_("\nUnits = %s of %d * %d = %d bytes\n\n"),
4700 units_per_sector, sector_size, units_per_sector * sector_size);
4704 * Check whether partition entries are ordered by their starting positions.
4705 * Return 0 if OK. Return i if partition i should have been earlier.
4706 * Two separate checks: primary and logical partitions.
4709 wrong_p_order(int *prev)
4711 const struct pte *pe;
4712 const struct partition *p;
4713 off_t last_p_start_pos = 0, p_start_pos;
4716 for (i = 0 ; i < partitions; i++) {
4719 last_p_start_pos = 0;
4722 if ((p = pe->part_table)->sys_ind) {
4723 p_start_pos = get_partition_start(pe);
4725 if (last_p_start_pos > p_start_pos) {
4731 last_p_start_pos = p_start_pos;
4738 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
4740 * Fix the chain of logicals.
4741 * extended_offset is unchanged, the set of sectors used is unchanged
4742 * The chain is sorted so that sectors increase, and so that
4743 * starting sectors increase.
4745 * After this it may still be that cfdisk doesnt like the table.
4746 * (This is because cfdisk considers expanded parts, from link to
4747 * end of partition, and these may still overlap.)
4749 * sfdisk /dev/hda > ohda; sfdisk /dev/hda < ohda
4753 fix_chain_of_logicals(void)
4755 int j, oj, ojj, sj, sjj;
4756 struct partition *pj,*pjj,tmp;
4758 /* Stage 1: sort sectors but leave sector of part 4 */
4759 /* (Its sector is the global extended_offset.) */
4761 for (j = 5; j < partitions-1; j++) {
4762 oj = ptes[j].offset;
4763 ojj = ptes[j+1].offset;
4765 ptes[j].offset = ojj;
4766 ptes[j+1].offset = oj;
4767 pj = ptes[j].part_table;
4768 set_start_sect(pj, get_start_sect(pj)+oj-ojj);
4769 pjj = ptes[j+1].part_table;
4770 set_start_sect(pjj, get_start_sect(pjj)+ojj-oj);
4771 set_start_sect(ptes[j-1].ext_pointer,
4772 ojj-extended_offset);
4773 set_start_sect(ptes[j].ext_pointer,
4774 oj-extended_offset);
4779 /* Stage 2: sort starting sectors */
4781 for (j = 4; j < partitions-1; j++) {
4782 pj = ptes[j].part_table;
4783 pjj = ptes[j+1].part_table;
4784 sj = get_start_sect(pj);
4785 sjj = get_start_sect(pjj);
4786 oj = ptes[j].offset;
4787 ojj = ptes[j+1].offset;
4788 if (oj+sj > ojj+sjj) {
4792 set_start_sect(pj, ojj+sjj-oj);
4793 set_start_sect(pjj, oj+sj-ojj);
4798 /* Probably something was changed */
4799 for (j = 4; j < partitions; j++)
4800 ptes[j].changed = 1;
4805 fix_partition_table_order(void)
4807 struct pte *pei, *pek;
4810 if (!wrong_p_order(NULL)) {
4811 printf(_("Nothing to do. Ordering is correct already.\n\n"));
4815 while ((i = wrong_p_order(&k)) != 0 && i < 4) {
4816 /* partition i should have come earlier, move it */
4817 /* We have to move data in the MBR */
4818 struct partition *pi, *pk, *pe, pbuf;
4822 pe = pei->ext_pointer;
4823 pei->ext_pointer = pek->ext_pointer;
4824 pek->ext_pointer = pe;
4826 pi = pei->part_table;
4827 pk = pek->part_table;
4829 memmove(&pbuf, pi, sizeof(struct partition));
4830 memmove(pi, pk, sizeof(struct partition));
4831 memmove(pk, &pbuf, sizeof(struct partition));
4833 pei->changed = pek->changed = 1;
4837 fix_chain_of_logicals();
4845 list_table(int xtra)
4847 const struct partition *p;
4850 #ifdef CONFIG_FEATURE_SUN_LABEL
4851 if (label_sun == current_label_type) {
4852 sun_list_table(xtra);
4857 #ifdef CONFIG_FEATURE_SGI_LABEL
4858 if (label_sgi == current_label_type) {
4859 sgi_list_table(xtra);
4864 list_disk_geometry();
4866 #ifdef CONFIG_FEATURE_OSF_LABEL
4867 if (label_osf == current_label_type) {
4868 xbsd_print_disklabel(xtra);
4873 /* Heuristic: we list partition 3 of /dev/foo as /dev/foo3,
4874 but if the device name ends in a digit, say /dev/foo1,
4875 then the partition is called /dev/foo1p3. */
4876 w = strlen(disk_device);
4877 if (w && isdigit(disk_device[w-1]))
4882 printf(_("%*s Boot Start End Blocks Id System\n"),
4885 for (i = 0; i < partitions; i++) {
4886 const struct pte *pe = &ptes[i];
4889 if (p && !is_cleared_partition(p)) {
4890 off_t psects = get_nr_sects(p);
4891 off_t pblocks = psects;
4892 unsigned int podd = 0;
4894 if (sector_size < 1024) {
4895 pblocks /= (1024 / sector_size);
4896 podd = psects % (1024 / sector_size);
4898 if (sector_size > 1024)
4899 pblocks *= (sector_size / 1024);
4901 "%s %c %11llu %11llu %11llu%c %2x %s\n",
4902 partname(disk_device, i+1, w+2),
4903 /* boot flag */ !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG
4905 /* start */ (unsigned long long) cround(get_partition_start(pe)),
4906 /* end */ (unsigned long long) cround(get_partition_start(pe) + psects
4907 - (psects ? 1 : 0)),
4908 /* odd flag on end */ (unsigned long long) pblocks, podd ? '+' : ' ',
4909 /* type id */ p->sys_ind,
4910 /* type name */ partition_type(p->sys_ind));
4911 check_consistency(p, i);
4915 /* Is partition table in disk order? It need not be, but... */
4916 /* partition table entries are not checked for correct order if this
4917 is a sgi, sun or aix labeled disk... */
4918 if (label_dos == current_label_type && wrong_p_order(NULL)) {
4920 printf(_("\nPartition table entries are not in disk order\n"));
4924 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
4926 x_list_table(int extend)
4928 const struct pte *pe;
4929 const struct partition *p;
4932 printf(_("\nDisk %s: %d heads, %d sectors, %d cylinders\n\n"),
4933 disk_device, heads, sectors, cylinders);
4934 printf(_("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n"));
4935 for (i = 0 ; i < partitions; i++) {
4937 p = (extend ? pe->ext_pointer : pe->part_table);
4939 printf("%2d %02x%4d%4d%5d%4d%4d%5d%11u%11u %02x\n",
4940 i + 1, p->boot_ind, p->head,
4942 cylinder(p->sector, p->cyl), p->end_head,
4943 sector(p->end_sector),
4944 cylinder(p->end_sector, p->end_cyl),
4945 get_start_sect(p), get_nr_sects(p), p->sys_ind);
4947 check_consistency(p, i);
4953 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4955 fill_bounds(off_t *first, off_t *last)
4958 const struct pte *pe = &ptes[0];
4959 const struct partition *p;
4961 for (i = 0; i < partitions; pe++,i++) {
4963 if (!p->sys_ind || IS_EXTENDED(p->sys_ind)) {
4964 first[i] = 0xffffffff;
4967 first[i] = get_partition_start(pe);
4968 last[i] = first[i] + get_nr_sects(p) - 1;
4974 check(int n, uint h, uint s, uint c, off_t start)
4976 off_t total, real_s, real_c;
4978 real_s = sector(s) - 1;
4979 real_c = cylinder(s, c);
4980 total = (real_c * sectors + real_s) * heads + h;
4982 fprintf(stderr, _("Warning: partition %d contains sector 0\n"), n);
4985 _("Partition %d: head %d greater than maximum %d\n"),
4987 if (real_s >= sectors)
4988 fprintf(stderr, _("Partition %d: sector %d greater than "
4989 "maximum %d\n"), n, s, sectors);
4990 if (real_c >= cylinders)
4991 fprintf(stderr, _("Partitions %d: cylinder %llu greater than "
4992 "maximum %d\n"), n, (unsigned long long)real_c + 1, cylinders);
4993 if (cylinders <= 1024 && start != total)
4995 _("Partition %d: previous sectors %llu disagrees with "
4996 "total %llu\n"), n, (unsigned long long)start, (unsigned long long)total);
5004 off_t first[partitions], last[partitions];
5005 struct partition *p;
5007 if (warn_geometry())
5010 #ifdef CONFIG_FEATURE_SUN_LABEL
5011 if (label_sun == current_label_type) {
5016 #ifdef CONFIG_FEATURE_SGI_LABEL
5017 if (label_sgi == current_label_type) {
5023 fill_bounds(first, last);
5024 for (i = 0; i < partitions; i++) {
5025 struct pte *pe = &ptes[i];
5028 if (p->sys_ind && !IS_EXTENDED(p->sys_ind)) {
5029 check_consistency(p, i);
5030 if (get_partition_start(pe) < first[i])
5031 printf(_("Warning: bad start-of-data in "
5032 "partition %d\n"), i + 1);
5033 check(i + 1, p->end_head, p->end_sector, p->end_cyl,
5035 total += last[i] + 1 - first[i];
5036 for (j = 0; j < i; j++)
5037 if ((first[i] >= first[j] && first[i] <= last[j])
5038 || ((last[i] <= last[j] && last[i] >= first[j]))) {
5039 printf(_("Warning: partition %d overlaps "
5040 "partition %d.\n"), j + 1, i + 1);
5041 total += first[i] >= first[j] ?
5042 first[i] : first[j];
5043 total -= last[i] <= last[j] ?
5049 if (extended_offset) {
5050 struct pte *pex = &ptes[ext_index];
5051 off_t e_last = get_start_sect(pex->part_table) +
5052 get_nr_sects(pex->part_table) - 1;
5054 for (i = 4; i < partitions; i++) {
5056 p = ptes[i].part_table;
5058 if (i != 4 || i + 1 < partitions)
5059 printf(_("Warning: partition %d "
5060 "is empty\n"), i + 1);
5062 else if (first[i] < extended_offset ||
5064 printf(_("Logical partition %d not entirely in "
5065 "partition %d\n"), i + 1, ext_index + 1);
5069 if (total > heads * sectors * cylinders)
5070 printf(_("Total allocated sectors %d greater than the maximum "
5071 "%d\n"), total, heads * sectors * cylinders);
5072 else if ((total = heads * sectors * cylinders - total) != 0)
5073 printf(_("%d unallocated sectors\n"), total);
5077 add_partition(int n, int sys)
5079 char mesg[256]; /* 48 does not suffice in Japanese */
5080 int i, num_read = 0;
5081 struct partition *p = ptes[n].part_table;
5082 struct partition *q = ptes[ext_index].part_table;
5084 off_t start, stop = 0, limit, temp,
5085 first[partitions], last[partitions];
5087 if (p && p->sys_ind) {
5088 printf(_("Partition %d is already defined. Delete "
5089 "it before re-adding it.\n"), n + 1);
5092 fill_bounds(first, last);
5094 start = sector_offset;
5095 if (display_in_cyl_units || !total_number_of_sectors)
5096 llimit = heads * sectors * cylinders - 1;
5098 llimit = total_number_of_sectors - 1;
5100 if (limit != llimit)
5102 if (extended_offset) {
5103 first[ext_index] = extended_offset;
5104 last[ext_index] = get_start_sect(q) +
5105 get_nr_sects(q) - 1;
5108 start = extended_offset + sector_offset;
5109 limit = get_start_sect(q) + get_nr_sects(q) - 1;
5111 if (display_in_cyl_units)
5112 for (i = 0; i < partitions; i++)
5113 first[i] = (cround(first[i]) - 1) * units_per_sector;
5115 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
5118 for (i = 0; i < partitions; i++) {
5121 if (start == ptes[i].offset)
5122 start += sector_offset;
5123 lastplusoff = last[i] + ((n < 4) ? 0 : sector_offset);
5124 if (start >= first[i] && start <= lastplusoff)
5125 start = lastplusoff + 1;
5129 if (start >= temp+units_per_sector && num_read) {
5130 printf(_("Sector %llu is already allocated\n"), (unsigned long long)temp);
5134 if (!num_read && start == temp) {
5137 saved_start = start;
5138 start = read_int(cround(saved_start), cround(saved_start), cround(limit),
5140 if (display_in_cyl_units) {
5141 start = (start - 1) * units_per_sector;
5142 if (start < saved_start) start = saved_start;
5146 } while (start != temp || !num_read);
5147 if (n > 4) { /* NOT for fifth partition */
5148 struct pte *pe = &ptes[n];
5150 pe->offset = start - sector_offset;
5151 if (pe->offset == extended_offset) { /* must be corrected */
5153 if (sector_offset == 1)
5158 for (i = 0; i < partitions; i++) {
5159 struct pte *pe = &ptes[i];
5161 if (start < pe->offset && limit >= pe->offset)
5162 limit = pe->offset - 1;
5163 if (start < first[i] && limit >= first[i])
5164 limit = first[i] - 1;
5166 if (start > limit) {
5167 printf(_("No free sectors available\n"));
5172 if (cround(start) == cround(limit)) {
5175 snprintf(mesg, sizeof(mesg),
5176 _("Last %s or +size or +sizeM or +sizeK"),
5177 str_units(SINGULAR));
5178 stop = read_int(cround(start), cround(limit), cround(limit),
5179 cround(start), mesg);
5180 if (display_in_cyl_units) {
5181 stop = stop * units_per_sector - 1;
5187 set_partition(n, 0, start, stop, sys);
5189 set_partition(n - 1, 1, ptes[n].offset, stop, EXTENDED);
5191 if (IS_EXTENDED(sys)) {
5192 struct pte *pe4 = &ptes[4];
5193 struct pte *pen = &ptes[n];
5196 pen->ext_pointer = p;
5197 pe4->offset = extended_offset = start;
5198 pe4->sectorbuffer = xcalloc(1, sector_size);
5199 pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
5200 pe4->ext_pointer = pe4->part_table + 1;
5209 if (partitions > 5 || ptes[4].part_table->sys_ind) {
5210 struct pte *pe = &ptes[partitions];
5212 pe->sectorbuffer = xcalloc(1, sector_size);
5213 pe->part_table = pt_offset(pe->sectorbuffer, 0);
5214 pe->ext_pointer = pe->part_table + 1;
5219 add_partition(partitions - 1, LINUX_NATIVE);
5225 int i, free_primary = 0;
5227 if (warn_geometry())
5230 #ifdef CONFIG_FEATURE_SUN_LABEL
5231 if (label_sun == current_label_type) {
5232 add_sun_partition(get_partition(0, partitions), LINUX_NATIVE);
5236 #ifdef CONFIG_FEATURE_SGI_LABEL
5237 if (label_sgi == current_label_type) {
5238 sgi_add_partition(get_partition(0, partitions), LINUX_NATIVE);
5242 #ifdef CONFIG_FEATURE_AIX_LABEL
5243 if (label_aix == current_label_type) {
5244 printf(_("\tSorry - this fdisk cannot handle AIX disk labels."
5245 "\n\tIf you want to add DOS-type partitions, create"
5246 "\n\ta new empty DOS partition table first. (Use o.)"
5248 "This will destroy the present disk contents.\n"));
5253 for (i = 0; i < 4; i++)
5254 free_primary += !ptes[i].part_table->sys_ind;
5256 if (!free_primary && partitions >= MAXIMUM_PARTS) {
5257 printf(_("The maximum number of partitions has been created\n"));
5261 if (!free_primary) {
5262 if (extended_offset)
5265 printf(_("You must delete some partition and add "
5266 "an extended partition first\n"));
5268 char c, line[LINE_LENGTH];
5269 snprintf(line, sizeof(line), "%s\n %s\n p primary "
5270 "partition (1-4)\n",
5271 "Command action", (extended_offset ?
5272 "l logical (5 or over)" : "e extended"));
5274 if ((c = read_char(line)) == 'p' || c == 'P') {
5275 i = get_nonexisting_partition(0, 4);
5277 add_partition(i, LINUX_NATIVE);
5280 else if (c == 'l' && extended_offset) {
5284 else if (c == 'e' && !extended_offset) {
5285 i = get_nonexisting_partition(0, 4);
5287 add_partition(i, EXTENDED);
5291 printf(_("Invalid partition number "
5292 "for type `%c'\n"), c);
5302 if (label_dos == current_label_type) {
5303 for (i = 0; i < 3; i++)
5304 if (ptes[i].changed)
5305 ptes[3].changed = 1;
5306 for (i = 3; i < partitions; i++) {
5307 struct pte *pe = &ptes[i];
5310 write_part_table_flag(pe->sectorbuffer);
5311 write_sector(pe->offset, pe->sectorbuffer);
5315 #ifdef CONFIG_FEATURE_SGI_LABEL
5316 else if (label_sgi == current_label_type) {
5317 /* no test on change? the printf below might be mistaken */
5321 #ifdef CONFIG_FEATURE_SUN_LABEL
5322 else if (label_sun == current_label_type) {
5325 for (i = 0; i < 8; i++)
5326 if (ptes[i].changed)
5333 printf(_("The partition table has been altered!\n\n"));
5334 reread_partition_table(1);
5338 reread_partition_table(int leave)
5343 printf(_("Calling ioctl() to re-read partition table.\n"));
5346 if ((i = ioctl(fd, BLKRRPART)) != 0) {
5349 /* some kernel versions (1.2.x) seem to have trouble
5350 rereading the partition table, but if asked to do it
5351 twice, the second time works. - biro@yggdrasil.com */
5354 if ((i = ioctl(fd, BLKRRPART)) != 0)
5359 printf(_("\nWARNING: Re-reading the partition table "
5360 "failed with error %d: %s.\n"
5361 "The kernel still uses the old table.\n"
5362 "The new table will be used "
5363 "at the next reboot.\n"),
5364 error, strerror(error));
5369 _("\nWARNING: If you have created or modified any DOS 6.x\n"
5370 "partitions, please see the fdisk manual page for additional\n"
5376 printf(_("Syncing disks.\n"));
5378 sleep(4); /* for sync() */
5382 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
5384 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
5385 #define MAX_PER_LINE 16
5387 print_buffer(char *pbuffer)
5391 for (i = 0, l = 0; i < sector_size; i++, l++) {
5393 printf("0x%03X:", i);
5394 printf(" %02X", (unsigned char) pbuffer[i]);
5395 if (l == MAX_PER_LINE - 1) {
5411 printf(_("Device: %s\n"), disk_device);
5412 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
5413 if (label_sun == current_label_type || label_sgi == current_label_type)
5414 print_buffer(MBRbuffer);
5417 for (i = 3; i < partitions; i++)
5418 print_buffer(ptes[i].sectorbuffer);
5424 struct pte *pe = &ptes[i];
5425 struct partition *p = pe->part_table;
5428 if (warn_geometry())
5430 if (!p->sys_ind || !get_nr_sects(p) || IS_EXTENDED(p->sys_ind)) {
5431 printf(_("Partition %d has no data area\n"), i + 1);
5434 first = get_partition_start(pe);
5435 new = read_int(first, first, first + get_nr_sects(p) - 1, first,
5436 _("New beginning of data")) - pe->offset;
5438 if (new != get_nr_sects(p)) {
5439 first = get_nr_sects(p) + get_start_sect(p) - new;
5440 set_nr_sects(p, first);
5441 set_start_sect(p, new);
5453 c = tolower(read_char(_("Expert command (m for help): ")));
5456 #ifdef CONFIG_FEATURE_SUN_LABEL
5457 if (label_sun == current_label_type)
5462 if (label_dos == current_label_type)
5463 move_begin(get_partition(0, partitions));
5466 user_cylinders = cylinders =
5467 read_int(1, cylinders, 1048576, 0,
5468 _("Number of cylinders"));
5469 #ifdef CONFIG_FEATURE_SUN_LABEL
5470 if (label_sun == current_label_type)
5471 sun_set_ncyl(cylinders);
5473 if (label_dos == current_label_type)
5480 #ifdef CONFIG_FEATURE_SGI_LABEL
5481 if (label_sgi == current_label_type)
5485 #ifdef CONFIG_FEATURE_SUN_LABEL
5486 if (label_sun == current_label_type)
5490 if (label_dos == current_label_type)
5494 if (label_dos == current_label_type)
5495 fix_partition_table_order();
5498 #ifdef CONFIG_FEATURE_SGI_LABEL
5503 user_heads = heads = read_int(1, heads, 256, 0,
5504 _("Number of heads"));
5508 #ifdef CONFIG_FEATURE_SUN_LABEL
5509 if (label_sun == current_label_type)
5514 #ifdef CONFIG_FEATURE_SUN_LABEL
5515 if (label_sun == current_label_type)
5520 #ifdef CONFIG_FEATURE_SUN_LABEL
5521 if (label_sun == current_label_type)
5534 user_sectors = sectors = read_int(1, sectors, 63, 0,
5535 _("Number of sectors"));
5536 if (dos_compatible_flag) {
5537 sector_offset = sectors;
5538 fprintf(stderr, _("Warning: setting "
5539 "sector offset for DOS "
5548 write_table(); /* does not return */
5551 #ifdef CONFIG_FEATURE_SUN_LABEL
5552 if (label_sun == current_label_type)
5553 sun_set_pcylcount();
5561 #endif /* ADVANCED mode */
5564 is_ide_cdrom_or_tape(const char *device)
5568 struct stat statbuf;
5571 /* No device was given explicitly, and we are trying some
5572 likely things. But opening /dev/hdc may produce errors like
5573 "hdc: tray open or drive not ready"
5574 if it happens to be a CD-ROM drive. It even happens that
5575 the process hangs on the attempt to read a music CD.
5576 So try to be careful. This only works since 2.1.73. */
5578 if (strncmp("/dev/hd", device, 7))
5581 snprintf(buf, sizeof(buf), "/proc/ide/%s/media", device+5);
5582 procf = fopen(buf, "r");
5583 if (procf != NULL && fgets(buf, sizeof(buf), procf))
5584 is_ide = (!strncmp(buf, "cdrom", 5) ||
5585 !strncmp(buf, "tape", 4));
5587 /* Now when this proc file does not exist, skip the
5588 device when it is read-only. */
5589 if (stat(device, &statbuf) == 0)
5590 is_ide = ((statbuf.st_mode & 0222) == 0);
5599 try(const char *device, int user_specified)
5603 disk_device = device;
5604 if (setjmp(listingbuf))
5606 if (!user_specified)
5607 if (is_ide_cdrom_or_tape(device))
5609 if ((fd = open(disk_device, type_open)) >= 0) {
5610 gb = get_boot(try_only);
5611 if (gb > 0) { /* I/O error */
5613 } else if (gb < 0) { /* no DOS signature */
5614 list_disk_geometry();
5615 if (label_aix == current_label_type){
5618 #ifdef CONFIG_FEATURE_OSF_LABEL
5619 if (btrydev(device) < 0)
5622 _("Disk %s doesn't contain a valid "
5623 "partition table\n"), device);
5628 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5629 if (label_sun != current_label_type && partitions > 4){
5630 delete_partition(ext_index);
5635 /* Ignore other errors, since we try IDE
5636 and SCSI hard disks which may not be
5637 installed on the system. */
5638 if (errno == EACCES) {
5639 fprintf(stderr, _("Cannot open %s\n"), device);
5645 /* for fdisk -l: try all things in /proc/partitions
5646 that look like a partition name (do not end in a digit) */
5651 char line[100], ptname[100], devname[120], *s;
5654 procpt = bb_wfopen(PROC_PARTITIONS, "r");
5656 while (fgets(line, sizeof(line), procpt)) {
5657 if (sscanf(line, " %d %d %d %[^\n ]",
5658 &ma, &mi, &sz, ptname) != 4)
5660 for (s = ptname; *s; s++);
5663 sprintf(devname, "/dev/%s", ptname);
5666 #ifdef CONFIG_FEATURE_CLEAN_UP
5671 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5673 unknown_command(int c)
5675 printf(_("%c: unknown command\n"), c);
5679 int fdisk_main(int argc, char **argv)
5682 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5685 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5691 * fdisk -l [-b sectorsize] [-u] device ...
5692 * fdisk -s [partition] ...
5693 * fdisk [-b sectorsize] [-u] device
5695 * Options -C, -H, -S set the geometry.
5698 while ((c = getopt(argc, argv, "b:C:H:lS:uvV"
5699 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5705 /* Ugly: this sector size is really per device,
5706 so cannot be combined with multiple disks,
5707 and te same goes for the C/H/S options.
5709 sector_size = atoi(optarg);
5710 if (sector_size != 512 && sector_size != 1024 &&
5711 sector_size != 2048)
5714 user_set_sector_size = 1;
5717 user_cylinders = atoi(optarg);
5720 user_heads = atoi(optarg);
5721 if (user_heads <= 0 || user_heads >= 256)
5725 user_sectors = atoi(optarg);
5726 if (user_sectors <= 0 || user_sectors >= 64)
5730 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5734 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5740 display_in_cyl_units = 0;
5744 printf("fdisk v" UTIL_LINUX_VERSION "\n");
5752 printf(_("This kernel finds the sector size itself - "
5753 "-b option ignored\n"));
5755 if (user_set_sector_size && argc-optind != 1)
5756 printf(_("Warning: the -b (set sector size) option should"
5757 " be used with one specified device\n"));
5760 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5764 type_open = O_RDONLY;
5765 if (argc > optind) {
5768 /* avoid gcc warning:
5769 variable `k' might be clobbered by `longjmp' */
5773 for (k = optind; k < argc; k++)
5776 /* we no longer have default device names */
5777 /* but, we can use /proc/partitions instead */
5781 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5785 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5791 type_open = O_RDONLY;
5793 opts = argc - optind;
5797 for (j = optind; j < argc; j++) {
5798 disk_device = argv[j];
5799 if ((fd = open(disk_device, type_open)) < 0)
5800 fdisk_fatal(unable_to_open);
5801 if (ioctl(fd, BLKGETSIZE, &size))
5802 fdisk_fatal(ioctl_error);
5805 printf("%ld\n", size/2);
5807 printf("%s: %ld\n", argv[j], size/2);
5813 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5814 if (argc-optind == 1)
5815 disk_device = argv[optind];
5821 #ifdef CONFIG_FEATURE_OSF_LABEL
5822 if (label_osf == current_label_type) {
5823 /* OSF label, and no DOS label */
5824 printf(_("Detected an OSF/1 disklabel on %s, entering "
5825 "disklabel mode.\n"),
5828 /*Why do we do this? It seems to be counter-intuitive*/
5829 current_label_type = label_dos;
5830 /* If we return we may want to make an empty DOS label? */
5836 c = tolower(read_char(_("Command (m for help): ")));
5839 if (label_dos == current_label_type)
5840 toggle_active(get_partition(1, partitions));
5841 #ifdef CONFIG_FEATURE_SUN_LABEL
5842 else if (label_sun == current_label_type)
5843 toggle_sunflags(get_partition(1, partitions),
5846 #ifdef CONFIG_FEATURE_SGI_LABEL
5847 else if (label_sgi == current_label_type)
5848 sgi_set_bootpartition(
5849 get_partition(1, partitions));
5855 #ifdef CONFIG_FEATURE_SGI_LABEL
5856 if (label_sgi == current_label_type) {
5857 printf(_("\nThe current boot file is: %s\n"),
5858 sgi_get_bootfile());
5859 if (read_chars(_("Please enter the name of the "
5860 "new boot file: ")) == '\n')
5861 printf(_("Boot file unchanged\n"));
5863 sgi_set_bootfile(line_ptr);
5866 #ifdef CONFIG_FEATURE_OSF_LABEL
5871 if (label_dos == current_label_type)
5872 toggle_dos_compatibility_flag();
5873 #ifdef CONFIG_FEATURE_SUN_LABEL
5874 else if (label_sun == current_label_type)
5875 toggle_sunflags(get_partition(1, partitions),
5878 #ifdef CONFIG_FEATURE_SGI_LABEL
5879 else if (label_sgi == current_label_type)
5880 sgi_set_swappartition(
5881 get_partition(1, partitions));
5889 #ifdef CONFIG_FEATURE_SGI_LABEL
5890 /* If sgi_label then don't use get_existing_partition,
5891 let the user select a partition, since
5892 get_existing_partition() only works for Linux-like
5894 if (label_sgi != current_label_type) {
5895 j = get_existing_partition(1, partitions);
5897 j = get_partition(1, partitions);
5900 j = get_existing_partition(1, partitions);
5903 delete_partition(j);
5907 #ifdef CONFIG_FEATURE_SGI_LABEL
5908 if (label_sgi == current_label_type)
5914 list_types(get_sys_types());
5933 #ifdef CONFIG_FEATURE_SUN_LABEL
5947 write_table(); /* does not return */
5949 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
5951 #ifdef CONFIG_FEATURE_SGI_LABEL
5952 if (label_sgi == current_label_type) {
5954 _("\n\tSorry, no experts menu for SGI "
5955 "partition tables available.\n\n"));
5968 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */