1 /* vi: set sw=4 ts=4: */
2 /* fdisk.c -- Partition table manipulator for Linux.
4 * Copyright (C) 1992 A. V. Le Blanc (LeBlanc@mcc.ac.uk)
5 * Copyright (C) 2001,2002 Vladimir Oleynik <dzo@simtreas.ru> (initial bb port)
7 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
10 /* Current changes have not compatibility with this version */
11 #define UTIL_LINUX_VERSION "2.12"
16 #define PROC_PARTITIONS "/proc/partitions"
19 #include <sys/types.h>
20 #include <sys/stat.h> /* stat */
29 #include <assert.h> /* assert */
32 #include <sys/ioctl.h>
33 #include <sys/param.h>
34 #include <sys/sysmacros.h> /* major */
36 #include <stdint.h> /* for uint32_t, uint16_t, uint8_t, int16_t, etc */
38 /* Copied from linux/major.h */
39 #define FLOPPY_MAJOR 2
41 #include <sys/utsname.h>
51 #define DEFAULT_SECTOR_SIZE 512
52 #define MAX_SECTOR_SIZE 2048
53 #define SECTOR_SIZE 512 /* still used in BSD code */
54 #define MAXIMUM_PARTS 60
56 #define ACTIVE_FLAG 0x80
59 #define WIN98_EXTENDED 0x0f
60 #define LINUX_PARTITION 0x81
61 #define LINUX_SWAP 0x82
62 #define LINUX_NATIVE 0x83
63 #define LINUX_EXTENDED 0x85
64 #define LINUX_LVM 0x8e
65 #define LINUX_RAID 0xfd
70 #define IS_EXTENDED(i) \
71 ((i) == EXTENDED || (i) == WIN98_EXTENDED || (i) == LINUX_EXTENDED)
73 #define SIZE(a) (sizeof(a)/sizeof((a)[0]))
75 #define cround(n) (display_in_cyl_units ? ((n)/units_per_sector)+1 : (n))
76 #define scround(x) (((x)+units_per_sector-1)/units_per_sector)
78 #ifdef CONFIG_FEATURE_SUN_LABEL
79 #define SCSI_IOCTL_GET_IDLUN 0x5382
83 /* including <linux/hdreg.h> also fails */
86 unsigned char sectors;
87 unsigned short cylinders;
91 #define HDIO_GETGEO 0x0301 /* get device geometry */
98 static uint sector_size = DEFAULT_SECTOR_SIZE;
99 static uint user_set_sector_size;
100 static uint sector_offset = 1;
103 * Raw disk label. For DOS-type partition tables the MBR,
104 * with descriptions of the primary partitions.
106 #if (MAX_SECTOR_SIZE) > (BUFSIZ+1)
107 static char MBRbuffer[MAX_SECTOR_SIZE];
109 # define MBRbuffer bb_common_bufsiz1
112 #ifdef CONFIG_FEATURE_OSF_LABEL
113 static int possibly_osf_label;
116 static uint heads, sectors, cylinders;
117 static void update_units(void);
121 * return partition name - uses static storage unless buf is supplied
124 partname(const char *dev, int pno, int lth)
126 static char buffer[80];
133 bufsiz = sizeof(buffer);
138 if (isdigit(dev[w-1]))
141 /* devfs kludge - note: fdisk partition names are not supposed
142 to equal kernel names, so there is no reason to do this */
143 if (strcmp(dev + w - 4, "disc") == 0) {
151 snprintf(bufp, bufsiz, "%*.*s%s%-2u",
152 lth-wp-2, w, dev, p, pno);
154 snprintf(bufp, bufsiz, "%.*s%s%-2u", w, dev, p, pno);
160 unsigned char boot_ind; /* 0x80 - active */
161 unsigned char head; /* starting head */
162 unsigned char sector; /* starting sector */
163 unsigned char cyl; /* starting cylinder */
164 unsigned char sys_ind; /* What partition type */
165 unsigned char end_head; /* end head */
166 unsigned char end_sector; /* end sector */
167 unsigned char end_cyl; /* end cylinder */
168 unsigned char start4[4]; /* starting sector counting from 0 */
169 unsigned char size4[4]; /* nr of sectors in partition */
173 ioctl_error, unable_to_open, unable_to_read, unable_to_seek,
178 label_dos, label_sun, label_sgi, label_aix, label_osf
181 enum action { fdisk, require, try_only, create_empty_dos, create_empty_sun };
183 static enum label_type current_label_type;
185 static const char *disk_device;
186 static int fd; /* the disk */
187 static int partitions = 4; /* maximum partition + 1 */
188 static uint display_in_cyl_units = 1;
189 static uint units_per_sector = 1;
190 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
191 static char *line_ptr;
192 static void change_units(void);
193 static void reread_partition_table(int leave);
194 static void delete_partition(int i);
195 static int get_partition(int warn, int max);
196 static void list_types(const struct systypes *sys);
197 static uint read_int(uint low, uint dflt, uint high, uint base, char *mesg);
199 static const char *partition_type(unsigned char type);
200 static void fdisk_fatal(enum failure why) ATTRIBUTE_NORETURN;
201 static void get_geometry(void);
202 static int get_boot(enum action what);
207 #define hex_val(c) ({ \
209 isdigit(_c) ? _c - '0' : \
210 tolower(_c) + 10 - 'a'; \
214 #define LINE_LENGTH 800
215 #define pt_offset(b, n) ((struct partition *)((b) + 0x1be + \
216 (n) * sizeof(struct partition)))
217 #define sector(s) ((s) & 0x3f)
218 #define cylinder(s, c) ((c) | (((s) & 0xc0) << 2))
220 #define hsc2sector(h,s,c) (sector(s) - 1 + sectors * \
221 ((h) + heads * cylinder(s,c)))
222 #define set_hsc(h,s,c,sector) { \
223 s = sector % sectors + 1; \
225 h = sector % heads; \
228 s |= (sector >> 2) & 0xc0; \
232 static int32_t get_start_sect(const struct partition *p);
233 static int32_t get_nr_sects(const struct partition *p);
236 * per partition table entry data
238 * The four primary partitions have the same sectorbuffer (MBRbuffer)
239 * and have NULL ext_pointer.
240 * Each logical partition table entry has two pointers, one for the
241 * partition and one link to the next one.
244 struct partition *part_table; /* points into sectorbuffer */
245 struct partition *ext_pointer; /* points into sectorbuffer */
246 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
247 char changed; /* boolean */
249 off_t offset; /* disk sector number */
250 char *sectorbuffer; /* disk sector contents */
251 } ptes[MAXIMUM_PARTS];
254 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
256 set_all_unchanged(void)
260 for (i = 0; i < MAXIMUM_PARTS; i++)
269 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
271 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_OSF_LABEL)
272 static struct partition *
273 get_part_table(int i)
275 return ptes[i].part_table;
281 { /* n==1: use singular */
283 return display_in_cyl_units ? _("cylinder") : _("sector");
285 return display_in_cyl_units ? _("cylinders") : _("sectors");
289 valid_part_table_flag(const char *mbuffer) {
290 const unsigned char *b = (const unsigned char *)mbuffer;
291 return (b[510] == 0x55 && b[511] == 0xaa);
294 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
295 static char line_buffer[LINE_LENGTH];
297 /* read line; return 0 or first char */
301 static int got_eof = 0;
303 fflush (stdout); /* requested by niles@scyld.com */
304 line_ptr = line_buffer;
305 if (!fgets(line_buffer, LINE_LENGTH, stdin)) {
307 got_eof++; /* user typed ^D ? */
309 fprintf(stderr, _("\ngot EOF thrice - exiting..\n"));
314 while (*line_ptr && !isgraph(*line_ptr))
320 read_char(const char *mesg)
324 } while (!read_line());
329 read_chars(const char *mesg)
340 read_hex(const struct systypes *sys)
345 read_char(_("Hex code (type L to list codes): "));
346 if (*line_ptr == 'l' || *line_ptr == 'L')
348 else if (isxdigit (*line_ptr)) {
351 hex = hex << 4 | hex_val(*line_ptr++);
352 while (isxdigit(*line_ptr));
357 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
359 #ifdef CONFIG_FEATURE_AIX_LABEL
361 * Copyright (C) Andreas Neuper, Sep 1998.
362 * This file may be redistributed under
363 * the terms of the GNU Public License.
367 unsigned int magic; /* expect AIX_LABEL_MAGIC */
368 unsigned int fillbytes1[124];
369 unsigned int physical_volume_id;
370 unsigned int fillbytes2[124];
373 #define AIX_LABEL_MAGIC 0xc9c2d4c1
374 #define AIX_LABEL_MAGIC_SWAPPED 0xc1d4c2c9
375 #define AIX_INFO_MAGIC 0x00072959
376 #define AIX_INFO_MAGIC_SWAPPED 0x59290700
378 #define aixlabel ((aix_partition *)MBRbuffer)
383 * 1999-03-20 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
384 * Internationalization
386 * 2003-03-20 Phillip Kesling <pkesling@sgi.com>
390 static int aix_other_endian;
391 static short aix_volumes = 1;
394 * only dealing with free blocks here
401 _("\n\tThere is a valid AIX label on this disk.\n"
402 "\tUnfortunately Linux cannot handle these\n"
403 "\tdisks at the moment. Nevertheless some\n"
405 "\t1. fdisk will destroy its contents on write.\n"
406 "\t2. Be sure that this disk is NOT a still vital\n"
407 "\t part of a volume group. (Otherwise you may\n"
408 "\t erase the other disks as well, if unmirrored.)\n"
409 "\t3. Before deleting this physical volume be sure\n"
410 "\t to remove the disk logically from your AIX\n"
411 "\t machine. (Otherwise you become an AIXpert).")
416 check_aix_label(void)
418 if (aixlabel->magic != AIX_LABEL_MAGIC &&
419 aixlabel->magic != AIX_LABEL_MAGIC_SWAPPED) {
420 current_label_type = 0;
421 aix_other_endian = 0;
424 aix_other_endian = (aixlabel->magic == AIX_LABEL_MAGIC_SWAPPED);
426 current_label_type = label_aix;
430 /*aix_nolabel();*/ /* %% */
431 /*aix_label = 1;*/ /* %% */
434 #endif /* AIX_LABEL */
436 #ifdef CONFIG_FEATURE_OSF_LABEL
438 * Copyright (c) 1987, 1988 Regents of the University of California.
439 * All rights reserved.
441 * Redistribution and use in source and binary forms, with or without
442 * modification, are permitted provided that the following conditions
444 * 1. Redistributions of source code must retain the above copyright
445 * notice, this list of conditions and the following disclaimer.
446 * 2. Redistributions in binary form must reproduce the above copyright
447 * notice, this list of conditions and the following disclaimer in the
448 * documentation and/or other materials provided with the distribution.
449 * 3. All advertising materials mentioning features or use of this software
450 * must display the following acknowledgment:
451 * This product includes software developed by the University of
452 * California, Berkeley and its contributors.
453 * 4. Neither the name of the University nor the names of its contributors
454 * may be used to endorse or promote products derived from this software
455 * without specific prior written permission.
457 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
458 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
459 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
460 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
461 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
462 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
463 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
464 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
465 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
466 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
471 #ifndef BSD_DISKMAGIC
472 #define BSD_DISKMAGIC ((uint32_t) 0x82564557)
475 #ifndef BSD_MAXPARTITIONS
476 #define BSD_MAXPARTITIONS 16
479 #define BSD_LINUX_BOOTDIR "/usr/ucb/mdec"
481 #if defined (i386) || defined (__sparc__) || defined (__arm__) || defined (__m68k__) || defined (__mips__) || defined (__s390__) || defined (__sh__) || defined(__x86_64__)
482 #define BSD_LABELSECTOR 1
483 #define BSD_LABELOFFSET 0
484 #elif defined (__alpha__) || defined (__powerpc__) || defined (__ia64__) || defined (__hppa__)
485 #define BSD_LABELSECTOR 0
486 #define BSD_LABELOFFSET 64
487 #elif defined (__s390__) || defined (__s390x__)
488 #define BSD_LABELSECTOR 1
489 #define BSD_LABELOFFSET 0
491 #error unknown architecture
494 #define BSD_BBSIZE 8192 /* size of boot area, with label */
495 #define BSD_SBSIZE 8192 /* max size of fs superblock */
497 struct xbsd_disklabel {
498 uint32_t d_magic; /* the magic number */
499 int16_t d_type; /* drive type */
500 int16_t d_subtype; /* controller/d_type specific */
501 char d_typename[16]; /* type name, e.g. "eagle" */
502 char d_packname[16]; /* pack identifier */
504 uint32_t d_secsize; /* # of bytes per sector */
505 uint32_t d_nsectors; /* # of data sectors per track */
506 uint32_t d_ntracks; /* # of tracks per cylinder */
507 uint32_t d_ncylinders; /* # of data cylinders per unit */
508 uint32_t d_secpercyl; /* # of data sectors per cylinder */
509 uint32_t d_secperunit; /* # of data sectors per unit */
511 * Spares (bad sector replacements) below
512 * are not counted in d_nsectors or d_secpercyl.
513 * Spare sectors are assumed to be physical sectors
514 * which occupy space at the end of each track and/or cylinder.
516 uint16_t d_sparespertrack; /* # of spare sectors per track */
517 uint16_t d_sparespercyl; /* # of spare sectors per cylinder */
519 * Alternate cylinders include maintenance, replacement,
520 * configuration description areas, etc.
522 uint32_t d_acylinders; /* # of alt. cylinders per unit */
524 /* hardware characteristics: */
526 * d_interleave, d_trackskew and d_cylskew describe perturbations
527 * in the media format used to compensate for a slow controller.
528 * Interleave is physical sector interleave, set up by the formatter
529 * or controller when formatting. When interleaving is in use,
530 * logically adjacent sectors are not physically contiguous,
531 * but instead are separated by some number of sectors.
532 * It is specified as the ratio of physical sectors traversed
533 * per logical sector. Thus an interleave of 1:1 implies contiguous
534 * layout, while 2:1 implies that logical sector 0 is separated
535 * by one sector from logical sector 1.
536 * d_trackskew is the offset of sector 0 on track N
537 * relative to sector 0 on track N-1 on the same cylinder.
538 * Finally, d_cylskew is the offset of sector 0 on cylinder N
539 * relative to sector 0 on cylinder N-1.
541 uint16_t d_rpm; /* rotational speed */
542 uint16_t d_interleave; /* hardware sector interleave */
543 uint16_t d_trackskew; /* sector 0 skew, per track */
544 uint16_t d_cylskew; /* sector 0 skew, per cylinder */
545 uint32_t d_headswitch; /* head switch time, usec */
546 uint32_t d_trkseek; /* track-to-track seek, usec */
547 uint32_t d_flags; /* generic flags */
549 uint32_t d_drivedata[NDDATA]; /* drive-type specific information */
551 uint32_t d_spare[NSPARE]; /* reserved for future use */
552 uint32_t d_magic2; /* the magic number (again) */
553 uint16_t d_checksum; /* xor of data incl. partitions */
554 /* filesystem and partition information: */
555 uint16_t d_npartitions; /* number of partitions in following */
556 uint32_t d_bbsize; /* size of boot area at sn0, bytes */
557 uint32_t d_sbsize; /* max size of fs superblock, bytes */
558 struct xbsd_partition { /* the partition table */
559 uint32_t p_size; /* number of sectors in partition */
560 uint32_t p_offset; /* starting sector */
561 uint32_t p_fsize; /* filesystem basic fragment size */
562 uint8_t p_fstype; /* filesystem type, see below */
563 uint8_t p_frag; /* filesystem fragments per block */
564 uint16_t p_cpg; /* filesystem cylinders per group */
565 } d_partitions[BSD_MAXPARTITIONS]; /* actually may be more */
569 #define BSD_DTYPE_SMD 1 /* SMD, XSMD; VAX hp/up */
570 #define BSD_DTYPE_MSCP 2 /* MSCP */
571 #define BSD_DTYPE_DEC 3 /* other DEC (rk, rl) */
572 #define BSD_DTYPE_SCSI 4 /* SCSI */
573 #define BSD_DTYPE_ESDI 5 /* ESDI interface */
574 #define BSD_DTYPE_ST506 6 /* ST506 etc. */
575 #define BSD_DTYPE_HPIB 7 /* CS/80 on HP-IB */
576 #define BSD_DTYPE_HPFL 8 /* HP Fiber-link */
577 #define BSD_DTYPE_FLOPPY 10 /* floppy */
579 /* d_subtype values: */
580 #define BSD_DSTYPE_INDOSPART 0x8 /* is inside dos partition */
581 #define BSD_DSTYPE_DOSPART(s) ((s) & 3) /* dos partition number */
582 #define BSD_DSTYPE_GEOMETRY 0x10 /* drive params in label */
585 static const char * const xbsd_dktypenames[] = {
599 #define BSD_DKMAXTYPES (sizeof(xbsd_dktypenames) / sizeof(xbsd_dktypenames[0]) - 1)
603 * Filesystem type and version.
604 * Used to interpret other filesystem-specific
605 * per-partition information.
607 #define BSD_FS_UNUSED 0 /* unused */
608 #define BSD_FS_SWAP 1 /* swap */
609 #define BSD_FS_V6 2 /* Sixth Edition */
610 #define BSD_FS_V7 3 /* Seventh Edition */
611 #define BSD_FS_SYSV 4 /* System V */
612 #define BSD_FS_V71K 5 /* V7 with 1K blocks (4.1, 2.9) */
613 #define BSD_FS_V8 6 /* Eighth Edition, 4K blocks */
614 #define BSD_FS_BSDFFS 7 /* 4.2BSD fast file system */
615 #define BSD_FS_BSDLFS 9 /* 4.4BSD log-structured file system */
616 #define BSD_FS_OTHER 10 /* in use, but unknown/unsupported */
617 #define BSD_FS_HPFS 11 /* OS/2 high-performance file system */
618 #define BSD_FS_ISO9660 12 /* ISO-9660 filesystem (cdrom) */
619 #define BSD_FS_ISOFS BSD_FS_ISO9660
620 #define BSD_FS_BOOT 13 /* partition contains bootstrap */
621 #define BSD_FS_ADOS 14 /* AmigaDOS fast file system */
622 #define BSD_FS_HFS 15 /* Macintosh HFS */
623 #define BSD_FS_ADVFS 16 /* Digital Unix AdvFS */
625 /* this is annoying, but it's also the way it is :-( */
627 #define BSD_FS_EXT2 8 /* ext2 file system */
629 #define BSD_FS_MSDOS 8 /* MS-DOS file system */
633 static const struct systypes xbsd_fstypes[] = {
634 { "\x00" "unused" }, /* BSD_FS_UNUSED */
635 { "\x01" "swap" }, /* BSD_FS_SWAP */
636 { "\x02" "Version 6" }, /* BSD_FS_V6 */
637 { "\x03" "Version 7" }, /* BSD_FS_V7 */
638 { "\x04" "System V" }, /* BSD_FS_SYSV */
639 { "\x05" "4.1BSD" }, /* BSD_FS_V71K */
640 { "\x06" "Eighth Edition" }, /* BSD_FS_V8 */
641 { "\x07" "4.2BSD" }, /* BSD_FS_BSDFFS */
643 { "\x08" "ext2" }, /* BSD_FS_EXT2 */
645 { "\x08" "MS-DOS" }, /* BSD_FS_MSDOS */
647 { "\x09" "4.4LFS" }, /* BSD_FS_BSDLFS */
648 { "\x0a" "unknown" }, /* BSD_FS_OTHER */
649 { "\x0b" "HPFS" }, /* BSD_FS_HPFS */
650 { "\x0c" "ISO-9660" }, /* BSD_FS_ISO9660 */
651 { "\x0d" "boot" }, /* BSD_FS_BOOT */
652 { "\x0e" "ADOS" }, /* BSD_FS_ADOS */
653 { "\x0f" "HFS" }, /* BSD_FS_HFS */
654 { "\x10" "AdvFS" }, /* BSD_FS_ADVFS */
657 #define BSD_FSMAXTYPES (SIZE(xbsd_fstypes)-1)
662 * flags shared by various drives:
664 #define BSD_D_REMOVABLE 0x01 /* removable media */
665 #define BSD_D_ECC 0x02 /* supports ECC */
666 #define BSD_D_BADSECT 0x04 /* supports bad sector forw. */
667 #define BSD_D_RAMDISK 0x08 /* disk emulator */
668 #define BSD_D_CHAIN 0x10 /* can do back-back transfers */
669 #define BSD_D_DOSPART 0x20 /* within MSDOS partition */
671 #endif /* OSF_LABEL */
674 * Copyright (C) Andreas Neuper, Sep 1998.
675 * This file may be modified and redistributed under
676 * the terms of the GNU Public License.
679 struct device_parameter { /* 48 bytes */
683 unsigned char sparecyl;
684 unsigned short pcylcount;
685 unsigned short head_vol0;
686 unsigned short ntrks; /* tracks in cyl 0 or vol 0 */
687 unsigned char cmd_tag_queue_depth;
688 unsigned char unused0;
689 unsigned short unused1;
690 unsigned short nsect; /* sectors/tracks in cyl 0 or vol 0 */
691 unsigned short bytes;
692 unsigned short ilfact;
693 unsigned int flags; /* controller flags */
694 unsigned int datarate;
695 unsigned int retries_on_error;
696 unsigned int ms_per_word;
697 unsigned short xylogics_gap1;
698 unsigned short xylogics_syncdelay;
699 unsigned short xylogics_readdelay;
700 unsigned short xylogics_gap2;
701 unsigned short xylogics_readgate;
702 unsigned short xylogics_writecont;
705 #define SGI_VOLHDR 0x00
706 /* 1 and 2 were used for drive types no longer supported by SGI */
707 #define SGI_SWAP 0x03
708 /* 4 and 5 were for filesystem types SGI haven't ever supported on MIPS CPUs */
709 #define SGI_VOLUME 0x06
711 #define SGI_LVOL 0x08
712 #define SGI_RLVOL 0x09
714 #define SGI_XFSLOG 0x0b
717 #define ENTIRE_DISK SGI_VOLUME
721 #define SECTOR_SLIP 0x01
722 #define SECTOR_FWD 0x02
723 #define TRACK_FWD 0x04
724 #define TRACK_MULTIVOL 0x08
725 #define IGNORE_ERRORS 0x10
727 #define ENABLE_CMDTAGQ 0x40
730 unsigned int magic; /* expect SGI_LABEL_MAGIC */
731 unsigned short boot_part; /* active boot partition */
732 unsigned short swap_part; /* active swap partition */
733 unsigned char boot_file[16]; /* name of the bootfile */
734 struct device_parameter devparam; /* 1 * 48 bytes */
735 struct volume_directory { /* 15 * 16 bytes */
736 unsigned char vol_file_name[8]; /* a character array */
737 unsigned int vol_file_start; /* number of logical block */
738 unsigned int vol_file_size; /* number of bytes */
740 struct sgi_partition { /* 16 * 12 bytes */
741 unsigned int num_sectors; /* number of blocks */
742 unsigned int start_sector; /* must be cylinder aligned */
746 unsigned int fillbytes;
750 unsigned int magic; /* looks like a magic number */
759 unsigned char scsi_string[50];
760 unsigned char serial[137];
761 unsigned short check1816;
762 unsigned char installer[225];
765 #define SGI_LABEL_MAGIC 0x0be5a941
766 #define SGI_LABEL_MAGIC_SWAPPED 0x41a9e50b
767 #define SGI_INFO_MAGIC 0x00072959
768 #define SGI_INFO_MAGIC_SWAPPED 0x59290700
769 #define SGI_SSWAP16(x) (sgi_other_endian ? __swap16(x) \
771 #define SGI_SSWAP32(x) (sgi_other_endian ? __swap32(x) \
774 #define sgilabel ((sgi_partition *)MBRbuffer)
775 #define sgiparam (sgilabel->devparam)
778 unsigned char info[128]; /* Informative text string */
779 unsigned char spare0[14];
781 unsigned char spare1;
783 unsigned char spare2;
786 unsigned char spare1[246]; /* Boot information etc. */
787 unsigned short rspeed; /* Disk rotational speed */
788 unsigned short pcylcount; /* Physical cylinder count */
789 unsigned short sparecyl; /* extra sects per cylinder */
790 unsigned char spare2[4]; /* More magic... */
791 unsigned short ilfact; /* Interleave factor */
792 unsigned short ncyl; /* Data cylinder count */
793 unsigned short nacyl; /* Alt. cylinder count */
794 unsigned short ntrks; /* Tracks per cylinder */
795 unsigned short nsect; /* Sectors per track */
796 unsigned char spare3[4]; /* Even more magic... */
797 struct sun_partition {
798 uint32_t start_cylinder;
799 uint32_t num_sectors;
801 unsigned short magic; /* Magic number */
802 unsigned short csum; /* Label xor'd checksum */
806 #define SUN_LABEL_MAGIC 0xDABE
807 #define SUN_LABEL_MAGIC_SWAPPED 0xBEDA
808 #define sunlabel ((sun_partition *)MBRbuffer)
809 #define SUN_SSWAP16(x) (sun_other_endian ? __swap16(x) \
811 #define SUN_SSWAP32(x) (sun_other_endian ? __swap32(x) \
815 #ifdef CONFIG_FEATURE_OSF_LABEL
818 19990319 - Arnaldo Carvalho de Melo <acme@conectiva.com.br> - i18n/nls
820 20000101 - David Huggins-Daines <dhuggins@linuxcare.com> - Better
821 support for OSF/1 disklabels on Alpha.
822 Also fixed unaligned accesses in alpha_bootblock_checksum()
825 #define FREEBSD_PARTITION 0xa5
826 #define NETBSD_PARTITION 0xa9
828 static void xbsd_delete_part(void);
829 static void xbsd_new_part(void);
830 static void xbsd_write_disklabel(void);
831 static int xbsd_create_disklabel(void);
832 static void xbsd_edit_disklabel(void);
833 static void xbsd_write_bootstrap(void);
834 static void xbsd_change_fstype(void);
835 static int xbsd_get_part_index(int max);
836 static int xbsd_check_new_partition(int *i);
837 static void xbsd_list_types(void);
838 static u_short xbsd_dkcksum(struct xbsd_disklabel *lp);
839 static int xbsd_initlabel(struct partition *p, struct xbsd_disklabel *d);
840 static int xbsd_readlabel(struct partition *p, struct xbsd_disklabel *d);
841 static int xbsd_writelabel(struct partition *p, struct xbsd_disklabel *d);
843 #if defined (__alpha__)
844 static void alpha_bootblock_checksum(char *boot);
847 #if !defined (__alpha__)
848 static int xbsd_translate_fstype(int linux_type);
849 static void xbsd_link_part(void);
850 static struct partition *xbsd_part;
851 static int xbsd_part_index;
854 #if defined (__alpha__)
855 /* We access this through a uint64_t * when checksumming */
856 static char disklabelbuffer[BSD_BBSIZE] ATTRIBUTE_ALIGNED(8);
858 static char disklabelbuffer[BSD_BBSIZE];
861 static struct xbsd_disklabel xbsd_dlabel;
863 #define bsd_cround(n) \
864 (display_in_cyl_units ? ((n)/xbsd_dlabel.d_secpercyl) + 1 : (n))
867 * Test whether the whole disk has BSD disk label magic.
869 * Note: often reformatting with DOS-type label leaves the BSD magic,
870 * so this does not mean that there is a BSD disk label.
873 check_osf_label(void)
875 if (xbsd_readlabel(NULL, &xbsd_dlabel) == 0)
880 static void xbsd_print_disklabel(int);
883 btrydev(const char * dev)
885 if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
887 printf(_("\nBSD label for device: %s\n"), dev);
888 xbsd_print_disklabel (0);
895 puts (_("Command action"));
896 puts (_("\td\tdelete a BSD partition"));
897 puts (_("\te\tedit drive data"));
898 puts (_("\ti\tinstall bootstrap"));
899 puts (_("\tl\tlist known filesystem types"));
900 puts (_("\tm\tprint this menu"));
901 puts (_("\tn\tadd a new BSD partition"));
902 puts (_("\tp\tprint BSD partition table"));
903 puts (_("\tq\tquit without saving changes"));
904 puts (_("\tr\treturn to main menu"));
905 puts (_("\ts\tshow complete disklabel"));
906 puts (_("\tt\tchange a partition's filesystem id"));
907 puts (_("\tu\tchange units (cylinders/sectors)"));
908 puts (_("\tw\twrite disklabel to disk"));
909 #if !defined (__alpha__)
910 puts (_("\tx\tlink BSD partition to non-BSD partition"));
914 #if !defined (__alpha__)
922 is_bsd_partition_type(int type)
924 return (type == FREEBSD_PARTITION ||
925 type == hidden(FREEBSD_PARTITION) ||
926 type == NETBSD_PARTITION ||
927 type == hidden(NETBSD_PARTITION));
934 #if !defined (__alpha__)
938 for (t = 0; t < 4; t++) {
939 p = get_part_table(t);
940 if (p && is_bsd_partition_type(p->sys_ind)) {
943 ss = get_start_sect(xbsd_part);
945 fprintf(stderr, _("Partition %s has invalid starting sector 0.\n"),
946 partname(disk_device, t+1, 0));
949 printf(_("Reading disklabel of %s at sector %d.\n"),
950 partname(disk_device, t+1, 0), ss + BSD_LABELSECTOR);
951 if (xbsd_readlabel(xbsd_part, &xbsd_dlabel) == 0)
952 if (xbsd_create_disklabel() == 0)
959 printf(_("There is no *BSD partition on %s.\n"), disk_device);
963 #elif defined (__alpha__)
965 if (xbsd_readlabel(NULL, &xbsd_dlabel) == 0)
966 if (xbsd_create_disklabel() == 0)
973 switch (tolower(read_char(_("BSD disklabel command (m for help): ")))) {
978 xbsd_edit_disklabel();
981 xbsd_write_bootstrap();
990 xbsd_print_disklabel(0);
998 xbsd_print_disklabel(1);
1001 xbsd_change_fstype();
1007 xbsd_write_disklabel();
1009 #if !defined (__alpha__)
1022 xbsd_delete_part(void)
1026 i = xbsd_get_part_index(xbsd_dlabel.d_npartitions);
1027 xbsd_dlabel.d_partitions[i].p_size = 0;
1028 xbsd_dlabel.d_partitions[i].p_offset = 0;
1029 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
1030 if (xbsd_dlabel.d_npartitions == i + 1)
1031 while (xbsd_dlabel.d_partitions[xbsd_dlabel.d_npartitions-1].p_size == 0)
1032 xbsd_dlabel.d_npartitions--;
1042 if (!xbsd_check_new_partition(&i))
1045 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
1046 begin = get_start_sect(xbsd_part);
1047 end = begin + get_nr_sects(xbsd_part) - 1;
1050 end = xbsd_dlabel.d_secperunit - 1;
1053 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
1054 begin = read_int(bsd_cround(begin), bsd_cround(begin), bsd_cround(end),
1057 if (display_in_cyl_units)
1058 begin = (begin - 1) * xbsd_dlabel.d_secpercyl;
1060 snprintf(mesg, sizeof(mesg), _("Last %s or +size or +sizeM or +sizeK"),
1061 str_units(SINGULAR));
1062 end = read_int(bsd_cround (begin), bsd_cround (end), bsd_cround (end),
1063 bsd_cround (begin), mesg);
1065 if (display_in_cyl_units)
1066 end = end * xbsd_dlabel.d_secpercyl - 1;
1068 xbsd_dlabel.d_partitions[i].p_size = end - begin + 1;
1069 xbsd_dlabel.d_partitions[i].p_offset = begin;
1070 xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
1074 xbsd_print_disklabel(int show_all)
1076 struct xbsd_disklabel *lp = &xbsd_dlabel;
1077 struct xbsd_partition *pp;
1081 #if defined (__alpha__)
1082 printf("# %s:\n", disk_device);
1084 printf("# %s:\n", partname(disk_device, xbsd_part_index+1, 0));
1086 if ((unsigned) lp->d_type < BSD_DKMAXTYPES)
1087 printf(_("type: %s\n"), xbsd_dktypenames[lp->d_type]);
1089 printf(_("type: %d\n"), lp->d_type);
1090 printf(_("disk: %.*s\n"), (int) sizeof(lp->d_typename), lp->d_typename);
1091 printf(_("label: %.*s\n"), (int) sizeof(lp->d_packname), lp->d_packname);
1092 printf(_("flags:"));
1093 if (lp->d_flags & BSD_D_REMOVABLE)
1094 printf(_(" removable"));
1095 if (lp->d_flags & BSD_D_ECC)
1097 if (lp->d_flags & BSD_D_BADSECT)
1098 printf(_(" badsect"));
1100 /* On various machines the fields of *lp are short/int/long */
1101 /* In order to avoid problems, we cast them all to long. */
1102 printf(_("bytes/sector: %ld\n"), (long) lp->d_secsize);
1103 printf(_("sectors/track: %ld\n"), (long) lp->d_nsectors);
1104 printf(_("tracks/cylinder: %ld\n"), (long) lp->d_ntracks);
1105 printf(_("sectors/cylinder: %ld\n"), (long) lp->d_secpercyl);
1106 printf(_("cylinders: %ld\n"), (long) lp->d_ncylinders);
1107 printf(_("rpm: %d\n"), lp->d_rpm);
1108 printf(_("interleave: %d\n"), lp->d_interleave);
1109 printf(_("trackskew: %d\n"), lp->d_trackskew);
1110 printf(_("cylinderskew: %d\n"), lp->d_cylskew);
1111 printf(_("headswitch: %ld\t\t# milliseconds\n"),
1112 (long) lp->d_headswitch);
1113 printf(_("track-to-track seek: %ld\t# milliseconds\n"),
1114 (long) lp->d_trkseek);
1115 printf(_("drivedata: "));
1116 for (i = NDDATA - 1; i >= 0; i--)
1117 if (lp->d_drivedata[i])
1121 for (j = 0; j <= i; j++)
1122 printf("%ld ", (long) lp->d_drivedata[j]);
1124 printf(_("\n%d partitions:\n"), lp->d_npartitions);
1125 printf(_("# start end size fstype [fsize bsize cpg]\n"));
1126 pp = lp->d_partitions;
1127 for (i = 0; i < lp->d_npartitions; i++, pp++) {
1129 if (display_in_cyl_units && lp->d_secpercyl) {
1130 printf(" %c: %8ld%c %8ld%c %8ld%c ",
1132 (long) pp->p_offset / lp->d_secpercyl + 1,
1133 (pp->p_offset % lp->d_secpercyl) ? '*' : ' ',
1134 (long) (pp->p_offset + pp->p_size + lp->d_secpercyl - 1) / lp->d_secpercyl,
1135 ((pp->p_offset + pp->p_size) % lp->d_secpercyl) ? '*' : ' ',
1136 (long) pp->p_size / lp->d_secpercyl,
1137 (pp->p_size % lp->d_secpercyl) ? '*' : ' '
1140 printf(" %c: %8ld %8ld %8ld ",
1142 (long) pp->p_offset,
1143 (long) pp->p_offset + pp->p_size - 1,
1148 if ((unsigned) pp->p_fstype < BSD_FSMAXTYPES)
1149 printf("%8.8s", xbsd_fstypes[pp->p_fstype].name);
1151 printf("%8x", pp->p_fstype);
1153 switch (pp->p_fstype) {
1155 printf(" %5ld %5ld %5.5s ",
1156 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, "");
1159 printf(" %5ld %5ld %5d ",
1160 (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, pp->p_cpg);
1163 printf("%22.22s", "");
1172 xbsd_write_disklabel(void)
1174 #if defined (__alpha__)
1175 printf(_("Writing disklabel to %s.\n"), disk_device);
1176 xbsd_writelabel(NULL, &xbsd_dlabel);
1178 printf(_("Writing disklabel to %s.\n"),
1179 partname(disk_device, xbsd_part_index + 1, 0));
1180 xbsd_writelabel(xbsd_part, &xbsd_dlabel);
1182 reread_partition_table(0); /* no exit yet */
1186 xbsd_create_disklabel(void)
1190 #if defined (__alpha__)
1191 fprintf(stderr, _("%s contains no disklabel.\n"), disk_device);
1193 fprintf(stderr, _("%s contains no disklabel.\n"),
1194 partname(disk_device, xbsd_part_index + 1, 0));
1198 c = read_char(_("Do you want to create a disklabel? (y/n) "));
1199 if (c == 'y' || c == 'Y') {
1201 #if defined (__alpha__) || defined (__powerpc__) || defined (__hppa__) || \
1202 defined (__s390__) || defined (__s390x__)
1205 xbsd_part, &xbsd_dlabel/* not used, xbsd_part_index*/
1208 xbsd_print_disklabel (1);
1212 } else if (c == 'n')
1218 edit_int(int def, char *mesg)
1221 fputs(mesg, stdout);
1222 printf(" (%d): ", def);
1225 } while (!isdigit(*line_ptr));
1226 return atoi(line_ptr);
1230 xbsd_edit_disklabel(void)
1232 struct xbsd_disklabel *d;
1236 #if defined (__alpha__) || defined (__ia64__)
1237 d->d_secsize = (u_long) edit_int((u_long) d->d_secsize ,_("bytes/sector"));
1238 d->d_nsectors = (u_long) edit_int((u_long) d->d_nsectors ,_("sectors/track"));
1239 d->d_ntracks = (u_long) edit_int((u_long) d->d_ntracks ,_("tracks/cylinder"));
1240 d->d_ncylinders = (u_long) edit_int((u_long) d->d_ncylinders ,_("cylinders"));
1243 /* d->d_secpercyl can be != d->d_nsectors * d->d_ntracks */
1245 d->d_secpercyl = (u_long) edit_int((u_long) d->d_nsectors * d->d_ntracks,
1246 _("sectors/cylinder"));
1247 if (d->d_secpercyl <= d->d_nsectors * d->d_ntracks)
1250 printf(_("Must be <= sectors/track * tracks/cylinder (default).\n"));
1252 d->d_rpm = (u_short) edit_int((u_short) d->d_rpm ,_("rpm"));
1253 d->d_interleave = (u_short) edit_int((u_short) d->d_interleave,_("interleave"));
1254 d->d_trackskew = (u_short) edit_int((u_short) d->d_trackskew ,_("trackskew"));
1255 d->d_cylskew = (u_short) edit_int((u_short) d->d_cylskew ,_("cylinderskew"));
1256 d->d_headswitch = (u_long) edit_int((u_long) d->d_headswitch ,_("headswitch"));
1257 d->d_trkseek = (u_long) edit_int((u_long) d->d_trkseek ,_("track-to-track seek"));
1259 d->d_secperunit = d->d_secpercyl * d->d_ncylinders;
1263 xbsd_get_bootstrap (char *path, void *ptr, int size)
1267 if ((fdb = open (path, O_RDONLY)) < 0) {
1271 if (read(fdb, ptr, size) < 0) {
1276 printf(" ... %s\n", path);
1284 printf(_("\nSyncing disks.\n"));
1286 sleep(4); /* What? */
1290 xbsd_write_bootstrap(void)
1292 char *bootdir = BSD_LINUX_BOOTDIR;
1293 char path[MAXPATHLEN];
1295 struct xbsd_disklabel dl;
1299 if (xbsd_dlabel.d_type == BSD_DTYPE_SCSI)
1304 printf(_("Bootstrap: %sboot -> boot%s (%s): "),
1305 dkbasename, dkbasename, dkbasename);
1307 line_ptr[strlen(line_ptr)-1] = '\0';
1308 dkbasename = line_ptr;
1310 snprintf(path, sizeof(path), "%s/%sboot", bootdir, dkbasename);
1311 if (!xbsd_get_bootstrap(path, disklabelbuffer, (int) xbsd_dlabel.d_secsize))
1314 /* We need a backup of the disklabel (xbsd_dlabel might have changed). */
1315 d = &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE];
1316 memmove(&dl, d, sizeof(struct xbsd_disklabel));
1318 /* The disklabel will be overwritten by 0's from bootxx anyway */
1319 memset(d, 0, sizeof(struct xbsd_disklabel));
1321 snprintf(path, sizeof(path), "%s/boot%s", bootdir, dkbasename);
1322 if (!xbsd_get_bootstrap (path, &disklabelbuffer[xbsd_dlabel.d_secsize],
1323 (int) xbsd_dlabel.d_bbsize - xbsd_dlabel.d_secsize))
1326 e = d + sizeof(struct xbsd_disklabel);
1327 for (p = d; p < e; p++)
1329 fprintf(stderr, _("Bootstrap overlaps with disk label!\n"));
1333 memmove(d, &dl, sizeof(struct xbsd_disklabel));
1335 #if defined (__powerpc__) || defined (__hppa__)
1337 #elif defined (__alpha__)
1339 alpha_bootblock_checksum(disklabelbuffer);
1341 sector = get_start_sect(xbsd_part);
1344 if (lseek(fd, sector * SECTOR_SIZE, SEEK_SET) == -1)
1345 fdisk_fatal(unable_to_seek);
1346 if (BSD_BBSIZE != write(fd, disklabelbuffer, BSD_BBSIZE))
1347 fdisk_fatal(unable_to_write);
1349 #if defined (__alpha__)
1350 printf(_("Bootstrap installed on %s.\n"), disk_device);
1352 printf(_("Bootstrap installed on %s.\n"),
1353 partname (disk_device, xbsd_part_index+1, 0));
1360 xbsd_change_fstype(void)
1364 i = xbsd_get_part_index(xbsd_dlabel.d_npartitions);
1365 xbsd_dlabel.d_partitions[i].p_fstype = read_hex(xbsd_fstypes);
1369 xbsd_get_part_index(int max)
1374 snprintf(prompt, sizeof(prompt), _("Partition (a-%c): "), 'a' + max - 1);
1376 l = tolower(read_char(prompt));
1377 while (l < 'a' || l > 'a' + max - 1);
1382 xbsd_check_new_partition(int *i)
1384 /* room for more? various BSD flavours have different maxima */
1385 if (xbsd_dlabel.d_npartitions == BSD_MAXPARTITIONS) {
1388 for (t = 0; t < BSD_MAXPARTITIONS; t++)
1389 if (xbsd_dlabel.d_partitions[t].p_size == 0)
1392 if (t == BSD_MAXPARTITIONS) {
1393 fprintf(stderr, _("The maximum number of partitions "
1394 "has been created\n"));
1399 *i = xbsd_get_part_index (BSD_MAXPARTITIONS);
1401 if (*i >= xbsd_dlabel.d_npartitions)
1402 xbsd_dlabel.d_npartitions = (*i) + 1;
1404 if (xbsd_dlabel.d_partitions[*i].p_size != 0) {
1405 fprintf(stderr, _("This partition already exists.\n"));
1413 xbsd_list_types(void)
1415 list_types(xbsd_fstypes);
1419 xbsd_dkcksum(struct xbsd_disklabel *lp)
1421 u_short *start, *end;
1424 start = (u_short *) lp;
1425 end = (u_short *) &lp->d_partitions[lp->d_npartitions];
1432 xbsd_initlabel(struct partition *p, struct xbsd_disklabel *d)
1434 struct xbsd_partition *pp;
1437 memset(d, 0, sizeof(struct xbsd_disklabel));
1439 d->d_magic = BSD_DISKMAGIC;
1441 if (strncmp(disk_device, "/dev/sd", 7) == 0)
1442 d->d_type = BSD_DTYPE_SCSI;
1444 d->d_type = BSD_DTYPE_ST506;
1446 #if !defined (__alpha__)
1447 d->d_flags = BSD_D_DOSPART;
1451 d->d_secsize = SECTOR_SIZE; /* bytes/sector */
1452 d->d_nsectors = sectors; /* sectors/track */
1453 d->d_ntracks = heads; /* tracks/cylinder (heads) */
1454 d->d_ncylinders = cylinders;
1455 d->d_secpercyl = sectors * heads;/* sectors/cylinder */
1456 if (d->d_secpercyl == 0)
1457 d->d_secpercyl = 1; /* avoid segfaults */
1458 d->d_secperunit = d->d_secpercyl * d->d_ncylinders;
1461 d->d_interleave = 1;
1464 d->d_headswitch = 0;
1467 d->d_magic2 = BSD_DISKMAGIC;
1468 d->d_bbsize = BSD_BBSIZE;
1469 d->d_sbsize = BSD_SBSIZE;
1471 #if !defined (__alpha__)
1472 d->d_npartitions = 4;
1473 pp = &d->d_partitions[2]; /* Partition C should be
1474 the NetBSD partition */
1475 pp->p_offset = get_start_sect(p);
1476 pp->p_size = get_nr_sects(p);
1477 pp->p_fstype = BSD_FS_UNUSED;
1478 pp = &d->d_partitions[3]; /* Partition D should be
1481 pp->p_size = d->d_secperunit;
1482 pp->p_fstype = BSD_FS_UNUSED;
1483 #elif defined (__alpha__)
1484 d->d_npartitions = 3;
1485 pp = &d->d_partitions[2]; /* Partition C should be
1488 pp->p_size = d->d_secperunit;
1489 pp->p_fstype = BSD_FS_UNUSED;
1496 * Read a xbsd_disklabel from sector 0 or from the starting sector of p.
1497 * If it has the right magic, return 1.
1500 xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d)
1504 /* p is used only to get the starting sector */
1505 #if !defined (__alpha__)
1506 sector = (p ? get_start_sect(p) : 0);
1507 #elif defined (__alpha__)
1511 if (lseek(fd, sector * SECTOR_SIZE, SEEK_SET) == -1)
1512 fdisk_fatal(unable_to_seek);
1513 if (BSD_BBSIZE != read(fd, disklabelbuffer, BSD_BBSIZE))
1514 fdisk_fatal(unable_to_read);
1516 memmove(d, &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
1517 sizeof(struct xbsd_disklabel));
1519 if (d->d_magic != BSD_DISKMAGIC || d->d_magic2 != BSD_DISKMAGIC)
1522 for (t = d->d_npartitions; t < BSD_MAXPARTITIONS; t++) {
1523 d->d_partitions[t].p_size = 0;
1524 d->d_partitions[t].p_offset = 0;
1525 d->d_partitions[t].p_fstype = BSD_FS_UNUSED;
1528 if (d->d_npartitions > BSD_MAXPARTITIONS)
1529 fprintf(stderr, _("Warning: too many partitions "
1530 "(%d, maximum is %d).\n"),
1531 d->d_npartitions, BSD_MAXPARTITIONS);
1536 xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d)
1538 unsigned int sector;
1540 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
1541 sector = get_start_sect(p) + BSD_LABELSECTOR;
1543 sector = BSD_LABELSECTOR;
1547 d->d_checksum = xbsd_dkcksum (d);
1549 /* This is necessary if we want to write the bootstrap later,
1550 otherwise we'd write the old disklabel with the bootstrap.
1552 memmove(&disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
1553 d, sizeof(struct xbsd_disklabel));
1555 #if defined (__alpha__) && BSD_LABELSECTOR == 0
1556 alpha_bootblock_checksum (disklabelbuffer);
1557 if (lseek(fd, 0, SEEK_SET) == -1)
1558 fdisk_fatal(unable_to_seek);
1559 if (BSD_BBSIZE != write(fd, disklabelbuffer, BSD_BBSIZE))
1560 fdisk_fatal(unable_to_write);
1562 if (lseek(fd, sector * SECTOR_SIZE + BSD_LABELOFFSET, SEEK_SET) == -1)
1563 fdisk_fatal(unable_to_seek);
1564 if (sizeof(struct xbsd_disklabel) != write(fd, d, sizeof(struct xbsd_disklabel)))
1565 fdisk_fatal(unable_to_write);
1572 #if !defined (__alpha__)
1574 xbsd_translate_fstype(int linux_type)
1576 switch (linux_type) {
1577 case 0x01: /* DOS 12-bit FAT */
1578 case 0x04: /* DOS 16-bit <32M */
1579 case 0x06: /* DOS 16-bit >=32M */
1580 case 0xe1: /* DOS access */
1581 case 0xe3: /* DOS R/O */
1582 case 0xf2: /* DOS secondary */
1583 return BSD_FS_MSDOS;
1584 case 0x07: /* OS/2 HPFS */
1587 return BSD_FS_OTHER;
1592 xbsd_link_part(void)
1595 struct partition *p;
1597 k = get_partition(1, partitions);
1599 if (!xbsd_check_new_partition(&i))
1602 p = get_part_table(k);
1604 xbsd_dlabel.d_partitions[i].p_size = get_nr_sects(p);
1605 xbsd_dlabel.d_partitions[i].p_offset = get_start_sect(p);
1606 xbsd_dlabel.d_partitions[i].p_fstype = xbsd_translate_fstype(p->sys_ind);
1610 #if defined (__alpha__)
1612 #if !defined(__GLIBC__)
1613 typedef unsigned long long uint64_t;
1617 alpha_bootblock_checksum(char *boot)
1622 dp = (uint64_t *)boot;
1624 for (i = 0; i < 63; i++)
1628 #endif /* __alpha__ */
1630 #endif /* OSF_LABEL */
1632 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
1633 static unsigned short
1634 __swap16(unsigned short x)
1636 return (((uint16_t)(x) & 0xFF) << 8) | (((uint16_t)(x) & 0xFF00) >> 8);
1640 __swap32(uint32_t x)
1642 return (((x & 0xFF) << 24) |
1643 ((x & 0xFF00) << 8) |
1644 ((x & 0xFF0000) >> 8) |
1645 ((x & 0xFF000000) >> 24));
1649 #ifdef CONFIG_FEATURE_SGI_LABEL
1654 * Copyright (C) Andreas Neuper, Sep 1998.
1655 * This file may be modified and redistributed under
1656 * the terms of the GNU Public License.
1658 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
1659 * Internationalization
1663 static int sgi_other_endian;
1665 static short sgi_volumes = 1;
1668 * only dealing with free blocks here
1675 static freeblocks freelist[17]; /* 16 partitions can produce 17 vacant slots */
1678 setfreelist(int i, unsigned int f, unsigned int l)
1680 freelist[i].first = f;
1681 freelist[i].last = l;
1685 add2freelist(unsigned int f, unsigned int l)
1688 for (i = 0; i < 17 ; i++)
1689 if (freelist[i].last == 0)
1691 setfreelist(i, f, l);
1699 for (i = 0; i < 17 ; i++)
1700 setfreelist(i, 0, 0);
1704 isinfreelist(unsigned int b)
1708 for (i = 0; i < 17 ; i++)
1709 if (freelist[i].first <= b && freelist[i].last >= b)
1710 return freelist[i].last;
1713 /* return last vacant block of this stride (never 0). */
1714 /* the '>=' is not quite correct, but simplifies the code */
1716 * end of free blocks section
1719 static const struct systypes sgi_sys_types[] = {
1720 /* SGI_VOLHDR */ { "\x00" "SGI volhdr" },
1721 /* 0x01 */ { "\x01" "SGI trkrepl" },
1722 /* 0x02 */ { "\x02" "SGI secrepl" },
1723 /* SGI_SWAP */ { "\x03" "SGI raw" },
1724 /* 0x04 */ { "\x04" "SGI bsd" },
1725 /* 0x05 */ { "\x05" "SGI sysv" },
1726 /* ENTIRE_DISK */ { "\x06" "SGI volume" },
1727 /* SGI_EFS */ { "\x07" "SGI efs" },
1728 /* 0x08 */ { "\x08" "SGI lvol" },
1729 /* 0x09 */ { "\x09" "SGI rlvol" },
1730 /* SGI_XFS */ { "\x0a" "SGI xfs" },
1731 /* SGI_XFSLOG */ { "\x0b" "SGI xfslog" },
1732 /* SGI_XLV */ { "\x0c" "SGI xlv" },
1733 /* SGI_XVM */ { "\x0d" "SGI xvm" },
1734 /* LINUX_SWAP */ { "\x82" "Linux swap" },
1735 /* LINUX_NATIVE */ { "\x83" "Linux native" },
1736 /* LINUX_LVM */ { "\x8d" "Linux LVM" },
1737 /* LINUX_RAID */ { "\xfd" "Linux RAID" },
1745 return SGI_SSWAP16(sgilabel->devparam.nsect);
1751 return SGI_SSWAP16(sgilabel->devparam.ntrks);
1755 two_s_complement_32bit_sum(unsigned int* base, int size /* in bytes */)
1758 unsigned int sum = 0;
1760 size /= sizeof(unsigned int);
1761 for (i = 0; i < size; i++)
1762 sum -= SGI_SSWAP32(base[i]);
1767 check_sgi_label(void)
1769 if (sizeof(sgilabel) > 512) {
1771 _("According to MIPS Computer Systems, Inc the "
1772 "Label must not contain more than 512 bytes\n"));
1776 if (sgilabel->magic != SGI_LABEL_MAGIC
1777 && sgilabel->magic != SGI_LABEL_MAGIC_SWAPPED) {
1778 current_label_type = label_dos;
1782 sgi_other_endian = (sgilabel->magic == SGI_LABEL_MAGIC_SWAPPED);
1784 * test for correct checksum
1786 if (two_s_complement_32bit_sum((unsigned int*)sgilabel,
1787 sizeof(*sgilabel))) {
1789 _("Detected sgi disklabel with wrong checksum.\n"));
1792 current_label_type = label_sgi;
1799 sgi_get_start_sector(int i)
1801 return SGI_SSWAP32(sgilabel->partitions[i].start_sector);
1805 sgi_get_num_sectors(int i)
1807 return SGI_SSWAP32(sgilabel->partitions[i].num_sectors);
1811 sgi_get_sysid(int i)
1813 return SGI_SSWAP32(sgilabel->partitions[i].id);
1817 sgi_get_bootpartition(void)
1819 return SGI_SSWAP16(sgilabel->boot_part);
1823 sgi_get_swappartition(void)
1825 return SGI_SSWAP16(sgilabel->swap_part);
1829 sgi_list_table(int xtra)
1832 int kpi = 0; /* kernel partition ID */
1835 printf(_("\nDisk %s (SGI disk label): %d heads, %d sectors\n"
1836 "%d cylinders, %d physical cylinders\n"
1837 "%d extra sects/cyl, interleave %d:1\n"
1839 "Units = %s of %d * 512 bytes\n\n"),
1840 disk_device, heads, sectors, cylinders,
1841 SGI_SSWAP16(sgiparam.pcylcount),
1842 SGI_SSWAP16(sgiparam.sparecyl),
1843 SGI_SSWAP16(sgiparam.ilfact),
1845 str_units(PLURAL), units_per_sector);
1847 printf( _("\nDisk %s (SGI disk label): "
1848 "%d heads, %d sectors, %d cylinders\n"
1849 "Units = %s of %d * 512 bytes\n\n"),
1850 disk_device, heads, sectors, cylinders,
1851 str_units(PLURAL), units_per_sector );
1854 w = strlen(disk_device);
1855 wd = strlen(_("Device"));
1859 printf(_("----- partitions -----\n"
1860 "Pt# %*s Info Start End Sectors Id System\n"),
1861 w + 2, _("Device"));
1862 for (i = 0 ; i < partitions; i++) {
1863 if( sgi_get_num_sectors(i) || debug ) {
1864 uint32_t start = sgi_get_start_sector(i);
1865 uint32_t len = sgi_get_num_sectors(i);
1866 kpi++; /* only count nonempty partitions */
1868 "%2d: %s %4s %9ld %9ld %9ld %2x %s\n",
1869 /* fdisk part number */ i+1,
1870 /* device */ partname(disk_device, kpi, w+3),
1871 /* flags */ (sgi_get_swappartition() == i) ? "swap" :
1872 /* flags */ (sgi_get_bootpartition() == i) ? "boot" : " ",
1873 /* start */ (long) scround(start),
1874 /* end */ (long) scround(start+len)-1,
1875 /* no odd flag on end */(long) len,
1876 /* type id */ sgi_get_sysid(i),
1877 /* type name */ partition_type(sgi_get_sysid(i)));
1880 printf(_("----- Bootinfo -----\nBootfile: %s\n"
1881 "----- Directory Entries -----\n"),
1882 sgilabel->boot_file);
1883 for (i = 0 ; i < sgi_volumes; i++) {
1884 if (sgilabel->directory[i].vol_file_size) {
1885 uint32_t start = SGI_SSWAP32(sgilabel->directory[i].vol_file_start);
1886 uint32_t len = SGI_SSWAP32(sgilabel->directory[i].vol_file_size);
1887 unsigned char *name = sgilabel->directory[i].vol_file_name;
1889 printf(_("%2d: %-10s sector%5u size%8u\n"),
1890 i, (char*)name, (unsigned int) start, (unsigned int) len);
1896 sgi_set_bootpartition(int i)
1898 sgilabel->boot_part = SGI_SSWAP16(((short)i));
1902 sgi_get_lastblock(void)
1904 return heads * sectors * cylinders;
1908 sgi_set_swappartition(int i)
1910 sgilabel->swap_part = SGI_SSWAP16(((short)i));
1914 sgi_check_bootfile(const char* aFile)
1916 if (strlen(aFile) < 3) /* "/a\n" is minimum */ {
1917 printf(_("\nInvalid Bootfile!\n"
1918 "\tThe bootfile must be an absolute non-zero pathname,\n"
1919 "\te.g. \"/unix\" or \"/unix.save\".\n"));
1922 if (strlen(aFile) > 16) {
1923 printf(_("\n\tName of Bootfile too long: "
1924 "16 bytes maximum.\n"));
1927 if (aFile[0] != '/') {
1928 printf(_("\n\tBootfile must have a "
1929 "fully qualified pathname.\n"));
1934 if (strncmp(aFile, (char*)sgilabel->boot_file, 16)) {
1935 printf(_("\n\tBe aware, that the bootfile is not checked for existence.\n\t"
1936 "SGI's default is \"/unix\" and for backup \"/unix.save\".\n"));
1937 /* filename is correct and did change */
1940 return 0; /* filename did not change */
1944 sgi_get_bootfile(void)
1946 return (char*)sgilabel->boot_file;
1950 sgi_set_bootfile(const char* aFile)
1954 if (sgi_check_bootfile(aFile)) {
1956 if ((aFile[i] != '\n') /* in principle caught again by next line */
1957 && (strlen(aFile) > i))
1958 sgilabel->boot_file[i] = aFile[i];
1960 sgilabel->boot_file[i] = 0;
1963 printf(_("\n\tBootfile is changed to \"%s\".\n"), sgilabel->boot_file);
1968 create_sgiinfo(void)
1970 /* I keep SGI's habit to write the sgilabel to the second block */
1971 sgilabel->directory[0].vol_file_start = SGI_SSWAP32(2);
1972 sgilabel->directory[0].vol_file_size = SGI_SSWAP32(sizeof(sgiinfo));
1973 strcpy((char*)sgilabel->directory[0].vol_file_name, "sgilabel");
1976 static sgiinfo *fill_sgiinfo(void);
1979 sgi_write_table(void)
1982 sgilabel->csum = SGI_SSWAP32(two_s_complement_32bit_sum(
1983 (unsigned int*)sgilabel, sizeof(*sgilabel)));
1984 assert(two_s_complement_32bit_sum(
1985 (unsigned int*)sgilabel, sizeof(*sgilabel)) == 0);
1987 if (lseek(fd, 0, SEEK_SET) < 0)
1988 fdisk_fatal(unable_to_seek);
1989 if (write(fd, sgilabel, SECTOR_SIZE) != SECTOR_SIZE)
1990 fdisk_fatal(unable_to_write);
1991 if (!strncmp((char*)sgilabel->directory[0].vol_file_name, "sgilabel", 8)) {
1993 * keep this habit of first writing the "sgilabel".
1994 * I never tested whether it works without (AN 981002).
1996 sgiinfo *info = fill_sgiinfo();
1997 int infostartblock = SGI_SSWAP32(sgilabel->directory[0].vol_file_start);
1998 if (lseek(fd, infostartblock*SECTOR_SIZE, SEEK_SET) < 0)
1999 fdisk_fatal(unable_to_seek);
2000 if (write(fd, info, SECTOR_SIZE) != SECTOR_SIZE)
2001 fdisk_fatal(unable_to_write);
2007 compare_start(int *x, int *y)
2010 * sort according to start sectors
2011 * and prefers largest partition:
2012 * entry zero is entire disk entry
2014 unsigned int i = *x;
2015 unsigned int j = *y;
2016 unsigned int a = sgi_get_start_sector(i);
2017 unsigned int b = sgi_get_start_sector(j);
2018 unsigned int c = sgi_get_num_sectors(i);
2019 unsigned int d = sgi_get_num_sectors(j);
2022 return (d > c) ? 1 : (d == c) ? 0 : -1;
2023 return (a > b) ? 1 : -1;
2028 verify_sgi(int verbose)
2030 int Index[16]; /* list of valid partitions */
2031 int sortcount = 0; /* number of used partitions, i.e. non-zero lengths */
2032 int entire = 0, i = 0;
2033 unsigned int start = 0;
2034 long long gap = 0; /* count unused blocks */
2035 unsigned int lastblock = sgi_get_lastblock();
2038 for (i = 0; i < 16; i++) {
2039 if (sgi_get_num_sectors(i) != 0) {
2040 Index[sortcount++] = i;
2041 if (sgi_get_sysid(i) == ENTIRE_DISK) {
2042 if (entire++ == 1) {
2044 printf(_("More than one entire disk entry present.\n"));
2049 if (sortcount == 0) {
2051 printf(_("No partitions defined\n"));
2052 return (lastblock > 0) ? 1 : (lastblock == 0) ? 0 : -1;
2054 qsort(Index, sortcount, sizeof(Index[0]), (void*)compare_start);
2055 if (sgi_get_sysid(Index[0]) == ENTIRE_DISK) {
2056 if ((Index[0] != 10) && verbose)
2057 printf(_("IRIX likes when Partition 11 covers the entire disk.\n"));
2058 if ((sgi_get_start_sector(Index[0]) != 0) && verbose)
2059 printf(_("The entire disk partition should start "
2061 "not at diskblock %d.\n"),
2062 sgi_get_start_sector(Index[0]));
2063 if (debug) /* I do not understand how some disks fulfil it */
2064 if ((sgi_get_num_sectors(Index[0]) != lastblock) && verbose)
2065 printf(_("The entire disk partition is only %d diskblock large,\n"
2066 "but the disk is %d diskblocks long.\n"),
2067 sgi_get_num_sectors(Index[0]), lastblock);
2068 lastblock = sgi_get_num_sectors(Index[0]);
2071 printf(_("One Partition (#11) should cover the entire disk.\n"));
2073 printf("sysid=%d\tpartition=%d\n",
2074 sgi_get_sysid(Index[0]), Index[0]+1);
2076 for (i = 1, start = 0; i < sortcount; i++) {
2077 int cylsize = sgi_get_nsect() * sgi_get_ntrks();
2079 if ((sgi_get_start_sector(Index[i]) % cylsize) != 0) {
2080 if (debug) /* I do not understand how some disks fulfil it */
2082 printf(_("Partition %d does not start on cylinder boundary.\n"),
2085 if (sgi_get_num_sectors(Index[i]) % cylsize != 0) {
2086 if (debug) /* I do not understand how some disks fulfil it */
2088 printf(_("Partition %d does not end on cylinder boundary.\n"),
2091 /* We cannot handle several "entire disk" entries. */
2092 if (sgi_get_sysid(Index[i]) == ENTIRE_DISK) continue;
2093 if (start > sgi_get_start_sector(Index[i])) {
2095 printf(_("The Partition %d and %d overlap by %d sectors.\n"),
2096 Index[i-1]+1, Index[i]+1,
2097 start - sgi_get_start_sector(Index[i]));
2098 if (gap > 0) gap = -gap;
2099 if (gap == 0) gap = -1;
2101 if (start < sgi_get_start_sector(Index[i])) {
2103 printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"),
2104 sgi_get_start_sector(Index[i]) - start,
2105 start, sgi_get_start_sector(Index[i])-1);
2106 gap += sgi_get_start_sector(Index[i]) - start;
2107 add2freelist(start, sgi_get_start_sector(Index[i]));
2109 start = sgi_get_start_sector(Index[i])
2110 + sgi_get_num_sectors(Index[i]);
2113 printf("%2d:%12d\t%12d\t%12d\n", Index[i],
2114 sgi_get_start_sector(Index[i]),
2115 sgi_get_num_sectors(Index[i]),
2116 sgi_get_sysid(Index[i]));
2119 if (start < lastblock) {
2121 printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"),
2122 lastblock - start, start, lastblock-1);
2123 gap += lastblock - start;
2124 add2freelist(start, lastblock);
2127 * Done with arithmetics
2128 * Go for details now
2131 if (!sgi_get_num_sectors(sgi_get_bootpartition())) {
2132 printf(_("\nThe boot partition does not exist.\n"));
2134 if (!sgi_get_num_sectors(sgi_get_swappartition())) {
2135 printf(_("\nThe swap partition does not exist.\n"));
2137 if ((sgi_get_sysid(sgi_get_swappartition()) != SGI_SWAP)
2138 && (sgi_get_sysid(sgi_get_swappartition()) != LINUX_SWAP))
2139 printf(_("\nThe swap partition has no swap type.\n"));
2141 if (sgi_check_bootfile("/unix"))
2142 printf(_("\tYou have chosen an unusual boot file name.\n"));
2144 return (gap > 0) ? 1 : (gap == 0) ? 0 : -1;
2151 * returned value is:
2152 * = 0 : disk is properly filled to the rim
2153 * < 0 : there is an overlap
2154 * > 0 : there is still some vacant space
2156 return verify_sgi(0);
2160 sgi_change_sysid(int i, int sys)
2162 if( sgi_get_num_sectors(i) == 0 ) { /* caught already before, ... */
2163 printf(_("Sorry You may change the Tag of non-empty partitions.\n"));
2166 if (((sys != ENTIRE_DISK ) && (sys != SGI_VOLHDR))
2167 && (sgi_get_start_sector(i) < 1) ) {
2169 _("It is highly recommended that the partition at offset 0\n"
2170 "is of type \"SGI volhdr\", the IRIX system will rely on it to\n"
2171 "retrieve from its directory standalone tools like sash and fx.\n"
2172 "Only the \"SGI volume\" entire disk section may violate this.\n"
2173 "Type YES if you are sure about tagging this partition differently.\n"));
2174 if (strcmp(line_ptr, _("YES\n")))
2177 sgilabel->partitions[i].id = SGI_SSWAP32(sys);
2180 /* returns partition index of first entry marked as entire disk */
2186 for (i = 0; i < 16; i++)
2187 if (sgi_get_sysid(i) == SGI_VOLUME)
2193 sgi_set_partition(int i, unsigned int start, unsigned int length, int sys)
2195 sgilabel->partitions[i].id = SGI_SSWAP32(sys);
2196 sgilabel->partitions[i].num_sectors = SGI_SSWAP32(length);
2197 sgilabel->partitions[i].start_sector = SGI_SSWAP32(start);
2199 if (sgi_gaps() < 0) /* rebuild freelist */
2200 printf(_("Do You know, You got a partition overlap on the disk?\n"));
2204 sgi_set_entire(void)
2208 for (n = 10; n < partitions; n++) {
2209 if(!sgi_get_num_sectors(n) ) {
2210 sgi_set_partition(n, 0, sgi_get_lastblock(), SGI_VOLUME);
2217 sgi_set_volhdr(void)
2221 for (n = 8; n < partitions; n++) {
2222 if (!sgi_get_num_sectors(n)) {
2224 * 5 cylinders is an arbitrary value I like
2225 * IRIX 5.3 stored files in the volume header
2226 * (like sash, symmon, fx, ide) with ca. 3200
2229 if (heads * sectors * 5 < sgi_get_lastblock())
2230 sgi_set_partition(n, 0, heads * sectors * 5, SGI_VOLHDR);
2237 sgi_delete_partition(int i)
2239 sgi_set_partition(i, 0, 0, 0);
2243 sgi_add_partition(int n, int sys)
2246 unsigned int first = 0, last = 0;
2250 } else if (n == 8) {
2253 if(sgi_get_num_sectors(n)) {
2254 printf(_("Partition %d is already defined. Delete "
2255 "it before re-adding it.\n"), n + 1);
2258 if ((sgi_entire() == -1) && (sys != SGI_VOLUME)) {
2259 printf(_("Attempting to generate entire disk entry automatically.\n"));
2263 if ((sgi_gaps() == 0) && (sys != SGI_VOLUME)) {
2264 printf(_("The entire disk is already covered with partitions.\n"));
2267 if (sgi_gaps() < 0) {
2268 printf(_("You got a partition overlap on the disk. Fix it first!\n"));
2271 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
2273 if(sys == SGI_VOLUME) {
2274 last = sgi_get_lastblock();
2275 first = read_int(0, 0, last-1, 0, mesg);
2277 printf(_("It is highly recommended that eleventh partition\n"
2278 "covers the entire disk and is of type `SGI volume'\n"));
2281 first = freelist[0].first;
2282 last = freelist[0].last;
2283 first = read_int(scround(first), scround(first), scround(last)-1,
2286 if (display_in_cyl_units)
2287 first *= units_per_sector;
2289 first = first; /* align to cylinder if you know how ... */
2291 last = isinfreelist(first);
2293 printf(_("You will get a partition overlap on the disk. "
2294 "Fix it first!\n"));
2298 snprintf(mesg, sizeof(mesg), _(" Last %s"), str_units(SINGULAR));
2299 last = read_int(scround(first), scround(last)-1, scround(last)-1,
2300 scround(first), mesg)+1;
2301 if (display_in_cyl_units)
2302 last *= units_per_sector;
2304 last = last; /* align to cylinder if You know how ... */
2305 if ( (sys == SGI_VOLUME) && (first != 0 || last != sgi_get_lastblock() ) )
2306 printf(_("It is highly recommended that eleventh partition\n"
2307 "covers the entire disk and is of type `SGI volume'\n"));
2308 sgi_set_partition(n, first, last-first, sys);
2311 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
2313 create_sgilabel(void)
2315 struct hd_geometry geometry;
2322 long longsectors; /* the number of sectors on the device */
2323 int res; /* the result from the ioctl */
2324 int sec_fac; /* the sector factor */
2326 sec_fac = sector_size / 512; /* determine the sector factor */
2329 _("Building a new SGI disklabel. Changes will remain in memory only,\n"
2330 "until you decide to write them. After that, of course, the previous\n"
2331 "content will be unrecoverably lost.\n\n"));
2333 sgi_other_endian = (BB_LITTLE_ENDIAN);
2334 res = ioctl(fd, BLKGETSIZE, &longsectors);
2335 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
2336 heads = geometry.heads;
2337 sectors = geometry.sectors;
2339 /* the get device size ioctl was successful */
2340 cylinders = longsectors / (heads * sectors);
2341 cylinders /= sec_fac;
2343 /* otherwise print error and use truncated version */
2344 cylinders = geometry.cylinders;
2346 _("Warning: BLKGETSIZE ioctl failed on %s. "
2347 "Using geometry cylinder value of %d.\n"
2348 "This value may be truncated for devices"
2349 " > 33.8 GB.\n"), disk_device, cylinders);
2352 for (i = 0; i < 4; i++) {
2354 if (valid_part_table_flag(MBRbuffer)) {
2355 if(get_part_table(i)->sys_ind) {
2356 old[i].sysid = get_part_table(i)->sys_ind;
2357 old[i].start = get_start_sect(get_part_table(i));
2358 old[i].nsect = get_nr_sects(get_part_table(i));
2359 printf(_("Trying to keep parameters of partition %d.\n"), i);
2361 printf(_("ID=%02x\tSTART=%d\tLENGTH=%d\n"),
2362 old[i].sysid, old[i].start, old[i].nsect);
2367 memset(MBRbuffer, 0, sizeof(MBRbuffer));
2368 sgilabel->magic = SGI_SSWAP32(SGI_LABEL_MAGIC);
2369 sgilabel->boot_part = SGI_SSWAP16(0);
2370 sgilabel->swap_part = SGI_SSWAP16(1);
2372 /* sizeof(sgilabel->boot_file) = 16 > 6 */
2373 memset(sgilabel->boot_file, 0, 16);
2374 strcpy((char*)sgilabel->boot_file, "/unix");
2376 sgilabel->devparam.skew = (0);
2377 sgilabel->devparam.gap1 = (0);
2378 sgilabel->devparam.gap2 = (0);
2379 sgilabel->devparam.sparecyl = (0);
2380 sgilabel->devparam.pcylcount = SGI_SSWAP16(geometry.cylinders);
2381 sgilabel->devparam.head_vol0 = SGI_SSWAP16(0);
2382 sgilabel->devparam.ntrks = SGI_SSWAP16(geometry.heads);
2383 /* tracks/cylinder (heads) */
2384 sgilabel->devparam.cmd_tag_queue_depth = (0);
2385 sgilabel->devparam.unused0 = (0);
2386 sgilabel->devparam.unused1 = SGI_SSWAP16(0);
2387 sgilabel->devparam.nsect = SGI_SSWAP16(geometry.sectors);
2389 sgilabel->devparam.bytes = SGI_SSWAP16(512);
2390 sgilabel->devparam.ilfact = SGI_SSWAP16(1);
2391 sgilabel->devparam.flags = SGI_SSWAP32(TRACK_FWD|
2392 IGNORE_ERRORS|RESEEK);
2393 sgilabel->devparam.datarate = SGI_SSWAP32(0);
2394 sgilabel->devparam.retries_on_error = SGI_SSWAP32(1);
2395 sgilabel->devparam.ms_per_word = SGI_SSWAP32(0);
2396 sgilabel->devparam.xylogics_gap1 = SGI_SSWAP16(0);
2397 sgilabel->devparam.xylogics_syncdelay = SGI_SSWAP16(0);
2398 sgilabel->devparam.xylogics_readdelay = SGI_SSWAP16(0);
2399 sgilabel->devparam.xylogics_gap2 = SGI_SSWAP16(0);
2400 sgilabel->devparam.xylogics_readgate = SGI_SSWAP16(0);
2401 sgilabel->devparam.xylogics_writecont = SGI_SSWAP16(0);
2402 memset( &(sgilabel->directory), 0, sizeof(struct volume_directory)*15 );
2403 memset( &(sgilabel->partitions), 0, sizeof(struct sgi_partition)*16 );
2404 current_label_type = label_sgi;
2409 for (i = 0; i < 4; i++) {
2411 sgi_set_partition(i, old[i].start, old[i].nsect, old[i].sysid);
2419 /* do nothing in the beginning */
2421 #endif /* CONFIG_FEATURE_FDISK_ADVANCED */
2423 /* _____________________________________________________________
2429 sgiinfo *info = calloc(1, sizeof(sgiinfo));
2431 info->magic = SGI_SSWAP32(SGI_INFO_MAGIC);
2432 info->b1 = SGI_SSWAP32(-1);
2433 info->b2 = SGI_SSWAP16(-1);
2434 info->b3 = SGI_SSWAP16(1);
2435 /* You may want to replace this string !!!!!!! */
2436 strcpy( (char*)info->scsi_string, "IBM OEM 0662S12 3 30" );
2437 strcpy( (char*)info->serial, "0000" );
2438 info->check1816 = SGI_SSWAP16(18*256 +16 );
2439 strcpy( (char*)info->installer, "Sfx version 5.3, Oct 18, 1994" );
2442 #endif /* SGI_LABEL */
2445 #ifdef CONFIG_FEATURE_SUN_LABEL
2449 * I think this is mostly, or entirely, due to
2450 * Jakub Jelinek (jj@sunsite.mff.cuni.cz), July 1996
2452 * Merged with fdisk for other architectures, aeb, June 1998.
2454 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
2455 * Internationalization
2459 static int sun_other_endian;
2460 static int scsi_disk;
2464 #define IDE0_MAJOR 3
2467 #define IDE1_MAJOR 22
2471 guess_device_type(void)
2473 struct stat bootstat;
2475 if (fstat(fd, &bootstat) < 0) {
2478 } else if (S_ISBLK(bootstat.st_mode)
2479 && (major(bootstat.st_rdev) == IDE0_MAJOR ||
2480 major(bootstat.st_rdev) == IDE1_MAJOR)) {
2483 } else if (S_ISBLK(bootstat.st_mode)
2484 && major(bootstat.st_rdev) == FLOPPY_MAJOR) {
2493 static const struct systypes sun_sys_types[] = {
2494 { "\x00" "Empty" }, /* 0 */
2495 { "\x01" "Boot" }, /* 1 */
2496 { "\x02" "SunOS root" }, /* 2 */
2497 { "\x03" "SunOS swap" }, /* SUNOS_SWAP */
2498 { "\x04" "SunOS usr" }, /* 4 */
2499 { "\x05" "Whole disk" }, /* WHOLE_DISK */
2500 { "\x06" "SunOS stand" }, /* 6 */
2501 { "\x07" "SunOS var" }, /* 7 */
2502 { "\x08" "SunOS home" }, /* 8 */
2503 { "\x82" "Linux swap" }, /* LINUX_SWAP */
2504 { "\x83" "Linux native" }, /* LINUX_NATIVE */
2505 { "\x8e" "Linux LVM" }, /* 0x8e */
2506 /* New (2.2.x) raid partition with autodetect using persistent superblock */
2507 { "\xfd" "Linux raid autodetect" }, /* 0xfd */
2513 set_sun_partition(int i, uint start, uint stop, int sysid)
2515 sunlabel->infos[i].id = sysid;
2516 sunlabel->partitions[i].start_cylinder =
2517 SUN_SSWAP32(start / (heads * sectors));
2518 sunlabel->partitions[i].num_sectors =
2519 SUN_SSWAP32(stop - start);
2524 check_sun_label(void)
2526 unsigned short *ush;
2529 if (sunlabel->magic != SUN_LABEL_MAGIC
2530 && sunlabel->magic != SUN_LABEL_MAGIC_SWAPPED) {
2531 current_label_type = label_dos;
2532 sun_other_endian = 0;
2535 sun_other_endian = (sunlabel->magic == SUN_LABEL_MAGIC_SWAPPED);
2536 ush = ((unsigned short *) (sunlabel + 1)) - 1;
2537 for (csum = 0; ush >= (unsigned short *)sunlabel;) csum ^= *ush--;
2539 fprintf(stderr,_("Detected sun disklabel with wrong checksum.\n"
2540 "Probably you'll have to set all the values,\n"
2541 "e.g. heads, sectors, cylinders and partitions\n"
2542 "or force a fresh label (s command in main menu)\n"));
2544 heads = SUN_SSWAP16(sunlabel->ntrks);
2545 cylinders = SUN_SSWAP16(sunlabel->ncyl);
2546 sectors = SUN_SSWAP16(sunlabel->nsect);
2549 current_label_type = label_sun;
2554 static const struct sun_predefined_drives {
2557 unsigned short sparecyl;
2558 unsigned short ncyl;
2559 unsigned short nacyl;
2560 unsigned short pcylcount;
2561 unsigned short ntrks;
2562 unsigned short nsect;
2563 unsigned short rspeed;
2565 { "Quantum","ProDrive 80S",1,832,2,834,6,34,3662},
2566 { "Quantum","ProDrive 105S",1,974,2,1019,6,35,3662},
2567 { "CDC","Wren IV 94171-344",3,1545,2,1549,9,46,3600},
2568 { "IBM","DPES-31080",0,4901,2,4903,4,108,5400},
2569 { "IBM","DORS-32160",0,1015,2,1017,67,62,5400},
2570 { "IBM","DNES-318350",0,11199,2,11474,10,320,7200},
2571 { "SEAGATE","ST34371",0,3880,2,3882,16,135,7228},
2572 { "","SUN0104",1,974,2,1019,6,35,3662},
2573 { "","SUN0207",4,1254,2,1272,9,36,3600},
2574 { "","SUN0327",3,1545,2,1549,9,46,3600},
2575 { "","SUN0340",0,1538,2,1544,6,72,4200},
2576 { "","SUN0424",2,1151,2,2500,9,80,4400},
2577 { "","SUN0535",0,1866,2,2500,7,80,5400},
2578 { "","SUN0669",5,1614,2,1632,15,54,3600},
2579 { "","SUN1.0G",5,1703,2,1931,15,80,3597},
2580 { "","SUN1.05",0,2036,2,2038,14,72,5400},
2581 { "","SUN1.3G",6,1965,2,3500,17,80,5400},
2582 { "","SUN2.1G",0,2733,2,3500,19,80,5400},
2583 { "IOMEGA","Jaz",0,1019,2,1021,64,32,5394},
2586 static const struct sun_predefined_drives *
2587 sun_autoconfigure_scsi(void)
2589 const struct sun_predefined_drives *p = NULL;
2591 #ifdef SCSI_IOCTL_GET_IDLUN
2601 if (!ioctl(fd, SCSI_IOCTL_GET_IDLUN, &id)) {
2603 "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n",
2604 /* This is very wrong (works only if you have one HBA),
2605 but I haven't found a way how to get hostno
2606 from the current kernel */
2612 pfd = fopen("/proc/scsi/scsi","r");
2614 while (fgets(buffer2, 2048, pfd)) {
2615 if (!strcmp(buffer, buffer2)) {
2616 if (fgets(buffer2,2048,pfd)) {
2617 q = strstr(buffer2,"Vendor: ");
2622 *q++ = 0; /* truncate vendor name */
2623 q = strstr(q,"Model: ");
2628 q = strstr(q," Rev: ");
2631 for (i = 0; i < SIZE(sun_drives); i++) {
2632 if (*sun_drives[i].vendor && strcasecmp(sun_drives[i].vendor, vendor))
2634 if (!strstr(model, sun_drives[i].model))
2636 printf(_("Autoconfigure found a %s%s%s\n"),sun_drives[i].vendor,(*sun_drives[i].vendor) ? " " : "",sun_drives[i].model);
2655 create_sunlabel(void)
2657 struct hd_geometry geometry;
2661 const struct sun_predefined_drives *p = NULL;
2664 _("Building a new sun disklabel. Changes will remain in memory only,\n"
2665 "until you decide to write them. After that, of course, the previous\n"
2666 "content won't be recoverable.\n\n"));
2667 sun_other_endian = BB_LITTLE_ENDIAN;
2668 memset(MBRbuffer, 0, sizeof(MBRbuffer));
2669 sunlabel->magic = SUN_SSWAP16(SUN_LABEL_MAGIC);
2671 puts(_("Drive type\n"
2672 " ? auto configure\n"
2673 " 0 custom (with hardware detected defaults)"));
2674 for (i = 0; i < SIZE(sun_drives); i++) {
2675 printf(" %c %s%s%s\n",
2676 i + 'a', sun_drives[i].vendor,
2677 (*sun_drives[i].vendor) ? " " : "",
2678 sun_drives[i].model);
2681 c = read_char(_("Select type (? for auto, 0 for custom): "));
2682 if (c >= 'a' && c < 'a' + SIZE(sun_drives)) {
2683 p = sun_drives + c - 'a';
2685 } else if (c >= 'A' && c < 'A' + SIZE(sun_drives)) {
2686 p = sun_drives + c - 'A';
2688 } else if (c == '0') {
2690 } else if (c == '?' && scsi_disk) {
2691 p = sun_autoconfigure_scsi();
2693 printf(_("Autoconfigure failed.\n"));
2700 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
2701 heads = geometry.heads;
2702 sectors = geometry.sectors;
2703 cylinders = geometry.cylinders;
2710 sunlabel->nacyl = 0;
2711 sunlabel->pcylcount = SUN_SSWAP16(cylinders);
2712 sunlabel->rspeed = SUN_SSWAP16(300);
2713 sunlabel->ilfact = SUN_SSWAP16(1);
2714 sunlabel->sparecyl = 0;
2716 heads = read_int(1,heads,1024,0,_("Heads"));
2717 sectors = read_int(1,sectors,1024,0,_("Sectors/track"));
2719 cylinders = read_int(1,cylinders-2,65535,0,_("Cylinders"));
2721 cylinders = read_int(1,0,65535,0,_("Cylinders"));
2722 sunlabel->nacyl = SUN_SSWAP16(read_int(0,2,65535,0, _("Alternate cylinders")));
2723 sunlabel->pcylcount = SUN_SSWAP16(read_int(0,cylinders+SUN_SSWAP16(sunlabel->nacyl), 65535,0, _("Physical cylinders")));
2724 sunlabel->rspeed = SUN_SSWAP16(read_int(1,5400,100000,0, _("Rotation speed (rpm)")));
2725 sunlabel->ilfact = SUN_SSWAP16(read_int(1,1,32,0, _("Interleave factor")));
2726 sunlabel->sparecyl = SUN_SSWAP16(read_int(0,0,sectors,0, _("Extra sectors per cylinder")));
2729 sunlabel->sparecyl = SUN_SSWAP16(p->sparecyl);
2730 sunlabel->ncyl = SUN_SSWAP16(p->ncyl);
2731 sunlabel->nacyl = SUN_SSWAP16(p->nacyl);
2732 sunlabel->pcylcount = SUN_SSWAP16(p->pcylcount);
2733 sunlabel->ntrks = SUN_SSWAP16(p->ntrks);
2734 sunlabel->nsect = SUN_SSWAP16(p->nsect);
2735 sunlabel->rspeed = SUN_SSWAP16(p->rspeed);
2736 sunlabel->ilfact = SUN_SSWAP16(1);
2737 cylinders = p->ncyl;
2740 puts(_("You may change all the disk params from the x menu"));
2743 snprintf((char *)(sunlabel->info), sizeof(sunlabel->info),
2744 "%s%s%s cyl %d alt %d hd %d sec %d",
2745 p ? p->vendor : "", (p && *p->vendor) ? " " : "",
2746 p ? p->model : (floppy ? _("3,5\" floppy") : _("Linux custom")),
2747 cylinders, SUN_SSWAP16(sunlabel->nacyl), heads, sectors);
2749 sunlabel->ntrks = SUN_SSWAP16(heads);
2750 sunlabel->nsect = SUN_SSWAP16(sectors);
2751 sunlabel->ncyl = SUN_SSWAP16(cylinders);
2753 set_sun_partition(0, 0, cylinders * heads * sectors, LINUX_NATIVE);
2755 if (cylinders * heads * sectors >= 150 * 2048) {
2756 ndiv = cylinders - (50 * 2048 / (heads * sectors)); /* 50M swap */
2758 ndiv = cylinders * 2 / 3;
2759 set_sun_partition(0, 0, ndiv * heads * sectors, LINUX_NATIVE);
2760 set_sun_partition(1, ndiv * heads * sectors, cylinders * heads * sectors, LINUX_SWAP);
2761 sunlabel->infos[1].flags |= 0x01; /* Not mountable */
2763 set_sun_partition(2, 0, cylinders * heads * sectors, WHOLE_DISK);
2765 unsigned short *ush = (unsigned short *)sunlabel;
2766 unsigned short csum = 0;
2767 while (ush < (unsigned short *)(&sunlabel->csum))
2769 sunlabel->csum = csum;
2772 set_all_unchanged();
2774 get_boot(create_empty_sun);
2778 toggle_sunflags(int i, unsigned char mask)
2780 if (sunlabel->infos[i].flags & mask)
2781 sunlabel->infos[i].flags &= ~mask;
2783 sunlabel->infos[i].flags |= mask;
2788 fetch_sun(uint *starts, uint *lens, uint *start, uint *stop)
2790 int i, continuous = 1;
2793 *stop = cylinders * heads * sectors;
2794 for (i = 0; i < partitions; i++) {
2795 if (sunlabel->partitions[i].num_sectors
2796 && sunlabel->infos[i].id
2797 && sunlabel->infos[i].id != WHOLE_DISK) {
2798 starts[i] = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
2799 lens[i] = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
2801 if (starts[i] == *start)
2803 else if (starts[i] + lens[i] >= *stop)
2807 /* There will be probably more gaps
2808 than one, so lets check afterwards */
2817 static uint *verify_sun_starts;
2820 verify_sun_cmp(int *a, int *b)
2822 if (*a == -1) return 1;
2823 if (*b == -1) return -1;
2824 if (verify_sun_starts[*a] > verify_sun_starts[*b]) return 1;
2831 uint starts[8], lens[8], start, stop;
2832 int i,j,k,starto,endo;
2835 verify_sun_starts = starts;
2836 fetch_sun(starts,lens,&start,&stop);
2837 for (k = 0; k < 7; k++) {
2838 for (i = 0; i < 8; i++) {
2839 if (k && (lens[i] % (heads * sectors))) {
2840 printf(_("Partition %d doesn't end on cylinder boundary\n"), i+1);
2843 for (j = 0; j < i; j++)
2845 if (starts[j] == starts[i]+lens[i]) {
2846 starts[j] = starts[i]; lens[j] += lens[i];
2848 } else if (starts[i] == starts[j]+lens[j]){
2852 if (starts[i] < starts[j]+lens[j]
2853 && starts[j] < starts[i]+lens[i]) {
2855 if (starts[j] > starto)
2857 endo = starts[i]+lens[i];
2858 if (starts[j]+lens[j] < endo)
2859 endo = starts[j]+lens[j];
2860 printf(_("Partition %d overlaps with others in "
2861 "sectors %d-%d\n"), i+1, starto, endo);
2868 for (i = 0; i < 8; i++) {
2874 qsort(array,SIZE(array),sizeof(array[0]),
2875 (int (*)(const void *,const void *)) verify_sun_cmp);
2876 if (array[0] == -1) {
2877 printf(_("No partitions defined\n"));
2880 stop = cylinders * heads * sectors;
2881 if (starts[array[0]])
2882 printf(_("Unused gap - sectors 0-%d\n"),starts[array[0]]);
2883 for (i = 0; i < 7 && array[i+1] != -1; i++) {
2884 printf(_("Unused gap - sectors %d-%d\n"),starts[array[i]]+lens[array[i]],starts[array[i+1]]);
2886 start = starts[array[i]] + lens[array[i]];
2888 printf(_("Unused gap - sectors %d-%d\n"),start,stop);
2892 add_sun_partition(int n, int sys)
2894 uint start, stop, stop2;
2895 uint starts[8], lens[8];
2901 if (sunlabel->partitions[n].num_sectors && sunlabel->infos[n].id) {
2902 printf(_("Partition %d is already defined. Delete "
2903 "it before re-adding it.\n"), n + 1);
2907 fetch_sun(starts,lens,&start,&stop);
2908 if (stop <= start) {
2912 printf(_("Other partitions already cover the whole disk.\nDelete "
2913 "some/shrink them before retry.\n"));
2917 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
2920 first = read_int(0, 0, 0, 0, mesg);
2922 first = read_int(scround(start), scround(stop)+1,
2923 scround(stop), 0, mesg);
2924 if (display_in_cyl_units)
2925 first *= units_per_sector;
2927 /* Starting sector has to be properly aligned */
2928 first = (first + heads * sectors - 1) / (heads * sectors);
2929 if (n == 2 && first != 0)
2931 It is highly recommended that the third partition covers the whole disk\n\
2932 and is of type `Whole disk'\n");
2933 /* ewt asks to add: "don't start a partition at cyl 0"
2934 However, edmundo@rano.demon.co.uk writes:
2935 "In addition to having a Sun partition table, to be able to
2936 boot from the disc, the first partition, /dev/sdX1, must
2937 start at cylinder 0. This means that /dev/sdX1 contains
2938 the partition table and the boot block, as these are the
2939 first two sectors of the disc. Therefore you must be
2940 careful what you use /dev/sdX1 for. In particular, you must
2941 not use a partition starting at cylinder 0 for Linux swap,
2942 as that would overwrite the partition table and the boot
2943 block. You may, however, use such a partition for a UFS
2944 or EXT2 file system, as these file systems leave the first
2945 1024 bytes undisturbed. */
2946 /* On the other hand, one should not use partitions
2947 starting at block 0 in an md, or the label will
2949 for (i = 0; i < partitions; i++)
2950 if (lens[i] && starts[i] <= first && starts[i] + lens[i] > first)
2952 if (i < partitions && !whole_disk) {
2953 if (n == 2 && !first) {
2957 printf(_("Sector %d is already allocated\n"), first);
2961 stop = cylinders * heads * sectors;
2963 for (i = 0; i < partitions; i++) {
2964 if (starts[i] > first && starts[i] < stop)
2967 snprintf(mesg, sizeof(mesg),
2968 _("Last %s or +size or +sizeM or +sizeK"),
2969 str_units(SINGULAR));
2971 last = read_int(scround(stop2), scround(stop2), scround(stop2),
2973 else if (n == 2 && !first)
2974 last = read_int(scround(first), scround(stop2), scround(stop2),
2975 scround(first), mesg);
2977 last = read_int(scround(first), scround(stop), scround(stop),
2978 scround(first), mesg);
2979 if (display_in_cyl_units)
2980 last *= units_per_sector;
2981 if (n == 2 && !first) {
2982 if (last >= stop2) {
2985 } else if (last > stop) {
2986 printf(_("You haven't covered the whole disk with "
2987 "the 3rd partition, but your value\n"
2988 "%d %s covers some other partition. "
2989 "Your entry has been changed\n"
2991 scround(last), str_units(SINGULAR),
2992 scround(stop), str_units(SINGULAR));
2995 } else if (!whole_disk && last > stop)
3000 set_sun_partition(n, first, last, sys);
3004 sun_delete_partition(int i)
3009 && sunlabel->infos[i].id == WHOLE_DISK
3010 && !sunlabel->partitions[i].start_cylinder
3011 && (nsec = SUN_SSWAP32(sunlabel->partitions[i].num_sectors)) == heads * sectors * cylinders)
3012 printf(_("If you want to maintain SunOS/Solaris compatibility, "
3013 "consider leaving this\n"
3014 "partition as Whole disk (5), starting at 0, with %u "
3015 "sectors\n"), nsec);
3016 sunlabel->infos[i].id = 0;
3017 sunlabel->partitions[i].num_sectors = 0;
3021 sun_change_sysid(int i, int sys)
3023 if (sys == LINUX_SWAP && !sunlabel->partitions[i].start_cylinder) {
3025 _("It is highly recommended that the partition at offset 0\n"
3026 "is UFS, EXT2FS filesystem or SunOS swap. Putting Linux swap\n"
3027 "there may destroy your partition table and bootblock.\n"
3028 "Type YES if you're very sure you would like that partition\n"
3029 "tagged with 82 (Linux swap): "));
3030 if (strcmp (line_ptr, _("YES\n")))
3036 /* swaps are not mountable by default */
3037 sunlabel->infos[i].flags |= 0x01;
3040 /* assume other types are mountable;
3041 user can change it anyway */
3042 sunlabel->infos[i].flags &= ~0x01;
3045 sunlabel->infos[i].id = sys;
3049 sun_list_table(int xtra)
3053 w = strlen(disk_device);
3056 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d rpm\n"
3057 "%d cylinders, %d alternate cylinders, %d physical cylinders\n"
3058 "%d extra sects/cyl, interleave %d:1\n"
3060 "Units = %s of %d * 512 bytes\n\n"),
3061 disk_device, heads, sectors, SUN_SSWAP16(sunlabel->rspeed),
3062 cylinders, SUN_SSWAP16(sunlabel->nacyl),
3063 SUN_SSWAP16(sunlabel->pcylcount),
3064 SUN_SSWAP16(sunlabel->sparecyl),
3065 SUN_SSWAP16(sunlabel->ilfact),
3067 str_units(PLURAL), units_per_sector);
3070 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d cylinders\n"
3071 "Units = %s of %d * 512 bytes\n\n"),
3072 disk_device, heads, sectors, cylinders,
3073 str_units(PLURAL), units_per_sector);
3075 printf(_("%*s Flag Start End Blocks Id System\n"),
3076 w + 1, _("Device"));
3077 for (i = 0 ; i < partitions; i++) {
3078 if (sunlabel->partitions[i].num_sectors) {
3079 uint32_t start = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
3080 uint32_t len = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
3081 printf("%s %c%c %9ld %9ld %9ld%c %2x %s\n",
3082 partname(disk_device, i+1, w), /* device */
3083 (sunlabel->infos[i].flags & 0x01) ? 'u' : ' ', /* flags */
3084 (sunlabel->infos[i].flags & 0x10) ? 'r' : ' ',
3085 (long) scround(start), /* start */
3086 (long) scround(start+len), /* end */
3087 (long) len / 2, len & 1 ? '+' : ' ', /* odd flag on end */
3088 sunlabel->infos[i].id, /* type id */
3089 partition_type(sunlabel->infos[i].id)); /* type name */
3094 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3097 sun_set_alt_cyl(void)
3100 SUN_SSWAP16(read_int(0,SUN_SSWAP16(sunlabel->nacyl), 65535, 0,
3101 _("Number of alternate cylinders")));
3105 sun_set_ncyl(int cyl)
3107 sunlabel->ncyl = SUN_SSWAP16(cyl);
3113 sunlabel->sparecyl =
3114 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->sparecyl), sectors, 0,
3115 _("Extra sectors per cylinder")));
3119 sun_set_ilfact(void)
3122 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->ilfact), 32, 0,
3123 _("Interleave factor")));
3127 sun_set_rspeed(void)
3130 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->rspeed), 100000, 0,
3131 _("Rotation speed (rpm)")));
3135 sun_set_pcylcount(void)
3137 sunlabel->pcylcount =
3138 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->pcylcount), 65535, 0,
3139 _("Number of physical cylinders")));
3141 #endif /* CONFIG_FEATURE_FDISK_ADVANCED */
3144 sun_write_table(void)
3146 unsigned short *ush = (unsigned short *)sunlabel;
3147 unsigned short csum = 0;
3149 while (ush < (unsigned short *)(&sunlabel->csum))
3151 sunlabel->csum = csum;
3152 if (lseek(fd, 0, SEEK_SET) < 0)
3153 fdisk_fatal(unable_to_seek);
3154 if (write(fd, sunlabel, SECTOR_SIZE) != SECTOR_SIZE)
3155 fdisk_fatal(unable_to_write);
3157 #endif /* SUN_LABEL */
3159 /* DOS partition types */
3161 static const struct systypes i386_sys_types[] = {
3164 { "\x04" "FAT16 <32M" },
3165 { "\x05" "Extended" }, /* DOS 3.3+ extended partition */
3166 { "\x06" "FAT16" }, /* DOS 16-bit >=32M */
3167 { "\x07" "HPFS/NTFS" }, /* OS/2 IFS, eg, HPFS or NTFS or QNX */
3168 { "\x0a" "OS/2 Boot Manager" },/* OS/2 Boot Manager */
3169 { "\x0b" "Win95 FAT32" },
3170 { "\x0c" "Win95 FAT32 (LBA)" },/* LBA really is `Extended Int 13h' */
3171 { "\x0e" "Win95 FAT16 (LBA)" },
3172 { "\x0f" "Win95 Ext'd (LBA)" },
3173 { "\x11" "Hidden FAT12" },
3174 { "\x12" "Compaq diagnostics" },
3175 { "\x14" "Hidden FAT16 <32M" },
3176 { "\x16" "Hidden FAT16" },
3177 { "\x17" "Hidden HPFS/NTFS" },
3178 { "\x1b" "Hidden Win95 FAT32" },
3179 { "\x1c" "Hidden Win95 FAT32 (LBA)" },
3180 { "\x1e" "Hidden Win95 FAT16 (LBA)" },
3181 { "\x3c" "PartitionMagic recovery" },
3182 { "\x41" "PPC PReP Boot" },
3184 { "\x63" "GNU HURD or SysV" }, /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */
3185 { "\x80" "Old Minix" }, /* Minix 1.4a and earlier */
3186 { "\x81" "Minix / old Linux" },/* Minix 1.4b and later */
3187 { "\x82" "Linux swap" }, /* also Solaris */
3189 { "\x84" "OS/2 hidden C: drive" },
3190 { "\x85" "Linux extended" },
3191 { "\x86" "NTFS volume set" },
3192 { "\x87" "NTFS volume set" },
3193 { "\x8e" "Linux LVM" },
3194 { "\x9f" "BSD/OS" }, /* BSDI */
3195 { "\xa0" "IBM Thinkpad hibernation" },
3196 { "\xa5" "FreeBSD" }, /* various BSD flavours */
3197 { "\xa6" "OpenBSD" },
3198 { "\xa8" "Darwin UFS" },
3199 { "\xa9" "NetBSD" },
3200 { "\xab" "Darwin boot" },
3201 { "\xb7" "BSDI fs" },
3202 { "\xb8" "BSDI swap" },
3203 { "\xbe" "Solaris boot" },
3204 { "\xeb" "BeOS fs" },
3205 { "\xee" "EFI GPT" }, /* Intel EFI GUID Partition Table */
3206 { "\xef" "EFI (FAT-12/16/32)" },/* Intel EFI System Partition */
3207 { "\xf0" "Linux/PA-RISC boot" },/* Linux/PA-RISC boot loader */
3208 { "\xf2" "DOS secondary" }, /* DOS 3.3+ secondary */
3209 { "\xfd" "Linux raid autodetect" },/* New (2.2.x) raid partition with
3210 autodetect using persistent
3212 #ifdef CONFIG_WEIRD_PARTITION_TYPES
3213 { "\x02" "XENIX root" },
3214 { "\x03" "XENIX usr" },
3215 { "\x08" "AIX" }, /* AIX boot (AIX -- PS/2 port) or SplitDrive */
3216 { "\x09" "AIX bootable" }, /* AIX data or Coherent */
3218 { "\x18" "AST SmartSleep" },
3219 { "\x24" "NEC DOS" },
3220 { "\x39" "Plan 9" },
3221 { "\x40" "Venix 80286" },
3222 { "\x4d" "QNX4.x" },
3223 { "\x4e" "QNX4.x 2nd part" },
3224 { "\x4f" "QNX4.x 3rd part" },
3225 { "\x50" "OnTrack DM" },
3226 { "\x51" "OnTrack DM6 Aux1" }, /* (or Novell) */
3227 { "\x52" "CP/M" }, /* CP/M or Microport SysV/AT */
3228 { "\x53" "OnTrack DM6 Aux3" },
3229 { "\x54" "OnTrackDM6" },
3230 { "\x55" "EZ-Drive" },
3231 { "\x56" "Golden Bow" },
3232 { "\x5c" "Priam Edisk" },
3233 { "\x61" "SpeedStor" },
3234 { "\x64" "Novell Netware 286" },
3235 { "\x65" "Novell Netware 386" },
3236 { "\x70" "DiskSecure Multi-Boot" },
3238 { "\x93" "Amoeba" },
3239 { "\x94" "Amoeba BBT" }, /* (bad block table) */
3240 { "\xa7" "NeXTSTEP" },
3241 { "\xbb" "Boot Wizard hidden" },
3242 { "\xc1" "DRDOS/sec (FAT-12)" },
3243 { "\xc4" "DRDOS/sec (FAT-16 < 32M)" },
3244 { "\xc6" "DRDOS/sec (FAT-16)" },
3245 { "\xc7" "Syrinx" },
3246 { "\xda" "Non-FS data" },
3247 { "\xdb" "CP/M / CTOS / ..." },/* CP/M or Concurrent CP/M or
3248 Concurrent DOS or CTOS */
3249 { "\xde" "Dell Utility" }, /* Dell PowerEdge Server utilities */
3250 { "\xdf" "BootIt" }, /* BootIt EMBRM */
3251 { "\xe1" "DOS access" }, /* DOS access or SpeedStor 12-bit FAT
3252 extended partition */
3253 { "\xe3" "DOS R/O" }, /* DOS R/O or SpeedStor */
3254 { "\xe4" "SpeedStor" }, /* SpeedStor 16-bit FAT extended
3255 partition < 1024 cyl. */
3256 { "\xf1" "SpeedStor" },
3257 { "\xf4" "SpeedStor" }, /* SpeedStor large partition */
3258 { "\xfe" "LANstep" }, /* SpeedStor >1024 cyl. or LANstep */
3259 { "\xff" "BBT" }, /* Xenix Bad Block Table */
3266 /* A valid partition table sector ends in 0x55 0xaa */
3268 part_table_flag(const char *b)
3270 return ((uint) b[510]) + (((uint) b[511]) << 8);
3274 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3276 write_part_table_flag(char *b)
3282 /* start_sect and nr_sects are stored little endian on all machines */
3283 /* moreover, they are not aligned correctly */
3285 store4_little_endian(unsigned char *cp, unsigned int val)
3287 cp[0] = (val & 0xff);
3288 cp[1] = ((val >> 8) & 0xff);
3289 cp[2] = ((val >> 16) & 0xff);
3290 cp[3] = ((val >> 24) & 0xff);
3292 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3295 read4_little_endian(const unsigned char *cp)
3297 return (uint)(cp[0]) + ((uint)(cp[1]) << 8)
3298 + ((uint)(cp[2]) << 16) + ((uint)(cp[3]) << 24);
3301 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3303 set_start_sect(struct partition *p, unsigned int start_sect)
3305 store4_little_endian(p->start4, start_sect);
3310 get_start_sect(const struct partition *p)
3312 return read4_little_endian(p->start4);
3315 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3317 set_nr_sects(struct partition *p, int32_t nr_sects)
3319 store4_little_endian(p->size4, nr_sects);
3324 get_nr_sects(const struct partition *p)
3326 return read4_little_endian(p->size4);
3329 /* normally O_RDWR, -l option gives O_RDONLY */
3330 static int type_open = O_RDWR;
3333 static int ext_index; /* the prime extended partition */
3334 static int listing; /* no aborts for fdisk -l */
3335 static int dos_compatible_flag = ~0;
3336 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3337 static int dos_changed;
3338 static int nowarn; /* no warnings for fdisk -l/-s */
3343 static uint user_cylinders, user_heads, user_sectors;
3344 static uint pt_heads, pt_sectors;
3345 static uint kern_heads, kern_sectors;
3347 static off_t extended_offset; /* offset of link pointers */
3349 static unsigned long long total_number_of_sectors;
3352 static jmp_buf listingbuf;
3354 static void fdisk_fatal(enum failure why)
3356 const char *message;
3360 longjmp(listingbuf, 1);
3364 case unable_to_open:
3365 message = "Unable to open %s\n";
3367 case unable_to_read:
3368 message = "Unable to read %s\n";
3370 case unable_to_seek:
3371 message = "Unable to seek on %s\n";
3373 case unable_to_write:
3374 message = "Unable to write %s\n";
3377 message = "BLKGETSIZE ioctl failed on %s\n";
3380 message = "Fatal error\n";
3383 fputc('\n', stderr);
3384 fprintf(stderr, message, disk_device);
3389 seek_sector(off_t secno)
3391 off_t offset = secno * sector_size;
3392 if (lseek(fd, offset, SEEK_SET) == (off_t) -1)
3393 fdisk_fatal(unable_to_seek);
3396 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3398 write_sector(off_t secno, char *buf)
3401 if (write(fd, buf, sector_size) != sector_size)
3402 fdisk_fatal(unable_to_write);
3406 /* Allocate a buffer and read a partition table sector */
3408 read_pte(struct pte *pe, off_t offset)
3410 pe->offset = offset;
3411 pe->sectorbuffer = (char *) xmalloc(sector_size);
3412 seek_sector(offset);
3413 if (read(fd, pe->sectorbuffer, sector_size) != sector_size)
3414 fdisk_fatal(unable_to_read);
3415 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3418 pe->part_table = pe->ext_pointer = NULL;
3422 get_partition_start(const struct pte *pe)
3424 return pe->offset + get_start_sect(pe->part_table);
3427 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3429 * Avoid warning about DOS partitions when no DOS partition was changed.
3430 * Here a heuristic "is probably dos partition".
3431 * We might also do the opposite and warn in all cases except
3432 * for "is probably nondos partition".
3435 is_dos_partition(int t)
3437 return (t == 1 || t == 4 || t == 6 ||
3438 t == 0x0b || t == 0x0c || t == 0x0e ||
3439 t == 0x11 || t == 0x12 || t == 0x14 || t == 0x16 ||
3440 t == 0x1b || t == 0x1c || t == 0x1e || t == 0x24 ||
3441 t == 0xc1 || t == 0xc4 || t == 0xc6);
3447 #ifdef CONFIG_FEATURE_SUN_LABEL
3448 if (label_sun == current_label_type) {
3449 puts(_("Command action"));
3450 puts(_("\ta\ttoggle a read only flag")); /* sun */
3451 puts(_("\tb\tedit bsd disklabel"));
3452 puts(_("\tc\ttoggle the mountable flag")); /* sun */
3453 puts(_("\td\tdelete a partition"));
3454 puts(_("\tl\tlist known partition types"));
3455 puts(_("\tm\tprint this menu"));
3456 puts(_("\tn\tadd a new partition"));
3457 puts(_("\to\tcreate a new empty DOS partition table"));
3458 puts(_("\tp\tprint the partition table"));
3459 puts(_("\tq\tquit without saving changes"));
3460 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3461 puts(_("\tt\tchange a partition's system id"));
3462 puts(_("\tu\tchange display/entry units"));
3463 puts(_("\tv\tverify the partition table"));
3464 puts(_("\tw\twrite table to disk and exit"));
3465 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3466 puts(_("\tx\textra functionality (experts only)"));
3470 #ifdef CONFIG_FEATURE_SGI_LABEL
3471 if (label_sgi == current_label_type) {
3472 puts(_("Command action"));
3473 puts(_("\ta\tselect bootable partition")); /* sgi flavour */
3474 puts(_("\tb\tedit bootfile entry")); /* sgi */
3475 puts(_("\tc\tselect sgi swap partition")); /* sgi flavour */
3476 puts(_("\td\tdelete a partition"));
3477 puts(_("\tl\tlist known partition types"));
3478 puts(_("\tm\tprint this menu"));
3479 puts(_("\tn\tadd a new partition"));
3480 puts(_("\to\tcreate a new empty DOS partition table"));
3481 puts(_("\tp\tprint the partition table"));
3482 puts(_("\tq\tquit without saving changes"));
3483 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3484 puts(_("\tt\tchange a partition's system id"));
3485 puts(_("\tu\tchange display/entry units"));
3486 puts(_("\tv\tverify the partition table"));
3487 puts(_("\tw\twrite table to disk and exit"));
3490 #ifdef CONFIG_FEATURE_AIX_LABEL
3491 if (label_aix == current_label_type) {
3492 puts(_("Command action"));
3493 puts(_("\tm\tprint this menu"));
3494 puts(_("\to\tcreate a new empty DOS partition table"));
3495 puts(_("\tq\tquit without saving changes"));
3496 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3500 puts(_("Command action"));
3501 puts(_("\ta\ttoggle a bootable flag"));
3502 puts(_("\tb\tedit bsd disklabel"));
3503 puts(_("\tc\ttoggle the dos compatibility flag"));
3504 puts(_("\td\tdelete a partition"));
3505 puts(_("\tl\tlist known partition types"));
3506 puts(_("\tm\tprint this menu"));
3507 puts(_("\tn\tadd a new partition"));
3508 puts(_("\to\tcreate a new empty DOS partition table"));
3509 puts(_("\tp\tprint the partition table"));
3510 puts(_("\tq\tquit without saving changes"));
3511 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3512 puts(_("\tt\tchange a partition's system id"));
3513 puts(_("\tu\tchange display/entry units"));
3514 puts(_("\tv\tverify the partition table"));
3515 puts(_("\tw\twrite table to disk and exit"));
3516 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3517 puts(_("\tx\textra functionality (experts only)"));
3521 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3524 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3528 #ifdef CONFIG_FEATURE_SUN_LABEL
3529 if (label_sun == current_label_type) {
3530 puts(_("Command action"));
3531 puts(_("\ta\tchange number of alternate cylinders")); /*sun*/
3532 puts(_("\tc\tchange number of cylinders"));
3533 puts(_("\td\tprint the raw data in the partition table"));
3534 puts(_("\te\tchange number of extra sectors per cylinder"));/*sun*/
3535 puts(_("\th\tchange number of heads"));
3536 puts(_("\ti\tchange interleave factor")); /*sun*/
3537 puts(_("\to\tchange rotation speed (rpm)")); /*sun*/
3538 puts(_("\tm\tprint this menu"));
3539 puts(_("\tp\tprint the partition table"));
3540 puts(_("\tq\tquit without saving changes"));
3541 puts(_("\tr\treturn to main menu"));
3542 puts(_("\ts\tchange number of sectors/track"));
3543 puts(_("\tv\tverify the partition table"));
3544 puts(_("\tw\twrite table to disk and exit"));
3545 puts(_("\ty\tchange number of physical cylinders")); /*sun*/
3548 #ifdef CONFIG_FEATURE_SGI_LABEL
3549 if (label_sgi == current_label_type) {
3550 puts(_("Command action"));
3551 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3552 puts(_("\tc\tchange number of cylinders"));
3553 puts(_("\td\tprint the raw data in the partition table"));
3554 puts(_("\te\tlist extended partitions")); /* !sun */
3555 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3556 puts(_("\th\tchange number of heads"));
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"));
3566 #ifdef CONFIG_FEATURE_AIX_LABEL
3567 if (label_aix == current_label_type) {
3568 puts(_("Command action"));
3569 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3570 puts(_("\tc\tchange number of cylinders"));
3571 puts(_("\td\tprint the raw data in the partition table"));
3572 puts(_("\te\tlist extended partitions")); /* !sun */
3573 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3574 puts(_("\th\tchange number of heads"));
3575 puts(_("\tm\tprint this menu"));
3576 puts(_("\tp\tprint the partition table"));
3577 puts(_("\tq\tquit without saving changes"));
3578 puts(_("\tr\treturn to main menu"));
3579 puts(_("\ts\tchange number of sectors/track"));
3580 puts(_("\tv\tverify the partition table"));
3581 puts(_("\tw\twrite table to disk and exit"));
3585 puts(_("Command action"));
3586 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3587 puts(_("\tc\tchange number of cylinders"));
3588 puts(_("\td\tprint the raw data in the partition table"));
3589 puts(_("\te\tlist extended partitions")); /* !sun */
3590 puts(_("\tf\tfix partition order")); /* !sun, !aix, !sgi */
3591 #ifdef CONFIG_FEATURE_SGI_LABEL
3592 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3594 puts(_("\th\tchange number of heads"));
3595 puts(_("\tm\tprint this menu"));
3596 puts(_("\tp\tprint the partition table"));
3597 puts(_("\tq\tquit without saving changes"));
3598 puts(_("\tr\treturn to main menu"));
3599 puts(_("\ts\tchange number of sectors/track"));
3600 puts(_("\tv\tverify the partition table"));
3601 puts(_("\tw\twrite table to disk and exit"));
3604 #endif /* ADVANCED mode */
3606 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3607 static const struct systypes *
3611 #ifdef CONFIG_FEATURE_SUN_LABEL
3612 label_sun == current_label_type ? sun_sys_types :
3614 #ifdef CONFIG_FEATURE_SGI_LABEL
3615 label_sgi == current_label_type ? sgi_sys_types :
3620 #define get_sys_types() i386_sys_types
3621 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3623 static const char *partition_type(unsigned char type)
3626 const struct systypes *types = get_sys_types();
3628 for (i = 0; types[i].name; i++)
3629 if ((unsigned char )types[i].name[0] == type)
3630 return types[i].name + 1;
3632 return _("Unknown");
3636 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3641 #ifdef CONFIG_FEATURE_SUN_LABEL
3642 label_sun == current_label_type ? sunlabel->infos[i].id :
3644 #ifdef CONFIG_FEATURE_SGI_LABEL
3645 label_sgi == current_label_type ? sgi_get_sysid(i) :
3647 ptes[i].part_table->sys_ind);
3650 void list_types(const struct systypes *sys)
3652 uint last[4], done = 0, next = 0, size;
3655 for (i = 0; sys[i].name; i++);
3658 for (i = 3; i >= 0; i--)
3659 last[3 - i] = done += (size + i - done) / (i + 1);
3663 printf("%c%2x %-15.15s", i ? ' ' : '\n',
3664 (unsigned char)sys[next].name[0],
3665 partition_type((unsigned char)sys[next].name[0]));
3666 next = last[i++] + done;
3667 if (i > 3 || next >= last[i]) {
3671 } while (done < last[0]);
3674 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3677 is_cleared_partition(const struct partition *p)
3679 return !(!p || p->boot_ind || p->head || p->sector || p->cyl ||
3680 p->sys_ind || p->end_head || p->end_sector || p->end_cyl ||
3681 get_start_sect(p) || get_nr_sects(p));
3685 clear_partition(struct partition *p)
3689 memset(p, 0, sizeof(struct partition));
3692 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3694 set_partition(int i, int doext, off_t start, off_t stop, int sysid)
3696 struct partition *p;
3700 p = ptes[i].ext_pointer;
3701 offset = extended_offset;
3703 p = ptes[i].part_table;
3704 offset = ptes[i].offset;
3708 set_start_sect(p, start - offset);
3709 set_nr_sects(p, stop - start + 1);
3710 if (dos_compatible_flag && (start/(sectors*heads) > 1023))
3711 start = heads*sectors*1024 - 1;
3712 set_hsc(p->head, p->sector, p->cyl, start);
3713 if (dos_compatible_flag && (stop/(sectors*heads) > 1023))
3714 stop = heads*sectors*1024 - 1;
3715 set_hsc(p->end_head, p->end_sector, p->end_cyl, stop);
3716 ptes[i].changed = 1;
3721 test_c(const char **m, const char *mesg)
3725 fprintf(stderr, _("You must set"));
3727 fprintf(stderr, " %s", *m);
3737 const char *m = NULL;
3741 prev = test_c(&m, _("heads"));
3743 prev = test_c(&m, _("sectors"));
3745 prev = test_c(&m, _("cylinders"));
3749 fprintf(stderr, "%s%s.\n"
3750 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3751 "You can do this from the extra functions menu.\n"
3753 , prev ? _(" and ") : " ", m);
3758 static void update_units(void)
3760 int cyl_units = heads * sectors;
3762 if (display_in_cyl_units && cyl_units)
3763 units_per_sector = cyl_units;
3765 units_per_sector = 1; /* in sectors */
3768 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3770 warn_cylinders(void)
3772 if (label_dos == current_label_type && cylinders > 1024 && !nowarn)
3773 fprintf(stderr, _("\n"
3774 "The number of cylinders for this disk is set to %d.\n"
3775 "There is nothing wrong with that, but this is larger than 1024,\n"
3776 "and could in certain setups cause problems with:\n"
3777 "1) software that runs at boot time (e.g., old versions of LILO)\n"
3778 "2) booting and partitioning software from other OSs\n"
3779 " (e.g., DOS FDISK, OS/2 FDISK)\n"),
3785 read_extended(int ext)
3789 struct partition *p, *q;
3793 pex->ext_pointer = pex->part_table;
3795 p = pex->part_table;
3796 if (!get_start_sect(p)) {
3798 _("Bad offset in primary extended partition\n"));
3802 while (IS_EXTENDED(p->sys_ind)) {
3803 struct pte *pe = &ptes[partitions];
3805 if (partitions >= MAXIMUM_PARTS) {
3806 /* This is not a Linux restriction, but
3807 this program uses arrays of size MAXIMUM_PARTS.
3808 Do not try to `improve' this test. */
3809 struct pte *pre = &ptes[partitions-1];
3810 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3812 _("Warning: deleting partitions after %d\n"),
3816 clear_partition(pre->ext_pointer);
3820 read_pte(pe, extended_offset + get_start_sect(p));
3822 if (!extended_offset)
3823 extended_offset = get_start_sect(p);
3825 q = p = pt_offset(pe->sectorbuffer, 0);
3826 for (i = 0; i < 4; i++, p++) if (get_nr_sects(p)) {
3827 if (IS_EXTENDED(p->sys_ind)) {
3828 if (pe->ext_pointer)
3830 _("Warning: extra link "
3831 "pointer in partition table"
3832 " %d\n"), partitions + 1);
3834 pe->ext_pointer = p;
3835 } else if (p->sys_ind) {
3838 _("Warning: ignoring extra "
3839 "data in partition table"
3840 " %d\n"), partitions + 1);
3846 /* very strange code here... */
3847 if (!pe->part_table) {
3848 if (q != pe->ext_pointer)
3851 pe->part_table = q + 1;
3853 if (!pe->ext_pointer) {
3854 if (q != pe->part_table)
3855 pe->ext_pointer = q;
3857 pe->ext_pointer = q + 1;
3860 p = pe->ext_pointer;
3864 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3865 /* remove empty links */
3867 for (i = 4; i < partitions; i++) {
3868 struct pte *pe = &ptes[i];
3870 if (!get_nr_sects(pe->part_table) &&
3871 (partitions > 5 || ptes[4].part_table->sys_ind)) {
3872 printf("omitting empty partition (%d)\n", i+1);
3873 delete_partition(i);
3874 goto remove; /* numbering changed */
3880 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3882 create_doslabel(void)
3887 _("Building a new DOS disklabel. Changes will remain in memory only,\n"
3888 "until you decide to write them. After that, of course, the previous\n"
3889 "content won't be recoverable.\n\n"));
3891 current_label_type = label_dos;
3893 #ifdef CONFIG_FEATURE_OSF_LABEL
3894 possibly_osf_label = 0;
3898 for (i = 510-64; i < 510; i++)
3900 write_part_table_flag(MBRbuffer);
3901 extended_offset = 0;
3902 set_all_unchanged();
3904 get_boot(create_empty_dos);
3906 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3909 get_sectorsize(void)
3911 if (!user_set_sector_size) {
3913 if (ioctl(fd, BLKSSZGET, &arg) == 0)
3915 if (sector_size != DEFAULT_SECTOR_SIZE)
3916 printf(_("Note: sector size is %d (not %d)\n"),
3917 sector_size, DEFAULT_SECTOR_SIZE);
3922 get_kernel_geometry(void)
3924 struct hd_geometry geometry;
3926 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
3927 kern_heads = geometry.heads;
3928 kern_sectors = geometry.sectors;
3929 /* never use geometry.cylinders - it is truncated */
3934 get_partition_table_geometry(void)
3936 const unsigned char *bufp = (const unsigned char *)MBRbuffer;
3937 struct partition *p;
3938 int i, h, s, hh, ss;
3942 if (!(valid_part_table_flag((char*)bufp)))
3946 for (i = 0; i < 4; i++) {
3947 p = pt_offset(bufp, i);
3948 if (p->sys_ind != 0) {
3949 h = p->end_head + 1;
3950 s = (p->end_sector & 077);
3955 } else if (hh != h || ss != s)
3960 if (!first && !bad) {
3970 unsigned long long bytes; /* really u64 */
3973 sec_fac = sector_size / 512;
3974 #ifdef CONFIG_FEATURE_SUN_LABEL
3975 guess_device_type();
3977 heads = cylinders = sectors = 0;
3978 kern_heads = kern_sectors = 0;
3979 pt_heads = pt_sectors = 0;
3981 get_kernel_geometry();
3982 get_partition_table_geometry();
3984 heads = user_heads ? user_heads :
3985 pt_heads ? pt_heads :
3986 kern_heads ? kern_heads : 255;
3987 sectors = user_sectors ? user_sectors :
3988 pt_sectors ? pt_sectors :
3989 kern_sectors ? kern_sectors : 63;
3990 if (ioctl(fd, BLKGETSIZE64, &bytes) == 0) {
3993 unsigned long longsectors;
3995 if (ioctl(fd, BLKGETSIZE, &longsectors))
3997 bytes = ((unsigned long long) longsectors) << 9;
4000 total_number_of_sectors = (bytes >> 9);
4003 if (dos_compatible_flag)
4004 sector_offset = sectors;
4006 cylinders = total_number_of_sectors / (heads * sectors * sec_fac);
4008 cylinders = user_cylinders;
4012 * Read MBR. Returns:
4013 * -1: no 0xaa55 flag present (possibly entire disk BSD)
4014 * 0: found or created label
4018 get_boot(enum action what)
4024 for (i = 0; i < 4; i++) {
4025 struct pte *pe = &ptes[i];
4027 pe->part_table = pt_offset(MBRbuffer, i);
4028 pe->ext_pointer = NULL;
4030 pe->sectorbuffer = MBRbuffer;
4031 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4032 pe->changed = (what == create_empty_dos);
4036 #ifdef CONFIG_FEATURE_SUN_LABEL
4037 if (what == create_empty_sun && check_sun_label())
4041 memset(MBRbuffer, 0, 512);
4043 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4044 if (what == create_empty_dos)
4045 goto got_dos_table; /* skip reading disk */
4047 if ((fd = open(disk_device, type_open)) < 0) {
4048 if ((fd = open(disk_device, O_RDONLY)) < 0) {
4049 if (what == try_only)
4051 fdisk_fatal(unable_to_open);
4053 printf(_("You will not be able to write "
4054 "the partition table.\n"));
4057 if (512 != read(fd, MBRbuffer, 512)) {
4058 if (what == try_only)
4060 fdisk_fatal(unable_to_read);
4063 if ((fd = open(disk_device, O_RDONLY)) < 0)
4065 if (512 != read(fd, MBRbuffer, 512))
4073 #ifdef CONFIG_FEATURE_SUN_LABEL
4074 if (check_sun_label())
4078 #ifdef CONFIG_FEATURE_SGI_LABEL
4079 if (check_sgi_label())
4083 #ifdef CONFIG_FEATURE_AIX_LABEL
4084 if (check_aix_label())
4088 #ifdef CONFIG_FEATURE_OSF_LABEL
4089 if (check_osf_label()) {
4090 possibly_osf_label = 1;
4091 if (!valid_part_table_flag(MBRbuffer)) {
4092 current_label_type = label_osf;
4095 printf(_("This disk has both DOS and BSD magic.\n"
4096 "Give the 'b' command to go to BSD mode.\n"));
4100 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4104 if (!valid_part_table_flag(MBRbuffer)) {
4105 #ifndef CONFIG_FEATURE_FDISK_WRITABLE
4111 _("Device contains neither a valid DOS "
4112 "partition table, nor Sun, SGI or OSF "
4115 #ifdef CONFIG_FEATURE_SUN_LABEL
4124 case create_empty_dos:
4125 #ifdef CONFIG_FEATURE_SUN_LABEL
4126 case create_empty_sun:
4130 fprintf(stderr, _("Internal error\n"));
4133 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
4136 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4141 for (i = 0; i < 4; i++) {
4142 struct pte *pe = &ptes[i];
4144 if (IS_EXTENDED(pe->part_table->sys_ind)) {
4145 if (partitions != 4)
4146 fprintf(stderr, _("Ignoring extra extended "
4147 "partition %d\n"), i + 1);
4153 for (i = 3; i < partitions; i++) {
4154 struct pte *pe = &ptes[i];
4156 if (!valid_part_table_flag(pe->sectorbuffer)) {
4158 _("Warning: invalid flag 0x%04x of partition "
4159 "table %d will be corrected by w(rite)\n"),
4160 part_table_flag(pe->sectorbuffer), i + 1);
4161 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4170 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4172 * Print the message MESG, then read an integer between LOW and HIGH (inclusive).
4173 * If the user hits Enter, DFLT is returned.
4174 * Answers like +10 are interpreted as offsets from BASE.
4176 * There is no default if DFLT is not between LOW and HIGH.
4179 read_int(uint low, uint dflt, uint high, uint base, char *mesg)
4183 static char *ms = NULL;
4184 static int mslen = 0;
4186 if (!ms || strlen(mesg)+100 > mslen) {
4187 mslen = strlen(mesg)+200;
4188 ms = xrealloc(ms,mslen);
4191 if (dflt < low || dflt > high)
4195 snprintf(ms, mslen, _("%s (%u-%u, default %u): "),
4196 mesg, low, high, dflt);
4198 snprintf(ms, mslen, "%s (%u-%u): ", mesg, low, high);
4201 int use_default = default_ok;
4203 /* ask question and read answer */
4204 while (read_chars(ms) != '\n' && !isdigit(*line_ptr)
4205 && *line_ptr != '-' && *line_ptr != '+')
4208 if (*line_ptr == '+' || *line_ptr == '-') {
4209 int minus = (*line_ptr == '-');
4212 i = atoi(line_ptr+1);
4214 while (isdigit(*++line_ptr))
4217 switch (*line_ptr) {
4220 if (!display_in_cyl_units)
4221 i *= heads * sectors;
4235 absolute = 1000000000;
4241 unsigned long long bytes;
4244 bytes = (unsigned long long) i * absolute;
4245 unit = sector_size * units_per_sector;
4246 bytes += unit/2; /* round */
4255 while (isdigit(*line_ptr)) {
4261 printf(_("Using default value %u\n"), i = dflt);
4262 if (i >= low && i <= high)
4265 printf(_("Value out of range.\n"));
4271 get_partition(int warn, int max)
4276 i = read_int(1, 0, max, 0, _("Partition number")) - 1;
4282 label_sun != current_label_type &&
4283 label_sgi != current_label_type &&
4284 !pe->part_table->sys_ind
4286 #ifdef CONFIG_FEATURE_SUN_LABEL
4288 label_sun == current_label_type &&
4290 !sunlabel->partitions[i].num_sectors
4291 || !sunlabel->infos[i].id
4295 #ifdef CONFIG_FEATURE_SGI_LABEL
4297 label_sgi == current_label_type &&
4298 !sgi_get_num_sectors(i)
4303 _("Warning: partition %d has empty type\n"),
4312 get_existing_partition(int warn, int max)
4317 for (i = 0; i < max; i++) {
4318 struct pte *pe = &ptes[i];
4319 struct partition *p = pe->part_table;
4321 if (p && !is_cleared_partition(p)) {
4328 printf(_("Selected partition %d\n"), pno+1);
4331 printf(_("No partition is defined yet!\n"));
4335 return get_partition(warn, max);
4339 get_nonexisting_partition(int warn, int max)
4344 for (i = 0; i < max; i++) {
4345 struct pte *pe = &ptes[i];
4346 struct partition *p = pe->part_table;
4348 if (p && is_cleared_partition(p)) {
4355 printf(_("Selected partition %d\n"), pno+1);
4358 printf(_("All primary partitions have been defined already!\n"));
4362 return get_partition(warn, max);
4366 void change_units(void)
4368 display_in_cyl_units = !display_in_cyl_units;
4370 printf(_("Changing display/entry units to %s\n"),
4375 toggle_active(int i)
4377 struct pte *pe = &ptes[i];
4378 struct partition *p = pe->part_table;
4380 if (IS_EXTENDED(p->sys_ind) && !p->boot_ind)
4382 _("WARNING: Partition %d is an extended partition\n"),
4384 p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG);
4389 toggle_dos_compatibility_flag(void)
4391 dos_compatible_flag = ~dos_compatible_flag;
4392 if (dos_compatible_flag) {
4393 sector_offset = sectors;
4394 printf(_("DOS Compatibility flag is set\n"));
4398 printf(_("DOS Compatibility flag is not set\n"));
4403 delete_partition(int i)
4405 struct pte *pe = &ptes[i];
4406 struct partition *p = pe->part_table;
4407 struct partition *q = pe->ext_pointer;
4409 /* Note that for the fifth partition (i == 4) we don't actually
4410 * decrement partitions.
4413 if (warn_geometry())
4414 return; /* C/H/S not set */
4417 #ifdef CONFIG_FEATURE_SUN_LABEL
4418 if (label_sun == current_label_type) {
4419 sun_delete_partition(i);
4423 #ifdef CONFIG_FEATURE_SGI_LABEL
4424 if (label_sgi == current_label_type) {
4425 sgi_delete_partition(i);
4431 if (IS_EXTENDED(p->sys_ind) && i == ext_index) {
4433 ptes[ext_index].ext_pointer = NULL;
4434 extended_offset = 0;
4440 if (!q->sys_ind && i > 4) {
4441 /* the last one in the chain - just delete */
4444 clear_partition(ptes[i].ext_pointer);
4445 ptes[i].changed = 1;
4447 /* not the last one - further ones will be moved down */
4449 /* delete this link in the chain */
4450 p = ptes[i-1].ext_pointer;
4452 set_start_sect(p, get_start_sect(q));
4453 set_nr_sects(p, get_nr_sects(q));
4454 ptes[i-1].changed = 1;
4455 } else if (partitions > 5) { /* 5 will be moved to 4 */
4456 /* the first logical in a longer chain */
4459 if (pe->part_table) /* prevent SEGFAULT */
4460 set_start_sect(pe->part_table,
4461 get_partition_start(pe) -
4463 pe->offset = extended_offset;
4467 if (partitions > 5) {
4469 while (i < partitions) {
4470 ptes[i] = ptes[i+1];
4474 /* the only logical: clear only */
4475 clear_partition(ptes[i].part_table);
4482 int i, sys, origsys;
4483 struct partition *p;
4485 #ifdef CONFIG_FEATURE_SGI_LABEL
4486 /* If sgi_label then don't use get_existing_partition,
4487 let the user select a partition, since get_existing_partition()
4488 only works for Linux like partition tables. */
4489 if (label_sgi != current_label_type) {
4490 i = get_existing_partition(0, partitions);
4492 i = get_partition(0, partitions);
4495 i = get_existing_partition(0, partitions);
4499 p = ptes[i].part_table;
4500 origsys = sys = get_sysid(i);
4502 /* if changing types T to 0 is allowed, then
4503 the reverse change must be allowed, too */
4504 if (!sys && label_sgi != current_label_type &&
4505 label_sun != current_label_type && !get_nr_sects(p))
4507 printf(_("Partition %d does not exist yet!\n"), i + 1);
4509 sys = read_hex (get_sys_types());
4511 if (!sys && label_sgi != current_label_type &&
4512 label_sun != current_label_type)
4514 printf(_("Type 0 means free space to many systems\n"
4515 "(but not to Linux). Having partitions of\n"
4516 "type 0 is probably unwise. You can delete\n"
4517 "a partition using the `d' command.\n"));
4521 if (label_sun != current_label_type && label_sgi != current_label_type) {
4522 if (IS_EXTENDED(sys) != IS_EXTENDED(p->sys_ind)) {
4523 printf(_("You cannot change a partition into"
4524 " an extended one or vice versa\n"
4525 "Delete it first.\n"));
4531 #ifdef CONFIG_FEATURE_SUN_LABEL
4532 if (label_sun == current_label_type && i == 2 && sys != WHOLE_DISK)
4533 printf(_("Consider leaving partition 3 "
4534 "as Whole disk (5),\n"
4535 "as SunOS/Solaris expects it and "
4536 "even Linux likes it.\n\n"));
4538 #ifdef CONFIG_FEATURE_SGI_LABEL
4539 if (label_sgi == current_label_type &&
4541 (i == 10 && sys != ENTIRE_DISK) ||
4542 (i == 8 && sys != 0)
4545 printf(_("Consider leaving partition 9 "
4546 "as volume header (0),\nand "
4547 "partition 11 as entire volume (6)"
4548 "as IRIX expects it.\n\n"));
4553 #ifdef CONFIG_FEATURE_SUN_LABEL
4554 if (label_sun == current_label_type) {
4555 sun_change_sysid(i, sys);
4558 #ifdef CONFIG_FEATURE_SGI_LABEL
4559 if (label_sgi == current_label_type) {
4560 sgi_change_sysid(i, sys);
4565 printf(_("Changed system type of partition %d "
4566 "to %x (%s)\n"), i + 1, sys,
4567 partition_type(sys));
4568 ptes[i].changed = 1;
4569 if (is_dos_partition(origsys) ||
4570 is_dos_partition(sys))
4576 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
4579 /* check_consistency() and long2chs() added Sat Mar 6 12:28:16 1993,
4580 * faith@cs.unc.edu, based on code fragments from pfdisk by Gordon W. Ross,
4581 * Jan. 1990 (version 1.2.1 by Gordon W. Ross Aug. 1990; Modified by S.
4582 * Lubkin Oct. 1991). */
4585 long2chs(ulong ls, uint *c, uint *h, uint *s)
4587 int spc = heads * sectors;
4592 *s = ls % sectors + 1; /* sectors count from 1 */
4596 check_consistency(const struct partition *p, int partition)
4598 uint pbc, pbh, pbs; /* physical beginning c, h, s */
4599 uint pec, peh, pes; /* physical ending c, h, s */
4600 uint lbc, lbh, lbs; /* logical beginning c, h, s */
4601 uint lec, leh, les; /* logical ending c, h, s */
4603 if (!heads || !sectors || (partition >= 4))
4604 return; /* do not check extended partitions */
4606 /* physical beginning c, h, s */
4607 pbc = (p->cyl & 0xff) | ((p->sector << 2) & 0x300);
4609 pbs = p->sector & 0x3f;
4611 /* physical ending c, h, s */
4612 pec = (p->end_cyl & 0xff) | ((p->end_sector << 2) & 0x300);
4614 pes = p->end_sector & 0x3f;
4616 /* compute logical beginning (c, h, s) */
4617 long2chs(get_start_sect(p), &lbc, &lbh, &lbs);
4619 /* compute logical ending (c, h, s) */
4620 long2chs(get_start_sect(p) + get_nr_sects(p) - 1, &lec, &leh, &les);
4622 /* Same physical / logical beginning? */
4623 if (cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) {
4624 printf(_("Partition %d has different physical/logical "
4625 "beginnings (non-Linux?):\n"), partition + 1);
4626 printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs);
4627 printf(_("logical=(%d, %d, %d)\n"),lbc, lbh, lbs);
4630 /* Same physical / logical ending? */
4631 if (cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) {
4632 printf(_("Partition %d has different physical/logical "
4633 "endings:\n"), partition + 1);
4634 printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
4635 printf(_("logical=(%d, %d, %d)\n"),lec, leh, les);
4638 /* Ending on cylinder boundary? */
4639 if (peh != (heads - 1) || pes != sectors) {
4640 printf(_("Partition %i does not end on cylinder boundary.\n"),
4646 list_disk_geometry(void)
4648 long long bytes = (total_number_of_sectors << 9);
4649 long megabytes = bytes/1000000;
4651 if (megabytes < 10000)
4652 printf(_("\nDisk %s: %ld MB, %lld bytes\n"),
4653 disk_device, megabytes, bytes);
4655 printf(_("\nDisk %s: %ld.%ld GB, %lld bytes\n"),
4656 disk_device, megabytes/1000, (megabytes/100)%10, bytes);
4657 printf(_("%d heads, %d sectors/track, %d cylinders"),
4658 heads, sectors, cylinders);
4659 if (units_per_sector == 1)
4660 printf(_(", total %llu sectors"),
4661 total_number_of_sectors / (sector_size/512));
4662 printf(_("\nUnits = %s of %d * %d = %d bytes\n\n"),
4664 units_per_sector, sector_size, units_per_sector * sector_size);
4668 * Check whether partition entries are ordered by their starting positions.
4669 * Return 0 if OK. Return i if partition i should have been earlier.
4670 * Two separate checks: primary and logical partitions.
4673 wrong_p_order(int *prev)
4675 const struct pte *pe;
4676 const struct partition *p;
4677 off_t last_p_start_pos = 0, p_start_pos;
4680 for (i = 0 ; i < partitions; i++) {
4683 last_p_start_pos = 0;
4686 if ((p = pe->part_table)->sys_ind) {
4687 p_start_pos = get_partition_start(pe);
4689 if (last_p_start_pos > p_start_pos) {
4695 last_p_start_pos = p_start_pos;
4702 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
4704 * Fix the chain of logicals.
4705 * extended_offset is unchanged, the set of sectors used is unchanged
4706 * The chain is sorted so that sectors increase, and so that
4707 * starting sectors increase.
4709 * After this it may still be that cfdisk doesnt like the table.
4710 * (This is because cfdisk considers expanded parts, from link to
4711 * end of partition, and these may still overlap.)
4713 * sfdisk /dev/hda > ohda; sfdisk /dev/hda < ohda
4717 fix_chain_of_logicals(void)
4719 int j, oj, ojj, sj, sjj;
4720 struct partition *pj,*pjj,tmp;
4722 /* Stage 1: sort sectors but leave sector of part 4 */
4723 /* (Its sector is the global extended_offset.) */
4725 for (j = 5; j < partitions-1; j++) {
4726 oj = ptes[j].offset;
4727 ojj = ptes[j+1].offset;
4729 ptes[j].offset = ojj;
4730 ptes[j+1].offset = oj;
4731 pj = ptes[j].part_table;
4732 set_start_sect(pj, get_start_sect(pj)+oj-ojj);
4733 pjj = ptes[j+1].part_table;
4734 set_start_sect(pjj, get_start_sect(pjj)+ojj-oj);
4735 set_start_sect(ptes[j-1].ext_pointer,
4736 ojj-extended_offset);
4737 set_start_sect(ptes[j].ext_pointer,
4738 oj-extended_offset);
4743 /* Stage 2: sort starting sectors */
4745 for (j = 4; j < partitions-1; j++) {
4746 pj = ptes[j].part_table;
4747 pjj = ptes[j+1].part_table;
4748 sj = get_start_sect(pj);
4749 sjj = get_start_sect(pjj);
4750 oj = ptes[j].offset;
4751 ojj = ptes[j+1].offset;
4752 if (oj+sj > ojj+sjj) {
4756 set_start_sect(pj, ojj+sjj-oj);
4757 set_start_sect(pjj, oj+sj-ojj);
4762 /* Probably something was changed */
4763 for (j = 4; j < partitions; j++)
4764 ptes[j].changed = 1;
4769 fix_partition_table_order(void)
4771 struct pte *pei, *pek;
4774 if (!wrong_p_order(NULL)) {
4775 printf(_("Nothing to do. Ordering is correct already.\n\n"));
4779 while ((i = wrong_p_order(&k)) != 0 && i < 4) {
4780 /* partition i should have come earlier, move it */
4781 /* We have to move data in the MBR */
4782 struct partition *pi, *pk, *pe, pbuf;
4786 pe = pei->ext_pointer;
4787 pei->ext_pointer = pek->ext_pointer;
4788 pek->ext_pointer = pe;
4790 pi = pei->part_table;
4791 pk = pek->part_table;
4793 memmove(&pbuf, pi, sizeof(struct partition));
4794 memmove(pi, pk, sizeof(struct partition));
4795 memmove(pk, &pbuf, sizeof(struct partition));
4797 pei->changed = pek->changed = 1;
4801 fix_chain_of_logicals();
4809 list_table(int xtra)
4811 const struct partition *p;
4814 #ifdef CONFIG_FEATURE_SUN_LABEL
4815 if (label_sun == current_label_type) {
4816 sun_list_table(xtra);
4821 #ifdef CONFIG_FEATURE_SGI_LABEL
4822 if (label_sgi == current_label_type) {
4823 sgi_list_table(xtra);
4828 list_disk_geometry();
4830 #ifdef CONFIG_FEATURE_OSF_LABEL
4831 if (label_osf == current_label_type) {
4832 xbsd_print_disklabel(xtra);
4837 /* Heuristic: we list partition 3 of /dev/foo as /dev/foo3,
4838 but if the device name ends in a digit, say /dev/foo1,
4839 then the partition is called /dev/foo1p3. */
4840 w = strlen(disk_device);
4841 if (w && isdigit(disk_device[w-1]))
4846 printf(_("%*s Boot Start End Blocks Id System\n"),
4849 for (i = 0; i < partitions; i++) {
4850 const struct pte *pe = &ptes[i];
4853 if (p && !is_cleared_partition(p)) {
4854 off_t psects = get_nr_sects(p);
4855 off_t pblocks = psects;
4856 unsigned int podd = 0;
4858 if (sector_size < 1024) {
4859 pblocks /= (1024 / sector_size);
4860 podd = psects % (1024 / sector_size);
4862 if (sector_size > 1024)
4863 pblocks *= (sector_size / 1024);
4865 "%s %c %11llu %11llu %11llu%c %2x %s\n",
4866 partname(disk_device, i+1, w+2),
4867 /* boot flag */ !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG
4869 /* start */ (unsigned long long) cround(get_partition_start(pe)),
4870 /* end */ (unsigned long long) cround(get_partition_start(pe) + psects
4871 - (psects ? 1 : 0)),
4872 /* odd flag on end */ (unsigned long long) pblocks, podd ? '+' : ' ',
4873 /* type id */ p->sys_ind,
4874 /* type name */ partition_type(p->sys_ind));
4875 check_consistency(p, i);
4879 /* Is partition table in disk order? It need not be, but... */
4880 /* partition table entries are not checked for correct order if this
4881 is a sgi, sun or aix labeled disk... */
4882 if (label_dos == current_label_type && wrong_p_order(NULL)) {
4884 printf(_("\nPartition table entries are not in disk order\n"));
4888 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
4890 x_list_table(int extend)
4892 const struct pte *pe;
4893 const struct partition *p;
4896 printf(_("\nDisk %s: %d heads, %d sectors, %d cylinders\n\n"),
4897 disk_device, heads, sectors, cylinders);
4898 printf(_("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n"));
4899 for (i = 0 ; i < partitions; i++) {
4901 p = (extend ? pe->ext_pointer : pe->part_table);
4903 printf("%2d %02x%4d%4d%5d%4d%4d%5d%11u%11u %02x\n",
4904 i + 1, p->boot_ind, p->head,
4906 cylinder(p->sector, p->cyl), p->end_head,
4907 sector(p->end_sector),
4908 cylinder(p->end_sector, p->end_cyl),
4909 get_start_sect(p), get_nr_sects(p), p->sys_ind);
4911 check_consistency(p, i);
4917 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4919 fill_bounds(off_t *first, off_t *last)
4922 const struct pte *pe = &ptes[0];
4923 const struct partition *p;
4925 for (i = 0; i < partitions; pe++,i++) {
4927 if (!p->sys_ind || IS_EXTENDED(p->sys_ind)) {
4928 first[i] = 0xffffffff;
4931 first[i] = get_partition_start(pe);
4932 last[i] = first[i] + get_nr_sects(p) - 1;
4938 check(int n, uint h, uint s, uint c, off_t start)
4940 off_t total, real_s, real_c;
4942 real_s = sector(s) - 1;
4943 real_c = cylinder(s, c);
4944 total = (real_c * sectors + real_s) * heads + h;
4946 fprintf(stderr, _("Warning: partition %d contains sector 0\n"), n);
4949 _("Partition %d: head %d greater than maximum %d\n"),
4951 if (real_s >= sectors)
4952 fprintf(stderr, _("Partition %d: sector %d greater than "
4953 "maximum %d\n"), n, s, sectors);
4954 if (real_c >= cylinders)
4955 fprintf(stderr, _("Partitions %d: cylinder %llu greater than "
4956 "maximum %d\n"), n, (unsigned long long)real_c + 1, cylinders);
4957 if (cylinders <= 1024 && start != total)
4959 _("Partition %d: previous sectors %llu disagrees with "
4960 "total %llu\n"), n, (unsigned long long)start, (unsigned long long)total);
4968 off_t first[partitions], last[partitions];
4969 struct partition *p;
4971 if (warn_geometry())
4974 #ifdef CONFIG_FEATURE_SUN_LABEL
4975 if (label_sun == current_label_type) {
4980 #ifdef CONFIG_FEATURE_SGI_LABEL
4981 if (label_sgi == current_label_type) {
4987 fill_bounds(first, last);
4988 for (i = 0; i < partitions; i++) {
4989 struct pte *pe = &ptes[i];
4992 if (p->sys_ind && !IS_EXTENDED(p->sys_ind)) {
4993 check_consistency(p, i);
4994 if (get_partition_start(pe) < first[i])
4995 printf(_("Warning: bad start-of-data in "
4996 "partition %d\n"), i + 1);
4997 check(i + 1, p->end_head, p->end_sector, p->end_cyl,
4999 total += last[i] + 1 - first[i];
5000 for (j = 0; j < i; j++)
5001 if ((first[i] >= first[j] && first[i] <= last[j])
5002 || ((last[i] <= last[j] && last[i] >= first[j]))) {
5003 printf(_("Warning: partition %d overlaps "
5004 "partition %d.\n"), j + 1, i + 1);
5005 total += first[i] >= first[j] ?
5006 first[i] : first[j];
5007 total -= last[i] <= last[j] ?
5013 if (extended_offset) {
5014 struct pte *pex = &ptes[ext_index];
5015 off_t e_last = get_start_sect(pex->part_table) +
5016 get_nr_sects(pex->part_table) - 1;
5018 for (i = 4; i < partitions; i++) {
5020 p = ptes[i].part_table;
5022 if (i != 4 || i + 1 < partitions)
5023 printf(_("Warning: partition %d "
5024 "is empty\n"), i + 1);
5026 else if (first[i] < extended_offset ||
5028 printf(_("Logical partition %d not entirely in "
5029 "partition %d\n"), i + 1, ext_index + 1);
5033 if (total > heads * sectors * cylinders)
5034 printf(_("Total allocated sectors %d greater than the maximum "
5035 "%d\n"), total, heads * sectors * cylinders);
5036 else if ((total = heads * sectors * cylinders - total) != 0)
5037 printf(_("%d unallocated sectors\n"), total);
5041 add_partition(int n, int sys)
5043 char mesg[256]; /* 48 does not suffice in Japanese */
5044 int i, num_read = 0;
5045 struct partition *p = ptes[n].part_table;
5046 struct partition *q = ptes[ext_index].part_table;
5048 off_t start, stop = 0, limit, temp,
5049 first[partitions], last[partitions];
5051 if (p && p->sys_ind) {
5052 printf(_("Partition %d is already defined. Delete "
5053 "it before re-adding it.\n"), n + 1);
5056 fill_bounds(first, last);
5058 start = sector_offset;
5059 if (display_in_cyl_units || !total_number_of_sectors)
5060 llimit = heads * sectors * cylinders - 1;
5062 llimit = total_number_of_sectors - 1;
5064 if (limit != llimit)
5066 if (extended_offset) {
5067 first[ext_index] = extended_offset;
5068 last[ext_index] = get_start_sect(q) +
5069 get_nr_sects(q) - 1;
5072 start = extended_offset + sector_offset;
5073 limit = get_start_sect(q) + get_nr_sects(q) - 1;
5075 if (display_in_cyl_units)
5076 for (i = 0; i < partitions; i++)
5077 first[i] = (cround(first[i]) - 1) * units_per_sector;
5079 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
5082 for (i = 0; i < partitions; i++) {
5085 if (start == ptes[i].offset)
5086 start += sector_offset;
5087 lastplusoff = last[i] + ((n < 4) ? 0 : sector_offset);
5088 if (start >= first[i] && start <= lastplusoff)
5089 start = lastplusoff + 1;
5093 if (start >= temp+units_per_sector && num_read) {
5094 printf(_("Sector %llu is already allocated\n"), (unsigned long long)temp);
5098 if (!num_read && start == temp) {
5101 saved_start = start;
5102 start = read_int(cround(saved_start), cround(saved_start), cround(limit),
5104 if (display_in_cyl_units) {
5105 start = (start - 1) * units_per_sector;
5106 if (start < saved_start) start = saved_start;
5110 } while (start != temp || !num_read);
5111 if (n > 4) { /* NOT for fifth partition */
5112 struct pte *pe = &ptes[n];
5114 pe->offset = start - sector_offset;
5115 if (pe->offset == extended_offset) { /* must be corrected */
5117 if (sector_offset == 1)
5122 for (i = 0; i < partitions; i++) {
5123 struct pte *pe = &ptes[i];
5125 if (start < pe->offset && limit >= pe->offset)
5126 limit = pe->offset - 1;
5127 if (start < first[i] && limit >= first[i])
5128 limit = first[i] - 1;
5130 if (start > limit) {
5131 printf(_("No free sectors available\n"));
5136 if (cround(start) == cround(limit)) {
5139 snprintf(mesg, sizeof(mesg),
5140 _("Last %s or +size or +sizeM or +sizeK"),
5141 str_units(SINGULAR));
5142 stop = read_int(cround(start), cround(limit), cround(limit),
5143 cround(start), mesg);
5144 if (display_in_cyl_units) {
5145 stop = stop * units_per_sector - 1;
5151 set_partition(n, 0, start, stop, sys);
5153 set_partition(n - 1, 1, ptes[n].offset, stop, EXTENDED);
5155 if (IS_EXTENDED(sys)) {
5156 struct pte *pe4 = &ptes[4];
5157 struct pte *pen = &ptes[n];
5160 pen->ext_pointer = p;
5161 pe4->offset = extended_offset = start;
5162 pe4->sectorbuffer = xzalloc(sector_size);
5163 pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
5164 pe4->ext_pointer = pe4->part_table + 1;
5173 if (partitions > 5 || ptes[4].part_table->sys_ind) {
5174 struct pte *pe = &ptes[partitions];
5176 pe->sectorbuffer = xzalloc(sector_size);
5177 pe->part_table = pt_offset(pe->sectorbuffer, 0);
5178 pe->ext_pointer = pe->part_table + 1;
5183 add_partition(partitions - 1, LINUX_NATIVE);
5189 int i, free_primary = 0;
5191 if (warn_geometry())
5194 #ifdef CONFIG_FEATURE_SUN_LABEL
5195 if (label_sun == current_label_type) {
5196 add_sun_partition(get_partition(0, partitions), LINUX_NATIVE);
5200 #ifdef CONFIG_FEATURE_SGI_LABEL
5201 if (label_sgi == current_label_type) {
5202 sgi_add_partition(get_partition(0, partitions), LINUX_NATIVE);
5206 #ifdef CONFIG_FEATURE_AIX_LABEL
5207 if (label_aix == current_label_type) {
5208 printf(_("\tSorry - this fdisk cannot handle AIX disk labels."
5209 "\n\tIf you want to add DOS-type partitions, create"
5210 "\n\ta new empty DOS partition table first. (Use o.)"
5212 "This will destroy the present disk contents.\n"));
5217 for (i = 0; i < 4; i++)
5218 free_primary += !ptes[i].part_table->sys_ind;
5220 if (!free_primary && partitions >= MAXIMUM_PARTS) {
5221 printf(_("The maximum number of partitions has been created\n"));
5225 if (!free_primary) {
5226 if (extended_offset)
5229 printf(_("You must delete some partition and add "
5230 "an extended partition first\n"));
5232 char c, line[LINE_LENGTH];
5233 snprintf(line, sizeof(line), "%s\n %s\n p primary "
5234 "partition (1-4)\n",
5235 "Command action", (extended_offset ?
5236 "l logical (5 or over)" : "e extended"));
5238 if ((c = read_char(line)) == 'p' || c == 'P') {
5239 i = get_nonexisting_partition(0, 4);
5241 add_partition(i, LINUX_NATIVE);
5244 else if (c == 'l' && extended_offset) {
5248 else if (c == 'e' && !extended_offset) {
5249 i = get_nonexisting_partition(0, 4);
5251 add_partition(i, EXTENDED);
5255 printf(_("Invalid partition number "
5256 "for type `%c'\n"), c);
5266 if (label_dos == current_label_type) {
5267 for (i = 0; i < 3; i++)
5268 if (ptes[i].changed)
5269 ptes[3].changed = 1;
5270 for (i = 3; i < partitions; i++) {
5271 struct pte *pe = &ptes[i];
5274 write_part_table_flag(pe->sectorbuffer);
5275 write_sector(pe->offset, pe->sectorbuffer);
5279 #ifdef CONFIG_FEATURE_SGI_LABEL
5280 else if (label_sgi == current_label_type) {
5281 /* no test on change? the printf below might be mistaken */
5285 #ifdef CONFIG_FEATURE_SUN_LABEL
5286 else if (label_sun == current_label_type) {
5289 for (i = 0; i < 8; i++)
5290 if (ptes[i].changed)
5297 printf(_("The partition table has been altered!\n\n"));
5298 reread_partition_table(1);
5302 reread_partition_table(int leave)
5307 printf(_("Calling ioctl() to re-read partition table.\n"));
5310 if ((i = ioctl(fd, BLKRRPART)) != 0) {
5313 /* some kernel versions (1.2.x) seem to have trouble
5314 rereading the partition table, but if asked to do it
5315 twice, the second time works. - biro@yggdrasil.com */
5318 if ((i = ioctl(fd, BLKRRPART)) != 0)
5323 printf(_("\nWARNING: Re-reading the partition table "
5324 "failed with error %d: %s.\n"
5325 "The kernel still uses the old table.\n"
5326 "The new table will be used "
5327 "at the next reboot.\n"),
5328 error, strerror(error));
5333 _("\nWARNING: If you have created or modified any DOS 6.x\n"
5334 "partitions, please see the fdisk manual page for additional\n"
5340 printf(_("Syncing disks.\n"));
5342 sleep(4); /* for sync() */
5346 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
5348 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
5349 #define MAX_PER_LINE 16
5351 print_buffer(char *pbuffer)
5355 for (i = 0, l = 0; i < sector_size; i++, l++) {
5357 printf("0x%03X:", i);
5358 printf(" %02X", (unsigned char) pbuffer[i]);
5359 if (l == MAX_PER_LINE - 1) {
5375 printf(_("Device: %s\n"), disk_device);
5376 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
5377 if (label_sun == current_label_type || label_sgi == current_label_type)
5378 print_buffer(MBRbuffer);
5381 for (i = 3; i < partitions; i++)
5382 print_buffer(ptes[i].sectorbuffer);
5388 struct pte *pe = &ptes[i];
5389 struct partition *p = pe->part_table;
5392 if (warn_geometry())
5394 if (!p->sys_ind || !get_nr_sects(p) || IS_EXTENDED(p->sys_ind)) {
5395 printf(_("Partition %d has no data area\n"), i + 1);
5398 first = get_partition_start(pe);
5399 new = read_int(first, first, first + get_nr_sects(p) - 1, first,
5400 _("New beginning of data")) - pe->offset;
5402 if (new != get_nr_sects(p)) {
5403 first = get_nr_sects(p) + get_start_sect(p) - new;
5404 set_nr_sects(p, first);
5405 set_start_sect(p, new);
5417 c = tolower(read_char(_("Expert command (m for help): ")));
5420 #ifdef CONFIG_FEATURE_SUN_LABEL
5421 if (label_sun == current_label_type)
5426 if (label_dos == current_label_type)
5427 move_begin(get_partition(0, partitions));
5430 user_cylinders = cylinders =
5431 read_int(1, cylinders, 1048576, 0,
5432 _("Number of cylinders"));
5433 #ifdef CONFIG_FEATURE_SUN_LABEL
5434 if (label_sun == current_label_type)
5435 sun_set_ncyl(cylinders);
5437 if (label_dos == current_label_type)
5444 #ifdef CONFIG_FEATURE_SGI_LABEL
5445 if (label_sgi == current_label_type)
5449 #ifdef CONFIG_FEATURE_SUN_LABEL
5450 if (label_sun == current_label_type)
5454 if (label_dos == current_label_type)
5458 if (label_dos == current_label_type)
5459 fix_partition_table_order();
5462 #ifdef CONFIG_FEATURE_SGI_LABEL
5467 user_heads = heads = read_int(1, heads, 256, 0,
5468 _("Number of heads"));
5472 #ifdef CONFIG_FEATURE_SUN_LABEL
5473 if (label_sun == current_label_type)
5478 #ifdef CONFIG_FEATURE_SUN_LABEL
5479 if (label_sun == current_label_type)
5484 #ifdef CONFIG_FEATURE_SUN_LABEL
5485 if (label_sun == current_label_type)
5498 user_sectors = sectors = read_int(1, sectors, 63, 0,
5499 _("Number of sectors"));
5500 if (dos_compatible_flag) {
5501 sector_offset = sectors;
5502 fprintf(stderr, _("Warning: setting "
5503 "sector offset for DOS "
5512 write_table(); /* does not return */
5515 #ifdef CONFIG_FEATURE_SUN_LABEL
5516 if (label_sun == current_label_type)
5517 sun_set_pcylcount();
5525 #endif /* ADVANCED mode */
5528 is_ide_cdrom_or_tape(const char *device)
5532 struct stat statbuf;
5535 /* No device was given explicitly, and we are trying some
5536 likely things. But opening /dev/hdc may produce errors like
5537 "hdc: tray open or drive not ready"
5538 if it happens to be a CD-ROM drive. It even happens that
5539 the process hangs on the attempt to read a music CD.
5540 So try to be careful. This only works since 2.1.73. */
5542 if (strncmp("/dev/hd", device, 7))
5545 snprintf(buf, sizeof(buf), "/proc/ide/%s/media", device+5);
5546 procf = fopen(buf, "r");
5547 if (procf != NULL && fgets(buf, sizeof(buf), procf))
5548 is_ide = (!strncmp(buf, "cdrom", 5) ||
5549 !strncmp(buf, "tape", 4));
5551 /* Now when this proc file does not exist, skip the
5552 device when it is read-only. */
5553 if (stat(device, &statbuf) == 0)
5554 is_ide = ((statbuf.st_mode & 0222) == 0);
5563 try(const char *device, int user_specified)
5567 disk_device = device;
5568 if (setjmp(listingbuf))
5570 if (!user_specified)
5571 if (is_ide_cdrom_or_tape(device))
5573 if ((fd = open(disk_device, type_open)) >= 0) {
5574 gb = get_boot(try_only);
5575 if (gb > 0) { /* I/O error */
5577 } else if (gb < 0) { /* no DOS signature */
5578 list_disk_geometry();
5579 if (label_aix == current_label_type){
5582 #ifdef CONFIG_FEATURE_OSF_LABEL
5583 if (btrydev(device) < 0)
5586 _("Disk %s doesn't contain a valid "
5587 "partition table\n"), device);
5592 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5593 if (label_sun != current_label_type && partitions > 4){
5594 delete_partition(ext_index);
5599 /* Ignore other errors, since we try IDE
5600 and SCSI hard disks which may not be
5601 installed on the system. */
5602 if (errno == EACCES) {
5603 fprintf(stderr, _("Cannot open %s\n"), device);
5609 /* for fdisk -l: try all things in /proc/partitions
5610 that look like a partition name (do not end in a digit) */
5615 char line[100], ptname[100], devname[120], *s;
5618 procpt = bb_wfopen(PROC_PARTITIONS, "r");
5620 while (fgets(line, sizeof(line), procpt)) {
5621 if (sscanf(line, " %d %d %d %[^\n ]",
5622 &ma, &mi, &sz, ptname) != 4)
5624 for (s = ptname; *s; s++);
5627 sprintf(devname, "/dev/%s", ptname);
5630 #ifdef CONFIG_FEATURE_CLEAN_UP
5635 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5637 unknown_command(int c)
5639 printf(_("%c: unknown command\n"), c);
5643 int fdisk_main(int argc, char **argv)
5646 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5649 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5655 * fdisk -l [-b sectorsize] [-u] device ...
5656 * fdisk -s [partition] ...
5657 * fdisk [-b sectorsize] [-u] device
5659 * Options -C, -H, -S set the geometry.
5662 while ((c = getopt(argc, argv, "b:C:H:lS:uvV"
5663 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5669 /* Ugly: this sector size is really per device,
5670 so cannot be combined with multiple disks,
5671 and te same goes for the C/H/S options.
5673 sector_size = xatoi_u(optarg);
5674 if (sector_size != 512 && sector_size != 1024 &&
5675 sector_size != 2048)
5678 user_set_sector_size = 1;
5681 user_cylinders = xatoi_u(optarg);
5684 user_heads = xatoi_u(optarg);
5685 if (user_heads <= 0 || user_heads >= 256)
5689 user_sectors = xatoi_u(optarg);
5690 if (user_sectors <= 0 || user_sectors >= 64)
5694 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5698 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5704 display_in_cyl_units = 0;
5708 printf("fdisk v" UTIL_LINUX_VERSION "\n");
5715 if (user_set_sector_size && argc-optind != 1)
5716 printf(_("Warning: the -b (set sector size) option should"
5717 " be used with one specified device\n"));
5719 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5723 type_open = O_RDONLY;
5724 if (argc > optind) {
5727 /* avoid gcc warning:
5728 variable `k' might be clobbered by `longjmp' */
5732 for (k = optind; k < argc; k++)
5735 /* we no longer have default device names */
5736 /* but, we can use /proc/partitions instead */
5740 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5744 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5750 type_open = O_RDONLY;
5752 opts = argc - optind;
5756 for (j = optind; j < argc; j++) {
5757 disk_device = argv[j];
5758 if ((fd = open(disk_device, type_open)) < 0)
5759 fdisk_fatal(unable_to_open);
5760 if (ioctl(fd, BLKGETSIZE, &size))
5761 fdisk_fatal(ioctl_error);
5764 printf("%ld\n", size/2);
5766 printf("%s: %ld\n", argv[j], size/2);
5772 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5773 if (argc-optind == 1)
5774 disk_device = argv[optind];
5780 #ifdef CONFIG_FEATURE_OSF_LABEL
5781 if (label_osf == current_label_type) {
5782 /* OSF label, and no DOS label */
5783 printf(_("Detected an OSF/1 disklabel on %s, entering "
5784 "disklabel mode.\n"),
5787 /*Why do we do this? It seems to be counter-intuitive*/
5788 current_label_type = label_dos;
5789 /* If we return we may want to make an empty DOS label? */
5795 c = tolower(read_char(_("Command (m for help): ")));
5798 if (label_dos == current_label_type)
5799 toggle_active(get_partition(1, partitions));
5800 #ifdef CONFIG_FEATURE_SUN_LABEL
5801 else if (label_sun == current_label_type)
5802 toggle_sunflags(get_partition(1, partitions),
5805 #ifdef CONFIG_FEATURE_SGI_LABEL
5806 else if (label_sgi == current_label_type)
5807 sgi_set_bootpartition(
5808 get_partition(1, partitions));
5814 #ifdef CONFIG_FEATURE_SGI_LABEL
5815 if (label_sgi == current_label_type) {
5816 printf(_("\nThe current boot file is: %s\n"),
5817 sgi_get_bootfile());
5818 if (read_chars(_("Please enter the name of the "
5819 "new boot file: ")) == '\n')
5820 printf(_("Boot file unchanged\n"));
5822 sgi_set_bootfile(line_ptr);
5825 #ifdef CONFIG_FEATURE_OSF_LABEL
5830 if (label_dos == current_label_type)
5831 toggle_dos_compatibility_flag();
5832 #ifdef CONFIG_FEATURE_SUN_LABEL
5833 else if (label_sun == current_label_type)
5834 toggle_sunflags(get_partition(1, partitions),
5837 #ifdef CONFIG_FEATURE_SGI_LABEL
5838 else if (label_sgi == current_label_type)
5839 sgi_set_swappartition(
5840 get_partition(1, partitions));
5848 #ifdef CONFIG_FEATURE_SGI_LABEL
5849 /* If sgi_label then don't use get_existing_partition,
5850 let the user select a partition, since
5851 get_existing_partition() only works for Linux-like
5853 if (label_sgi != current_label_type) {
5854 j = get_existing_partition(1, partitions);
5856 j = get_partition(1, partitions);
5859 j = get_existing_partition(1, partitions);
5862 delete_partition(j);
5866 #ifdef CONFIG_FEATURE_SGI_LABEL
5867 if (label_sgi == current_label_type)
5873 list_types(get_sys_types());
5892 #ifdef CONFIG_FEATURE_SUN_LABEL
5906 write_table(); /* does not return */
5908 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
5910 #ifdef CONFIG_FEATURE_SGI_LABEL
5911 if (label_sgi == current_label_type) {
5913 _("\n\tSorry, no experts menu for SGI "
5914 "partition tables available.\n\n"));
5927 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */