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);
1226 while (!isdigit(*line_ptr)); /* FIXME: ?!! */
1227 return atoi(line_ptr);
1231 xbsd_edit_disklabel(void)
1233 struct xbsd_disklabel *d;
1237 #if defined (__alpha__) || defined (__ia64__)
1238 d->d_secsize = (u_long) edit_int((u_long) d->d_secsize ,_("bytes/sector"));
1239 d->d_nsectors = (u_long) edit_int((u_long) d->d_nsectors ,_("sectors/track"));
1240 d->d_ntracks = (u_long) edit_int((u_long) d->d_ntracks ,_("tracks/cylinder"));
1241 d->d_ncylinders = (u_long) edit_int((u_long) d->d_ncylinders ,_("cylinders"));
1244 /* d->d_secpercyl can be != d->d_nsectors * d->d_ntracks */
1246 d->d_secpercyl = (u_long) edit_int((u_long) d->d_nsectors * d->d_ntracks,
1247 _("sectors/cylinder"));
1248 if (d->d_secpercyl <= d->d_nsectors * d->d_ntracks)
1251 printf(_("Must be <= sectors/track * tracks/cylinder (default).\n"));
1253 d->d_rpm = (u_short) edit_int((u_short) d->d_rpm ,_("rpm"));
1254 d->d_interleave = (u_short) edit_int((u_short) d->d_interleave,_("interleave"));
1255 d->d_trackskew = (u_short) edit_int((u_short) d->d_trackskew ,_("trackskew"));
1256 d->d_cylskew = (u_short) edit_int((u_short) d->d_cylskew ,_("cylinderskew"));
1257 d->d_headswitch = (u_long) edit_int((u_long) d->d_headswitch ,_("headswitch"));
1258 d->d_trkseek = (u_long) edit_int((u_long) d->d_trkseek ,_("track-to-track seek"));
1260 d->d_secperunit = d->d_secpercyl * d->d_ncylinders;
1264 xbsd_get_bootstrap (char *path, void *ptr, int size)
1268 if ((fdb = open (path, O_RDONLY)) < 0) {
1272 if (read(fdb, ptr, size) < 0) {
1277 printf(" ... %s\n", path);
1285 printf(_("\nSyncing disks.\n"));
1287 sleep(4); /* What? */
1291 xbsd_write_bootstrap(void)
1293 char *bootdir = BSD_LINUX_BOOTDIR;
1294 char path[MAXPATHLEN];
1296 struct xbsd_disklabel dl;
1300 if (xbsd_dlabel.d_type == BSD_DTYPE_SCSI)
1305 printf(_("Bootstrap: %sboot -> boot%s (%s): "),
1306 dkbasename, dkbasename, dkbasename);
1308 line_ptr[strlen(line_ptr)-1] = '\0';
1309 dkbasename = line_ptr;
1311 snprintf(path, sizeof(path), "%s/%sboot", bootdir, dkbasename);
1312 if (!xbsd_get_bootstrap(path, disklabelbuffer, (int) xbsd_dlabel.d_secsize))
1315 /* We need a backup of the disklabel (xbsd_dlabel might have changed). */
1316 d = &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE];
1317 memmove(&dl, d, sizeof(struct xbsd_disklabel));
1319 /* The disklabel will be overwritten by 0's from bootxx anyway */
1320 memset(d, 0, sizeof(struct xbsd_disklabel));
1322 snprintf(path, sizeof(path), "%s/boot%s", bootdir, dkbasename);
1323 if (!xbsd_get_bootstrap (path, &disklabelbuffer[xbsd_dlabel.d_secsize],
1324 (int) xbsd_dlabel.d_bbsize - xbsd_dlabel.d_secsize))
1327 e = d + sizeof(struct xbsd_disklabel);
1328 for (p = d; p < e; p++)
1330 fprintf(stderr, _("Bootstrap overlaps with disk label!\n"));
1334 memmove(d, &dl, sizeof(struct xbsd_disklabel));
1336 #if defined (__powerpc__) || defined (__hppa__)
1338 #elif defined (__alpha__)
1340 alpha_bootblock_checksum(disklabelbuffer);
1342 sector = get_start_sect(xbsd_part);
1345 if (lseek(fd, sector * SECTOR_SIZE, SEEK_SET) == -1)
1346 fdisk_fatal(unable_to_seek);
1347 if (BSD_BBSIZE != write(fd, disklabelbuffer, BSD_BBSIZE))
1348 fdisk_fatal(unable_to_write);
1350 #if defined (__alpha__)
1351 printf(_("Bootstrap installed on %s.\n"), disk_device);
1353 printf(_("Bootstrap installed on %s.\n"),
1354 partname (disk_device, xbsd_part_index+1, 0));
1361 xbsd_change_fstype(void)
1365 i = xbsd_get_part_index(xbsd_dlabel.d_npartitions);
1366 xbsd_dlabel.d_partitions[i].p_fstype = read_hex(xbsd_fstypes);
1370 xbsd_get_part_index(int max)
1375 snprintf(prompt, sizeof(prompt), _("Partition (a-%c): "), 'a' + max - 1);
1377 l = tolower(read_char(prompt));
1378 while (l < 'a' || l > 'a' + max - 1);
1383 xbsd_check_new_partition(int *i)
1385 /* room for more? various BSD flavours have different maxima */
1386 if (xbsd_dlabel.d_npartitions == BSD_MAXPARTITIONS) {
1389 for (t = 0; t < BSD_MAXPARTITIONS; t++)
1390 if (xbsd_dlabel.d_partitions[t].p_size == 0)
1393 if (t == BSD_MAXPARTITIONS) {
1394 fprintf(stderr, _("The maximum number of partitions "
1395 "has been created\n"));
1400 *i = xbsd_get_part_index (BSD_MAXPARTITIONS);
1402 if (*i >= xbsd_dlabel.d_npartitions)
1403 xbsd_dlabel.d_npartitions = (*i) + 1;
1405 if (xbsd_dlabel.d_partitions[*i].p_size != 0) {
1406 fprintf(stderr, _("This partition already exists.\n"));
1414 xbsd_list_types(void)
1416 list_types(xbsd_fstypes);
1420 xbsd_dkcksum(struct xbsd_disklabel *lp)
1422 u_short *start, *end;
1425 start = (u_short *) lp;
1426 end = (u_short *) &lp->d_partitions[lp->d_npartitions];
1433 xbsd_initlabel(struct partition *p, struct xbsd_disklabel *d)
1435 struct xbsd_partition *pp;
1438 memset(d, 0, sizeof(struct xbsd_disklabel));
1440 d->d_magic = BSD_DISKMAGIC;
1442 if (strncmp(disk_device, "/dev/sd", 7) == 0)
1443 d->d_type = BSD_DTYPE_SCSI;
1445 d->d_type = BSD_DTYPE_ST506;
1447 #if !defined (__alpha__)
1448 d->d_flags = BSD_D_DOSPART;
1452 d->d_secsize = SECTOR_SIZE; /* bytes/sector */
1453 d->d_nsectors = sectors; /* sectors/track */
1454 d->d_ntracks = heads; /* tracks/cylinder (heads) */
1455 d->d_ncylinders = cylinders;
1456 d->d_secpercyl = sectors * heads;/* sectors/cylinder */
1457 if (d->d_secpercyl == 0)
1458 d->d_secpercyl = 1; /* avoid segfaults */
1459 d->d_secperunit = d->d_secpercyl * d->d_ncylinders;
1462 d->d_interleave = 1;
1465 d->d_headswitch = 0;
1468 d->d_magic2 = BSD_DISKMAGIC;
1469 d->d_bbsize = BSD_BBSIZE;
1470 d->d_sbsize = BSD_SBSIZE;
1472 #if !defined (__alpha__)
1473 d->d_npartitions = 4;
1474 pp = &d->d_partitions[2]; /* Partition C should be
1475 the NetBSD partition */
1476 pp->p_offset = get_start_sect(p);
1477 pp->p_size = get_nr_sects(p);
1478 pp->p_fstype = BSD_FS_UNUSED;
1479 pp = &d->d_partitions[3]; /* Partition D should be
1482 pp->p_size = d->d_secperunit;
1483 pp->p_fstype = BSD_FS_UNUSED;
1484 #elif defined (__alpha__)
1485 d->d_npartitions = 3;
1486 pp = &d->d_partitions[2]; /* Partition C should be
1489 pp->p_size = d->d_secperunit;
1490 pp->p_fstype = BSD_FS_UNUSED;
1497 * Read a xbsd_disklabel from sector 0 or from the starting sector of p.
1498 * If it has the right magic, return 1.
1501 xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d)
1505 /* p is used only to get the starting sector */
1506 #if !defined (__alpha__)
1507 sector = (p ? get_start_sect(p) : 0);
1508 #elif defined (__alpha__)
1512 if (lseek(fd, sector * SECTOR_SIZE, SEEK_SET) == -1)
1513 fdisk_fatal(unable_to_seek);
1514 if (BSD_BBSIZE != read(fd, disklabelbuffer, BSD_BBSIZE))
1515 fdisk_fatal(unable_to_read);
1517 memmove(d, &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
1518 sizeof(struct xbsd_disklabel));
1520 if (d->d_magic != BSD_DISKMAGIC || d->d_magic2 != BSD_DISKMAGIC)
1523 for (t = d->d_npartitions; t < BSD_MAXPARTITIONS; t++) {
1524 d->d_partitions[t].p_size = 0;
1525 d->d_partitions[t].p_offset = 0;
1526 d->d_partitions[t].p_fstype = BSD_FS_UNUSED;
1529 if (d->d_npartitions > BSD_MAXPARTITIONS)
1530 fprintf(stderr, _("Warning: too many partitions "
1531 "(%d, maximum is %d).\n"),
1532 d->d_npartitions, BSD_MAXPARTITIONS);
1537 xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d)
1539 unsigned int sector;
1541 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
1542 sector = get_start_sect(p) + BSD_LABELSECTOR;
1544 sector = BSD_LABELSECTOR;
1548 d->d_checksum = xbsd_dkcksum (d);
1550 /* This is necessary if we want to write the bootstrap later,
1551 otherwise we'd write the old disklabel with the bootstrap.
1553 memmove(&disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
1554 d, sizeof(struct xbsd_disklabel));
1556 #if defined (__alpha__) && BSD_LABELSECTOR == 0
1557 alpha_bootblock_checksum (disklabelbuffer);
1558 if (lseek(fd, 0, SEEK_SET) == -1)
1559 fdisk_fatal(unable_to_seek);
1560 if (BSD_BBSIZE != write(fd, disklabelbuffer, BSD_BBSIZE))
1561 fdisk_fatal(unable_to_write);
1563 if (lseek(fd, sector * SECTOR_SIZE + BSD_LABELOFFSET, SEEK_SET) == -1)
1564 fdisk_fatal(unable_to_seek);
1565 if (sizeof(struct xbsd_disklabel) != write(fd, d, sizeof(struct xbsd_disklabel)))
1566 fdisk_fatal(unable_to_write);
1573 #if !defined (__alpha__)
1575 xbsd_translate_fstype(int linux_type)
1577 switch (linux_type) {
1578 case 0x01: /* DOS 12-bit FAT */
1579 case 0x04: /* DOS 16-bit <32M */
1580 case 0x06: /* DOS 16-bit >=32M */
1581 case 0xe1: /* DOS access */
1582 case 0xe3: /* DOS R/O */
1583 case 0xf2: /* DOS secondary */
1584 return BSD_FS_MSDOS;
1585 case 0x07: /* OS/2 HPFS */
1588 return BSD_FS_OTHER;
1593 xbsd_link_part(void)
1596 struct partition *p;
1598 k = get_partition(1, partitions);
1600 if (!xbsd_check_new_partition(&i))
1603 p = get_part_table(k);
1605 xbsd_dlabel.d_partitions[i].p_size = get_nr_sects(p);
1606 xbsd_dlabel.d_partitions[i].p_offset = get_start_sect(p);
1607 xbsd_dlabel.d_partitions[i].p_fstype = xbsd_translate_fstype(p->sys_ind);
1611 #if defined (__alpha__)
1613 #if !defined(__GLIBC__)
1614 typedef unsigned long long uint64_t;
1618 alpha_bootblock_checksum(char *boot)
1623 dp = (uint64_t *)boot;
1625 for (i = 0; i < 63; i++)
1629 #endif /* __alpha__ */
1631 #endif /* OSF_LABEL */
1633 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
1634 static inline unsigned short
1635 __swap16(unsigned short x)
1637 return (((uint16_t)(x) & 0xFF) << 8) | (((uint16_t)(x) & 0xFF00) >> 8);
1640 static inline uint32_t
1641 __swap32(uint32_t x)
1643 return (((x & 0xFF) << 24) |
1644 ((x & 0xFF00) << 8) |
1645 ((x & 0xFF0000) >> 8) |
1646 ((x & 0xFF000000) >> 24));
1650 #ifdef CONFIG_FEATURE_SGI_LABEL
1655 * Copyright (C) Andreas Neuper, Sep 1998.
1656 * This file may be modified and redistributed under
1657 * the terms of the GNU Public License.
1659 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
1660 * Internationalization
1664 static int sgi_other_endian;
1666 static short sgi_volumes = 1;
1669 * only dealing with free blocks here
1676 static freeblocks freelist[17]; /* 16 partitions can produce 17 vacant slots */
1679 setfreelist(int i, unsigned int f, unsigned int l)
1681 freelist[i].first = f;
1682 freelist[i].last = l;
1686 add2freelist(unsigned int f, unsigned int l)
1689 for (i = 0; i < 17 ; i++)
1690 if (freelist[i].last == 0)
1692 setfreelist(i, f, l);
1700 for (i = 0; i < 17 ; i++)
1701 setfreelist(i, 0, 0);
1705 isinfreelist(unsigned int b)
1709 for (i = 0; i < 17 ; i++)
1710 if (freelist[i].first <= b && freelist[i].last >= b)
1711 return freelist[i].last;
1714 /* return last vacant block of this stride (never 0). */
1715 /* the '>=' is not quite correct, but simplifies the code */
1717 * end of free blocks section
1720 static const struct systypes sgi_sys_types[] = {
1721 /* SGI_VOLHDR */ { "\x00" "SGI volhdr" },
1722 /* 0x01 */ { "\x01" "SGI trkrepl" },
1723 /* 0x02 */ { "\x02" "SGI secrepl" },
1724 /* SGI_SWAP */ { "\x03" "SGI raw" },
1725 /* 0x04 */ { "\x04" "SGI bsd" },
1726 /* 0x05 */ { "\x05" "SGI sysv" },
1727 /* ENTIRE_DISK */ { "\x06" "SGI volume" },
1728 /* SGI_EFS */ { "\x07" "SGI efs" },
1729 /* 0x08 */ { "\x08" "SGI lvol" },
1730 /* 0x09 */ { "\x09" "SGI rlvol" },
1731 /* SGI_XFS */ { "\x0a" "SGI xfs" },
1732 /* SGI_XFSLOG */ { "\x0b" "SGI xfslog" },
1733 /* SGI_XLV */ { "\x0c" "SGI xlv" },
1734 /* SGI_XVM */ { "\x0d" "SGI xvm" },
1735 /* LINUX_SWAP */ { "\x82" "Linux swap" },
1736 /* LINUX_NATIVE */ { "\x83" "Linux native" },
1737 /* LINUX_LVM */ { "\x8d" "Linux LVM" },
1738 /* LINUX_RAID */ { "\xfd" "Linux RAID" },
1746 return SGI_SSWAP16(sgilabel->devparam.nsect);
1752 return SGI_SSWAP16(sgilabel->devparam.ntrks);
1756 two_s_complement_32bit_sum(unsigned int* base, int size /* in bytes */)
1759 unsigned int sum = 0;
1761 size /= sizeof(unsigned int);
1762 for (i = 0; i < size; i++)
1763 sum -= SGI_SSWAP32(base[i]);
1768 check_sgi_label(void)
1770 if (sizeof(sgilabel) > 512) {
1772 _("According to MIPS Computer Systems, Inc the "
1773 "Label must not contain more than 512 bytes\n"));
1777 if (sgilabel->magic != SGI_LABEL_MAGIC
1778 && sgilabel->magic != SGI_LABEL_MAGIC_SWAPPED) {
1779 current_label_type = label_dos;
1783 sgi_other_endian = (sgilabel->magic == SGI_LABEL_MAGIC_SWAPPED);
1785 * test for correct checksum
1787 if (two_s_complement_32bit_sum((unsigned int*)sgilabel,
1788 sizeof(*sgilabel))) {
1790 _("Detected sgi disklabel with wrong checksum.\n"));
1793 current_label_type = label_sgi;
1800 sgi_get_start_sector(int i)
1802 return SGI_SSWAP32(sgilabel->partitions[i].start_sector);
1806 sgi_get_num_sectors(int i)
1808 return SGI_SSWAP32(sgilabel->partitions[i].num_sectors);
1812 sgi_get_sysid(int i)
1814 return SGI_SSWAP32(sgilabel->partitions[i].id);
1818 sgi_get_bootpartition(void)
1820 return SGI_SSWAP16(sgilabel->boot_part);
1824 sgi_get_swappartition(void)
1826 return SGI_SSWAP16(sgilabel->swap_part);
1830 sgi_list_table(int xtra)
1833 int kpi = 0; /* kernel partition ID */
1836 printf(_("\nDisk %s (SGI disk label): %d heads, %d sectors\n"
1837 "%d cylinders, %d physical cylinders\n"
1838 "%d extra sects/cyl, interleave %d:1\n"
1840 "Units = %s of %d * 512 bytes\n\n"),
1841 disk_device, heads, sectors, cylinders,
1842 SGI_SSWAP16(sgiparam.pcylcount),
1843 SGI_SSWAP16(sgiparam.sparecyl),
1844 SGI_SSWAP16(sgiparam.ilfact),
1846 str_units(PLURAL), units_per_sector);
1848 printf( _("\nDisk %s (SGI disk label): "
1849 "%d heads, %d sectors, %d cylinders\n"
1850 "Units = %s of %d * 512 bytes\n\n"),
1851 disk_device, heads, sectors, cylinders,
1852 str_units(PLURAL), units_per_sector );
1855 w = strlen(disk_device);
1856 wd = strlen(_("Device"));
1860 printf(_("----- partitions -----\n"
1861 "Pt# %*s Info Start End Sectors Id System\n"),
1862 w + 2, _("Device"));
1863 for (i = 0 ; i < partitions; i++) {
1864 if( sgi_get_num_sectors(i) || debug ) {
1865 uint32_t start = sgi_get_start_sector(i);
1866 uint32_t len = sgi_get_num_sectors(i);
1867 kpi++; /* only count nonempty partitions */
1869 "%2d: %s %4s %9ld %9ld %9ld %2x %s\n",
1870 /* fdisk part number */ i+1,
1871 /* device */ partname(disk_device, kpi, w+3),
1872 /* flags */ (sgi_get_swappartition() == i) ? "swap" :
1873 /* flags */ (sgi_get_bootpartition() == i) ? "boot" : " ",
1874 /* start */ (long) scround(start),
1875 /* end */ (long) scround(start+len)-1,
1876 /* no odd flag on end */(long) len,
1877 /* type id */ sgi_get_sysid(i),
1878 /* type name */ partition_type(sgi_get_sysid(i)));
1881 printf(_("----- Bootinfo -----\nBootfile: %s\n"
1882 "----- Directory Entries -----\n"),
1883 sgilabel->boot_file);
1884 for (i = 0 ; i < sgi_volumes; i++) {
1885 if (sgilabel->directory[i].vol_file_size) {
1886 uint32_t start = SGI_SSWAP32(sgilabel->directory[i].vol_file_start);
1887 uint32_t len = SGI_SSWAP32(sgilabel->directory[i].vol_file_size);
1888 unsigned char *name = sgilabel->directory[i].vol_file_name;
1890 printf(_("%2d: %-10s sector%5u size%8u\n"),
1891 i, (char*)name, (unsigned int) start, (unsigned int) len);
1897 sgi_set_bootpartition(int i)
1899 sgilabel->boot_part = SGI_SSWAP16(((short)i));
1903 sgi_get_lastblock(void)
1905 return heads * sectors * cylinders;
1909 sgi_set_swappartition(int i)
1911 sgilabel->swap_part = SGI_SSWAP16(((short)i));
1915 sgi_check_bootfile(const char* aFile)
1917 if (strlen(aFile) < 3) /* "/a\n" is minimum */ {
1918 printf(_("\nInvalid Bootfile!\n"
1919 "\tThe bootfile must be an absolute non-zero pathname,\n"
1920 "\te.g. \"/unix\" or \"/unix.save\".\n"));
1923 if (strlen(aFile) > 16) {
1924 printf(_("\n\tName of Bootfile too long: "
1925 "16 bytes maximum.\n"));
1928 if (aFile[0] != '/') {
1929 printf(_("\n\tBootfile must have a "
1930 "fully qualified pathname.\n"));
1935 if (strncmp(aFile, (char*)sgilabel->boot_file, 16)) {
1936 printf(_("\n\tBe aware, that the bootfile is not checked for existence.\n\t"
1937 "SGI's default is \"/unix\" and for backup \"/unix.save\".\n"));
1938 /* filename is correct and did change */
1941 return 0; /* filename did not change */
1945 sgi_get_bootfile(void)
1947 return (char*)sgilabel->boot_file;
1951 sgi_set_bootfile(const char* aFile)
1955 if (sgi_check_bootfile(aFile)) {
1957 if ((aFile[i] != '\n') /* in principle caught again by next line */
1958 && (strlen(aFile) > i))
1959 sgilabel->boot_file[i] = aFile[i];
1961 sgilabel->boot_file[i] = 0;
1964 printf(_("\n\tBootfile is changed to \"%s\".\n"), sgilabel->boot_file);
1969 create_sgiinfo(void)
1971 /* I keep SGI's habit to write the sgilabel to the second block */
1972 sgilabel->directory[0].vol_file_start = SGI_SSWAP32(2);
1973 sgilabel->directory[0].vol_file_size = SGI_SSWAP32(sizeof(sgiinfo));
1974 strcpy((char*)sgilabel->directory[0].vol_file_name, "sgilabel");
1977 static sgiinfo *fill_sgiinfo(void);
1980 sgi_write_table(void)
1983 sgilabel->csum = SGI_SSWAP32(two_s_complement_32bit_sum(
1984 (unsigned int*)sgilabel, sizeof(*sgilabel)));
1985 assert(two_s_complement_32bit_sum(
1986 (unsigned int*)sgilabel, sizeof(*sgilabel)) == 0);
1988 if (lseek(fd, 0, SEEK_SET) < 0)
1989 fdisk_fatal(unable_to_seek);
1990 if (write(fd, sgilabel, SECTOR_SIZE) != SECTOR_SIZE)
1991 fdisk_fatal(unable_to_write);
1992 if (!strncmp((char*)sgilabel->directory[0].vol_file_name, "sgilabel", 8)) {
1994 * keep this habit of first writing the "sgilabel".
1995 * I never tested whether it works without (AN 981002).
1997 sgiinfo *info = fill_sgiinfo();
1998 int infostartblock = SGI_SSWAP32(sgilabel->directory[0].vol_file_start);
1999 if (lseek(fd, infostartblock*SECTOR_SIZE, SEEK_SET) < 0)
2000 fdisk_fatal(unable_to_seek);
2001 if (write(fd, info, SECTOR_SIZE) != SECTOR_SIZE)
2002 fdisk_fatal(unable_to_write);
2008 compare_start(int *x, int *y)
2011 * sort according to start sectors
2012 * and prefers largest partition:
2013 * entry zero is entire disk entry
2015 unsigned int i = *x;
2016 unsigned int j = *y;
2017 unsigned int a = sgi_get_start_sector(i);
2018 unsigned int b = sgi_get_start_sector(j);
2019 unsigned int c = sgi_get_num_sectors(i);
2020 unsigned int d = sgi_get_num_sectors(j);
2023 return (d > c) ? 1 : (d == c) ? 0 : -1;
2024 return (a > b) ? 1 : -1;
2029 verify_sgi(int verbose)
2031 int Index[16]; /* list of valid partitions */
2032 int sortcount = 0; /* number of used partitions, i.e. non-zero lengths */
2033 int entire = 0, i = 0;
2034 unsigned int start = 0;
2035 long long gap = 0; /* count unused blocks */
2036 unsigned int lastblock = sgi_get_lastblock();
2039 for (i = 0; i < 16; i++) {
2040 if (sgi_get_num_sectors(i) != 0) {
2041 Index[sortcount++] = i;
2042 if (sgi_get_sysid(i) == ENTIRE_DISK) {
2043 if (entire++ == 1) {
2045 printf(_("More than one entire disk entry present.\n"));
2050 if (sortcount == 0) {
2052 printf(_("No partitions defined\n"));
2053 return (lastblock > 0) ? 1 : (lastblock == 0) ? 0 : -1;
2055 qsort(Index, sortcount, sizeof(Index[0]), (void*)compare_start);
2056 if (sgi_get_sysid(Index[0]) == ENTIRE_DISK) {
2057 if ((Index[0] != 10) && verbose)
2058 printf(_("IRIX likes when Partition 11 covers the entire disk.\n"));
2059 if ((sgi_get_start_sector(Index[0]) != 0) && verbose)
2060 printf(_("The entire disk partition should start "
2062 "not at diskblock %d.\n"),
2063 sgi_get_start_sector(Index[0]));
2064 if (debug) /* I do not understand how some disks fulfil it */
2065 if ((sgi_get_num_sectors(Index[0]) != lastblock) && verbose)
2066 printf(_("The entire disk partition is only %d diskblock large,\n"
2067 "but the disk is %d diskblocks long.\n"),
2068 sgi_get_num_sectors(Index[0]), lastblock);
2069 lastblock = sgi_get_num_sectors(Index[0]);
2072 printf(_("One Partition (#11) should cover the entire disk.\n"));
2074 printf("sysid=%d\tpartition=%d\n",
2075 sgi_get_sysid(Index[0]), Index[0]+1);
2077 for (i = 1, start = 0; i < sortcount; i++) {
2078 int cylsize = sgi_get_nsect() * sgi_get_ntrks();
2080 if ((sgi_get_start_sector(Index[i]) % cylsize) != 0) {
2081 if (debug) /* I do not understand how some disks fulfil it */
2083 printf(_("Partition %d does not start on cylinder boundary.\n"),
2086 if (sgi_get_num_sectors(Index[i]) % cylsize != 0) {
2087 if (debug) /* I do not understand how some disks fulfil it */
2089 printf(_("Partition %d does not end on cylinder boundary.\n"),
2092 /* We cannot handle several "entire disk" entries. */
2093 if (sgi_get_sysid(Index[i]) == ENTIRE_DISK) continue;
2094 if (start > sgi_get_start_sector(Index[i])) {
2096 printf(_("The Partition %d and %d overlap by %d sectors.\n"),
2097 Index[i-1]+1, Index[i]+1,
2098 start - sgi_get_start_sector(Index[i]));
2099 if (gap > 0) gap = -gap;
2100 if (gap == 0) gap = -1;
2102 if (start < sgi_get_start_sector(Index[i])) {
2104 printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"),
2105 sgi_get_start_sector(Index[i]) - start,
2106 start, sgi_get_start_sector(Index[i])-1);
2107 gap += sgi_get_start_sector(Index[i]) - start;
2108 add2freelist(start, sgi_get_start_sector(Index[i]));
2110 start = sgi_get_start_sector(Index[i])
2111 + sgi_get_num_sectors(Index[i]);
2114 printf("%2d:%12d\t%12d\t%12d\n", Index[i],
2115 sgi_get_start_sector(Index[i]),
2116 sgi_get_num_sectors(Index[i]),
2117 sgi_get_sysid(Index[i]));
2120 if (start < lastblock) {
2122 printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"),
2123 lastblock - start, start, lastblock-1);
2124 gap += lastblock - start;
2125 add2freelist(start, lastblock);
2128 * Done with arithmetics
2129 * Go for details now
2132 if (!sgi_get_num_sectors(sgi_get_bootpartition())) {
2133 printf(_("\nThe boot partition does not exist.\n"));
2135 if (!sgi_get_num_sectors(sgi_get_swappartition())) {
2136 printf(_("\nThe swap partition does not exist.\n"));
2138 if ((sgi_get_sysid(sgi_get_swappartition()) != SGI_SWAP)
2139 && (sgi_get_sysid(sgi_get_swappartition()) != LINUX_SWAP))
2140 printf(_("\nThe swap partition has no swap type.\n"));
2142 if (sgi_check_bootfile("/unix"))
2143 printf(_("\tYou have chosen an unusual boot file name.\n"));
2145 return (gap > 0) ? 1 : (gap == 0) ? 0 : -1;
2152 * returned value is:
2153 * = 0 : disk is properly filled to the rim
2154 * < 0 : there is an overlap
2155 * > 0 : there is still some vacant space
2157 return verify_sgi(0);
2161 sgi_change_sysid(int i, int sys)
2163 if( sgi_get_num_sectors(i) == 0 ) { /* caught already before, ... */
2164 printf(_("Sorry You may change the Tag of non-empty partitions.\n"));
2167 if (((sys != ENTIRE_DISK ) && (sys != SGI_VOLHDR))
2168 && (sgi_get_start_sector(i) < 1) ) {
2170 _("It is highly recommended that the partition at offset 0\n"
2171 "is of type \"SGI volhdr\", the IRIX system will rely on it to\n"
2172 "retrieve from its directory standalone tools like sash and fx.\n"
2173 "Only the \"SGI volume\" entire disk section may violate this.\n"
2174 "Type YES if you are sure about tagging this partition differently.\n"));
2175 if (strcmp(line_ptr, _("YES\n")))
2178 sgilabel->partitions[i].id = SGI_SSWAP32(sys);
2181 /* returns partition index of first entry marked as entire disk */
2187 for (i = 0; i < 16; i++)
2188 if (sgi_get_sysid(i) == SGI_VOLUME)
2194 sgi_set_partition(int i, unsigned int start, unsigned int length, int sys)
2196 sgilabel->partitions[i].id = SGI_SSWAP32(sys);
2197 sgilabel->partitions[i].num_sectors = SGI_SSWAP32(length);
2198 sgilabel->partitions[i].start_sector = SGI_SSWAP32(start);
2200 if (sgi_gaps() < 0) /* rebuild freelist */
2201 printf(_("Do You know, You got a partition overlap on the disk?\n"));
2205 sgi_set_entire(void)
2209 for (n = 10; n < partitions; n++) {
2210 if(!sgi_get_num_sectors(n) ) {
2211 sgi_set_partition(n, 0, sgi_get_lastblock(), SGI_VOLUME);
2218 sgi_set_volhdr(void)
2222 for (n = 8; n < partitions; n++) {
2223 if (!sgi_get_num_sectors(n)) {
2225 * 5 cylinders is an arbitrary value I like
2226 * IRIX 5.3 stored files in the volume header
2227 * (like sash, symmon, fx, ide) with ca. 3200
2230 if (heads * sectors * 5 < sgi_get_lastblock())
2231 sgi_set_partition(n, 0, heads * sectors * 5, SGI_VOLHDR);
2238 sgi_delete_partition(int i)
2240 sgi_set_partition(i, 0, 0, 0);
2244 sgi_add_partition(int n, int sys)
2247 unsigned int first = 0, last = 0;
2251 } else if (n == 8) {
2254 if(sgi_get_num_sectors(n)) {
2255 printf(_("Partition %d is already defined. Delete "
2256 "it before re-adding it.\n"), n + 1);
2259 if ((sgi_entire() == -1) && (sys != SGI_VOLUME)) {
2260 printf(_("Attempting to generate entire disk entry automatically.\n"));
2264 if ((sgi_gaps() == 0) && (sys != SGI_VOLUME)) {
2265 printf(_("The entire disk is already covered with partitions.\n"));
2268 if (sgi_gaps() < 0) {
2269 printf(_("You got a partition overlap on the disk. Fix it first!\n"));
2272 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
2274 if(sys == SGI_VOLUME) {
2275 last = sgi_get_lastblock();
2276 first = read_int(0, 0, last-1, 0, mesg);
2278 printf(_("It is highly recommended that eleventh partition\n"
2279 "covers the entire disk and is of type `SGI volume'\n"));
2282 first = freelist[0].first;
2283 last = freelist[0].last;
2284 first = read_int(scround(first), scround(first), scround(last)-1,
2287 if (display_in_cyl_units)
2288 first *= units_per_sector;
2290 first = first; /* align to cylinder if you know how ... */
2292 last = isinfreelist(first);
2294 printf(_("You will get a partition overlap on the disk. "
2295 "Fix it first!\n"));
2299 snprintf(mesg, sizeof(mesg), _(" Last %s"), str_units(SINGULAR));
2300 last = read_int(scround(first), scround(last)-1, scround(last)-1,
2301 scround(first), mesg)+1;
2302 if (display_in_cyl_units)
2303 last *= units_per_sector;
2305 last = last; /* align to cylinder if You know how ... */
2306 if ( (sys == SGI_VOLUME) && (first != 0 || last != sgi_get_lastblock() ) )
2307 printf(_("It is highly recommended that eleventh partition\n"
2308 "covers the entire disk and is of type `SGI volume'\n"));
2309 sgi_set_partition(n, first, last-first, sys);
2312 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
2314 create_sgilabel(void)
2316 struct hd_geometry geometry;
2323 long longsectors; /* the number of sectors on the device */
2324 int res; /* the result from the ioctl */
2325 int sec_fac; /* the sector factor */
2327 sec_fac = sector_size / 512; /* determine the sector factor */
2330 _("Building a new SGI disklabel. Changes will remain in memory only,\n"
2331 "until you decide to write them. After that, of course, the previous\n"
2332 "content will be unrecoverably lost.\n\n"));
2334 sgi_other_endian = (BB_LITTLE_ENDIAN);
2335 res = ioctl(fd, BLKGETSIZE, &longsectors);
2336 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
2337 heads = geometry.heads;
2338 sectors = geometry.sectors;
2340 /* the get device size ioctl was successful */
2341 cylinders = longsectors / (heads * sectors);
2342 cylinders /= sec_fac;
2344 /* otherwise print error and use truncated version */
2345 cylinders = geometry.cylinders;
2347 _("Warning: BLKGETSIZE ioctl failed on %s. "
2348 "Using geometry cylinder value of %d.\n"
2349 "This value may be truncated for devices"
2350 " > 33.8 GB.\n"), disk_device, cylinders);
2353 for (i = 0; i < 4; i++) {
2355 if (valid_part_table_flag(MBRbuffer)) {
2356 if(get_part_table(i)->sys_ind) {
2357 old[i].sysid = get_part_table(i)->sys_ind;
2358 old[i].start = get_start_sect(get_part_table(i));
2359 old[i].nsect = get_nr_sects(get_part_table(i));
2360 printf(_("Trying to keep parameters of partition %d.\n"), i);
2362 printf(_("ID=%02x\tSTART=%d\tLENGTH=%d\n"),
2363 old[i].sysid, old[i].start, old[i].nsect);
2368 memset(MBRbuffer, 0, sizeof(MBRbuffer));
2369 sgilabel->magic = SGI_SSWAP32(SGI_LABEL_MAGIC);
2370 sgilabel->boot_part = SGI_SSWAP16(0);
2371 sgilabel->swap_part = SGI_SSWAP16(1);
2373 /* sizeof(sgilabel->boot_file) = 16 > 6 */
2374 memset(sgilabel->boot_file, 0, 16);
2375 strcpy((char*)sgilabel->boot_file, "/unix");
2377 sgilabel->devparam.skew = (0);
2378 sgilabel->devparam.gap1 = (0);
2379 sgilabel->devparam.gap2 = (0);
2380 sgilabel->devparam.sparecyl = (0);
2381 sgilabel->devparam.pcylcount = SGI_SSWAP16(geometry.cylinders);
2382 sgilabel->devparam.head_vol0 = SGI_SSWAP16(0);
2383 sgilabel->devparam.ntrks = SGI_SSWAP16(geometry.heads);
2384 /* tracks/cylinder (heads) */
2385 sgilabel->devparam.cmd_tag_queue_depth = (0);
2386 sgilabel->devparam.unused0 = (0);
2387 sgilabel->devparam.unused1 = SGI_SSWAP16(0);
2388 sgilabel->devparam.nsect = SGI_SSWAP16(geometry.sectors);
2390 sgilabel->devparam.bytes = SGI_SSWAP16(512);
2391 sgilabel->devparam.ilfact = SGI_SSWAP16(1);
2392 sgilabel->devparam.flags = SGI_SSWAP32(TRACK_FWD|
2393 IGNORE_ERRORS|RESEEK);
2394 sgilabel->devparam.datarate = SGI_SSWAP32(0);
2395 sgilabel->devparam.retries_on_error = SGI_SSWAP32(1);
2396 sgilabel->devparam.ms_per_word = SGI_SSWAP32(0);
2397 sgilabel->devparam.xylogics_gap1 = SGI_SSWAP16(0);
2398 sgilabel->devparam.xylogics_syncdelay = SGI_SSWAP16(0);
2399 sgilabel->devparam.xylogics_readdelay = SGI_SSWAP16(0);
2400 sgilabel->devparam.xylogics_gap2 = SGI_SSWAP16(0);
2401 sgilabel->devparam.xylogics_readgate = SGI_SSWAP16(0);
2402 sgilabel->devparam.xylogics_writecont = SGI_SSWAP16(0);
2403 memset( &(sgilabel->directory), 0, sizeof(struct volume_directory)*15 );
2404 memset( &(sgilabel->partitions), 0, sizeof(struct sgi_partition)*16 );
2405 current_label_type = label_sgi;
2410 for (i = 0; i < 4; i++) {
2412 sgi_set_partition(i, old[i].start, old[i].nsect, old[i].sysid);
2420 /* do nothing in the beginning */
2422 #endif /* CONFIG_FEATURE_FDISK_ADVANCED */
2424 /* _____________________________________________________________
2430 sgiinfo *info = calloc(1, sizeof(sgiinfo));
2432 info->magic = SGI_SSWAP32(SGI_INFO_MAGIC);
2433 info->b1 = SGI_SSWAP32(-1);
2434 info->b2 = SGI_SSWAP16(-1);
2435 info->b3 = SGI_SSWAP16(1);
2436 /* You may want to replace this string !!!!!!! */
2437 strcpy( (char*)info->scsi_string, "IBM OEM 0662S12 3 30" );
2438 strcpy( (char*)info->serial, "0000" );
2439 info->check1816 = SGI_SSWAP16(18*256 +16 );
2440 strcpy( (char*)info->installer, "Sfx version 5.3, Oct 18, 1994" );
2443 #endif /* SGI_LABEL */
2446 #ifdef CONFIG_FEATURE_SUN_LABEL
2450 * I think this is mostly, or entirely, due to
2451 * Jakub Jelinek (jj@sunsite.mff.cuni.cz), July 1996
2453 * Merged with fdisk for other architectures, aeb, June 1998.
2455 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
2456 * Internationalization
2460 static int sun_other_endian;
2461 static int scsi_disk;
2465 #define IDE0_MAJOR 3
2468 #define IDE1_MAJOR 22
2472 guess_device_type(void)
2474 struct stat bootstat;
2476 if (fstat(fd, &bootstat) < 0) {
2479 } else if (S_ISBLK(bootstat.st_mode)
2480 && (major(bootstat.st_rdev) == IDE0_MAJOR ||
2481 major(bootstat.st_rdev) == IDE1_MAJOR)) {
2484 } else if (S_ISBLK(bootstat.st_mode)
2485 && major(bootstat.st_rdev) == FLOPPY_MAJOR) {
2494 static const struct systypes sun_sys_types[] = {
2495 { "\x00" "Empty" }, /* 0 */
2496 { "\x01" "Boot" }, /* 1 */
2497 { "\x02" "SunOS root" }, /* 2 */
2498 { "\x03" "SunOS swap" }, /* SUNOS_SWAP */
2499 { "\x04" "SunOS usr" }, /* 4 */
2500 { "\x05" "Whole disk" }, /* WHOLE_DISK */
2501 { "\x06" "SunOS stand" }, /* 6 */
2502 { "\x07" "SunOS var" }, /* 7 */
2503 { "\x08" "SunOS home" }, /* 8 */
2504 { "\x82" "Linux swap" }, /* LINUX_SWAP */
2505 { "\x83" "Linux native" }, /* LINUX_NATIVE */
2506 { "\x8e" "Linux LVM" }, /* 0x8e */
2507 /* New (2.2.x) raid partition with autodetect using persistent superblock */
2508 { "\xfd" "Linux raid autodetect" }, /* 0xfd */
2514 set_sun_partition(int i, uint start, uint stop, int sysid)
2516 sunlabel->infos[i].id = sysid;
2517 sunlabel->partitions[i].start_cylinder =
2518 SUN_SSWAP32(start / (heads * sectors));
2519 sunlabel->partitions[i].num_sectors =
2520 SUN_SSWAP32(stop - start);
2525 check_sun_label(void)
2527 unsigned short *ush;
2530 if (sunlabel->magic != SUN_LABEL_MAGIC
2531 && sunlabel->magic != SUN_LABEL_MAGIC_SWAPPED) {
2532 current_label_type = label_dos;
2533 sun_other_endian = 0;
2536 sun_other_endian = (sunlabel->magic == SUN_LABEL_MAGIC_SWAPPED);
2537 ush = ((unsigned short *) (sunlabel + 1)) - 1;
2538 for (csum = 0; ush >= (unsigned short *)sunlabel;) csum ^= *ush--;
2540 fprintf(stderr,_("Detected sun disklabel with wrong checksum.\n"
2541 "Probably you'll have to set all the values,\n"
2542 "e.g. heads, sectors, cylinders and partitions\n"
2543 "or force a fresh label (s command in main menu)\n"));
2545 heads = SUN_SSWAP16(sunlabel->ntrks);
2546 cylinders = SUN_SSWAP16(sunlabel->ncyl);
2547 sectors = SUN_SSWAP16(sunlabel->nsect);
2550 current_label_type = label_sun;
2555 static const struct sun_predefined_drives {
2558 unsigned short sparecyl;
2559 unsigned short ncyl;
2560 unsigned short nacyl;
2561 unsigned short pcylcount;
2562 unsigned short ntrks;
2563 unsigned short nsect;
2564 unsigned short rspeed;
2566 { "Quantum","ProDrive 80S",1,832,2,834,6,34,3662},
2567 { "Quantum","ProDrive 105S",1,974,2,1019,6,35,3662},
2568 { "CDC","Wren IV 94171-344",3,1545,2,1549,9,46,3600},
2569 { "IBM","DPES-31080",0,4901,2,4903,4,108,5400},
2570 { "IBM","DORS-32160",0,1015,2,1017,67,62,5400},
2571 { "IBM","DNES-318350",0,11199,2,11474,10,320,7200},
2572 { "SEAGATE","ST34371",0,3880,2,3882,16,135,7228},
2573 { "","SUN0104",1,974,2,1019,6,35,3662},
2574 { "","SUN0207",4,1254,2,1272,9,36,3600},
2575 { "","SUN0327",3,1545,2,1549,9,46,3600},
2576 { "","SUN0340",0,1538,2,1544,6,72,4200},
2577 { "","SUN0424",2,1151,2,2500,9,80,4400},
2578 { "","SUN0535",0,1866,2,2500,7,80,5400},
2579 { "","SUN0669",5,1614,2,1632,15,54,3600},
2580 { "","SUN1.0G",5,1703,2,1931,15,80,3597},
2581 { "","SUN1.05",0,2036,2,2038,14,72,5400},
2582 { "","SUN1.3G",6,1965,2,3500,17,80,5400},
2583 { "","SUN2.1G",0,2733,2,3500,19,80,5400},
2584 { "IOMEGA","Jaz",0,1019,2,1021,64,32,5394},
2587 static const struct sun_predefined_drives *
2588 sun_autoconfigure_scsi(void)
2590 const struct sun_predefined_drives *p = NULL;
2592 #ifdef SCSI_IOCTL_GET_IDLUN
2602 if (!ioctl(fd, SCSI_IOCTL_GET_IDLUN, &id)) {
2604 "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n",
2605 /* This is very wrong (works only if you have one HBA),
2606 but I haven't found a way how to get hostno
2607 from the current kernel */
2613 pfd = fopen("/proc/scsi/scsi","r");
2615 while (fgets(buffer2, 2048, pfd)) {
2616 if (!strcmp(buffer, buffer2)) {
2617 if (fgets(buffer2,2048,pfd)) {
2618 q = strstr(buffer2,"Vendor: ");
2623 *q++ = 0; /* truncate vendor name */
2624 q = strstr(q,"Model: ");
2629 q = strstr(q," Rev: ");
2632 for (i = 0; i < SIZE(sun_drives); i++) {
2633 if (*sun_drives[i].vendor && strcasecmp(sun_drives[i].vendor, vendor))
2635 if (!strstr(model, sun_drives[i].model))
2637 printf(_("Autoconfigure found a %s%s%s\n"),sun_drives[i].vendor,(*sun_drives[i].vendor) ? " " : "",sun_drives[i].model);
2656 create_sunlabel(void)
2658 struct hd_geometry geometry;
2662 const struct sun_predefined_drives *p = NULL;
2665 _("Building a new sun disklabel. Changes will remain in memory only,\n"
2666 "until you decide to write them. After that, of course, the previous\n"
2667 "content won't be recoverable.\n\n"));
2668 sun_other_endian = BB_LITTLE_ENDIAN;
2669 memset(MBRbuffer, 0, sizeof(MBRbuffer));
2670 sunlabel->magic = SUN_SSWAP16(SUN_LABEL_MAGIC);
2672 puts(_("Drive type\n"
2673 " ? auto configure\n"
2674 " 0 custom (with hardware detected defaults)"));
2675 for (i = 0; i < SIZE(sun_drives); i++) {
2676 printf(" %c %s%s%s\n",
2677 i + 'a', sun_drives[i].vendor,
2678 (*sun_drives[i].vendor) ? " " : "",
2679 sun_drives[i].model);
2682 c = read_char(_("Select type (? for auto, 0 for custom): "));
2683 if (c >= 'a' && c < 'a' + SIZE(sun_drives)) {
2684 p = sun_drives + c - 'a';
2686 } else if (c >= 'A' && c < 'A' + SIZE(sun_drives)) {
2687 p = sun_drives + c - 'A';
2689 } else if (c == '0') {
2691 } else if (c == '?' && scsi_disk) {
2692 p = sun_autoconfigure_scsi();
2694 printf(_("Autoconfigure failed.\n"));
2701 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
2702 heads = geometry.heads;
2703 sectors = geometry.sectors;
2704 cylinders = geometry.cylinders;
2711 sunlabel->nacyl = 0;
2712 sunlabel->pcylcount = SUN_SSWAP16(cylinders);
2713 sunlabel->rspeed = SUN_SSWAP16(300);
2714 sunlabel->ilfact = SUN_SSWAP16(1);
2715 sunlabel->sparecyl = 0;
2717 heads = read_int(1,heads,1024,0,_("Heads"));
2718 sectors = read_int(1,sectors,1024,0,_("Sectors/track"));
2720 cylinders = read_int(1,cylinders-2,65535,0,_("Cylinders"));
2722 cylinders = read_int(1,0,65535,0,_("Cylinders"));
2723 sunlabel->nacyl = SUN_SSWAP16(read_int(0,2,65535,0, _("Alternate cylinders")));
2724 sunlabel->pcylcount = SUN_SSWAP16(read_int(0,cylinders+SUN_SSWAP16(sunlabel->nacyl), 65535,0, _("Physical cylinders")));
2725 sunlabel->rspeed = SUN_SSWAP16(read_int(1,5400,100000,0, _("Rotation speed (rpm)")));
2726 sunlabel->ilfact = SUN_SSWAP16(read_int(1,1,32,0, _("Interleave factor")));
2727 sunlabel->sparecyl = SUN_SSWAP16(read_int(0,0,sectors,0, _("Extra sectors per cylinder")));
2730 sunlabel->sparecyl = SUN_SSWAP16(p->sparecyl);
2731 sunlabel->ncyl = SUN_SSWAP16(p->ncyl);
2732 sunlabel->nacyl = SUN_SSWAP16(p->nacyl);
2733 sunlabel->pcylcount = SUN_SSWAP16(p->pcylcount);
2734 sunlabel->ntrks = SUN_SSWAP16(p->ntrks);
2735 sunlabel->nsect = SUN_SSWAP16(p->nsect);
2736 sunlabel->rspeed = SUN_SSWAP16(p->rspeed);
2737 sunlabel->ilfact = SUN_SSWAP16(1);
2738 cylinders = p->ncyl;
2741 puts(_("You may change all the disk params from the x menu"));
2744 snprintf((char *)(sunlabel->info), sizeof(sunlabel->info),
2745 "%s%s%s cyl %d alt %d hd %d sec %d",
2746 p ? p->vendor : "", (p && *p->vendor) ? " " : "",
2747 p ? p->model : (floppy ? _("3,5\" floppy") : _("Linux custom")),
2748 cylinders, SUN_SSWAP16(sunlabel->nacyl), heads, sectors);
2750 sunlabel->ntrks = SUN_SSWAP16(heads);
2751 sunlabel->nsect = SUN_SSWAP16(sectors);
2752 sunlabel->ncyl = SUN_SSWAP16(cylinders);
2754 set_sun_partition(0, 0, cylinders * heads * sectors, LINUX_NATIVE);
2756 if (cylinders * heads * sectors >= 150 * 2048) {
2757 ndiv = cylinders - (50 * 2048 / (heads * sectors)); /* 50M swap */
2759 ndiv = cylinders * 2 / 3;
2760 set_sun_partition(0, 0, ndiv * heads * sectors, LINUX_NATIVE);
2761 set_sun_partition(1, ndiv * heads * sectors, cylinders * heads * sectors, LINUX_SWAP);
2762 sunlabel->infos[1].flags |= 0x01; /* Not mountable */
2764 set_sun_partition(2, 0, cylinders * heads * sectors, WHOLE_DISK);
2766 unsigned short *ush = (unsigned short *)sunlabel;
2767 unsigned short csum = 0;
2768 while (ush < (unsigned short *)(&sunlabel->csum))
2770 sunlabel->csum = csum;
2773 set_all_unchanged();
2775 get_boot(create_empty_sun);
2779 toggle_sunflags(int i, unsigned char mask)
2781 if (sunlabel->infos[i].flags & mask)
2782 sunlabel->infos[i].flags &= ~mask;
2784 sunlabel->infos[i].flags |= mask;
2789 fetch_sun(uint *starts, uint *lens, uint *start, uint *stop)
2791 int i, continuous = 1;
2794 *stop = cylinders * heads * sectors;
2795 for (i = 0; i < partitions; i++) {
2796 if (sunlabel->partitions[i].num_sectors
2797 && sunlabel->infos[i].id
2798 && sunlabel->infos[i].id != WHOLE_DISK) {
2799 starts[i] = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
2800 lens[i] = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
2802 if (starts[i] == *start)
2804 else if (starts[i] + lens[i] >= *stop)
2808 /* There will be probably more gaps
2809 than one, so lets check afterwards */
2818 static uint *verify_sun_starts;
2821 verify_sun_cmp(int *a, int *b)
2823 if (*a == -1) return 1;
2824 if (*b == -1) return -1;
2825 if (verify_sun_starts[*a] > verify_sun_starts[*b]) return 1;
2832 uint starts[8], lens[8], start, stop;
2833 int i,j,k,starto,endo;
2836 verify_sun_starts = starts;
2837 fetch_sun(starts,lens,&start,&stop);
2838 for (k = 0; k < 7; k++) {
2839 for (i = 0; i < 8; i++) {
2840 if (k && (lens[i] % (heads * sectors))) {
2841 printf(_("Partition %d doesn't end on cylinder boundary\n"), i+1);
2844 for (j = 0; j < i; j++)
2846 if (starts[j] == starts[i]+lens[i]) {
2847 starts[j] = starts[i]; lens[j] += lens[i];
2849 } else if (starts[i] == starts[j]+lens[j]){
2853 if (starts[i] < starts[j]+lens[j]
2854 && starts[j] < starts[i]+lens[i]) {
2856 if (starts[j] > starto)
2858 endo = starts[i]+lens[i];
2859 if (starts[j]+lens[j] < endo)
2860 endo = starts[j]+lens[j];
2861 printf(_("Partition %d overlaps with others in "
2862 "sectors %d-%d\n"), i+1, starto, endo);
2869 for (i = 0; i < 8; i++) {
2875 qsort(array,SIZE(array),sizeof(array[0]),
2876 (int (*)(const void *,const void *)) verify_sun_cmp);
2877 if (array[0] == -1) {
2878 printf(_("No partitions defined\n"));
2881 stop = cylinders * heads * sectors;
2882 if (starts[array[0]])
2883 printf(_("Unused gap - sectors 0-%d\n"),starts[array[0]]);
2884 for (i = 0; i < 7 && array[i+1] != -1; i++) {
2885 printf(_("Unused gap - sectors %d-%d\n"),starts[array[i]]+lens[array[i]],starts[array[i+1]]);
2887 start = starts[array[i]] + lens[array[i]];
2889 printf(_("Unused gap - sectors %d-%d\n"),start,stop);
2893 add_sun_partition(int n, int sys)
2895 uint start, stop, stop2;
2896 uint starts[8], lens[8];
2902 if (sunlabel->partitions[n].num_sectors && sunlabel->infos[n].id) {
2903 printf(_("Partition %d is already defined. Delete "
2904 "it before re-adding it.\n"), n + 1);
2908 fetch_sun(starts,lens,&start,&stop);
2909 if (stop <= start) {
2913 printf(_("Other partitions already cover the whole disk.\nDelete "
2914 "some/shrink them before retry.\n"));
2918 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
2921 first = read_int(0, 0, 0, 0, mesg);
2923 first = read_int(scround(start), scround(stop)+1,
2924 scround(stop), 0, mesg);
2925 if (display_in_cyl_units)
2926 first *= units_per_sector;
2928 /* Starting sector has to be properly aligned */
2929 first = (first + heads * sectors - 1) / (heads * sectors);
2930 if (n == 2 && first != 0)
2932 It is highly recommended that the third partition covers the whole disk\n\
2933 and is of type `Whole disk'\n");
2934 /* ewt asks to add: "don't start a partition at cyl 0"
2935 However, edmundo@rano.demon.co.uk writes:
2936 "In addition to having a Sun partition table, to be able to
2937 boot from the disc, the first partition, /dev/sdX1, must
2938 start at cylinder 0. This means that /dev/sdX1 contains
2939 the partition table and the boot block, as these are the
2940 first two sectors of the disc. Therefore you must be
2941 careful what you use /dev/sdX1 for. In particular, you must
2942 not use a partition starting at cylinder 0 for Linux swap,
2943 as that would overwrite the partition table and the boot
2944 block. You may, however, use such a partition for a UFS
2945 or EXT2 file system, as these file systems leave the first
2946 1024 bytes undisturbed. */
2947 /* On the other hand, one should not use partitions
2948 starting at block 0 in an md, or the label will
2950 for (i = 0; i < partitions; i++)
2951 if (lens[i] && starts[i] <= first && starts[i] + lens[i] > first)
2953 if (i < partitions && !whole_disk) {
2954 if (n == 2 && !first) {
2958 printf(_("Sector %d is already allocated\n"), first);
2962 stop = cylinders * heads * sectors;
2964 for (i = 0; i < partitions; i++) {
2965 if (starts[i] > first && starts[i] < stop)
2968 snprintf(mesg, sizeof(mesg),
2969 _("Last %s or +size or +sizeM or +sizeK"),
2970 str_units(SINGULAR));
2972 last = read_int(scround(stop2), scround(stop2), scround(stop2),
2974 else if (n == 2 && !first)
2975 last = read_int(scround(first), scround(stop2), scround(stop2),
2976 scround(first), mesg);
2978 last = read_int(scround(first), scround(stop), scround(stop),
2979 scround(first), mesg);
2980 if (display_in_cyl_units)
2981 last *= units_per_sector;
2982 if (n == 2 && !first) {
2983 if (last >= stop2) {
2986 } else if (last > stop) {
2987 printf(_("You haven't covered the whole disk with "
2988 "the 3rd partition, but your value\n"
2989 "%d %s covers some other partition. "
2990 "Your entry has been changed\n"
2992 scround(last), str_units(SINGULAR),
2993 scround(stop), str_units(SINGULAR));
2996 } else if (!whole_disk && last > stop)
3001 set_sun_partition(n, first, last, sys);
3005 sun_delete_partition(int i)
3010 && sunlabel->infos[i].id == WHOLE_DISK
3011 && !sunlabel->partitions[i].start_cylinder
3012 && (nsec = SUN_SSWAP32(sunlabel->partitions[i].num_sectors)) == heads * sectors * cylinders)
3013 printf(_("If you want to maintain SunOS/Solaris compatibility, "
3014 "consider leaving this\n"
3015 "partition as Whole disk (5), starting at 0, with %u "
3016 "sectors\n"), nsec);
3017 sunlabel->infos[i].id = 0;
3018 sunlabel->partitions[i].num_sectors = 0;
3022 sun_change_sysid(int i, int sys)
3024 if (sys == LINUX_SWAP && !sunlabel->partitions[i].start_cylinder) {
3026 _("It is highly recommended that the partition at offset 0\n"
3027 "is UFS, EXT2FS filesystem or SunOS swap. Putting Linux swap\n"
3028 "there may destroy your partition table and bootblock.\n"
3029 "Type YES if you're very sure you would like that partition\n"
3030 "tagged with 82 (Linux swap): "));
3031 if (strcmp (line_ptr, _("YES\n")))
3037 /* swaps are not mountable by default */
3038 sunlabel->infos[i].flags |= 0x01;
3041 /* assume other types are mountable;
3042 user can change it anyway */
3043 sunlabel->infos[i].flags &= ~0x01;
3046 sunlabel->infos[i].id = sys;
3050 sun_list_table(int xtra)
3054 w = strlen(disk_device);
3057 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d rpm\n"
3058 "%d cylinders, %d alternate cylinders, %d physical cylinders\n"
3059 "%d extra sects/cyl, interleave %d:1\n"
3061 "Units = %s of %d * 512 bytes\n\n"),
3062 disk_device, heads, sectors, SUN_SSWAP16(sunlabel->rspeed),
3063 cylinders, SUN_SSWAP16(sunlabel->nacyl),
3064 SUN_SSWAP16(sunlabel->pcylcount),
3065 SUN_SSWAP16(sunlabel->sparecyl),
3066 SUN_SSWAP16(sunlabel->ilfact),
3068 str_units(PLURAL), units_per_sector);
3071 _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d cylinders\n"
3072 "Units = %s of %d * 512 bytes\n\n"),
3073 disk_device, heads, sectors, cylinders,
3074 str_units(PLURAL), units_per_sector);
3076 printf(_("%*s Flag Start End Blocks Id System\n"),
3077 w + 1, _("Device"));
3078 for (i = 0 ; i < partitions; i++) {
3079 if (sunlabel->partitions[i].num_sectors) {
3080 uint32_t start = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
3081 uint32_t len = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
3082 printf("%s %c%c %9ld %9ld %9ld%c %2x %s\n",
3083 partname(disk_device, i+1, w), /* device */
3084 (sunlabel->infos[i].flags & 0x01) ? 'u' : ' ', /* flags */
3085 (sunlabel->infos[i].flags & 0x10) ? 'r' : ' ',
3086 (long) scround(start), /* start */
3087 (long) scround(start+len), /* end */
3088 (long) len / 2, len & 1 ? '+' : ' ', /* odd flag on end */
3089 sunlabel->infos[i].id, /* type id */
3090 partition_type(sunlabel->infos[i].id)); /* type name */
3095 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3098 sun_set_alt_cyl(void)
3101 SUN_SSWAP16(read_int(0,SUN_SSWAP16(sunlabel->nacyl), 65535, 0,
3102 _("Number of alternate cylinders")));
3106 sun_set_ncyl(int cyl)
3108 sunlabel->ncyl = SUN_SSWAP16(cyl);
3114 sunlabel->sparecyl =
3115 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->sparecyl), sectors, 0,
3116 _("Extra sectors per cylinder")));
3120 sun_set_ilfact(void)
3123 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->ilfact), 32, 0,
3124 _("Interleave factor")));
3128 sun_set_rspeed(void)
3131 SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->rspeed), 100000, 0,
3132 _("Rotation speed (rpm)")));
3136 sun_set_pcylcount(void)
3138 sunlabel->pcylcount =
3139 SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->pcylcount), 65535, 0,
3140 _("Number of physical cylinders")));
3142 #endif /* CONFIG_FEATURE_FDISK_ADVANCED */
3145 sun_write_table(void)
3147 unsigned short *ush = (unsigned short *)sunlabel;
3148 unsigned short csum = 0;
3150 while (ush < (unsigned short *)(&sunlabel->csum))
3152 sunlabel->csum = csum;
3153 if (lseek(fd, 0, SEEK_SET) < 0)
3154 fdisk_fatal(unable_to_seek);
3155 if (write(fd, sunlabel, SECTOR_SIZE) != SECTOR_SIZE)
3156 fdisk_fatal(unable_to_write);
3158 #endif /* SUN_LABEL */
3160 /* DOS partition types */
3162 static const struct systypes i386_sys_types[] = {
3165 { "\x04" "FAT16 <32M" },
3166 { "\x05" "Extended" }, /* DOS 3.3+ extended partition */
3167 { "\x06" "FAT16" }, /* DOS 16-bit >=32M */
3168 { "\x07" "HPFS/NTFS" }, /* OS/2 IFS, eg, HPFS or NTFS or QNX */
3169 { "\x0a" "OS/2 Boot Manager" },/* OS/2 Boot Manager */
3170 { "\x0b" "Win95 FAT32" },
3171 { "\x0c" "Win95 FAT32 (LBA)" },/* LBA really is `Extended Int 13h' */
3172 { "\x0e" "Win95 FAT16 (LBA)" },
3173 { "\x0f" "Win95 Ext'd (LBA)" },
3174 { "\x11" "Hidden FAT12" },
3175 { "\x12" "Compaq diagnostics" },
3176 { "\x14" "Hidden FAT16 <32M" },
3177 { "\x16" "Hidden FAT16" },
3178 { "\x17" "Hidden HPFS/NTFS" },
3179 { "\x1b" "Hidden Win95 FAT32" },
3180 { "\x1c" "Hidden Win95 FAT32 (LBA)" },
3181 { "\x1e" "Hidden Win95 FAT16 (LBA)" },
3182 { "\x3c" "PartitionMagic recovery" },
3183 { "\x41" "PPC PReP Boot" },
3185 { "\x63" "GNU HURD or SysV" }, /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */
3186 { "\x80" "Old Minix" }, /* Minix 1.4a and earlier */
3187 { "\x81" "Minix / old Linux" },/* Minix 1.4b and later */
3188 { "\x82" "Linux swap" }, /* also Solaris */
3190 { "\x84" "OS/2 hidden C: drive" },
3191 { "\x85" "Linux extended" },
3192 { "\x86" "NTFS volume set" },
3193 { "\x87" "NTFS volume set" },
3194 { "\x8e" "Linux LVM" },
3195 { "\x9f" "BSD/OS" }, /* BSDI */
3196 { "\xa0" "IBM Thinkpad hibernation" },
3197 { "\xa5" "FreeBSD" }, /* various BSD flavours */
3198 { "\xa6" "OpenBSD" },
3199 { "\xa8" "Darwin UFS" },
3200 { "\xa9" "NetBSD" },
3201 { "\xab" "Darwin boot" },
3202 { "\xb7" "BSDI fs" },
3203 { "\xb8" "BSDI swap" },
3204 { "\xbe" "Solaris boot" },
3205 { "\xeb" "BeOS fs" },
3206 { "\xee" "EFI GPT" }, /* Intel EFI GUID Partition Table */
3207 { "\xef" "EFI (FAT-12/16/32)" },/* Intel EFI System Partition */
3208 { "\xf0" "Linux/PA-RISC boot" },/* Linux/PA-RISC boot loader */
3209 { "\xf2" "DOS secondary" }, /* DOS 3.3+ secondary */
3210 { "\xfd" "Linux raid autodetect" },/* New (2.2.x) raid partition with
3211 autodetect using persistent
3213 #ifdef CONFIG_WEIRD_PARTITION_TYPES
3214 { "\x02" "XENIX root" },
3215 { "\x03" "XENIX usr" },
3216 { "\x08" "AIX" }, /* AIX boot (AIX -- PS/2 port) or SplitDrive */
3217 { "\x09" "AIX bootable" }, /* AIX data or Coherent */
3219 { "\x18" "AST SmartSleep" },
3220 { "\x24" "NEC DOS" },
3221 { "\x39" "Plan 9" },
3222 { "\x40" "Venix 80286" },
3223 { "\x4d" "QNX4.x" },
3224 { "\x4e" "QNX4.x 2nd part" },
3225 { "\x4f" "QNX4.x 3rd part" },
3226 { "\x50" "OnTrack DM" },
3227 { "\x51" "OnTrack DM6 Aux1" }, /* (or Novell) */
3228 { "\x52" "CP/M" }, /* CP/M or Microport SysV/AT */
3229 { "\x53" "OnTrack DM6 Aux3" },
3230 { "\x54" "OnTrackDM6" },
3231 { "\x55" "EZ-Drive" },
3232 { "\x56" "Golden Bow" },
3233 { "\x5c" "Priam Edisk" },
3234 { "\x61" "SpeedStor" },
3235 { "\x64" "Novell Netware 286" },
3236 { "\x65" "Novell Netware 386" },
3237 { "\x70" "DiskSecure Multi-Boot" },
3239 { "\x93" "Amoeba" },
3240 { "\x94" "Amoeba BBT" }, /* (bad block table) */
3241 { "\xa7" "NeXTSTEP" },
3242 { "\xbb" "Boot Wizard hidden" },
3243 { "\xc1" "DRDOS/sec (FAT-12)" },
3244 { "\xc4" "DRDOS/sec (FAT-16 < 32M)" },
3245 { "\xc6" "DRDOS/sec (FAT-16)" },
3246 { "\xc7" "Syrinx" },
3247 { "\xda" "Non-FS data" },
3248 { "\xdb" "CP/M / CTOS / ..." },/* CP/M or Concurrent CP/M or
3249 Concurrent DOS or CTOS */
3250 { "\xde" "Dell Utility" }, /* Dell PowerEdge Server utilities */
3251 { "\xdf" "BootIt" }, /* BootIt EMBRM */
3252 { "\xe1" "DOS access" }, /* DOS access or SpeedStor 12-bit FAT
3253 extended partition */
3254 { "\xe3" "DOS R/O" }, /* DOS R/O or SpeedStor */
3255 { "\xe4" "SpeedStor" }, /* SpeedStor 16-bit FAT extended
3256 partition < 1024 cyl. */
3257 { "\xf1" "SpeedStor" },
3258 { "\xf4" "SpeedStor" }, /* SpeedStor large partition */
3259 { "\xfe" "LANstep" }, /* SpeedStor >1024 cyl. or LANstep */
3260 { "\xff" "BBT" }, /* Xenix Bad Block Table */
3267 /* A valid partition table sector ends in 0x55 0xaa */
3269 part_table_flag(const char *b)
3271 return ((uint) b[510]) + (((uint) b[511]) << 8);
3275 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3277 write_part_table_flag(char *b)
3283 /* start_sect and nr_sects are stored little endian on all machines */
3284 /* moreover, they are not aligned correctly */
3286 store4_little_endian(unsigned char *cp, unsigned int val)
3288 cp[0] = (val & 0xff);
3289 cp[1] = ((val >> 8) & 0xff);
3290 cp[2] = ((val >> 16) & 0xff);
3291 cp[3] = ((val >> 24) & 0xff);
3293 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3296 read4_little_endian(const unsigned char *cp)
3298 return (uint)(cp[0]) + ((uint)(cp[1]) << 8)
3299 + ((uint)(cp[2]) << 16) + ((uint)(cp[3]) << 24);
3302 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3304 set_start_sect(struct partition *p, unsigned int start_sect)
3306 store4_little_endian(p->start4, start_sect);
3311 get_start_sect(const struct partition *p)
3313 return read4_little_endian(p->start4);
3316 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3318 set_nr_sects(struct partition *p, int32_t nr_sects)
3320 store4_little_endian(p->size4, nr_sects);
3325 get_nr_sects(const struct partition *p)
3327 return read4_little_endian(p->size4);
3330 /* normally O_RDWR, -l option gives O_RDONLY */
3331 static int type_open = O_RDWR;
3334 static int ext_index; /* the prime extended partition */
3335 static int listing; /* no aborts for fdisk -l */
3336 static int dos_compatible_flag = ~0;
3337 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3338 static int dos_changed;
3339 static int nowarn; /* no warnings for fdisk -l/-s */
3344 static uint user_cylinders, user_heads, user_sectors;
3345 static uint pt_heads, pt_sectors;
3346 static uint kern_heads, kern_sectors;
3348 static off_t extended_offset; /* offset of link pointers */
3350 static unsigned long long total_number_of_sectors;
3353 static jmp_buf listingbuf;
3355 static void fdisk_fatal(enum failure why)
3357 const char *message;
3361 longjmp(listingbuf, 1);
3365 case unable_to_open:
3366 message = "Unable to open %s\n";
3368 case unable_to_read:
3369 message = "Unable to read %s\n";
3371 case unable_to_seek:
3372 message = "Unable to seek on %s\n";
3374 case unable_to_write:
3375 message = "Unable to write %s\n";
3378 message = "BLKGETSIZE ioctl failed on %s\n";
3381 message = "Fatal error\n";
3384 fputc('\n', stderr);
3385 fprintf(stderr, message, disk_device);
3390 seek_sector(off_t secno)
3392 off_t offset = secno * sector_size;
3393 if (lseek(fd, offset, SEEK_SET) == (off_t) -1)
3394 fdisk_fatal(unable_to_seek);
3397 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3399 write_sector(off_t secno, char *buf)
3402 if (write(fd, buf, sector_size) != sector_size)
3403 fdisk_fatal(unable_to_write);
3407 /* Allocate a buffer and read a partition table sector */
3409 read_pte(struct pte *pe, off_t offset)
3411 pe->offset = offset;
3412 pe->sectorbuffer = (char *) xmalloc(sector_size);
3413 seek_sector(offset);
3414 if (read(fd, pe->sectorbuffer, sector_size) != sector_size)
3415 fdisk_fatal(unable_to_read);
3416 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3419 pe->part_table = pe->ext_pointer = NULL;
3423 get_partition_start(const struct pte *pe)
3425 return pe->offset + get_start_sect(pe->part_table);
3428 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3430 * Avoid warning about DOS partitions when no DOS partition was changed.
3431 * Here a heuristic "is probably dos partition".
3432 * We might also do the opposite and warn in all cases except
3433 * for "is probably nondos partition".
3436 is_dos_partition(int t)
3438 return (t == 1 || t == 4 || t == 6 ||
3439 t == 0x0b || t == 0x0c || t == 0x0e ||
3440 t == 0x11 || t == 0x12 || t == 0x14 || t == 0x16 ||
3441 t == 0x1b || t == 0x1c || t == 0x1e || t == 0x24 ||
3442 t == 0xc1 || t == 0xc4 || t == 0xc6);
3448 #ifdef CONFIG_FEATURE_SUN_LABEL
3449 if (label_sun == current_label_type) {
3450 puts(_("Command action"));
3451 puts(_("\ta\ttoggle a read only flag")); /* sun */
3452 puts(_("\tb\tedit bsd disklabel"));
3453 puts(_("\tc\ttoggle the mountable flag")); /* sun */
3454 puts(_("\td\tdelete a partition"));
3455 puts(_("\tl\tlist known partition types"));
3456 puts(_("\tm\tprint this menu"));
3457 puts(_("\tn\tadd a new partition"));
3458 puts(_("\to\tcreate a new empty DOS partition table"));
3459 puts(_("\tp\tprint the partition table"));
3460 puts(_("\tq\tquit without saving changes"));
3461 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3462 puts(_("\tt\tchange a partition's system id"));
3463 puts(_("\tu\tchange display/entry units"));
3464 puts(_("\tv\tverify the partition table"));
3465 puts(_("\tw\twrite table to disk and exit"));
3466 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3467 puts(_("\tx\textra functionality (experts only)"));
3471 #ifdef CONFIG_FEATURE_SGI_LABEL
3472 if (label_sgi == current_label_type) {
3473 puts(_("Command action"));
3474 puts(_("\ta\tselect bootable partition")); /* sgi flavour */
3475 puts(_("\tb\tedit bootfile entry")); /* sgi */
3476 puts(_("\tc\tselect sgi swap partition")); /* sgi flavour */
3477 puts(_("\td\tdelete a partition"));
3478 puts(_("\tl\tlist known partition types"));
3479 puts(_("\tm\tprint this menu"));
3480 puts(_("\tn\tadd a new partition"));
3481 puts(_("\to\tcreate a new empty DOS partition table"));
3482 puts(_("\tp\tprint the partition table"));
3483 puts(_("\tq\tquit without saving changes"));
3484 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3485 puts(_("\tt\tchange a partition's system id"));
3486 puts(_("\tu\tchange display/entry units"));
3487 puts(_("\tv\tverify the partition table"));
3488 puts(_("\tw\twrite table to disk and exit"));
3491 #ifdef CONFIG_FEATURE_AIX_LABEL
3492 if (label_aix == current_label_type) {
3493 puts(_("Command action"));
3494 puts(_("\tm\tprint this menu"));
3495 puts(_("\to\tcreate a new empty DOS partition table"));
3496 puts(_("\tq\tquit without saving changes"));
3497 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3501 puts(_("Command action"));
3502 puts(_("\ta\ttoggle a bootable flag"));
3503 puts(_("\tb\tedit bsd disklabel"));
3504 puts(_("\tc\ttoggle the dos compatibility flag"));
3505 puts(_("\td\tdelete a partition"));
3506 puts(_("\tl\tlist known partition types"));
3507 puts(_("\tm\tprint this menu"));
3508 puts(_("\tn\tadd a new partition"));
3509 puts(_("\to\tcreate a new empty DOS partition table"));
3510 puts(_("\tp\tprint the partition table"));
3511 puts(_("\tq\tquit without saving changes"));
3512 puts(_("\ts\tcreate a new empty Sun disklabel")); /* sun */
3513 puts(_("\tt\tchange a partition's system id"));
3514 puts(_("\tu\tchange display/entry units"));
3515 puts(_("\tv\tverify the partition table"));
3516 puts(_("\tw\twrite table to disk and exit"));
3517 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3518 puts(_("\tx\textra functionality (experts only)"));
3522 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3525 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
3529 #ifdef CONFIG_FEATURE_SUN_LABEL
3530 if (label_sun == current_label_type) {
3531 puts(_("Command action"));
3532 puts(_("\ta\tchange number of alternate cylinders")); /*sun*/
3533 puts(_("\tc\tchange number of cylinders"));
3534 puts(_("\td\tprint the raw data in the partition table"));
3535 puts(_("\te\tchange number of extra sectors per cylinder"));/*sun*/
3536 puts(_("\th\tchange number of heads"));
3537 puts(_("\ti\tchange interleave factor")); /*sun*/
3538 puts(_("\to\tchange rotation speed (rpm)")); /*sun*/
3539 puts(_("\tm\tprint this menu"));
3540 puts(_("\tp\tprint the partition table"));
3541 puts(_("\tq\tquit without saving changes"));
3542 puts(_("\tr\treturn to main menu"));
3543 puts(_("\ts\tchange number of sectors/track"));
3544 puts(_("\tv\tverify the partition table"));
3545 puts(_("\tw\twrite table to disk and exit"));
3546 puts(_("\ty\tchange number of physical cylinders")); /*sun*/
3549 #ifdef CONFIG_FEATURE_SGI_LABEL
3550 if (label_sgi == current_label_type) {
3551 puts(_("Command action"));
3552 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3553 puts(_("\tc\tchange number of cylinders"));
3554 puts(_("\td\tprint the raw data in the partition table"));
3555 puts(_("\te\tlist extended partitions")); /* !sun */
3556 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3557 puts(_("\th\tchange number of heads"));
3558 puts(_("\tm\tprint this menu"));
3559 puts(_("\tp\tprint the partition table"));
3560 puts(_("\tq\tquit without saving changes"));
3561 puts(_("\tr\treturn to main menu"));
3562 puts(_("\ts\tchange number of sectors/track"));
3563 puts(_("\tv\tverify the partition table"));
3564 puts(_("\tw\twrite table to disk and exit"));
3567 #ifdef CONFIG_FEATURE_AIX_LABEL
3568 if (label_aix == current_label_type) {
3569 puts(_("Command action"));
3570 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3571 puts(_("\tc\tchange number of cylinders"));
3572 puts(_("\td\tprint the raw data in the partition table"));
3573 puts(_("\te\tlist extended partitions")); /* !sun */
3574 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3575 puts(_("\th\tchange number of heads"));
3576 puts(_("\tm\tprint this menu"));
3577 puts(_("\tp\tprint the partition table"));
3578 puts(_("\tq\tquit without saving changes"));
3579 puts(_("\tr\treturn to main menu"));
3580 puts(_("\ts\tchange number of sectors/track"));
3581 puts(_("\tv\tverify the partition table"));
3582 puts(_("\tw\twrite table to disk and exit"));
3586 puts(_("Command action"));
3587 puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
3588 puts(_("\tc\tchange number of cylinders"));
3589 puts(_("\td\tprint the raw data in the partition table"));
3590 puts(_("\te\tlist extended partitions")); /* !sun */
3591 puts(_("\tf\tfix partition order")); /* !sun, !aix, !sgi */
3592 #ifdef CONFIG_FEATURE_SGI_LABEL
3593 puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
3595 puts(_("\th\tchange number of heads"));
3596 puts(_("\tm\tprint this menu"));
3597 puts(_("\tp\tprint the partition table"));
3598 puts(_("\tq\tquit without saving changes"));
3599 puts(_("\tr\treturn to main menu"));
3600 puts(_("\ts\tchange number of sectors/track"));
3601 puts(_("\tv\tverify the partition table"));
3602 puts(_("\tw\twrite table to disk and exit"));
3605 #endif /* ADVANCED mode */
3607 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3608 static const struct systypes *
3612 #ifdef CONFIG_FEATURE_SUN_LABEL
3613 label_sun == current_label_type ? sun_sys_types :
3615 #ifdef CONFIG_FEATURE_SGI_LABEL
3616 label_sgi == current_label_type ? sgi_sys_types :
3621 #define get_sys_types() i386_sys_types
3622 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3624 static const char *partition_type(unsigned char type)
3627 const struct systypes *types = get_sys_types();
3629 for (i = 0; types[i].name; i++)
3630 if ((unsigned char )types[i].name[0] == type)
3631 return types[i].name + 1;
3633 return _("Unknown");
3637 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3642 #ifdef CONFIG_FEATURE_SUN_LABEL
3643 label_sun == current_label_type ? sunlabel->infos[i].id :
3645 #ifdef CONFIG_FEATURE_SGI_LABEL
3646 label_sgi == current_label_type ? sgi_get_sysid(i) :
3648 ptes[i].part_table->sys_ind);
3651 void list_types(const struct systypes *sys)
3653 uint last[4], done = 0, next = 0, size;
3656 for (i = 0; sys[i].name; i++);
3659 for (i = 3; i >= 0; i--)
3660 last[3 - i] = done += (size + i - done) / (i + 1);
3664 printf("%c%2x %-15.15s", i ? ' ' : '\n',
3665 (unsigned char)sys[next].name[0],
3666 partition_type((unsigned char)sys[next].name[0]));
3667 next = last[i++] + done;
3668 if (i > 3 || next >= last[i]) {
3672 } while (done < last[0]);
3675 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3678 is_cleared_partition(const struct partition *p)
3680 return !(!p || p->boot_ind || p->head || p->sector || p->cyl ||
3681 p->sys_ind || p->end_head || p->end_sector || p->end_cyl ||
3682 get_start_sect(p) || get_nr_sects(p));
3686 clear_partition(struct partition *p)
3690 memset(p, 0, sizeof(struct partition));
3693 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3695 set_partition(int i, int doext, off_t start, off_t stop, int sysid)
3697 struct partition *p;
3701 p = ptes[i].ext_pointer;
3702 offset = extended_offset;
3704 p = ptes[i].part_table;
3705 offset = ptes[i].offset;
3709 set_start_sect(p, start - offset);
3710 set_nr_sects(p, stop - start + 1);
3711 if (dos_compatible_flag && (start/(sectors*heads) > 1023))
3712 start = heads*sectors*1024 - 1;
3713 set_hsc(p->head, p->sector, p->cyl, start);
3714 if (dos_compatible_flag && (stop/(sectors*heads) > 1023))
3715 stop = heads*sectors*1024 - 1;
3716 set_hsc(p->end_head, p->end_sector, p->end_cyl, stop);
3717 ptes[i].changed = 1;
3722 test_c(const char **m, const char *mesg)
3726 fprintf(stderr, _("You must set"));
3728 fprintf(stderr, " %s", *m);
3738 const char *m = NULL;
3742 prev = test_c(&m, _("heads"));
3744 prev = test_c(&m, _("sectors"));
3746 prev = test_c(&m, _("cylinders"));
3750 fprintf(stderr, "%s%s.\n"
3751 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3752 "You can do this from the extra functions menu.\n"
3754 , prev ? _(" and ") : " ", m);
3759 static void update_units(void)
3761 int cyl_units = heads * sectors;
3763 if (display_in_cyl_units && cyl_units)
3764 units_per_sector = cyl_units;
3766 units_per_sector = 1; /* in sectors */
3769 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3771 warn_cylinders(void)
3773 if (label_dos == current_label_type && cylinders > 1024 && !nowarn)
3774 fprintf(stderr, _("\n"
3775 "The number of cylinders for this disk is set to %d.\n"
3776 "There is nothing wrong with that, but this is larger than 1024,\n"
3777 "and could in certain setups cause problems with:\n"
3778 "1) software that runs at boot time (e.g., old versions of LILO)\n"
3779 "2) booting and partitioning software from other OSs\n"
3780 " (e.g., DOS FDISK, OS/2 FDISK)\n"),
3786 read_extended(int ext)
3790 struct partition *p, *q;
3794 pex->ext_pointer = pex->part_table;
3796 p = pex->part_table;
3797 if (!get_start_sect(p)) {
3799 _("Bad offset in primary extended partition\n"));
3803 while (IS_EXTENDED(p->sys_ind)) {
3804 struct pte *pe = &ptes[partitions];
3806 if (partitions >= MAXIMUM_PARTS) {
3807 /* This is not a Linux restriction, but
3808 this program uses arrays of size MAXIMUM_PARTS.
3809 Do not try to `improve' this test. */
3810 struct pte *pre = &ptes[partitions-1];
3811 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3813 _("Warning: deleting partitions after %d\n"),
3817 clear_partition(pre->ext_pointer);
3821 read_pte(pe, extended_offset + get_start_sect(p));
3823 if (!extended_offset)
3824 extended_offset = get_start_sect(p);
3826 q = p = pt_offset(pe->sectorbuffer, 0);
3827 for (i = 0; i < 4; i++, p++) if (get_nr_sects(p)) {
3828 if (IS_EXTENDED(p->sys_ind)) {
3829 if (pe->ext_pointer)
3831 _("Warning: extra link "
3832 "pointer in partition table"
3833 " %d\n"), partitions + 1);
3835 pe->ext_pointer = p;
3836 } else if (p->sys_ind) {
3839 _("Warning: ignoring extra "
3840 "data in partition table"
3841 " %d\n"), partitions + 1);
3847 /* very strange code here... */
3848 if (!pe->part_table) {
3849 if (q != pe->ext_pointer)
3852 pe->part_table = q + 1;
3854 if (!pe->ext_pointer) {
3855 if (q != pe->part_table)
3856 pe->ext_pointer = q;
3858 pe->ext_pointer = q + 1;
3861 p = pe->ext_pointer;
3865 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3866 /* remove empty links */
3868 for (i = 4; i < partitions; i++) {
3869 struct pte *pe = &ptes[i];
3871 if (!get_nr_sects(pe->part_table) &&
3872 (partitions > 5 || ptes[4].part_table->sys_ind)) {
3873 printf("omitting empty partition (%d)\n", i+1);
3874 delete_partition(i);
3875 goto remove; /* numbering changed */
3881 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
3883 create_doslabel(void)
3888 _("Building a new DOS disklabel. Changes will remain in memory only,\n"
3889 "until you decide to write them. After that, of course, the previous\n"
3890 "content won't be recoverable.\n\n"));
3892 current_label_type = label_dos;
3894 #ifdef CONFIG_FEATURE_OSF_LABEL
3895 possibly_osf_label = 0;
3899 for (i = 510-64; i < 510; i++)
3901 write_part_table_flag(MBRbuffer);
3902 extended_offset = 0;
3903 set_all_unchanged();
3905 get_boot(create_empty_dos);
3907 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
3910 get_sectorsize(void)
3912 if (!user_set_sector_size) {
3914 if (ioctl(fd, BLKSSZGET, &arg) == 0)
3916 if (sector_size != DEFAULT_SECTOR_SIZE)
3917 printf(_("Note: sector size is %d (not %d)\n"),
3918 sector_size, DEFAULT_SECTOR_SIZE);
3923 get_kernel_geometry(void)
3925 struct hd_geometry geometry;
3927 if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
3928 kern_heads = geometry.heads;
3929 kern_sectors = geometry.sectors;
3930 /* never use geometry.cylinders - it is truncated */
3935 get_partition_table_geometry(void)
3937 const unsigned char *bufp = (const unsigned char *)MBRbuffer;
3938 struct partition *p;
3939 int i, h, s, hh, ss;
3943 if (!(valid_part_table_flag((char*)bufp)))
3947 for (i = 0; i < 4; i++) {
3948 p = pt_offset(bufp, i);
3949 if (p->sys_ind != 0) {
3950 h = p->end_head + 1;
3951 s = (p->end_sector & 077);
3956 } else if (hh != h || ss != s)
3961 if (!first && !bad) {
3971 unsigned long long bytes; /* really u64 */
3974 sec_fac = sector_size / 512;
3975 #ifdef CONFIG_FEATURE_SUN_LABEL
3976 guess_device_type();
3978 heads = cylinders = sectors = 0;
3979 kern_heads = kern_sectors = 0;
3980 pt_heads = pt_sectors = 0;
3982 get_kernel_geometry();
3983 get_partition_table_geometry();
3985 heads = user_heads ? user_heads :
3986 pt_heads ? pt_heads :
3987 kern_heads ? kern_heads : 255;
3988 sectors = user_sectors ? user_sectors :
3989 pt_sectors ? pt_sectors :
3990 kern_sectors ? kern_sectors : 63;
3991 if (ioctl(fd, BLKGETSIZE64, &bytes) == 0) {
3994 unsigned long longsectors;
3996 if (ioctl(fd, BLKGETSIZE, &longsectors))
3998 bytes = ((unsigned long long) longsectors) << 9;
4001 total_number_of_sectors = (bytes >> 9);
4004 if (dos_compatible_flag)
4005 sector_offset = sectors;
4007 cylinders = total_number_of_sectors / (heads * sectors * sec_fac);
4009 cylinders = user_cylinders;
4013 * Read MBR. Returns:
4014 * -1: no 0xaa55 flag present (possibly entire disk BSD)
4015 * 0: found or created label
4019 get_boot(enum action what)
4025 for (i = 0; i < 4; i++) {
4026 struct pte *pe = &ptes[i];
4028 pe->part_table = pt_offset(MBRbuffer, i);
4029 pe->ext_pointer = NULL;
4031 pe->sectorbuffer = MBRbuffer;
4032 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4033 pe->changed = (what == create_empty_dos);
4037 #ifdef CONFIG_FEATURE_SUN_LABEL
4038 if (what == create_empty_sun && check_sun_label())
4042 memset(MBRbuffer, 0, 512);
4044 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4045 if (what == create_empty_dos)
4046 goto got_dos_table; /* skip reading disk */
4048 if ((fd = open(disk_device, type_open)) < 0) {
4049 if ((fd = open(disk_device, O_RDONLY)) < 0) {
4050 if (what == try_only)
4052 fdisk_fatal(unable_to_open);
4054 printf(_("You will not be able to write "
4055 "the partition table.\n"));
4058 if (512 != read(fd, MBRbuffer, 512)) {
4059 if (what == try_only)
4061 fdisk_fatal(unable_to_read);
4064 if ((fd = open(disk_device, O_RDONLY)) < 0)
4066 if (512 != read(fd, MBRbuffer, 512))
4074 #ifdef CONFIG_FEATURE_SUN_LABEL
4075 if (check_sun_label())
4079 #ifdef CONFIG_FEATURE_SGI_LABEL
4080 if (check_sgi_label())
4084 #ifdef CONFIG_FEATURE_AIX_LABEL
4085 if (check_aix_label())
4089 #ifdef CONFIG_FEATURE_OSF_LABEL
4090 if (check_osf_label()) {
4091 possibly_osf_label = 1;
4092 if (!valid_part_table_flag(MBRbuffer)) {
4093 current_label_type = label_osf;
4096 printf(_("This disk has both DOS and BSD magic.\n"
4097 "Give the 'b' command to go to BSD mode.\n"));
4101 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4105 if (!valid_part_table_flag(MBRbuffer)) {
4106 #ifndef CONFIG_FEATURE_FDISK_WRITABLE
4112 _("Device contains neither a valid DOS "
4113 "partition table, nor Sun, SGI or OSF "
4116 #ifdef CONFIG_FEATURE_SUN_LABEL
4125 case create_empty_dos:
4126 #ifdef CONFIG_FEATURE_SUN_LABEL
4127 case create_empty_sun:
4131 fprintf(stderr, _("Internal error\n"));
4134 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
4137 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4142 for (i = 0; i < 4; i++) {
4143 struct pte *pe = &ptes[i];
4145 if (IS_EXTENDED(pe->part_table->sys_ind)) {
4146 if (partitions != 4)
4147 fprintf(stderr, _("Ignoring extra extended "
4148 "partition %d\n"), i + 1);
4154 for (i = 3; i < partitions; i++) {
4155 struct pte *pe = &ptes[i];
4157 if (!valid_part_table_flag(pe->sectorbuffer)) {
4159 _("Warning: invalid flag 0x%04x of partition "
4160 "table %d will be corrected by w(rite)\n"),
4161 part_table_flag(pe->sectorbuffer), i + 1);
4162 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4171 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4173 * Print the message MESG, then read an integer between LOW and HIGH (inclusive).
4174 * If the user hits Enter, DFLT is returned.
4175 * Answers like +10 are interpreted as offsets from BASE.
4177 * There is no default if DFLT is not between LOW and HIGH.
4180 read_int(uint low, uint dflt, uint high, uint base, char *mesg)
4184 static char *ms = NULL;
4185 static int mslen = 0;
4187 if (!ms || strlen(mesg)+100 > mslen) {
4188 mslen = strlen(mesg)+200;
4189 ms = xrealloc(ms,mslen);
4192 if (dflt < low || dflt > high)
4196 snprintf(ms, mslen, _("%s (%u-%u, default %u): "),
4197 mesg, low, high, dflt);
4199 snprintf(ms, mslen, "%s (%u-%u): ", mesg, low, high);
4202 int use_default = default_ok;
4204 /* ask question and read answer */
4205 while (read_chars(ms) != '\n' && !isdigit(*line_ptr)
4206 && *line_ptr != '-' && *line_ptr != '+')
4209 if (*line_ptr == '+' || *line_ptr == '-') {
4210 int minus = (*line_ptr == '-');
4213 i = atoi(line_ptr+1);
4215 while (isdigit(*++line_ptr))
4218 switch (*line_ptr) {
4221 if (!display_in_cyl_units)
4222 i *= heads * sectors;
4236 absolute = 1000000000;
4242 unsigned long long bytes;
4245 bytes = (unsigned long long) i * absolute;
4246 unit = sector_size * units_per_sector;
4247 bytes += unit/2; /* round */
4256 while (isdigit(*line_ptr)) {
4262 printf(_("Using default value %u\n"), i = dflt);
4263 if (i >= low && i <= high)
4266 printf(_("Value out of range.\n"));
4272 get_partition(int warn, int max)
4277 i = read_int(1, 0, max, 0, _("Partition number")) - 1;
4283 label_sun != current_label_type &&
4284 label_sgi != current_label_type &&
4285 !pe->part_table->sys_ind
4287 #ifdef CONFIG_FEATURE_SUN_LABEL
4289 label_sun == current_label_type &&
4291 !sunlabel->partitions[i].num_sectors
4292 || !sunlabel->infos[i].id
4296 #ifdef CONFIG_FEATURE_SGI_LABEL
4298 label_sgi == current_label_type &&
4299 !sgi_get_num_sectors(i)
4304 _("Warning: partition %d has empty type\n"),
4313 get_existing_partition(int warn, int max)
4318 for (i = 0; i < max; i++) {
4319 struct pte *pe = &ptes[i];
4320 struct partition *p = pe->part_table;
4322 if (p && !is_cleared_partition(p)) {
4329 printf(_("Selected partition %d\n"), pno+1);
4332 printf(_("No partition is defined yet!\n"));
4336 return get_partition(warn, max);
4340 get_nonexisting_partition(int warn, int max)
4345 for (i = 0; i < max; i++) {
4346 struct pte *pe = &ptes[i];
4347 struct partition *p = pe->part_table;
4349 if (p && is_cleared_partition(p)) {
4356 printf(_("Selected partition %d\n"), pno+1);
4359 printf(_("All primary partitions have been defined already!\n"));
4363 return get_partition(warn, max);
4367 void change_units(void)
4369 display_in_cyl_units = !display_in_cyl_units;
4371 printf(_("Changing display/entry units to %s\n"),
4376 toggle_active(int i)
4378 struct pte *pe = &ptes[i];
4379 struct partition *p = pe->part_table;
4381 if (IS_EXTENDED(p->sys_ind) && !p->boot_ind)
4383 _("WARNING: Partition %d is an extended partition\n"),
4385 p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG);
4390 toggle_dos_compatibility_flag(void)
4392 dos_compatible_flag = ~dos_compatible_flag;
4393 if (dos_compatible_flag) {
4394 sector_offset = sectors;
4395 printf(_("DOS Compatibility flag is set\n"));
4399 printf(_("DOS Compatibility flag is not set\n"));
4404 delete_partition(int i)
4406 struct pte *pe = &ptes[i];
4407 struct partition *p = pe->part_table;
4408 struct partition *q = pe->ext_pointer;
4410 /* Note that for the fifth partition (i == 4) we don't actually
4411 * decrement partitions.
4414 if (warn_geometry())
4415 return; /* C/H/S not set */
4418 #ifdef CONFIG_FEATURE_SUN_LABEL
4419 if (label_sun == current_label_type) {
4420 sun_delete_partition(i);
4424 #ifdef CONFIG_FEATURE_SGI_LABEL
4425 if (label_sgi == current_label_type) {
4426 sgi_delete_partition(i);
4432 if (IS_EXTENDED(p->sys_ind) && i == ext_index) {
4434 ptes[ext_index].ext_pointer = NULL;
4435 extended_offset = 0;
4441 if (!q->sys_ind && i > 4) {
4442 /* the last one in the chain - just delete */
4445 clear_partition(ptes[i].ext_pointer);
4446 ptes[i].changed = 1;
4448 /* not the last one - further ones will be moved down */
4450 /* delete this link in the chain */
4451 p = ptes[i-1].ext_pointer;
4453 set_start_sect(p, get_start_sect(q));
4454 set_nr_sects(p, get_nr_sects(q));
4455 ptes[i-1].changed = 1;
4456 } else if (partitions > 5) { /* 5 will be moved to 4 */
4457 /* the first logical in a longer chain */
4460 if (pe->part_table) /* prevent SEGFAULT */
4461 set_start_sect(pe->part_table,
4462 get_partition_start(pe) -
4464 pe->offset = extended_offset;
4468 if (partitions > 5) {
4470 while (i < partitions) {
4471 ptes[i] = ptes[i+1];
4475 /* the only logical: clear only */
4476 clear_partition(ptes[i].part_table);
4483 int i, sys, origsys;
4484 struct partition *p;
4486 #ifdef CONFIG_FEATURE_SGI_LABEL
4487 /* If sgi_label then don't use get_existing_partition,
4488 let the user select a partition, since get_existing_partition()
4489 only works for Linux like partition tables. */
4490 if (label_sgi != current_label_type) {
4491 i = get_existing_partition(0, partitions);
4493 i = get_partition(0, partitions);
4496 i = get_existing_partition(0, partitions);
4500 p = ptes[i].part_table;
4501 origsys = sys = get_sysid(i);
4503 /* if changing types T to 0 is allowed, then
4504 the reverse change must be allowed, too */
4505 if (!sys && label_sgi != current_label_type &&
4506 label_sun != current_label_type && !get_nr_sects(p))
4508 printf(_("Partition %d does not exist yet!\n"), i + 1);
4511 sys = read_hex (get_sys_types());
4513 if (!sys && label_sgi != current_label_type &&
4514 label_sun != current_label_type)
4516 printf(_("Type 0 means free space to many systems\n"
4517 "(but not to Linux). Having partitions of\n"
4518 "type 0 is probably unwise. You can delete\n"
4519 "a partition using the `d' command.\n"));
4523 if (label_sun != current_label_type && label_sgi != current_label_type) {
4524 if (IS_EXTENDED(sys) != IS_EXTENDED(p->sys_ind)) {
4525 printf(_("You cannot change a partition into"
4526 " an extended one or vice versa\n"
4527 "Delete it first.\n"));
4533 #ifdef CONFIG_FEATURE_SUN_LABEL
4534 if (label_sun == current_label_type && i == 2 && sys != WHOLE_DISK)
4535 printf(_("Consider leaving partition 3 "
4536 "as Whole disk (5),\n"
4537 "as SunOS/Solaris expects it and "
4538 "even Linux likes it.\n\n"));
4540 #ifdef CONFIG_FEATURE_SGI_LABEL
4541 if (label_sgi == current_label_type &&
4543 (i == 10 && sys != ENTIRE_DISK) ||
4544 (i == 8 && sys != 0)
4547 printf(_("Consider leaving partition 9 "
4548 "as volume header (0),\nand "
4549 "partition 11 as entire volume (6)"
4550 "as IRIX expects it.\n\n"));
4555 #ifdef CONFIG_FEATURE_SUN_LABEL
4556 if (label_sun == current_label_type) {
4557 sun_change_sysid(i, sys);
4560 #ifdef CONFIG_FEATURE_SGI_LABEL
4561 if (label_sgi == current_label_type) {
4562 sgi_change_sysid(i, sys);
4567 printf(_("Changed system type of partition %d "
4568 "to %x (%s)\n"), i + 1, sys,
4569 partition_type(sys));
4570 ptes[i].changed = 1;
4571 if (is_dos_partition(origsys) ||
4572 is_dos_partition(sys))
4579 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
4582 /* check_consistency() and long2chs() added Sat Mar 6 12:28:16 1993,
4583 * faith@cs.unc.edu, based on code fragments from pfdisk by Gordon W. Ross,
4584 * Jan. 1990 (version 1.2.1 by Gordon W. Ross Aug. 1990; Modified by S.
4585 * Lubkin Oct. 1991). */
4588 long2chs(ulong ls, uint *c, uint *h, uint *s)
4590 int spc = heads * sectors;
4595 *s = ls % sectors + 1; /* sectors count from 1 */
4599 check_consistency(const struct partition *p, int partition)
4601 uint pbc, pbh, pbs; /* physical beginning c, h, s */
4602 uint pec, peh, pes; /* physical ending c, h, s */
4603 uint lbc, lbh, lbs; /* logical beginning c, h, s */
4604 uint lec, leh, les; /* logical ending c, h, s */
4606 if (!heads || !sectors || (partition >= 4))
4607 return; /* do not check extended partitions */
4609 /* physical beginning c, h, s */
4610 pbc = (p->cyl & 0xff) | ((p->sector << 2) & 0x300);
4612 pbs = p->sector & 0x3f;
4614 /* physical ending c, h, s */
4615 pec = (p->end_cyl & 0xff) | ((p->end_sector << 2) & 0x300);
4617 pes = p->end_sector & 0x3f;
4619 /* compute logical beginning (c, h, s) */
4620 long2chs(get_start_sect(p), &lbc, &lbh, &lbs);
4622 /* compute logical ending (c, h, s) */
4623 long2chs(get_start_sect(p) + get_nr_sects(p) - 1, &lec, &leh, &les);
4625 /* Same physical / logical beginning? */
4626 if (cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) {
4627 printf(_("Partition %d has different physical/logical "
4628 "beginnings (non-Linux?):\n"), partition + 1);
4629 printf(_(" phys=(%d, %d, %d) "), pbc, pbh, pbs);
4630 printf(_("logical=(%d, %d, %d)\n"),lbc, lbh, lbs);
4633 /* Same physical / logical ending? */
4634 if (cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) {
4635 printf(_("Partition %d has different physical/logical "
4636 "endings:\n"), partition + 1);
4637 printf(_(" phys=(%d, %d, %d) "), pec, peh, pes);
4638 printf(_("logical=(%d, %d, %d)\n"),lec, leh, les);
4641 /* Ending on cylinder boundary? */
4642 if (peh != (heads - 1) || pes != sectors) {
4643 printf(_("Partition %i does not end on cylinder boundary.\n"),
4649 list_disk_geometry(void)
4651 long long bytes = (total_number_of_sectors << 9);
4652 long megabytes = bytes/1000000;
4654 if (megabytes < 10000)
4655 printf(_("\nDisk %s: %ld MB, %lld bytes\n"),
4656 disk_device, megabytes, bytes);
4658 printf(_("\nDisk %s: %ld.%ld GB, %lld bytes\n"),
4659 disk_device, megabytes/1000, (megabytes/100)%10, bytes);
4660 printf(_("%d heads, %d sectors/track, %d cylinders"),
4661 heads, sectors, cylinders);
4662 if (units_per_sector == 1)
4663 printf(_(", total %llu sectors"),
4664 total_number_of_sectors / (sector_size/512));
4665 printf(_("\nUnits = %s of %d * %d = %d bytes\n\n"),
4667 units_per_sector, sector_size, units_per_sector * sector_size);
4671 * Check whether partition entries are ordered by their starting positions.
4672 * Return 0 if OK. Return i if partition i should have been earlier.
4673 * Two separate checks: primary and logical partitions.
4676 wrong_p_order(int *prev)
4678 const struct pte *pe;
4679 const struct partition *p;
4680 off_t last_p_start_pos = 0, p_start_pos;
4683 for (i = 0 ; i < partitions; i++) {
4686 last_p_start_pos = 0;
4689 if ((p = pe->part_table)->sys_ind) {
4690 p_start_pos = get_partition_start(pe);
4692 if (last_p_start_pos > p_start_pos) {
4698 last_p_start_pos = p_start_pos;
4705 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
4707 * Fix the chain of logicals.
4708 * extended_offset is unchanged, the set of sectors used is unchanged
4709 * The chain is sorted so that sectors increase, and so that
4710 * starting sectors increase.
4712 * After this it may still be that cfdisk doesnt like the table.
4713 * (This is because cfdisk considers expanded parts, from link to
4714 * end of partition, and these may still overlap.)
4716 * sfdisk /dev/hda > ohda; sfdisk /dev/hda < ohda
4720 fix_chain_of_logicals(void)
4722 int j, oj, ojj, sj, sjj;
4723 struct partition *pj,*pjj,tmp;
4725 /* Stage 1: sort sectors but leave sector of part 4 */
4726 /* (Its sector is the global extended_offset.) */
4728 for (j = 5; j < partitions-1; j++) {
4729 oj = ptes[j].offset;
4730 ojj = ptes[j+1].offset;
4732 ptes[j].offset = ojj;
4733 ptes[j+1].offset = oj;
4734 pj = ptes[j].part_table;
4735 set_start_sect(pj, get_start_sect(pj)+oj-ojj);
4736 pjj = ptes[j+1].part_table;
4737 set_start_sect(pjj, get_start_sect(pjj)+ojj-oj);
4738 set_start_sect(ptes[j-1].ext_pointer,
4739 ojj-extended_offset);
4740 set_start_sect(ptes[j].ext_pointer,
4741 oj-extended_offset);
4746 /* Stage 2: sort starting sectors */
4748 for (j = 4; j < partitions-1; j++) {
4749 pj = ptes[j].part_table;
4750 pjj = ptes[j+1].part_table;
4751 sj = get_start_sect(pj);
4752 sjj = get_start_sect(pjj);
4753 oj = ptes[j].offset;
4754 ojj = ptes[j+1].offset;
4755 if (oj+sj > ojj+sjj) {
4759 set_start_sect(pj, ojj+sjj-oj);
4760 set_start_sect(pjj, oj+sj-ojj);
4765 /* Probably something was changed */
4766 for (j = 4; j < partitions; j++)
4767 ptes[j].changed = 1;
4772 fix_partition_table_order(void)
4774 struct pte *pei, *pek;
4777 if (!wrong_p_order(NULL)) {
4778 printf(_("Nothing to do. Ordering is correct already.\n\n"));
4782 while ((i = wrong_p_order(&k)) != 0 && i < 4) {
4783 /* partition i should have come earlier, move it */
4784 /* We have to move data in the MBR */
4785 struct partition *pi, *pk, *pe, pbuf;
4789 pe = pei->ext_pointer;
4790 pei->ext_pointer = pek->ext_pointer;
4791 pek->ext_pointer = pe;
4793 pi = pei->part_table;
4794 pk = pek->part_table;
4796 memmove(&pbuf, pi, sizeof(struct partition));
4797 memmove(pi, pk, sizeof(struct partition));
4798 memmove(pk, &pbuf, sizeof(struct partition));
4800 pei->changed = pek->changed = 1;
4804 fix_chain_of_logicals();
4812 list_table(int xtra)
4814 const struct partition *p;
4817 #ifdef CONFIG_FEATURE_SUN_LABEL
4818 if (label_sun == current_label_type) {
4819 sun_list_table(xtra);
4824 #ifdef CONFIG_FEATURE_SGI_LABEL
4825 if (label_sgi == current_label_type) {
4826 sgi_list_table(xtra);
4831 list_disk_geometry();
4833 #ifdef CONFIG_FEATURE_OSF_LABEL
4834 if (label_osf == current_label_type) {
4835 xbsd_print_disklabel(xtra);
4840 /* Heuristic: we list partition 3 of /dev/foo as /dev/foo3,
4841 but if the device name ends in a digit, say /dev/foo1,
4842 then the partition is called /dev/foo1p3. */
4843 w = strlen(disk_device);
4844 if (w && isdigit(disk_device[w-1]))
4849 printf(_("%*s Boot Start End Blocks Id System\n"),
4852 for (i = 0; i < partitions; i++) {
4853 const struct pte *pe = &ptes[i];
4856 if (p && !is_cleared_partition(p)) {
4857 off_t psects = get_nr_sects(p);
4858 off_t pblocks = psects;
4859 unsigned int podd = 0;
4861 if (sector_size < 1024) {
4862 pblocks /= (1024 / sector_size);
4863 podd = psects % (1024 / sector_size);
4865 if (sector_size > 1024)
4866 pblocks *= (sector_size / 1024);
4868 "%s %c %11llu %11llu %11llu%c %2x %s\n",
4869 partname(disk_device, i+1, w+2),
4870 /* boot flag */ !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG
4872 /* start */ (unsigned long long) cround(get_partition_start(pe)),
4873 /* end */ (unsigned long long) cround(get_partition_start(pe) + psects
4874 - (psects ? 1 : 0)),
4875 /* odd flag on end */ (unsigned long long) pblocks, podd ? '+' : ' ',
4876 /* type id */ p->sys_ind,
4877 /* type name */ partition_type(p->sys_ind));
4878 check_consistency(p, i);
4882 /* Is partition table in disk order? It need not be, but... */
4883 /* partition table entries are not checked for correct order if this
4884 is a sgi, sun or aix labeled disk... */
4885 if (label_dos == current_label_type && wrong_p_order(NULL)) {
4887 printf(_("\nPartition table entries are not in disk order\n"));
4891 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
4893 x_list_table(int extend)
4895 const struct pte *pe;
4896 const struct partition *p;
4899 printf(_("\nDisk %s: %d heads, %d sectors, %d cylinders\n\n"),
4900 disk_device, heads, sectors, cylinders);
4901 printf(_("Nr AF Hd Sec Cyl Hd Sec Cyl Start Size ID\n"));
4902 for (i = 0 ; i < partitions; i++) {
4904 p = (extend ? pe->ext_pointer : pe->part_table);
4906 printf("%2d %02x%4d%4d%5d%4d%4d%5d%11u%11u %02x\n",
4907 i + 1, p->boot_ind, p->head,
4909 cylinder(p->sector, p->cyl), p->end_head,
4910 sector(p->end_sector),
4911 cylinder(p->end_sector, p->end_cyl),
4912 get_start_sect(p), get_nr_sects(p), p->sys_ind);
4914 check_consistency(p, i);
4920 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
4922 fill_bounds(off_t *first, off_t *last)
4925 const struct pte *pe = &ptes[0];
4926 const struct partition *p;
4928 for (i = 0; i < partitions; pe++,i++) {
4930 if (!p->sys_ind || IS_EXTENDED(p->sys_ind)) {
4931 first[i] = 0xffffffff;
4934 first[i] = get_partition_start(pe);
4935 last[i] = first[i] + get_nr_sects(p) - 1;
4941 check(int n, uint h, uint s, uint c, off_t start)
4943 off_t total, real_s, real_c;
4945 real_s = sector(s) - 1;
4946 real_c = cylinder(s, c);
4947 total = (real_c * sectors + real_s) * heads + h;
4949 fprintf(stderr, _("Warning: partition %d contains sector 0\n"), n);
4952 _("Partition %d: head %d greater than maximum %d\n"),
4954 if (real_s >= sectors)
4955 fprintf(stderr, _("Partition %d: sector %d greater than "
4956 "maximum %d\n"), n, s, sectors);
4957 if (real_c >= cylinders)
4958 fprintf(stderr, _("Partitions %d: cylinder %llu greater than "
4959 "maximum %d\n"), n, (unsigned long long)real_c + 1, cylinders);
4960 if (cylinders <= 1024 && start != total)
4962 _("Partition %d: previous sectors %llu disagrees with "
4963 "total %llu\n"), n, (unsigned long long)start, (unsigned long long)total);
4971 off_t first[partitions], last[partitions];
4972 struct partition *p;
4974 if (warn_geometry())
4977 #ifdef CONFIG_FEATURE_SUN_LABEL
4978 if (label_sun == current_label_type) {
4983 #ifdef CONFIG_FEATURE_SGI_LABEL
4984 if (label_sgi == current_label_type) {
4990 fill_bounds(first, last);
4991 for (i = 0; i < partitions; i++) {
4992 struct pte *pe = &ptes[i];
4995 if (p->sys_ind && !IS_EXTENDED(p->sys_ind)) {
4996 check_consistency(p, i);
4997 if (get_partition_start(pe) < first[i])
4998 printf(_("Warning: bad start-of-data in "
4999 "partition %d\n"), i + 1);
5000 check(i + 1, p->end_head, p->end_sector, p->end_cyl,
5002 total += last[i] + 1 - first[i];
5003 for (j = 0; j < i; j++)
5004 if ((first[i] >= first[j] && first[i] <= last[j])
5005 || ((last[i] <= last[j] && last[i] >= first[j]))) {
5006 printf(_("Warning: partition %d overlaps "
5007 "partition %d.\n"), j + 1, i + 1);
5008 total += first[i] >= first[j] ?
5009 first[i] : first[j];
5010 total -= last[i] <= last[j] ?
5016 if (extended_offset) {
5017 struct pte *pex = &ptes[ext_index];
5018 off_t e_last = get_start_sect(pex->part_table) +
5019 get_nr_sects(pex->part_table) - 1;
5021 for (i = 4; i < partitions; i++) {
5023 p = ptes[i].part_table;
5025 if (i != 4 || i + 1 < partitions)
5026 printf(_("Warning: partition %d "
5027 "is empty\n"), i + 1);
5029 else if (first[i] < extended_offset ||
5031 printf(_("Logical partition %d not entirely in "
5032 "partition %d\n"), i + 1, ext_index + 1);
5036 if (total > heads * sectors * cylinders)
5037 printf(_("Total allocated sectors %d greater than the maximum "
5038 "%d\n"), total, heads * sectors * cylinders);
5039 else if ((total = heads * sectors * cylinders - total) != 0)
5040 printf(_("%d unallocated sectors\n"), total);
5044 add_partition(int n, int sys)
5046 char mesg[256]; /* 48 does not suffice in Japanese */
5047 int i, num_read = 0;
5048 struct partition *p = ptes[n].part_table;
5049 struct partition *q = ptes[ext_index].part_table;
5051 off_t start, stop = 0, limit, temp,
5052 first[partitions], last[partitions];
5054 if (p && p->sys_ind) {
5055 printf(_("Partition %d is already defined. Delete "
5056 "it before re-adding it.\n"), n + 1);
5059 fill_bounds(first, last);
5061 start = sector_offset;
5062 if (display_in_cyl_units || !total_number_of_sectors)
5063 llimit = heads * sectors * cylinders - 1;
5065 llimit = total_number_of_sectors - 1;
5067 if (limit != llimit)
5069 if (extended_offset) {
5070 first[ext_index] = extended_offset;
5071 last[ext_index] = get_start_sect(q) +
5072 get_nr_sects(q) - 1;
5075 start = extended_offset + sector_offset;
5076 limit = get_start_sect(q) + get_nr_sects(q) - 1;
5078 if (display_in_cyl_units)
5079 for (i = 0; i < partitions; i++)
5080 first[i] = (cround(first[i]) - 1) * units_per_sector;
5082 snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
5085 for (i = 0; i < partitions; i++) {
5088 if (start == ptes[i].offset)
5089 start += sector_offset;
5090 lastplusoff = last[i] + ((n < 4) ? 0 : sector_offset);
5091 if (start >= first[i] && start <= lastplusoff)
5092 start = lastplusoff + 1;
5096 if (start >= temp+units_per_sector && num_read) {
5097 printf(_("Sector %llu is already allocated\n"), (unsigned long long)temp);
5101 if (!num_read && start == temp) {
5104 saved_start = start;
5105 start = read_int(cround(saved_start), cround(saved_start), cround(limit),
5107 if (display_in_cyl_units) {
5108 start = (start - 1) * units_per_sector;
5109 if (start < saved_start) start = saved_start;
5113 } while (start != temp || !num_read);
5114 if (n > 4) { /* NOT for fifth partition */
5115 struct pte *pe = &ptes[n];
5117 pe->offset = start - sector_offset;
5118 if (pe->offset == extended_offset) { /* must be corrected */
5120 if (sector_offset == 1)
5125 for (i = 0; i < partitions; i++) {
5126 struct pte *pe = &ptes[i];
5128 if (start < pe->offset && limit >= pe->offset)
5129 limit = pe->offset - 1;
5130 if (start < first[i] && limit >= first[i])
5131 limit = first[i] - 1;
5133 if (start > limit) {
5134 printf(_("No free sectors available\n"));
5139 if (cround(start) == cround(limit)) {
5142 snprintf(mesg, sizeof(mesg),
5143 _("Last %s or +size or +sizeM or +sizeK"),
5144 str_units(SINGULAR));
5145 stop = read_int(cround(start), cround(limit), cround(limit),
5146 cround(start), mesg);
5147 if (display_in_cyl_units) {
5148 stop = stop * units_per_sector - 1;
5154 set_partition(n, 0, start, stop, sys);
5156 set_partition(n - 1, 1, ptes[n].offset, stop, EXTENDED);
5158 if (IS_EXTENDED(sys)) {
5159 struct pte *pe4 = &ptes[4];
5160 struct pte *pen = &ptes[n];
5163 pen->ext_pointer = p;
5164 pe4->offset = extended_offset = start;
5165 pe4->sectorbuffer = xcalloc(1, sector_size);
5166 pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
5167 pe4->ext_pointer = pe4->part_table + 1;
5176 if (partitions > 5 || ptes[4].part_table->sys_ind) {
5177 struct pte *pe = &ptes[partitions];
5179 pe->sectorbuffer = xcalloc(1, sector_size);
5180 pe->part_table = pt_offset(pe->sectorbuffer, 0);
5181 pe->ext_pointer = pe->part_table + 1;
5186 add_partition(partitions - 1, LINUX_NATIVE);
5192 int i, free_primary = 0;
5194 if (warn_geometry())
5197 #ifdef CONFIG_FEATURE_SUN_LABEL
5198 if (label_sun == current_label_type) {
5199 add_sun_partition(get_partition(0, partitions), LINUX_NATIVE);
5203 #ifdef CONFIG_FEATURE_SGI_LABEL
5204 if (label_sgi == current_label_type) {
5205 sgi_add_partition(get_partition(0, partitions), LINUX_NATIVE);
5209 #ifdef CONFIG_FEATURE_AIX_LABEL
5210 if (label_aix == current_label_type) {
5211 printf(_("\tSorry - this fdisk cannot handle AIX disk labels."
5212 "\n\tIf you want to add DOS-type partitions, create"
5213 "\n\ta new empty DOS partition table first. (Use o.)"
5215 "This will destroy the present disk contents.\n"));
5220 for (i = 0; i < 4; i++)
5221 free_primary += !ptes[i].part_table->sys_ind;
5223 if (!free_primary && partitions >= MAXIMUM_PARTS) {
5224 printf(_("The maximum number of partitions has been created\n"));
5228 if (!free_primary) {
5229 if (extended_offset)
5232 printf(_("You must delete some partition and add "
5233 "an extended partition first\n"));
5235 char c, line[LINE_LENGTH];
5236 snprintf(line, sizeof(line), "%s\n %s\n p primary "
5237 "partition (1-4)\n",
5238 "Command action", (extended_offset ?
5239 "l logical (5 or over)" : "e extended"));
5241 if ((c = read_char(line)) == 'p' || c == 'P') {
5242 i = get_nonexisting_partition(0, 4);
5244 add_partition(i, LINUX_NATIVE);
5247 else if (c == 'l' && extended_offset) {
5251 else if (c == 'e' && !extended_offset) {
5252 i = get_nonexisting_partition(0, 4);
5254 add_partition(i, EXTENDED);
5258 printf(_("Invalid partition number "
5259 "for type `%c'\n"), c);
5269 if (label_dos == current_label_type) {
5270 for (i = 0; i < 3; i++)
5271 if (ptes[i].changed)
5272 ptes[3].changed = 1;
5273 for (i = 3; i < partitions; i++) {
5274 struct pte *pe = &ptes[i];
5277 write_part_table_flag(pe->sectorbuffer);
5278 write_sector(pe->offset, pe->sectorbuffer);
5282 #ifdef CONFIG_FEATURE_SGI_LABEL
5283 else if (label_sgi == current_label_type) {
5284 /* no test on change? the printf below might be mistaken */
5288 #ifdef CONFIG_FEATURE_SUN_LABEL
5289 else if (label_sun == current_label_type) {
5292 for (i = 0; i < 8; i++)
5293 if (ptes[i].changed)
5300 printf(_("The partition table has been altered!\n\n"));
5301 reread_partition_table(1);
5305 reread_partition_table(int leave)
5310 printf(_("Calling ioctl() to re-read partition table.\n"));
5313 if ((i = ioctl(fd, BLKRRPART)) != 0) {
5316 /* some kernel versions (1.2.x) seem to have trouble
5317 rereading the partition table, but if asked to do it
5318 twice, the second time works. - biro@yggdrasil.com */
5321 if ((i = ioctl(fd, BLKRRPART)) != 0)
5326 printf(_("\nWARNING: Re-reading the partition table "
5327 "failed with error %d: %s.\n"
5328 "The kernel still uses the old table.\n"
5329 "The new table will be used "
5330 "at the next reboot.\n"),
5331 error, strerror(error));
5336 _("\nWARNING: If you have created or modified any DOS 6.x\n"
5337 "partitions, please see the fdisk manual page for additional\n"
5343 printf(_("Syncing disks.\n"));
5345 sleep(4); /* for sync() */
5349 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
5351 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
5352 #define MAX_PER_LINE 16
5354 print_buffer(char *pbuffer)
5358 for (i = 0, l = 0; i < sector_size; i++, l++) {
5360 printf("0x%03X:", i);
5361 printf(" %02X", (unsigned char) pbuffer[i]);
5362 if (l == MAX_PER_LINE - 1) {
5378 printf(_("Device: %s\n"), disk_device);
5379 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
5380 if (label_sun == current_label_type || label_sgi == current_label_type)
5381 print_buffer(MBRbuffer);
5384 for (i = 3; i < partitions; i++)
5385 print_buffer(ptes[i].sectorbuffer);
5391 struct pte *pe = &ptes[i];
5392 struct partition *p = pe->part_table;
5395 if (warn_geometry())
5397 if (!p->sys_ind || !get_nr_sects(p) || IS_EXTENDED(p->sys_ind)) {
5398 printf(_("Partition %d has no data area\n"), i + 1);
5401 first = get_partition_start(pe);
5402 new = read_int(first, first, first + get_nr_sects(p) - 1, first,
5403 _("New beginning of data")) - pe->offset;
5405 if (new != get_nr_sects(p)) {
5406 first = get_nr_sects(p) + get_start_sect(p) - new;
5407 set_nr_sects(p, first);
5408 set_start_sect(p, new);
5420 c = tolower(read_char(_("Expert command (m for help): ")));
5423 #ifdef CONFIG_FEATURE_SUN_LABEL
5424 if (label_sun == current_label_type)
5429 if (label_dos == current_label_type)
5430 move_begin(get_partition(0, partitions));
5433 user_cylinders = cylinders =
5434 read_int(1, cylinders, 1048576, 0,
5435 _("Number of cylinders"));
5436 #ifdef CONFIG_FEATURE_SUN_LABEL
5437 if (label_sun == current_label_type)
5438 sun_set_ncyl(cylinders);
5440 if (label_dos == current_label_type)
5447 #ifdef CONFIG_FEATURE_SGI_LABEL
5448 if (label_sgi == current_label_type)
5452 #ifdef CONFIG_FEATURE_SUN_LABEL
5453 if (label_sun == current_label_type)
5457 if (label_dos == current_label_type)
5461 if (label_dos == current_label_type)
5462 fix_partition_table_order();
5465 #ifdef CONFIG_FEATURE_SGI_LABEL
5470 user_heads = heads = read_int(1, heads, 256, 0,
5471 _("Number of heads"));
5475 #ifdef CONFIG_FEATURE_SUN_LABEL
5476 if (label_sun == current_label_type)
5481 #ifdef CONFIG_FEATURE_SUN_LABEL
5482 if (label_sun == current_label_type)
5487 #ifdef CONFIG_FEATURE_SUN_LABEL
5488 if (label_sun == current_label_type)
5501 user_sectors = sectors = read_int(1, sectors, 63, 0,
5502 _("Number of sectors"));
5503 if (dos_compatible_flag) {
5504 sector_offset = sectors;
5505 fprintf(stderr, _("Warning: setting "
5506 "sector offset for DOS "
5515 write_table(); /* does not return */
5518 #ifdef CONFIG_FEATURE_SUN_LABEL
5519 if (label_sun == current_label_type)
5520 sun_set_pcylcount();
5528 #endif /* ADVANCED mode */
5531 is_ide_cdrom_or_tape(const char *device)
5535 struct stat statbuf;
5538 /* No device was given explicitly, and we are trying some
5539 likely things. But opening /dev/hdc may produce errors like
5540 "hdc: tray open or drive not ready"
5541 if it happens to be a CD-ROM drive. It even happens that
5542 the process hangs on the attempt to read a music CD.
5543 So try to be careful. This only works since 2.1.73. */
5545 if (strncmp("/dev/hd", device, 7))
5548 snprintf(buf, sizeof(buf), "/proc/ide/%s/media", device+5);
5549 procf = fopen(buf, "r");
5550 if (procf != NULL && fgets(buf, sizeof(buf), procf))
5551 is_ide = (!strncmp(buf, "cdrom", 5) ||
5552 !strncmp(buf, "tape", 4));
5554 /* Now when this proc file does not exist, skip the
5555 device when it is read-only. */
5556 if (stat(device, &statbuf) == 0)
5557 is_ide = ((statbuf.st_mode & 0222) == 0);
5566 try(const char *device, int user_specified)
5570 disk_device = device;
5571 if (setjmp(listingbuf))
5573 if (!user_specified)
5574 if (is_ide_cdrom_or_tape(device))
5576 if ((fd = open(disk_device, type_open)) >= 0) {
5577 gb = get_boot(try_only);
5578 if (gb > 0) { /* I/O error */
5580 } else if (gb < 0) { /* no DOS signature */
5581 list_disk_geometry();
5582 if (label_aix == current_label_type){
5585 #ifdef CONFIG_FEATURE_OSF_LABEL
5586 if (btrydev(device) < 0)
5589 _("Disk %s doesn't contain a valid "
5590 "partition table\n"), device);
5595 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5596 if (label_sun != current_label_type && partitions > 4){
5597 delete_partition(ext_index);
5602 /* Ignore other errors, since we try IDE
5603 and SCSI hard disks which may not be
5604 installed on the system. */
5605 if (errno == EACCES) {
5606 fprintf(stderr, _("Cannot open %s\n"), device);
5612 /* for fdisk -l: try all things in /proc/partitions
5613 that look like a partition name (do not end in a digit) */
5618 char line[100], ptname[100], devname[120], *s;
5621 procpt = bb_wfopen(PROC_PARTITIONS, "r");
5623 while (fgets(line, sizeof(line), procpt)) {
5624 if (sscanf(line, " %d %d %d %[^\n ]",
5625 &ma, &mi, &sz, ptname) != 4)
5627 for (s = ptname; *s; s++);
5630 sprintf(devname, "/dev/%s", ptname);
5633 #ifdef CONFIG_FEATURE_CLEAN_UP
5638 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5640 unknown_command(int c)
5642 printf(_("%c: unknown command\n"), c);
5646 int fdisk_main(int argc, char **argv)
5649 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5652 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5658 * fdisk -l [-b sectorsize] [-u] device ...
5659 * fdisk -s [partition] ...
5660 * fdisk [-b sectorsize] [-u] device
5662 * Options -C, -H, -S set the geometry.
5665 while ((c = getopt(argc, argv, "b:C:H:lS:uvV"
5666 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5672 /* Ugly: this sector size is really per device,
5673 so cannot be combined with multiple disks,
5674 and te same goes for the C/H/S options.
5676 sector_size = atoi(optarg);
5677 if (sector_size != 512 && sector_size != 1024 &&
5678 sector_size != 2048)
5681 user_set_sector_size = 1;
5684 user_cylinders = atoi(optarg);
5687 user_heads = atoi(optarg);
5688 if (user_heads <= 0 || user_heads >= 256)
5692 user_sectors = atoi(optarg);
5693 if (user_sectors <= 0 || user_sectors >= 64)
5697 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5701 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5707 display_in_cyl_units = 0;
5711 printf("fdisk v" UTIL_LINUX_VERSION "\n");
5718 if (user_set_sector_size && argc-optind != 1)
5719 printf(_("Warning: the -b (set sector size) option should"
5720 " be used with one specified device\n"));
5722 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5726 type_open = O_RDONLY;
5727 if (argc > optind) {
5730 /* avoid gcc warning:
5731 variable `k' might be clobbered by `longjmp' */
5735 for (k = optind; k < argc; k++)
5738 /* we no longer have default device names */
5739 /* but, we can use /proc/partitions instead */
5743 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5747 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
5753 type_open = O_RDONLY;
5755 opts = argc - optind;
5759 for (j = optind; j < argc; j++) {
5760 disk_device = argv[j];
5761 if ((fd = open(disk_device, type_open)) < 0)
5762 fdisk_fatal(unable_to_open);
5763 if (ioctl(fd, BLKGETSIZE, &size))
5764 fdisk_fatal(ioctl_error);
5767 printf("%ld\n", size/2);
5769 printf("%s: %ld\n", argv[j], size/2);
5775 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
5776 if (argc-optind == 1)
5777 disk_device = argv[optind];
5783 #ifdef CONFIG_FEATURE_OSF_LABEL
5784 if (label_osf == current_label_type) {
5785 /* OSF label, and no DOS label */
5786 printf(_("Detected an OSF/1 disklabel on %s, entering "
5787 "disklabel mode.\n"),
5790 /*Why do we do this? It seems to be counter-intuitive*/
5791 current_label_type = label_dos;
5792 /* If we return we may want to make an empty DOS label? */
5798 c = tolower(read_char(_("Command (m for help): ")));
5801 if (label_dos == current_label_type)
5802 toggle_active(get_partition(1, partitions));
5803 #ifdef CONFIG_FEATURE_SUN_LABEL
5804 else if (label_sun == current_label_type)
5805 toggle_sunflags(get_partition(1, partitions),
5808 #ifdef CONFIG_FEATURE_SGI_LABEL
5809 else if (label_sgi == current_label_type)
5810 sgi_set_bootpartition(
5811 get_partition(1, partitions));
5817 #ifdef CONFIG_FEATURE_SGI_LABEL
5818 if (label_sgi == current_label_type) {
5819 printf(_("\nThe current boot file is: %s\n"),
5820 sgi_get_bootfile());
5821 if (read_chars(_("Please enter the name of the "
5822 "new boot file: ")) == '\n')
5823 printf(_("Boot file unchanged\n"));
5825 sgi_set_bootfile(line_ptr);
5828 #ifdef CONFIG_FEATURE_OSF_LABEL
5833 if (label_dos == current_label_type)
5834 toggle_dos_compatibility_flag();
5835 #ifdef CONFIG_FEATURE_SUN_LABEL
5836 else if (label_sun == current_label_type)
5837 toggle_sunflags(get_partition(1, partitions),
5840 #ifdef CONFIG_FEATURE_SGI_LABEL
5841 else if (label_sgi == current_label_type)
5842 sgi_set_swappartition(
5843 get_partition(1, partitions));
5851 #ifdef CONFIG_FEATURE_SGI_LABEL
5852 /* If sgi_label then don't use get_existing_partition,
5853 let the user select a partition, since
5854 get_existing_partition() only works for Linux-like
5856 if (label_sgi != current_label_type) {
5857 j = get_existing_partition(1, partitions);
5859 j = get_partition(1, partitions);
5862 j = get_existing_partition(1, partitions);
5865 delete_partition(j);
5869 #ifdef CONFIG_FEATURE_SGI_LABEL
5870 if (label_sgi == current_label_type)
5876 list_types(get_sys_types());
5895 #ifdef CONFIG_FEATURE_SUN_LABEL
5909 write_table(); /* does not return */
5911 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
5913 #ifdef CONFIG_FEATURE_SGI_LABEL
5914 if (label_sgi == current_label_type) {
5916 _("\n\tSorry, no experts menu for SGI "
5917 "partition tables available.\n\n"));
5930 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */