Ignore:
Timestamp:
Nov 4, 2007, 3:16:40 AM (16 years ago)
Author:
Bruno Cornec
Message:

Update to busybox 1.7.2

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/2.2.5/mindi-busybox/util-linux/fdisk.c

    r821 r1765  
     1/* vi: set sw=4 ts=4: */
    12/* fdisk.c -- Partition table manipulator for Linux.
    23 *
     
    78 */
    89
    9 /* Current changes have not compatibility with this version */
    10 #define UTIL_LINUX_VERSION "2.12"
    11 
    12 
    13 #define _(x) x
    14 
    15 #define PROC_PARTITIONS "/proc/partitions"
    16 
    17 #include <features.h>
    18 #include <sys/types.h>
    19 #include <sys/stat.h>           /* stat */
    20 #include <ctype.h>
    21 #include <stdlib.h>
    22 #include <stdio.h>
    23 #include <string.h>
    24 #include <errno.h>
    25 #include <unistd.h>
    26 #include <fcntl.h>
    27 #include <setjmp.h>
     10#ifndef _LARGEFILE64_SOURCE
     11/* For lseek64 */
     12#define _LARGEFILE64_SOURCE
     13#endif
    2814#include <assert.h>             /* assert */
    29 #include <getopt.h>
    30 #include <endian.h>
    31 #include <sys/ioctl.h>
    32 #include <sys/param.h>
    33 #include <sys/sysmacros.h>     /* major */
    34 
    35 #include <stdint.h>        /* for uint32_t, uint16_t, uint8_t, int16_t, etc */
    36 
    37 /* Copied from linux/major.h */
    38 #define FLOPPY_MAJOR    2
    39 
    40 #include <sys/utsname.h>
    41 
    42 #include "busybox.h"
    43 
    44 #define DKTYPENAMES
    45 
    46 /*
    47    fdisk.h
    48 */
     15#include "libbb.h"
     16
     17/* Looks like someone forgot to add this to config system */
     18#ifndef ENABLE_FEATURE_FDISK_BLKSIZE
     19# define ENABLE_FEATURE_FDISK_BLKSIZE 0
     20# define USE_FEATURE_FDISK_BLKSIZE(a)
     21#endif
    4922
    5023#define DEFAULT_SECTOR_SIZE     512
    5124#define MAX_SECTOR_SIZE 2048
    52 #define SECTOR_SIZE     512     /* still used in BSD code */
     25#define SECTOR_SIZE     512     /* still used in osf/sgi/sun code */
    5326#define MAXIMUM_PARTS   60
    5427
     
    6437#define LINUX_RAID      0xfd
    6538
    66 #define SUNOS_SWAP 3
    67 #define WHOLE_DISK 5
    68 
    69 #define IS_EXTENDED(i) \
    70     ((i) == EXTENDED || (i) == WIN98_EXTENDED || (i) == LINUX_EXTENDED)
    71 
    72 #define SIZE(a) (sizeof(a)/sizeof((a)[0]))
    73 
    74 #define cround(n)       (display_in_cyl_units ? ((n)/units_per_sector)+1 : (n))
    75 #define scround(x)      (((x)+units_per_sector-1)/units_per_sector)
    76 
    77 #ifdef CONFIG_FEATURE_SUN_LABEL
    78 #define SCSI_IOCTL_GET_IDLUN 0x5382
    79 #endif
    80 
    81 
    82 /* including <linux/hdreg.h> also fails */
     39/* Used for sector numbers. Today's disk sizes make it necessary */
     40typedef unsigned long long ullong;
     41
    8342struct hd_geometry {
    8443    unsigned char heads;
     
    8847};
    8948
    90 #define HDIO_GETGEO             0x0301  /* get device geometry */
    91 
    92 
    93 struct systypes {
    94     const char *name;
    95 };
    96 
    97 static uint sector_size = DEFAULT_SECTOR_SIZE;
    98 static uint user_set_sector_size;
    99 static uint sector_offset = 1;
    100 
    101 /*
    102  * Raw disk label. For DOS-type partition tables the MBR,
    103  * with descriptions of the primary partitions.
    104  */
    105 #if (MAX_SECTOR_SIZE) > (BUFSIZ+1)
    106 static char MBRbuffer[MAX_SECTOR_SIZE];
    107 #else
    108 # define MBRbuffer bb_common_bufsiz1
    109 #endif
    110 
    111 #ifdef CONFIG_FEATURE_OSF_LABEL
     49#define HDIO_GETGEO     0x0301  /* get device geometry */
     50
     51static const char msg_building_new_label[] ALIGN1 =
     52"Building a new %s. Changes will remain in memory only,\n"
     53"until you decide to write them. After that the previous content\n"
     54"won't be recoverable.\n\n";
     55
     56static const char msg_part_already_defined[] ALIGN1 =
     57"Partition %d is already defined, delete it before re-adding\n";
     58
     59
     60static unsigned sector_size = DEFAULT_SECTOR_SIZE;
     61static unsigned user_set_sector_size;
     62static unsigned sector_offset = 1;
     63
     64#if ENABLE_FEATURE_OSF_LABEL
    11265static int possibly_osf_label;
    11366#endif
    11467
    115 static uint heads, sectors, cylinders;
     68static unsigned heads, sectors, cylinders;
    11669static void update_units(void);
    11770
    118 
    119 /*
    120  * return partition name - uses static storage unless buf is supplied
    121  */
    122 static const char *
    123 partname(const char *dev, int pno, int lth)
    124 {
    125     static char buffer[80];
    126     const char *p;
    127     int w, wp;
    128     int bufsiz;
    129     char *bufp;
    130 
    131     bufp = buffer;
    132     bufsiz = sizeof(buffer);
    133 
    134     w = strlen(dev);
    135     p = "";
    136 
    137     if (isdigit(dev[w-1]))
    138         p = "p";
    139 
    140     /* devfs kludge - note: fdisk partition names are not supposed
    141        to equal kernel names, so there is no reason to do this */
    142     if (strcmp(dev + w - 4, "disc") == 0) {
    143         w -= 4;
    144         p = "part";
    145     }
    146 
    147     wp = strlen(p);
    148 
    149     if (lth) {
    150         snprintf(bufp, bufsiz, "%*.*s%s%-2u",
    151              lth-wp-2, w, dev, p, pno);
    152     } else {
    153         snprintf(bufp, bufsiz, "%.*s%s%-2u", w, dev, p, pno);
    154     }
    155     return bufp;
    156 }
    15771
    15872struct partition {
     
    16983} ATTRIBUTE_PACKED;
    17084
    171 enum failure {
    172     ioctl_error, unable_to_open, unable_to_read, unable_to_seek,
    173     unable_to_write
    174 };
    175 
    176 enum label_type{
     85static const char unable_to_open[] ALIGN1 = "cannot open %s";
     86static const char unable_to_read[] ALIGN1 = "cannot read from %s";
     87static const char unable_to_seek[] ALIGN1 = "cannot seek on %s";
     88static const char unable_to_write[] ALIGN1 = "cannot write to %s";
     89static const char ioctl_error[] ALIGN1 = "BLKGETSIZE ioctl failed on %s";
     90static void fdisk_fatal(const char *why) ATTRIBUTE_NORETURN;
     91
     92enum label_type {
    17793    label_dos, label_sun, label_sgi, label_aix, label_osf
    17894};
     95
     96#define LABEL_IS_DOS    (label_dos == current_label_type)
     97
     98#if ENABLE_FEATURE_SUN_LABEL
     99#define LABEL_IS_SUN    (label_sun == current_label_type)
     100#define STATIC_SUN static
     101#else
     102#define LABEL_IS_SUN    0
     103#define STATIC_SUN extern
     104#endif
     105
     106#if ENABLE_FEATURE_SGI_LABEL
     107#define LABEL_IS_SGI    (label_sgi == current_label_type)
     108#define STATIC_SGI static
     109#else
     110#define LABEL_IS_SGI    0
     111#define STATIC_SGI extern
     112#endif
     113
     114#if ENABLE_FEATURE_AIX_LABEL
     115#define LABEL_IS_AIX    (label_aix == current_label_type)
     116#define STATIC_AIX static
     117#else
     118#define LABEL_IS_AIX    0
     119#define STATIC_AIX extern
     120#endif
     121
     122#if ENABLE_FEATURE_OSF_LABEL
     123#define LABEL_IS_OSF    (label_osf == current_label_type)
     124#define STATIC_OSF static
     125#else
     126#define LABEL_IS_OSF    0
     127#define STATIC_OSF extern
     128#endif
    179129
    180130enum action { fdisk, require, try_only, create_empty_dos, create_empty_sun };
     
    185135static int fd;                  /* the disk */
    186136static int partitions = 4;      /* maximum partition + 1 */
    187 static uint display_in_cyl_units = 1;
    188 static uint units_per_sector = 1;
    189 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
    190 static char *line_ptr;
     137static int display_in_cyl_units = 1;
     138static unsigned units_per_sector = 1;
     139#if ENABLE_FEATURE_FDISK_WRITABLE
    191140static void change_units(void);
    192141static void reread_partition_table(int leave);
    193142static void delete_partition(int i);
    194143static int get_partition(int warn, int max);
    195 static void list_types(const struct systypes *sys);
    196 static uint read_int(uint low, uint dflt, uint high, uint base, char *mesg);
     144static void list_types(const char *const *sys);
     145static unsigned read_int(unsigned low, unsigned dflt, unsigned high, unsigned base, const char *mesg);
    197146#endif
    198147static const char *partition_type(unsigned char type);
    199 static void fdisk_fatal(enum failure why) ATTRIBUTE_NORETURN;
    200148static void get_geometry(void);
    201149static int get_boot(enum action what);
     
    204152#define SINGULAR 1
    205153
    206 #define hex_val(c)      ({ \
    207                 char _c = (c); \
    208                 isdigit(_c) ? _c - '0' : \
    209                 tolower(_c) + 10 - 'a'; \
    210             })
    211 
    212 
    213 #define LINE_LENGTH     800
    214 #define pt_offset(b, n) ((struct partition *)((b) + 0x1be + \
    215                 (n) * sizeof(struct partition)))
    216 #define sector(s)       ((s) & 0x3f)
    217 #define cylinder(s, c)  ((c) | (((s) & 0xc0) << 2))
    218 
    219 #define hsc2sector(h,s,c) (sector(s) - 1 + sectors * \
    220                 ((h) + heads * cylinder(s,c)))
    221 #define set_hsc(h,s,c,sector) { \
    222                 s = sector % sectors + 1;       \
    223                 sector /= sectors;      \
    224                 h = sector % heads;     \
    225                 sector /= heads;        \
    226                 c = sector & 0xff;      \
    227                 s |= (sector >> 2) & 0xc0;      \
    228             }
    229 
    230 
    231 static int32_t get_start_sect(const struct partition *p);
    232 static int32_t get_nr_sects(const struct partition *p);
     154static unsigned get_start_sect(const struct partition *p);
     155static unsigned get_nr_sects(const struct partition *p);
    233156
    234157/*
     
    240163 * partition and one link to the next one.
    241164 */
    242 static struct pte {
     165struct pte {
    243166    struct partition *part_table;   /* points into sectorbuffer */
    244167    struct partition *ext_pointer;  /* points into sectorbuffer */
    245 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
     168    ullong offset;          /* disk sector number */
     169    char *sectorbuffer;     /* disk sector contents */
     170#if ENABLE_FEATURE_FDISK_WRITABLE
    246171    char changed;           /* boolean */
    247172#endif
    248     off_t offset;            /* disk sector number */
    249     char *sectorbuffer;     /* disk sector contents */
    250 } ptes[MAXIMUM_PARTS];
    251 
    252 
    253 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
     173};
     174
     175/* DOS partition types */
     176
     177static const char *const i386_sys_types[] = {
     178    "\x00" "Empty",
     179    "\x01" "FAT12",
     180    "\x04" "FAT16 <32M",
     181    "\x05" "Extended",         /* DOS 3.3+ extended partition */
     182    "\x06" "FAT16",            /* DOS 16-bit >=32M */
     183    "\x07" "HPFS/NTFS",        /* OS/2 IFS, eg, HPFS or NTFS or QNX */
     184    "\x0a" "OS/2 Boot Manager",/* OS/2 Boot Manager */
     185    "\x0b" "Win95 FAT32",
     186    "\x0c" "Win95 FAT32 (LBA)",/* LBA really is 'Extended Int 13h' */
     187    "\x0e" "Win95 FAT16 (LBA)",
     188    "\x0f" "Win95 Ext'd (LBA)",
     189    "\x11" "Hidden FAT12",
     190    "\x12" "Compaq diagnostics",
     191    "\x14" "Hidden FAT16 <32M",
     192    "\x16" "Hidden FAT16",
     193    "\x17" "Hidden HPFS/NTFS",
     194    "\x1b" "Hidden Win95 FAT32",
     195    "\x1c" "Hidden W95 FAT32 (LBA)",
     196    "\x1e" "Hidden W95 FAT16 (LBA)",
     197    "\x3c" "Part.Magic recovery",
     198    "\x41" "PPC PReP Boot",
     199    "\x42" "SFS",
     200    "\x63" "GNU HURD or SysV", /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */
     201    "\x80" "Old Minix",        /* Minix 1.4a and earlier */
     202    "\x81" "Minix / old Linux",/* Minix 1.4b and later */
     203    "\x82" "Linux swap",       /* also Solaris */
     204    "\x83" "Linux",
     205    "\x84" "OS/2 hidden C: drive",
     206    "\x85" "Linux extended",
     207    "\x86" "NTFS volume set",
     208    "\x87" "NTFS volume set",
     209    "\x8e" "Linux LVM",
     210    "\x9f" "BSD/OS",           /* BSDI */
     211    "\xa0" "Thinkpad hibernation",
     212    "\xa5" "FreeBSD",          /* various BSD flavours */
     213    "\xa6" "OpenBSD",
     214    "\xa8" "Darwin UFS",
     215    "\xa9" "NetBSD",
     216    "\xab" "Darwin boot",
     217    "\xb7" "BSDI fs",
     218    "\xb8" "BSDI swap",
     219    "\xbe" "Solaris boot",
     220    "\xeb" "BeOS fs",
     221    "\xee" "EFI GPT",                    /* Intel EFI GUID Partition Table */
     222    "\xef" "EFI (FAT-12/16/32)",         /* Intel EFI System Partition */
     223    "\xf0" "Linux/PA-RISC boot",         /* Linux/PA-RISC boot loader */
     224    "\xf2" "DOS secondary",              /* DOS 3.3+ secondary */
     225    "\xfd" "Linux raid autodetect",      /* New (2.2.x) raid partition with
     226                        autodetect using persistent
     227                        superblock */
     228#if 0 /* ENABLE_WEIRD_PARTITION_TYPES */
     229    "\x02" "XENIX root",
     230    "\x03" "XENIX usr",
     231    "\x08" "AIX",              /* AIX boot (AIX -- PS/2 port) or SplitDrive */
     232    "\x09" "AIX bootable",     /* AIX data or Coherent */
     233    "\x10" "OPUS",
     234    "\x18" "AST SmartSleep",
     235    "\x24" "NEC DOS",
     236    "\x39" "Plan 9",
     237    "\x40" "Venix 80286",
     238    "\x4d" "QNX4.x",
     239    "\x4e" "QNX4.x 2nd part",
     240    "\x4f" "QNX4.x 3rd part",
     241    "\x50" "OnTrack DM",
     242    "\x51" "OnTrack DM6 Aux1", /* (or Novell) */
     243    "\x52" "CP/M",             /* CP/M or Microport SysV/AT */
     244    "\x53" "OnTrack DM6 Aux3",
     245    "\x54" "OnTrackDM6",
     246    "\x55" "EZ-Drive",
     247    "\x56" "Golden Bow",
     248    "\x5c" "Priam Edisk",
     249    "\x61" "SpeedStor",
     250    "\x64" "Novell Netware 286",
     251    "\x65" "Novell Netware 386",
     252    "\x70" "DiskSecure Multi-Boot",
     253    "\x75" "PC/IX",
     254    "\x93" "Amoeba",
     255    "\x94" "Amoeba BBT",       /* (bad block table) */
     256    "\xa7" "NeXTSTEP",
     257    "\xbb" "Boot Wizard hidden",
     258    "\xc1" "DRDOS/sec (FAT-12)",
     259    "\xc4" "DRDOS/sec (FAT-16 < 32M)",
     260    "\xc6" "DRDOS/sec (FAT-16)",
     261    "\xc7" "Syrinx",
     262    "\xda" "Non-FS data",
     263    "\xdb" "CP/M / CTOS / ...",/* CP/M or Concurrent CP/M or
     264                                  Concurrent DOS or CTOS */
     265    "\xde" "Dell Utility",     /* Dell PowerEdge Server utilities */
     266    "\xdf" "BootIt",           /* BootIt EMBRM */
     267    "\xe1" "DOS access",       /* DOS access or SpeedStor 12-bit FAT
     268                                  extended partition */
     269    "\xe3" "DOS R/O",          /* DOS R/O or SpeedStor */
     270    "\xe4" "SpeedStor",        /* SpeedStor 16-bit FAT extended
     271                                  partition < 1024 cyl. */
     272    "\xf1" "SpeedStor",
     273    "\xf4" "SpeedStor",        /* SpeedStor large partition */
     274    "\xfe" "LANstep",          /* SpeedStor >1024 cyl. or LANstep */
     275    "\xff" "BBT",              /* Xenix Bad Block Table */
     276#endif
     277    NULL
     278};
     279
     280
     281/* Globals */
     282
     283struct globals {
     284    char *line_ptr;
     285    char line_buffer[80];
     286    char partname_buffer[80];
     287    jmp_buf listingbuf;
     288    /* Raw disk label. For DOS-type partition tables the MBR,
     289     * with descriptions of the primary partitions. */
     290    char MBRbuffer[MAX_SECTOR_SIZE];
     291    /* Partition tables */
     292    struct pte ptes[MAXIMUM_PARTS];
     293};
     294/* bb_common_bufsiz1 is too small for this on 64 bit CPUs */
     295#define G (*ptr_to_globals)
     296
     297#define line_ptr        (G.line_ptr)
     298#define listingbuf      (G.listingbuf)
     299#define line_buffer     (G.line_buffer)
     300#define partname_buffer (G.partname_buffer)
     301#define MBRbuffer       (G.MBRbuffer)
     302#define ptes            (G.ptes)
     303
     304
     305/* Code */
     306
     307#define IS_EXTENDED(i) \
     308    ((i) == EXTENDED || (i) == WIN98_EXTENDED || (i) == LINUX_EXTENDED)
     309
     310#define cround(n)       (display_in_cyl_units ? ((n)/units_per_sector)+1 : (n))
     311
     312#define scround(x)      (((x)+units_per_sector-1)/units_per_sector)
     313
     314#define pt_offset(b, n) \
     315    ((struct partition *)((b) + 0x1be + (n) * sizeof(struct partition)))
     316
     317#define sector(s)       ((s) & 0x3f)
     318
     319#define cylinder(s, c)  ((c) | (((s) & 0xc0) << 2))
     320
     321#define hsc2sector(h,s,c) \
     322    (sector(s) - 1 + sectors * ((h) + heads * cylinder(s,c)))
     323
     324#define set_hsc(h,s,c,sector) \
     325    do { \
     326        s = sector % sectors + 1;  \
     327        sector /= sectors;         \
     328        h = sector % heads;        \
     329        sector /= heads;           \
     330        c = sector & 0xff;         \
     331        s |= (sector >> 2) & 0xc0; \
     332    } while (0)
     333
     334#if ENABLE_FEATURE_FDISK_WRITABLE
     335/* read line; return 0 or first printable char */
     336static int
     337read_line(const char *prompt)
     338{
     339    int sz;
     340
     341    sz = read_line_input(prompt, line_buffer, sizeof(line_buffer), NULL);
     342    if (sz <= 0)
     343        exit(0); /* Ctrl-D or Ctrl-C */
     344
     345    if (line_buffer[sz-1] == '\n')
     346        line_buffer[--sz] = '\0';
     347
     348    line_ptr = line_buffer;
     349    while (*line_ptr && !isgraph(*line_ptr))
     350        line_ptr++;
     351    return *line_ptr;
     352}
     353#endif
     354
     355/*
     356 * return partition name - uses static storage
     357 */
     358static const char *
     359partname(const char *dev, int pno, int lth)
     360{
     361    const char *p;
     362    int w, wp;
     363    int bufsiz;
     364    char *bufp;
     365
     366    bufp = partname_buffer;
     367    bufsiz = sizeof(partname_buffer);
     368
     369    w = strlen(dev);
     370    p = "";
     371
     372    if (isdigit(dev[w-1]))
     373        p = "p";
     374
     375    /* devfs kludge - note: fdisk partition names are not supposed
     376       to equal kernel names, so there is no reason to do this */
     377    if (strcmp(dev + w - 4, "disc") == 0) {
     378        w -= 4;
     379        p = "part";
     380    }
     381
     382    wp = strlen(p);
     383
     384    if (lth) {
     385        snprintf(bufp, bufsiz, "%*.*s%s%-2u",
     386             lth-wp-2, w, dev, p, pno);
     387    } else {
     388        snprintf(bufp, bufsiz, "%.*s%s%-2u", w, dev, p, pno);
     389    }
     390    return bufp;
     391}
     392
     393#if ENABLE_FEATURE_FDISK_WRITABLE
    254394static void
    255395set_all_unchanged(void)
     
    261401}
    262402
    263 static void
     403static ALWAYS_INLINE void
    264404set_changed(int i)
    265405{
    266406    ptes[i].changed = 1;
    267407}
    268 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
    269 
    270 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_OSF_LABEL)
    271 static struct partition *
     408#endif /* FEATURE_FDISK_WRITABLE */
     409
     410static ALWAYS_INLINE struct partition *
    272411get_part_table(int i)
    273412{
    274413    return ptes[i].part_table;
    275414}
    276 #endif
    277415
    278416static const char *
     
    280418{      /* n==1: use singular */
    281419    if (n == 1)
    282         return display_in_cyl_units ? _("cylinder") : _("sector");
    283     else
    284         return display_in_cyl_units ? _("cylinders") : _("sectors");
     420        return display_in_cyl_units ? "cylinder" : "sector";
     421    return display_in_cyl_units ? "cylinders" : "sectors";
    285422}
    286423
    287424static int
    288 valid_part_table_flag(const char *mbuffer) {
    289     const unsigned char *b = (const unsigned char *)mbuffer;
    290     return (b[510] == 0x55 && b[511] == 0xaa);
    291 }
    292 
    293 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
    294 static char  line_buffer[LINE_LENGTH];
    295 
    296 /* read line; return 0 or first char */
     425valid_part_table_flag(const char *mbuffer)
     426{
     427    return (mbuffer[510] == 0x55 && (uint8_t)mbuffer[511] == 0xaa);
     428}
     429
     430#if ENABLE_FEATURE_FDISK_WRITABLE
     431static ALWAYS_INLINE void
     432write_part_table_flag(char *b)
     433{
     434    b[510] = 0x55;
     435    b[511] = 0xaa;
     436}
     437
     438static char
     439read_nonempty(const char *mesg)
     440{
     441    while (!read_line(mesg)) /* repeat */;
     442    return *line_ptr;
     443}
     444
     445static char
     446read_maybe_empty(const char *mesg)
     447{
     448    if (!read_line(mesg)) {
     449        line_ptr = line_buffer;
     450        line_ptr[0] = '\n';
     451        line_ptr[1] = '\0';
     452    }
     453    return line_ptr[0];
     454}
     455
    297456static int
    298 read_line(void)
    299 {
    300     static int got_eof = 0;
    301 
    302     fflush (stdout);         /* requested by niles@scyld.com */
    303     line_ptr = line_buffer;
    304     if (!fgets(line_buffer, LINE_LENGTH, stdin)) {
    305         if (feof(stdin))
    306             got_eof++;      /* user typed ^D ? */
    307         if (got_eof >= 3) {
    308             fprintf(stderr, _("\ngot EOF thrice - exiting..\n"));
    309             exit(1);
    310         }
    311         return 0;
    312     }
    313     while (*line_ptr && !isgraph(*line_ptr))
    314         line_ptr++;
    315     return *line_ptr;
    316 }
    317 
    318 static char
    319 read_char(const char *mesg)
    320 {
    321     do {
    322         fputs(mesg, stdout);
    323     } while (!read_line());
    324     return *line_ptr;
    325 }
    326 
    327 static char
    328 read_chars(const char *mesg)
    329 {
    330     fputs(mesg, stdout);
    331     if (!read_line()) {
    332         *line_ptr = '\n';
    333         line_ptr[1] = 0;
    334     }
    335     return *line_ptr;
    336 }
    337 
    338 static int
    339 read_hex(const struct systypes *sys)
    340 {
    341     int hex;
    342 
     457read_hex(const char *const *sys)
     458{
     459    unsigned long v;
    343460    while (1) {
    344         read_char(_("Hex code (type L to list codes): "));
    345         if (*line_ptr == 'l' || *line_ptr == 'L')
     461        read_nonempty("Hex code (type L to list codes): ");
     462        if (*line_ptr == 'l' || *line_ptr == 'L') {
    346463            list_types(sys);
    347         else if (isxdigit (*line_ptr)) {
    348             hex = 0;
    349             do
    350                 hex = hex << 4 | hex_val(*line_ptr++);
    351             while (isxdigit(*line_ptr));
    352             return hex;
    353         }
    354     }
    355 }
    356 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
    357 
    358 #ifdef CONFIG_FEATURE_AIX_LABEL
    359 /*
    360  * Copyright (C) Andreas Neuper, Sep 1998.
    361  *      This file may be redistributed under
    362  *      the terms of the GNU Public License.
    363  */
    364 
    365 typedef struct {
    366     unsigned int   magic;        /* expect AIX_LABEL_MAGIC */
    367     unsigned int   fillbytes1[124];
    368     unsigned int   physical_volume_id;
    369     unsigned int   fillbytes2[124];
    370 } aix_partition;
    371 
    372 #define AIX_LABEL_MAGIC         0xc9c2d4c1
    373 #define AIX_LABEL_MAGIC_SWAPPED 0xc1d4c2c9
    374 #define AIX_INFO_MAGIC          0x00072959
    375 #define AIX_INFO_MAGIC_SWAPPED  0x59290700
    376 
    377 #define aixlabel ((aix_partition *)MBRbuffer)
    378 
    379 
    380 /*
    381   Changes:
    382   * 1999-03-20 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
    383   *     Internationalization
    384   *
    385   * 2003-03-20 Phillip Kesling <pkesling@sgi.com>
    386   *      Some fixes
    387 */
    388 
    389 static int aix_other_endian;
    390 static short aix_volumes = 1;
    391 
    392 /*
    393  * only dealing with free blocks here
    394  */
    395 
    396 static void
    397 aix_info(void)
    398 {
    399     puts(
    400         _("\n\tThere is a valid AIX label on this disk.\n"
    401         "\tUnfortunately Linux cannot handle these\n"
    402         "\tdisks at the moment.  Nevertheless some\n"
    403         "\tadvice:\n"
    404         "\t1. fdisk will destroy its contents on write.\n"
    405         "\t2. Be sure that this disk is NOT a still vital\n"
    406         "\t   part of a volume group. (Otherwise you may\n"
    407         "\t   erase the other disks as well, if unmirrored.)\n"
    408         "\t3. Before deleting this physical volume be sure\n"
    409         "\t   to remove the disk logically from your AIX\n"
    410         "\t   machine.  (Otherwise you become an AIXpert).")
    411     );
    412 }
    413 
    414 static int
    415 check_aix_label(void)
    416 {
    417     if (aixlabel->magic != AIX_LABEL_MAGIC &&
    418         aixlabel->magic != AIX_LABEL_MAGIC_SWAPPED) {
    419         current_label_type = 0;
    420         aix_other_endian = 0;
    421         return 0;
    422     }
    423     aix_other_endian = (aixlabel->magic == AIX_LABEL_MAGIC_SWAPPED);
    424     update_units();
    425     current_label_type = label_aix;
    426     partitions = 1016;
    427     aix_volumes = 15;
    428     aix_info();
    429     /*aix_nolabel();*/              /* %% */
    430     /*aix_label = 1;*/              /* %% */
    431     return 1;
    432 }
    433 #endif  /* AIX_LABEL */
    434 
    435 #ifdef CONFIG_FEATURE_OSF_LABEL
    436 /*
    437  * Copyright (c) 1987, 1988 Regents of the University of California.
    438  * All rights reserved.
    439  *
    440  * Redistribution and use in source and binary forms, with or without
    441  * modification, are permitted provided that the following conditions
    442  * are met:
    443  * 1. Redistributions of source code must retain the above copyright
    444  *    notice, this list of conditions and the following disclaimer.
    445  * 2. Redistributions in binary form must reproduce the above copyright
    446  *    notice, this list of conditions and the following disclaimer in the
    447  *    documentation and/or other materials provided with the distribution.
    448  * 3. All advertising materials mentioning features or use of this software
    449  *    must display the following acknowledgment:
    450  *      This product includes software developed by the University of
    451  *      California, Berkeley and its contributors.
    452  * 4. Neither the name of the University nor the names of its contributors
    453  *    may be used to endorse or promote products derived from this software
    454  *    without specific prior written permission.
    455  *
    456  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
    457  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    458  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    459  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
    460  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    461  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    462  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    463  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    464  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    465  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    466  * SUCH DAMAGE.
    467  */
    468 
    469 
    470 #ifndef BSD_DISKMAGIC
    471 #define BSD_DISKMAGIC     ((uint32_t) 0x82564557)
    472 #endif
    473 
    474 #ifndef BSD_MAXPARTITIONS
    475 #define BSD_MAXPARTITIONS 16
    476 #endif
    477 
    478 #define BSD_LINUX_BOOTDIR "/usr/ucb/mdec"
    479 
    480 #if defined (i386) || defined (__sparc__) || defined (__arm__) || defined (__m68k__) || defined (__mips__) || defined (__s390__) || defined (__sh__) || defined(__x86_64__)
    481 #define BSD_LABELSECTOR   1
    482 #define BSD_LABELOFFSET   0
    483 #elif defined (__alpha__) || defined (__powerpc__) || defined (__ia64__) || defined (__hppa__)
    484 #define BSD_LABELSECTOR   0
    485 #define BSD_LABELOFFSET   64
    486 #elif defined (__s390__) || defined (__s390x__)
    487 #define BSD_LABELSECTOR   1
    488 #define BSD_LABELOFFSET   0
    489 #else
    490 #error unknown architecture
    491 #endif
    492 
    493 #define BSD_BBSIZE        8192          /* size of boot area, with label */
    494 #define BSD_SBSIZE        8192          /* max size of fs superblock */
    495 
    496 struct xbsd_disklabel {
    497     uint32_t   d_magic;                /* the magic number */
    498     int16_t    d_type;                 /* drive type */
    499     int16_t    d_subtype;              /* controller/d_type specific */
    500     char       d_typename[16];         /* type name, e.g. "eagle" */
    501     char       d_packname[16];                 /* pack identifier */
    502             /* disk geometry: */
    503     uint32_t   d_secsize;              /* # of bytes per sector */
    504     uint32_t   d_nsectors;             /* # of data sectors per track */
    505     uint32_t   d_ntracks;              /* # of tracks per cylinder */
    506     uint32_t   d_ncylinders;           /* # of data cylinders per unit */
    507     uint32_t   d_secpercyl;            /* # of data sectors per cylinder */
    508     uint32_t   d_secperunit;           /* # of data sectors per unit */
    509     /*
    510      * Spares (bad sector replacements) below
    511      * are not counted in d_nsectors or d_secpercyl.
    512      * Spare sectors are assumed to be physical sectors
    513      * which occupy space at the end of each track and/or cylinder.
    514      */
    515     uint16_t   d_sparespertrack;       /* # of spare sectors per track */
    516     uint16_t   d_sparespercyl;         /* # of spare sectors per cylinder */
    517     /*
    518      * Alternate cylinders include maintenance, replacement,
    519      * configuration description areas, etc.
    520      */
    521     uint32_t   d_acylinders;           /* # of alt. cylinders per unit */
    522 
    523             /* hardware characteristics: */
    524     /*
    525      * d_interleave, d_trackskew and d_cylskew describe perturbations
    526      * in the media format used to compensate for a slow controller.
    527      * Interleave is physical sector interleave, set up by the formatter
    528      * or controller when formatting.  When interleaving is in use,
    529      * logically adjacent sectors are not physically contiguous,
    530      * but instead are separated by some number of sectors.
    531      * It is specified as the ratio of physical sectors traversed
    532      * per logical sector.  Thus an interleave of 1:1 implies contiguous
    533      * layout, while 2:1 implies that logical sector 0 is separated
    534      * by one sector from logical sector 1.
    535      * d_trackskew is the offset of sector 0 on track N
    536      * relative to sector 0 on track N-1 on the same cylinder.
    537      * Finally, d_cylskew is the offset of sector 0 on cylinder N
    538      * relative to sector 0 on cylinder N-1.
    539      */
    540     uint16_t   d_rpm;                  /* rotational speed */
    541     uint16_t   d_interleave;           /* hardware sector interleave */
    542     uint16_t   d_trackskew;            /* sector 0 skew, per track */
    543     uint16_t   d_cylskew;              /* sector 0 skew, per cylinder */
    544     uint32_t   d_headswitch;           /* head switch time, usec */
    545     uint32_t   d_trkseek;              /* track-to-track seek, usec */
    546     uint32_t   d_flags;                /* generic flags */
    547 #define NDDATA 5
    548     uint32_t   d_drivedata[NDDATA];    /* drive-type specific information */
    549 #define NSPARE 5
    550     uint32_t   d_spare[NSPARE];        /* reserved for future use */
    551     uint32_t   d_magic2;               /* the magic number (again) */
    552     uint16_t   d_checksum;             /* xor of data incl. partitions */
    553             /* filesystem and partition information: */
    554     uint16_t   d_npartitions;          /* number of partitions in following */
    555     uint32_t   d_bbsize;               /* size of boot area at sn0, bytes */
    556     uint32_t   d_sbsize;               /* max size of fs superblock, bytes */
    557     struct xbsd_partition    {      /* the partition table */
    558         uint32_t   p_size;         /* number of sectors in partition */
    559         uint32_t   p_offset;       /* starting sector */
    560         uint32_t   p_fsize;        /* filesystem basic fragment size */
    561         uint8_t    p_fstype;       /* filesystem type, see below */
    562         uint8_t    p_frag;         /* filesystem fragments per block */
    563         uint16_t   p_cpg;          /* filesystem cylinders per group */
    564     } d_partitions[BSD_MAXPARTITIONS]; /* actually may be more */
    565 };
    566 
    567 /* d_type values: */
    568 #define BSD_DTYPE_SMD           1               /* SMD, XSMD; VAX hp/up */
    569 #define BSD_DTYPE_MSCP          2               /* MSCP */
    570 #define BSD_DTYPE_DEC           3               /* other DEC (rk, rl) */
    571 #define BSD_DTYPE_SCSI          4               /* SCSI */
    572 #define BSD_DTYPE_ESDI          5               /* ESDI interface */
    573 #define BSD_DTYPE_ST506         6               /* ST506 etc. */
    574 #define BSD_DTYPE_HPIB          7               /* CS/80 on HP-IB */
    575 #define BSD_DTYPE_HPFL          8               /* HP Fiber-link */
    576 #define BSD_DTYPE_FLOPPY        10              /* floppy */
    577 
    578 /* d_subtype values: */
    579 #define BSD_DSTYPE_INDOSPART    0x8             /* is inside dos partition */
    580 #define BSD_DSTYPE_DOSPART(s)   ((s) & 3)       /* dos partition number */
    581 #define BSD_DSTYPE_GEOMETRY     0x10            /* drive params in label */
    582 
    583 #ifdef DKTYPENAMES
    584 static const char * const xbsd_dktypenames[] = {
    585     "unknown",
    586     "SMD",
    587     "MSCP",
    588     "old DEC",
    589     "SCSI",
    590     "ESDI",
    591     "ST506",
    592     "HP-IB",
    593     "HP-FL",
    594     "type 9",
    595     "floppy",
    596     0
    597 };
    598 #define BSD_DKMAXTYPES  (sizeof(xbsd_dktypenames) / sizeof(xbsd_dktypenames[0]) - 1)
    599 #endif
    600 
    601 /*
    602  * Filesystem type and version.
    603  * Used to interpret other filesystem-specific
    604  * per-partition information.
    605  */
    606 #define BSD_FS_UNUSED   0               /* unused */
    607 #define BSD_FS_SWAP     1               /* swap */
    608 #define BSD_FS_V6       2               /* Sixth Edition */
    609 #define BSD_FS_V7       3               /* Seventh Edition */
    610 #define BSD_FS_SYSV     4               /* System V */
    611 #define BSD_FS_V71K     5               /* V7 with 1K blocks (4.1, 2.9) */
    612 #define BSD_FS_V8       6               /* Eighth Edition, 4K blocks */
    613 #define BSD_FS_BSDFFS   7               /* 4.2BSD fast file system */
    614 #define BSD_FS_BSDLFS   9               /* 4.4BSD log-structured file system */
    615 #define BSD_FS_OTHER    10              /* in use, but unknown/unsupported */
    616 #define BSD_FS_HPFS     11              /* OS/2 high-performance file system */
    617 #define BSD_FS_ISO9660  12              /* ISO-9660 filesystem (cdrom) */
    618 #define BSD_FS_ISOFS    BSD_FS_ISO9660
    619 #define BSD_FS_BOOT     13              /* partition contains bootstrap */
    620 #define BSD_FS_ADOS     14              /* AmigaDOS fast file system */
    621 #define BSD_FS_HFS      15              /* Macintosh HFS */
    622 #define BSD_FS_ADVFS    16              /* Digital Unix AdvFS */
    623 
    624 /* this is annoying, but it's also the way it is :-( */
    625 #ifdef __alpha__
    626 #define BSD_FS_EXT2     8               /* ext2 file system */
    627 #else
    628 #define BSD_FS_MSDOS    8               /* MS-DOS file system */
    629 #endif
    630 
    631 #ifdef  DKTYPENAMES
    632 static const struct systypes xbsd_fstypes[] = {
    633     { "\x00" "unused" },            /* BSD_FS_UNUSED  */
    634     { "\x01" "swap" },              /* BSD_FS_SWAP    */
    635     { "\x02" "Version 6" },         /* BSD_FS_V6      */
    636     { "\x03" "Version 7" },         /* BSD_FS_V7      */
    637     { "\x04" "System V" },          /* BSD_FS_SYSV    */
    638     { "\x05" "4.1BSD" },            /* BSD_FS_V71K    */
    639     { "\x06" "Eighth Edition" },    /* BSD_FS_V8      */
    640     { "\x07" "4.2BSD" },            /* BSD_FS_BSDFFS  */
    641 #ifdef __alpha__
    642     { "\x08" "ext2" },              /* BSD_FS_EXT2    */
    643 #else
    644     { "\x08" "MS-DOS" },            /* BSD_FS_MSDOS   */
    645 #endif
    646     { "\x09" "4.4LFS" },            /* BSD_FS_BSDLFS  */
    647     { "\x0a" "unknown" },           /* BSD_FS_OTHER   */
    648     { "\x0b" "HPFS" },              /* BSD_FS_HPFS    */
    649     { "\x0c" "ISO-9660" },          /* BSD_FS_ISO9660 */
    650     { "\x0d" "boot" },              /* BSD_FS_BOOT    */
    651     { "\x0e" "ADOS" },              /* BSD_FS_ADOS    */
    652     { "\x0f" "HFS" },               /* BSD_FS_HFS     */
    653     { "\x10" "AdvFS" },             /* BSD_FS_ADVFS   */
    654     { NULL }
    655 };
    656 #define BSD_FSMAXTYPES (SIZE(xbsd_fstypes)-1)
    657 
    658 #endif
    659 
    660 /*
    661  * flags shared by various drives:
    662  */
    663 #define BSD_D_REMOVABLE 0x01            /* removable media */
    664 #define BSD_D_ECC       0x02            /* supports ECC */
    665 #define BSD_D_BADSECT   0x04            /* supports bad sector forw. */
    666 #define BSD_D_RAMDISK   0x08            /* disk emulator */
    667 #define BSD_D_CHAIN     0x10            /* can do back-back transfers */
    668 #define BSD_D_DOSPART   0x20            /* within MSDOS partition */
    669 
    670 #endif /* OSF_LABEL */
    671 
    672 /*
    673  * Copyright (C) Andreas Neuper, Sep 1998.
    674  *      This file may be modified and redistributed under
    675  *      the terms of the GNU Public License.
    676  */
    677 
    678 struct device_parameter { /* 48 bytes */
    679     unsigned char  skew;
    680     unsigned char  gap1;
    681     unsigned char  gap2;
    682     unsigned char  sparecyl;
    683     unsigned short pcylcount;
    684     unsigned short head_vol0;
    685     unsigned short ntrks;   /* tracks in cyl 0 or vol 0 */
    686     unsigned char  cmd_tag_queue_depth;
    687     unsigned char  unused0;
    688     unsigned short unused1;
    689     unsigned short nsect;   /* sectors/tracks in cyl 0 or vol 0 */
    690     unsigned short bytes;
    691     unsigned short ilfact;
    692     unsigned int   flags;           /* controller flags */
    693     unsigned int   datarate;
    694     unsigned int   retries_on_error;
    695     unsigned int   ms_per_word;
    696     unsigned short xylogics_gap1;
    697     unsigned short xylogics_syncdelay;
    698     unsigned short xylogics_readdelay;
    699     unsigned short xylogics_gap2;
    700     unsigned short xylogics_readgate;
    701     unsigned short xylogics_writecont;
    702 };
    703 
    704 #define SGI_VOLHDR      0x00
    705 /* 1 and 2 were used for drive types no longer supported by SGI */
    706 #define SGI_SWAP        0x03
    707 /* 4 and 5 were for filesystem types SGI haven't ever supported on MIPS CPUs */
    708 #define SGI_VOLUME      0x06
    709 #define SGI_EFS         0x07
    710 #define SGI_LVOL        0x08
    711 #define SGI_RLVOL       0x09
    712 #define SGI_XFS         0x0a
    713 #define SGI_XFSLOG      0x0b
    714 #define SGI_XLV         0x0c
    715 #define SGI_XVM         0x0d
    716 #define ENTIRE_DISK     SGI_VOLUME
    717 /*
    718  * controller flags
    719  */
    720 #define SECTOR_SLIP     0x01
    721 #define SECTOR_FWD      0x02
    722 #define TRACK_FWD       0x04
    723 #define TRACK_MULTIVOL  0x08
    724 #define IGNORE_ERRORS   0x10
    725 #define RESEEK          0x20
    726 #define ENABLE_CMDTAGQ  0x40
    727 
    728 typedef struct {
    729     unsigned int   magic;            /* expect SGI_LABEL_MAGIC */
    730     unsigned short boot_part;        /* active boot partition */
    731     unsigned short swap_part;        /* active swap partition */
    732     unsigned char  boot_file[16];    /* name of the bootfile */
    733     struct device_parameter devparam;       /*  1 * 48 bytes */
    734     struct volume_directory {               /* 15 * 16 bytes */
    735         unsigned char vol_file_name[8]; /* a character array */
    736         unsigned int  vol_file_start;   /* number of logical block */
    737         unsigned int  vol_file_size;    /* number of bytes */
    738     } directory[15];
    739     struct sgi_partition {                  /* 16 * 12 bytes */
    740         unsigned int num_sectors;       /* number of blocks */
    741         unsigned int start_sector;      /* must be cylinder aligned */
    742         unsigned int id;
    743     } partitions[16];
    744     unsigned int   csum;
    745     unsigned int   fillbytes;
    746 } sgi_partition;
    747 
    748 typedef struct {
    749     unsigned int   magic;           /* looks like a magic number */
    750     unsigned int   a2;
    751     unsigned int   a3;
    752     unsigned int   a4;
    753     unsigned int   b1;
    754     unsigned short b2;
    755     unsigned short b3;
    756     unsigned int   c[16];
    757     unsigned short d[3];
    758     unsigned char  scsi_string[50];
    759     unsigned char  serial[137];
    760     unsigned short check1816;
    761     unsigned char  installer[225];
    762 } sgiinfo;
    763 
    764 #define SGI_LABEL_MAGIC         0x0be5a941
    765 #define SGI_LABEL_MAGIC_SWAPPED 0x41a9e50b
    766 #define SGI_INFO_MAGIC          0x00072959
    767 #define SGI_INFO_MAGIC_SWAPPED  0x59290700
    768 #define SGI_SSWAP16(x) (sgi_other_endian ? __swap16(x) \
    769                  : (uint16_t)(x))
    770 #define SGI_SSWAP32(x) (sgi_other_endian ? __swap32(x) \
    771                  : (uint32_t)(x))
    772 
    773 #define sgilabel ((sgi_partition *)MBRbuffer)
    774 #define sgiparam (sgilabel->devparam)
     464            continue;
     465        }
     466        v = bb_strtoul(line_ptr, NULL, 16);
     467        if (v > 0xff)
     468            /* Bad input also triggers this */
     469            continue;
     470        return v;
     471    }
     472}
     473#endif /* FEATURE_FDISK_WRITABLE */
     474
     475#include "fdisk_aix.c"
    775476
    776477typedef struct {
     
    794495    unsigned short nsect;      /* Sectors per track */
    795496    unsigned char spare3[4];   /* Even more magic... */
    796     struct sun_partition {
     497    struct sun_partinfo {
    797498        uint32_t start_cylinder;
    798499        uint32_t num_sectors;
     
    801502    unsigned short csum;       /* Label xor'd checksum */
    802503} sun_partition;
    803 
    804 
    805 #define SUN_LABEL_MAGIC          0xDABE
    806 #define SUN_LABEL_MAGIC_SWAPPED  0xBEDA
    807504#define sunlabel ((sun_partition *)MBRbuffer)
    808 #define SUN_SSWAP16(x) (sun_other_endian ? __swap16(x) \
    809                  : (uint16_t)(x))
    810 #define SUN_SSWAP32(x) (sun_other_endian ? __swap32(x) \
    811                  : (uint32_t)(x))
    812 
    813 
    814 #ifdef CONFIG_FEATURE_OSF_LABEL
    815 /*
    816    Changes:
    817    19990319 - Arnaldo Carvalho de Melo <acme@conectiva.com.br> - i18n/nls
    818 
    819    20000101 - David Huggins-Daines <dhuggins@linuxcare.com> - Better
    820    support for OSF/1 disklabels on Alpha.
    821    Also fixed unaligned accesses in alpha_bootblock_checksum()
    822 */
    823 
    824 #define FREEBSD_PARTITION       0xa5
    825 #define NETBSD_PARTITION        0xa9
    826 
    827 static void xbsd_delete_part(void);
    828 static void xbsd_new_part(void);
    829 static void xbsd_write_disklabel(void);
    830 static int xbsd_create_disklabel(void);
    831 static void xbsd_edit_disklabel(void);
    832 static void xbsd_write_bootstrap(void);
    833 static void xbsd_change_fstype(void);
    834 static int xbsd_get_part_index(int max);
    835 static int xbsd_check_new_partition(int *i);
    836 static void xbsd_list_types(void);
    837 static u_short xbsd_dkcksum(struct xbsd_disklabel *lp);
    838 static int xbsd_initlabel(struct partition *p, struct xbsd_disklabel *d);
    839 static int xbsd_readlabel(struct partition *p, struct xbsd_disklabel *d);
    840 static int xbsd_writelabel(struct partition *p, struct xbsd_disklabel *d);
    841 
    842 #if defined (__alpha__)
    843 static void alpha_bootblock_checksum(char *boot);
    844 #endif
    845 
    846 #if !defined (__alpha__)
    847 static int xbsd_translate_fstype(int linux_type);
    848 static void xbsd_link_part(void);
    849 static struct partition *xbsd_part;
    850 static int xbsd_part_index;
    851 #endif
    852 
    853 #if defined (__alpha__)
    854 /* We access this through a uint64_t * when checksumming */
    855 static char disklabelbuffer[BSD_BBSIZE] ATTRIBUTE_ALIGNED(8);
    856 #else
    857 static char disklabelbuffer[BSD_BBSIZE];
    858 #endif
    859 
    860 static struct xbsd_disklabel xbsd_dlabel;
    861 
    862 #define bsd_cround(n) \
    863     (display_in_cyl_units ? ((n)/xbsd_dlabel.d_secpercyl) + 1 : (n))
    864 
    865 /*
    866  * Test whether the whole disk has BSD disk label magic.
    867  *
    868  * Note: often reformatting with DOS-type label leaves the BSD magic,
    869  * so this does not mean that there is a BSD disk label.
    870  */
    871 static int
    872 check_osf_label(void)
    873 {
    874     if (xbsd_readlabel(NULL, &xbsd_dlabel) == 0)
    875         return 0;
    876     return 1;
    877 }
    878 
    879 static void xbsd_print_disklabel(int);
    880 
    881 static int
    882 btrydev(const char * dev)
    883 {
    884     if (xbsd_readlabel (NULL, &xbsd_dlabel) == 0)
    885         return -1;
    886     printf(_("\nBSD label for device: %s\n"), dev);
    887     xbsd_print_disklabel (0);
    888     return 0;
    889 }
    890 
    891 static void
    892 bmenu(void)
    893 {
    894     puts (_("Command action"));
    895     puts (_("\td\tdelete a BSD partition"));
    896     puts (_("\te\tedit drive data"));
    897     puts (_("\ti\tinstall bootstrap"));
    898     puts (_("\tl\tlist known filesystem types"));
    899     puts (_("\tm\tprint this menu"));
    900     puts (_("\tn\tadd a new BSD partition"));
    901     puts (_("\tp\tprint BSD partition table"));
    902     puts (_("\tq\tquit without saving changes"));
    903     puts (_("\tr\treturn to main menu"));
    904     puts (_("\ts\tshow complete disklabel"));
    905     puts (_("\tt\tchange a partition's filesystem id"));
    906     puts (_("\tu\tchange units (cylinders/sectors)"));
    907     puts (_("\tw\twrite disklabel to disk"));
    908 #if !defined (__alpha__)
    909     puts (_("\tx\tlink BSD partition to non-BSD partition"));
    910 #endif
    911 }
    912 
    913 #if !defined (__alpha__)
    914 static int
    915 hidden(int type)
    916 {
    917     return type ^ 0x10;
    918 }
    919 
    920 static int
    921 is_bsd_partition_type(int type)
    922 {
    923     return (type == FREEBSD_PARTITION ||
    924         type == hidden(FREEBSD_PARTITION) ||
    925         type == NETBSD_PARTITION ||
    926         type == hidden(NETBSD_PARTITION));
    927 }
    928 #endif
    929 
    930 static void
    931 bselect(void)
    932 {
    933 #if !defined (__alpha__)
    934     int t, ss;
    935     struct partition *p;
    936 
    937     for (t = 0; t < 4; t++) {
    938         p = get_part_table(t);
    939         if (p && is_bsd_partition_type(p->sys_ind)) {
    940             xbsd_part = p;
    941             xbsd_part_index = t;
    942             ss = get_start_sect(xbsd_part);
    943             if (ss == 0) {
    944                 fprintf(stderr, _("Partition %s has invalid starting sector 0.\n"),
    945                     partname(disk_device, t+1, 0));
    946                 return;
    947             }
    948                 printf(_("Reading disklabel of %s at sector %d.\n"),
    949                     partname(disk_device, t+1, 0), ss + BSD_LABELSECTOR);
    950             if (xbsd_readlabel(xbsd_part, &xbsd_dlabel) == 0)
    951                 if (xbsd_create_disklabel() == 0)
    952                     return;
    953                 break;
    954         }
    955     }
    956 
    957     if (t == 4) {
    958         printf(_("There is no *BSD partition on %s.\n"), disk_device);
    959         return;
    960     }
    961 
    962 #elif defined (__alpha__)
    963 
    964     if (xbsd_readlabel(NULL, &xbsd_dlabel) == 0)
    965         if (xbsd_create_disklabel() == 0)
    966             exit (EXIT_SUCCESS);
    967 
    968 #endif
    969 
    970     while (1) {
    971         putchar('\n');
    972         switch (tolower(read_char(_("BSD disklabel command (m for help): ")))) {
    973         case 'd':
    974             xbsd_delete_part();
    975             break;
    976         case 'e':
    977             xbsd_edit_disklabel();
    978             break;
    979         case 'i':
    980             xbsd_write_bootstrap();
    981             break;
    982         case 'l':
    983             xbsd_list_types();
    984             break;
    985         case 'n':
    986             xbsd_new_part();
    987             break;
    988         case 'p':
    989             xbsd_print_disklabel(0);
    990             break;
    991         case 'q':
    992             close(fd);
    993             exit(EXIT_SUCCESS);
    994         case 'r':
    995             return;
    996         case 's':
    997             xbsd_print_disklabel(1);
    998             break;
    999         case 't':
    1000             xbsd_change_fstype();
    1001             break;
    1002         case 'u':
    1003             change_units();
    1004             break;
    1005         case 'w':
    1006             xbsd_write_disklabel();
    1007             break;
    1008 #if !defined (__alpha__)
    1009         case 'x':
    1010             xbsd_link_part();
    1011             break;
    1012 #endif
    1013         default:
    1014             bmenu();
    1015             break;
    1016         }
    1017     }
    1018 }
    1019 
    1020 static void
    1021 xbsd_delete_part(void)
    1022 {
    1023     int i;
    1024 
    1025     i = xbsd_get_part_index(xbsd_dlabel.d_npartitions);
    1026     xbsd_dlabel.d_partitions[i].p_size   = 0;
    1027     xbsd_dlabel.d_partitions[i].p_offset = 0;
    1028     xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
    1029     if (xbsd_dlabel.d_npartitions == i + 1)
    1030         while (xbsd_dlabel.d_partitions[xbsd_dlabel.d_npartitions-1].p_size == 0)
    1031             xbsd_dlabel.d_npartitions--;
    1032 }
    1033 
    1034 static void
    1035 xbsd_new_part(void)
    1036 {
    1037     off_t begin, end;
    1038     char mesg[256];
    1039     int i;
    1040 
    1041     if (!xbsd_check_new_partition(&i))
    1042         return;
    1043 
    1044 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
    1045     begin = get_start_sect(xbsd_part);
    1046     end = begin + get_nr_sects(xbsd_part) - 1;
    1047 #else
    1048     begin = 0;
    1049     end = xbsd_dlabel.d_secperunit - 1;
    1050 #endif
    1051 
    1052     snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
    1053     begin = read_int(bsd_cround(begin), bsd_cround(begin), bsd_cround(end),
    1054         0, mesg);
    1055 
    1056     if (display_in_cyl_units)
    1057         begin = (begin - 1) * xbsd_dlabel.d_secpercyl;
    1058 
    1059     snprintf(mesg, sizeof(mesg), _("Last %s or +size or +sizeM or +sizeK"),
    1060         str_units(SINGULAR));
    1061     end = read_int(bsd_cround (begin), bsd_cround (end), bsd_cround (end),
    1062         bsd_cround (begin), mesg);
    1063 
    1064     if (display_in_cyl_units)
    1065         end = end * xbsd_dlabel.d_secpercyl - 1;
    1066 
    1067     xbsd_dlabel.d_partitions[i].p_size   = end - begin + 1;
    1068     xbsd_dlabel.d_partitions[i].p_offset = begin;
    1069     xbsd_dlabel.d_partitions[i].p_fstype = BSD_FS_UNUSED;
    1070 }
    1071 
    1072 static void
    1073 xbsd_print_disklabel(int show_all)
    1074 {
    1075     struct xbsd_disklabel *lp = &xbsd_dlabel;
    1076     struct xbsd_partition *pp;
    1077     int i, j;
    1078 
    1079     if (show_all) {
    1080 #if defined (__alpha__)
    1081         printf("# %s:\n", disk_device);
    1082 #else
    1083         printf("# %s:\n", partname(disk_device, xbsd_part_index+1, 0));
    1084 #endif
    1085         if ((unsigned) lp->d_type < BSD_DKMAXTYPES)
    1086             printf(_("type: %s\n"), xbsd_dktypenames[lp->d_type]);
    1087         else
    1088             printf(_("type: %d\n"), lp->d_type);
    1089         printf(_("disk: %.*s\n"), (int) sizeof(lp->d_typename), lp->d_typename);
    1090         printf(_("label: %.*s\n"), (int) sizeof(lp->d_packname), lp->d_packname);
    1091         printf(_("flags:"));
    1092         if (lp->d_flags & BSD_D_REMOVABLE)
    1093             printf(_(" removable"));
    1094         if (lp->d_flags & BSD_D_ECC)
    1095             printf(_(" ecc"));
    1096         if (lp->d_flags & BSD_D_BADSECT)
    1097             printf(_(" badsect"));
    1098         printf("\n");
    1099         /* On various machines the fields of *lp are short/int/long */
    1100         /* In order to avoid problems, we cast them all to long. */
    1101         printf(_("bytes/sector: %ld\n"), (long) lp->d_secsize);
    1102         printf(_("sectors/track: %ld\n"), (long) lp->d_nsectors);
    1103         printf(_("tracks/cylinder: %ld\n"), (long) lp->d_ntracks);
    1104         printf(_("sectors/cylinder: %ld\n"), (long) lp->d_secpercyl);
    1105         printf(_("cylinders: %ld\n"), (long) lp->d_ncylinders);
    1106         printf(_("rpm: %d\n"), lp->d_rpm);
    1107         printf(_("interleave: %d\n"), lp->d_interleave);
    1108         printf(_("trackskew: %d\n"), lp->d_trackskew);
    1109         printf(_("cylinderskew: %d\n"), lp->d_cylskew);
    1110         printf(_("headswitch: %ld\t\t# milliseconds\n"),
    1111             (long) lp->d_headswitch);
    1112         printf(_("track-to-track seek: %ld\t# milliseconds\n"),
    1113             (long) lp->d_trkseek);
    1114         printf(_("drivedata: "));
    1115         for (i = NDDATA - 1; i >= 0; i--)
    1116             if (lp->d_drivedata[i])
    1117                 break;
    1118         if (i < 0)
    1119             i = 0;
    1120         for (j = 0; j <= i; j++)
    1121             printf("%ld ", (long) lp->d_drivedata[j]);
    1122     }
    1123     printf(_("\n%d partitions:\n"), lp->d_npartitions);
    1124     printf(_("#       start       end      size     fstype   [fsize bsize   cpg]\n"));
    1125     pp = lp->d_partitions;
    1126     for (i = 0; i < lp->d_npartitions; i++, pp++) {
    1127         if (pp->p_size) {
    1128             if (display_in_cyl_units && lp->d_secpercyl) {
    1129                 printf("  %c: %8ld%c %8ld%c %8ld%c  ",
    1130                     'a' + i,
    1131                     (long) pp->p_offset / lp->d_secpercyl + 1,
    1132                     (pp->p_offset % lp->d_secpercyl) ? '*' : ' ',
    1133                     (long) (pp->p_offset + pp->p_size + lp->d_secpercyl - 1) / lp->d_secpercyl,
    1134                     ((pp->p_offset + pp->p_size) % lp->d_secpercyl) ? '*' : ' ',
    1135                     (long) pp->p_size / lp->d_secpercyl,
    1136                     (pp->p_size % lp->d_secpercyl) ? '*' : ' '
    1137                 );
    1138             } else {
    1139                 printf("  %c: %8ld  %8ld  %8ld   ",
    1140                     'a' + i,
    1141                     (long) pp->p_offset,
    1142                     (long) pp->p_offset + pp->p_size - 1,
    1143                     (long) pp->p_size
    1144                 );
    1145             }
    1146 
    1147             if ((unsigned) pp->p_fstype < BSD_FSMAXTYPES)
    1148                 printf("%8.8s", xbsd_fstypes[pp->p_fstype].name);
    1149             else
    1150                 printf("%8x", pp->p_fstype);
    1151 
    1152             switch (pp->p_fstype) {
    1153             case BSD_FS_UNUSED:
    1154                 printf("    %5ld %5ld %5.5s ",
    1155                     (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, "");
    1156                 break;
    1157             case BSD_FS_BSDFFS:
    1158                 printf("    %5ld %5ld %5d ",
    1159                     (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, pp->p_cpg);
    1160                 break;
    1161             default:
    1162                 printf("%22.22s", "");
    1163                 break;
    1164             }
    1165             printf("\n");
    1166         }
    1167     }
    1168 }
    1169 
    1170 static void
    1171 xbsd_write_disklabel(void)
    1172 {
    1173 #if defined (__alpha__)
    1174     printf(_("Writing disklabel to %s.\n"), disk_device);
    1175     xbsd_writelabel(NULL, &xbsd_dlabel);
    1176 #else
    1177     printf(_("Writing disklabel to %s.\n"),
    1178         partname(disk_device, xbsd_part_index + 1, 0));
    1179     xbsd_writelabel(xbsd_part, &xbsd_dlabel);
    1180 #endif
    1181     reread_partition_table(0);      /* no exit yet */
    1182 }
    1183 
    1184 static int
    1185 xbsd_create_disklabel(void)
    1186 {
    1187     char c;
    1188 
    1189 #if defined (__alpha__)
    1190     fprintf(stderr, _("%s contains no disklabel.\n"), disk_device);
    1191 #else
    1192     fprintf(stderr, _("%s contains no disklabel.\n"),
    1193         partname(disk_device, xbsd_part_index + 1, 0));
    1194 #endif
    1195 
    1196     while (1) {
    1197         c = read_char(_("Do you want to create a disklabel? (y/n) "));
    1198         if (c == 'y' || c == 'Y') {
    1199             if (xbsd_initlabel(
    1200 #if defined (__alpha__) || defined (__powerpc__) || defined (__hppa__) || \
    1201     defined (__s390__) || defined (__s390x__)
    1202                 NULL, &xbsd_dlabel
    1203 #else
    1204                 xbsd_part, &xbsd_dlabel/* not used, xbsd_part_index*/
    1205 #endif
    1206                 ) == 1) {
    1207                 xbsd_print_disklabel (1);
    1208                 return 1;
    1209             } else
    1210                 return 0;
    1211         } else if (c == 'n')
    1212             return 0;
    1213     }
    1214 }
    1215 
    1216 static int
    1217 edit_int(int def, char *mesg)
    1218 {
    1219     do {
    1220         fputs(mesg, stdout);
    1221         printf(" (%d): ", def);
    1222         if (!read_line())
    1223             return def;
    1224     }
    1225     while (!isdigit(*line_ptr));    /* FIXME: ?!! */
    1226     return atoi(line_ptr);
    1227 }
    1228 
    1229 static void
    1230 xbsd_edit_disklabel(void)
    1231 {
    1232     struct xbsd_disklabel *d;
    1233 
    1234     d = &xbsd_dlabel;
    1235 
    1236 #if defined (__alpha__) || defined (__ia64__)
    1237     d->d_secsize    = (u_long) edit_int((u_long) d->d_secsize     ,_("bytes/sector"));
    1238     d->d_nsectors   = (u_long) edit_int((u_long) d->d_nsectors    ,_("sectors/track"));
    1239     d->d_ntracks    = (u_long) edit_int((u_long) d->d_ntracks     ,_("tracks/cylinder"));
    1240     d->d_ncylinders = (u_long) edit_int((u_long) d->d_ncylinders  ,_("cylinders"));
    1241 #endif
    1242 
    1243   /* d->d_secpercyl can be != d->d_nsectors * d->d_ntracks */
    1244     while (1) {
    1245         d->d_secpercyl = (u_long) edit_int((u_long) d->d_nsectors * d->d_ntracks,
    1246                 _("sectors/cylinder"));
    1247         if (d->d_secpercyl <= d->d_nsectors * d->d_ntracks)
    1248             break;
    1249 
    1250         printf(_("Must be <= sectors/track * tracks/cylinder (default).\n"));
    1251     }
    1252     d->d_rpm        = (u_short) edit_int((u_short) d->d_rpm       ,_("rpm"));
    1253     d->d_interleave = (u_short) edit_int((u_short) d->d_interleave,_("interleave"));
    1254     d->d_trackskew  = (u_short) edit_int((u_short) d->d_trackskew ,_("trackskew"));
    1255     d->d_cylskew    = (u_short) edit_int((u_short) d->d_cylskew   ,_("cylinderskew"));
    1256     d->d_headswitch = (u_long) edit_int((u_long) d->d_headswitch  ,_("headswitch"));
    1257     d->d_trkseek    = (u_long) edit_int((u_long) d->d_trkseek     ,_("track-to-track seek"));
    1258 
    1259     d->d_secperunit = d->d_secpercyl * d->d_ncylinders;
    1260 }
    1261 
    1262 static int
    1263 xbsd_get_bootstrap (char *path, void *ptr, int size)
    1264 {
    1265     int fdb;
    1266 
    1267     if ((fdb = open (path, O_RDONLY)) < 0) {
    1268         perror(path);
    1269         return 0;
    1270     }
    1271     if (read(fdb, ptr, size) < 0) {
    1272         perror(path);
    1273         close(fdb);
    1274         return 0;
    1275     }
    1276     printf(" ... %s\n", path);
    1277     close(fdb);
    1278     return 1;
    1279 }
    1280 
    1281 static void
    1282 sync_disks(void)
    1283 {
    1284     printf(_("\nSyncing disks.\n"));
    1285     sync();
    1286     sleep(4); /* What? */
    1287 }
    1288 
    1289 static void
    1290 xbsd_write_bootstrap(void)
    1291 {
    1292     char *bootdir = BSD_LINUX_BOOTDIR;
    1293     char path[MAXPATHLEN];
    1294     char *dkbasename;
    1295     struct xbsd_disklabel dl;
    1296     char *d, *p, *e;
    1297     int sector;
    1298 
    1299     if (xbsd_dlabel.d_type == BSD_DTYPE_SCSI)
    1300         dkbasename = "sd";
    1301     else
    1302         dkbasename = "wd";
    1303 
    1304     printf(_("Bootstrap: %sboot -> boot%s (%s): "),
    1305         dkbasename, dkbasename, dkbasename);
    1306     if (read_line()) {
    1307         line_ptr[strlen(line_ptr)-1] = '\0';
    1308         dkbasename = line_ptr;
    1309     }
    1310     snprintf(path, sizeof(path), "%s/%sboot", bootdir, dkbasename);
    1311     if (!xbsd_get_bootstrap(path, disklabelbuffer, (int) xbsd_dlabel.d_secsize))
    1312         return;
    1313 
    1314 /* We need a backup of the disklabel (xbsd_dlabel might have changed). */
    1315     d = &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE];
    1316     memmove(&dl, d, sizeof(struct xbsd_disklabel));
    1317 
    1318 /* The disklabel will be overwritten by 0's from bootxx anyway */
    1319     memset(d, 0, sizeof(struct xbsd_disklabel));
    1320 
    1321     snprintf(path, sizeof(path), "%s/boot%s", bootdir, dkbasename);
    1322     if (!xbsd_get_bootstrap (path, &disklabelbuffer[xbsd_dlabel.d_secsize],
    1323               (int) xbsd_dlabel.d_bbsize - xbsd_dlabel.d_secsize))
    1324         return;
    1325 
    1326     e = d + sizeof(struct xbsd_disklabel);
    1327     for (p = d; p < e; p++)
    1328         if (*p) {
    1329             fprintf(stderr, _("Bootstrap overlaps with disk label!\n"));
    1330             exit(EXIT_FAILURE);
    1331         }
    1332 
    1333     memmove(d, &dl, sizeof(struct xbsd_disklabel));
    1334 
    1335 #if defined (__powerpc__) || defined (__hppa__)
    1336     sector = 0;
    1337 #elif defined (__alpha__)
    1338     sector = 0;
    1339     alpha_bootblock_checksum(disklabelbuffer);
    1340 #else
    1341     sector = get_start_sect(xbsd_part);
    1342 #endif
    1343 
    1344     if (lseek(fd, sector * SECTOR_SIZE, SEEK_SET) == -1)
    1345         fdisk_fatal(unable_to_seek);
    1346     if (BSD_BBSIZE != write(fd, disklabelbuffer, BSD_BBSIZE))
    1347         fdisk_fatal(unable_to_write);
    1348 
    1349 #if defined (__alpha__)
    1350     printf(_("Bootstrap installed on %s.\n"), disk_device);
    1351 #else
    1352     printf(_("Bootstrap installed on %s.\n"),
    1353         partname (disk_device, xbsd_part_index+1, 0));
    1354 #endif
    1355 
    1356     sync_disks();
    1357 }
    1358 
    1359 static void
    1360 xbsd_change_fstype(void)
    1361 {
    1362     int i;
    1363 
    1364     i = xbsd_get_part_index(xbsd_dlabel.d_npartitions);
    1365     xbsd_dlabel.d_partitions[i].p_fstype = read_hex(xbsd_fstypes);
    1366 }
    1367 
    1368 static int
    1369 xbsd_get_part_index(int max)
    1370 {
    1371     char prompt[256];
    1372     char l;
    1373 
    1374     snprintf(prompt, sizeof(prompt), _("Partition (a-%c): "), 'a' + max - 1);
    1375     do
    1376             l = tolower(read_char(prompt));
    1377     while (l < 'a' || l > 'a' + max - 1);
    1378     return l - 'a';
    1379 }
    1380 
    1381 static int
    1382 xbsd_check_new_partition(int *i)
    1383 {
    1384     /* room for more? various BSD flavours have different maxima */
    1385     if (xbsd_dlabel.d_npartitions == BSD_MAXPARTITIONS) {
    1386         int t;
    1387 
    1388         for (t = 0; t < BSD_MAXPARTITIONS; t++)
    1389             if (xbsd_dlabel.d_partitions[t].p_size == 0)
    1390                 break;
    1391 
    1392         if (t == BSD_MAXPARTITIONS) {
    1393             fprintf(stderr, _("The maximum number of partitions "
    1394                        "has been created\n"));
    1395             return 0;
    1396         }
    1397     }
    1398 
    1399     *i = xbsd_get_part_index (BSD_MAXPARTITIONS);
    1400 
    1401     if (*i >= xbsd_dlabel.d_npartitions)
    1402         xbsd_dlabel.d_npartitions = (*i) + 1;
    1403 
    1404     if (xbsd_dlabel.d_partitions[*i].p_size != 0) {
    1405         fprintf(stderr, _("This partition already exists.\n"));
    1406         return 0;
    1407     }
    1408 
    1409     return 1;
    1410 }
    1411 
    1412 static void
    1413 xbsd_list_types(void)
    1414 {
    1415     list_types(xbsd_fstypes);
    1416 }
    1417 
    1418 static u_short
    1419 xbsd_dkcksum(struct xbsd_disklabel *lp)
    1420 {
    1421     u_short *start, *end;
    1422     u_short sum = 0;
    1423 
    1424     start = (u_short *) lp;
    1425     end = (u_short *) &lp->d_partitions[lp->d_npartitions];
    1426     while (start < end)
    1427         sum ^= *start++;
    1428     return sum;
    1429 }
    1430 
    1431 static int
    1432 xbsd_initlabel(struct partition *p, struct xbsd_disklabel *d)
    1433 {
    1434     struct xbsd_partition *pp;
    1435 
    1436     get_geometry();
    1437     memset(d, 0, sizeof(struct xbsd_disklabel));
    1438 
    1439     d->d_magic = BSD_DISKMAGIC;
    1440 
    1441     if (strncmp(disk_device, "/dev/sd", 7) == 0)
    1442         d->d_type = BSD_DTYPE_SCSI;
    1443     else
    1444         d->d_type = BSD_DTYPE_ST506;
    1445 
    1446 #if 0 /* not used (at least not written to disk) by NetBSD/i386 1.0 */
    1447     d->d_subtype = BSD_DSTYPE_INDOSPART & pindex;
    1448 #endif
    1449 
    1450 #if !defined (__alpha__)
    1451     d->d_flags = BSD_D_DOSPART;
    1452 #else
    1453     d->d_flags = 0;
    1454 #endif
    1455     d->d_secsize = SECTOR_SIZE;           /* bytes/sector  */
    1456     d->d_nsectors = sectors;            /* sectors/track */
    1457     d->d_ntracks = heads;               /* tracks/cylinder (heads) */
    1458     d->d_ncylinders = cylinders;
    1459     d->d_secpercyl  = sectors * heads;/* sectors/cylinder */
    1460     if (d->d_secpercyl == 0)
    1461         d->d_secpercyl = 1;           /* avoid segfaults */
    1462     d->d_secperunit = d->d_secpercyl * d->d_ncylinders;
    1463 
    1464     d->d_rpm = 3600;
    1465     d->d_interleave = 1;
    1466     d->d_trackskew = 0;
    1467     d->d_cylskew = 0;
    1468     d->d_headswitch = 0;
    1469     d->d_trkseek = 0;
    1470 
    1471     d->d_magic2 = BSD_DISKMAGIC;
    1472     d->d_bbsize = BSD_BBSIZE;
    1473     d->d_sbsize = BSD_SBSIZE;
    1474 
    1475 #if !defined (__alpha__)
    1476     d->d_npartitions = 4;
    1477     pp = &d->d_partitions[2];             /* Partition C should be
    1478                            the NetBSD partition */
    1479     pp->p_offset = get_start_sect(p);
    1480     pp->p_size   = get_nr_sects(p);
    1481     pp->p_fstype = BSD_FS_UNUSED;
    1482     pp = &d->d_partitions[3];             /* Partition D should be
    1483                            the whole disk */
    1484     pp->p_offset = 0;
    1485     pp->p_size   = d->d_secperunit;
    1486     pp->p_fstype = BSD_FS_UNUSED;
    1487 #elif defined (__alpha__)
    1488     d->d_npartitions = 3;
    1489     pp = &d->d_partitions[2];             /* Partition C should be
    1490                            the whole disk */
    1491     pp->p_offset = 0;
    1492     pp->p_size   = d->d_secperunit;
    1493     pp->p_fstype = BSD_FS_UNUSED;
    1494 #endif
    1495 
    1496     return 1;
    1497 }
    1498 
    1499 /*
    1500  * Read a xbsd_disklabel from sector 0 or from the starting sector of p.
    1501  * If it has the right magic, return 1.
    1502  */
    1503 static int
    1504 xbsd_readlabel (struct partition *p, struct xbsd_disklabel *d)
    1505 {
    1506     int t, sector;
    1507 
    1508     /* p is used only to get the starting sector */
    1509 #if !defined (__alpha__)
    1510     sector = (p ? get_start_sect(p) : 0);
    1511 #elif defined (__alpha__)
    1512     sector = 0;
    1513 #endif
    1514 
    1515     if (lseek(fd, sector * SECTOR_SIZE, SEEK_SET) == -1)
    1516         fdisk_fatal(unable_to_seek);
    1517     if (BSD_BBSIZE != read(fd, disklabelbuffer, BSD_BBSIZE))
    1518         fdisk_fatal(unable_to_read);
    1519 
    1520     memmove(d, &disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
    1521            sizeof(struct xbsd_disklabel));
    1522 
    1523     if (d->d_magic != BSD_DISKMAGIC || d->d_magic2 != BSD_DISKMAGIC)
    1524         return 0;
    1525 
    1526     for (t = d->d_npartitions; t < BSD_MAXPARTITIONS; t++) {
    1527         d->d_partitions[t].p_size   = 0;
    1528         d->d_partitions[t].p_offset = 0;
    1529         d->d_partitions[t].p_fstype = BSD_FS_UNUSED;
    1530     }
    1531 
    1532     if (d->d_npartitions > BSD_MAXPARTITIONS)
    1533         fprintf(stderr, _("Warning: too many partitions "
    1534                 "(%d, maximum is %d).\n"),
    1535             d->d_npartitions, BSD_MAXPARTITIONS);
    1536     return 1;
    1537 }
    1538 
    1539 static int
    1540 xbsd_writelabel (struct partition *p, struct xbsd_disklabel *d)
    1541 {
    1542     unsigned int sector;
    1543 
    1544 #if !defined (__alpha__) && !defined (__powerpc__) && !defined (__hppa__)
    1545     sector = get_start_sect(p) + BSD_LABELSECTOR;
    1546 #else
    1547     sector = BSD_LABELSECTOR;
    1548 #endif
    1549 
    1550     d->d_checksum = 0;
    1551     d->d_checksum = xbsd_dkcksum (d);
    1552 
    1553     /* This is necessary if we want to write the bootstrap later,
    1554        otherwise we'd write the old disklabel with the bootstrap.
    1555     */
    1556     memmove(&disklabelbuffer[BSD_LABELSECTOR * SECTOR_SIZE + BSD_LABELOFFSET],
    1557         d, sizeof(struct xbsd_disklabel));
    1558 
    1559 #if defined (__alpha__) && BSD_LABELSECTOR == 0
    1560     alpha_bootblock_checksum (disklabelbuffer);
    1561     if (lseek(fd, 0, SEEK_SET) == -1)
    1562         fdisk_fatal(unable_to_seek);
    1563     if (BSD_BBSIZE != write(fd, disklabelbuffer, BSD_BBSIZE))
    1564         fdisk_fatal(unable_to_write);
    1565 #else
    1566     if (lseek(fd, sector * SECTOR_SIZE + BSD_LABELOFFSET, SEEK_SET) == -1)
    1567         fdisk_fatal(unable_to_seek);
    1568     if (sizeof(struct xbsd_disklabel) != write(fd, d, sizeof(struct xbsd_disklabel)))
    1569         fdisk_fatal(unable_to_write);
    1570 #endif
    1571     sync_disks();
    1572     return 1;
    1573 }
    1574 
    1575 
    1576 #if !defined (__alpha__)
    1577 static int
    1578 xbsd_translate_fstype(int linux_type)
    1579 {
    1580     switch (linux_type) {
    1581     case 0x01: /* DOS 12-bit FAT   */
    1582     case 0x04: /* DOS 16-bit <32M  */
    1583     case 0x06: /* DOS 16-bit >=32M */
    1584     case 0xe1: /* DOS access       */
    1585     case 0xe3: /* DOS R/O          */
    1586     case 0xf2: /* DOS secondary    */
    1587         return BSD_FS_MSDOS;
    1588     case 0x07: /* OS/2 HPFS        */
    1589         return BSD_FS_HPFS;
    1590     default:
    1591         return BSD_FS_OTHER;
    1592     }
    1593 }
    1594 
    1595 static void
    1596 xbsd_link_part(void)
    1597 {
    1598     int k, i;
    1599     struct partition *p;
    1600 
    1601     k = get_partition(1, partitions);
    1602 
    1603     if (!xbsd_check_new_partition(&i))
    1604         return;
    1605 
    1606     p = get_part_table(k);
    1607 
    1608     xbsd_dlabel.d_partitions[i].p_size   = get_nr_sects(p);
    1609     xbsd_dlabel.d_partitions[i].p_offset = get_start_sect(p);
    1610     xbsd_dlabel.d_partitions[i].p_fstype = xbsd_translate_fstype(p->sys_ind);
    1611 }
    1612 #endif
    1613 
    1614 #if defined (__alpha__)
    1615 
    1616 #if !defined(__GLIBC__)
    1617 typedef unsigned long long uint64_t;
    1618 #endif
    1619 
    1620 static void
    1621 alpha_bootblock_checksum(char *boot)
    1622 {
    1623     uint64_t *dp, sum;
    1624     int i;
    1625 
    1626     dp = (uint64_t *)boot;
    1627     sum = 0;
    1628     for (i = 0; i < 63; i++)
    1629         sum += dp[i];
    1630     dp[63] = sum;
    1631 }
    1632 #endif /* __alpha__ */
    1633 
    1634 #endif /* OSF_LABEL */
    1635 
    1636 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
    1637 static inline unsigned short
    1638 __swap16(unsigned short x)
    1639 {
    1640     return (((uint16_t)(x) & 0xFF) << 8) | (((uint16_t)(x) & 0xFF00) >> 8);
    1641 }
    1642 
    1643 static inline uint32_t
    1644 __swap32(uint32_t x)
    1645 {
    1646     return (((x & 0xFF) << 24) |
    1647         ((x & 0xFF00) << 8) |
    1648         ((x & 0xFF0000) >> 8) |
    1649         ((x & 0xFF000000) >> 24));
    1650 }
    1651 #endif
    1652 
    1653 #ifdef CONFIG_FEATURE_SGI_LABEL
    1654 /*
    1655  *
    1656  * fdisksgilabel.c
    1657  *
    1658  * Copyright (C) Andreas Neuper, Sep 1998.
    1659  *      This file may be modified and redistributed under
    1660  *      the terms of the GNU Public License.
    1661  *
    1662  * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
    1663  *      Internationalization
    1664  */
    1665 
    1666 
    1667 static int sgi_other_endian;
    1668 static int debug;
    1669 static short sgi_volumes = 1;
    1670 
    1671 /*
    1672  * only dealing with free blocks here
    1673  */
    1674 
    1675 typedef struct {
    1676     unsigned int first;
    1677     unsigned int last;
    1678 } freeblocks;
    1679 static freeblocks freelist[17]; /* 16 partitions can produce 17 vacant slots */
    1680 
    1681 static void
    1682 setfreelist(int i, unsigned int f, unsigned int l)
    1683 {
    1684     freelist[i].first = f;
    1685     freelist[i].last = l;
    1686 }
    1687 
    1688 static void
    1689 add2freelist(unsigned int f, unsigned int l)
    1690 {
    1691     int i;
    1692     for (i = 0; i < 17 ; i++)
    1693         if (freelist[i].last == 0)
    1694             break;
    1695     setfreelist(i, f, l);
    1696 }
    1697 
    1698 static void
    1699 clearfreelist(void)
    1700 {
    1701     int i;
    1702 
    1703     for (i = 0; i < 17 ; i++)
    1704         setfreelist(i, 0, 0);
    1705 }
    1706 
    1707 static unsigned int
    1708 isinfreelist(unsigned int b)
    1709 {
    1710     int i;
    1711 
    1712     for (i = 0; i < 17 ; i++)
    1713         if (freelist[i].first <= b && freelist[i].last >= b)
    1714             return freelist[i].last;
    1715     return 0;
    1716 }
    1717     /* return last vacant block of this stride (never 0). */
    1718     /* the '>=' is not quite correct, but simplifies the code */
    1719 /*
    1720  * end of free blocks section
    1721  */
    1722 
    1723 static const struct systypes sgi_sys_types[] = {
    1724 /* SGI_VOLHDR   */  { "\x00" "SGI volhdr"   },
    1725 /* 0x01         */  { "\x01" "SGI trkrepl"  },
    1726 /* 0x02         */  { "\x02" "SGI secrepl"  },
    1727 /* SGI_SWAP     */  { "\x03" "SGI raw"      },
    1728 /* 0x04         */  { "\x04" "SGI bsd"      },
    1729 /* 0x05         */  { "\x05" "SGI sysv"     },
    1730 /* ENTIRE_DISK  */  { "\x06" "SGI volume"   },
    1731 /* SGI_EFS      */  { "\x07" "SGI efs"      },
    1732 /* 0x08         */  { "\x08" "SGI lvol"     },
    1733 /* 0x09         */  { "\x09" "SGI rlvol"    },
    1734 /* SGI_XFS      */  { "\x0a" "SGI xfs"      },
    1735 /* SGI_XFSLOG   */  { "\x0b" "SGI xfslog"   },
    1736 /* SGI_XLV      */  { "\x0c" "SGI xlv"      },
    1737 /* SGI_XVM      */  { "\x0d" "SGI xvm"      },
    1738 /* LINUX_SWAP   */  { "\x82" "Linux swap"   },
    1739 /* LINUX_NATIVE */  { "\x83" "Linux native" },
    1740 /* LINUX_LVM    */  { "\x8d" "Linux LVM"    },
    1741 /* LINUX_RAID   */  { "\xfd" "Linux RAID"   },
    1742             { NULL             }
    1743 };
    1744 
    1745 
    1746 static int
    1747 sgi_get_nsect(void)
    1748 {
    1749     return SGI_SSWAP16(sgilabel->devparam.nsect);
    1750 }
    1751 
    1752 static int
    1753 sgi_get_ntrks(void)
    1754 {
    1755     return SGI_SSWAP16(sgilabel->devparam.ntrks);
    1756 }
    1757 
    1758 static unsigned int
    1759 two_s_complement_32bit_sum(unsigned int* base, int size /* in bytes */)
    1760 {
    1761     int i = 0;
    1762     unsigned int sum = 0;
    1763 
    1764     size /= sizeof(unsigned int);
    1765     for (i = 0; i < size; i++)
    1766         sum -= SGI_SSWAP32(base[i]);
    1767     return sum;
    1768 }
    1769 
    1770 static int
    1771 check_sgi_label(void)
    1772 {
    1773     if (sizeof(sgilabel) > 512) {
    1774         fprintf(stderr,
    1775             _("According to MIPS Computer Systems, Inc the "
    1776             "Label must not contain more than 512 bytes\n"));
    1777         exit(1);
    1778     }
    1779 
    1780     if (sgilabel->magic != SGI_LABEL_MAGIC
    1781      && sgilabel->magic != SGI_LABEL_MAGIC_SWAPPED) {
    1782         current_label_type = label_dos;
    1783         return 0;
    1784     }
    1785 
    1786     sgi_other_endian = (sgilabel->magic == SGI_LABEL_MAGIC_SWAPPED);
    1787     /*
    1788      * test for correct checksum
    1789      */
    1790     if (two_s_complement_32bit_sum((unsigned int*)sgilabel,
    1791                 sizeof(*sgilabel))) {
    1792         fprintf(stderr,
    1793             _("Detected sgi disklabel with wrong checksum.\n"));
    1794     }
    1795     update_units();
    1796     current_label_type = label_sgi;
    1797     partitions = 16;
    1798     sgi_volumes = 15;
    1799     return 1;
    1800 }
    1801 
    1802 static unsigned int
    1803 sgi_get_start_sector(int i)
    1804 {
    1805     return SGI_SSWAP32(sgilabel->partitions[i].start_sector);
    1806 }
    1807 
    1808 static unsigned int
    1809 sgi_get_num_sectors(int i)
    1810 {
    1811     return SGI_SSWAP32(sgilabel->partitions[i].num_sectors);
    1812 }
    1813 
    1814 static int
    1815 sgi_get_sysid(int i)
    1816 {
    1817     return SGI_SSWAP32(sgilabel->partitions[i].id);
    1818 }
    1819 
    1820 static int
    1821 sgi_get_bootpartition(void)
    1822 {
    1823     return SGI_SSWAP16(sgilabel->boot_part);
    1824 }
    1825 
    1826 static int
    1827 sgi_get_swappartition(void)
    1828 {
    1829     return SGI_SSWAP16(sgilabel->swap_part);
    1830 }
    1831 
    1832 static void
    1833 sgi_list_table(int xtra)
    1834 {
    1835     int i, w, wd;
    1836     int kpi = 0;                /* kernel partition ID */
    1837 
    1838     if(xtra) {
    1839         printf(_("\nDisk %s (SGI disk label): %d heads, %d sectors\n"
    1840             "%d cylinders, %d physical cylinders\n"
    1841             "%d extra sects/cyl, interleave %d:1\n"
    1842             "%s\n"
    1843             "Units = %s of %d * 512 bytes\n\n"),
    1844             disk_device, heads, sectors, cylinders,
    1845             SGI_SSWAP16(sgiparam.pcylcount),
    1846             SGI_SSWAP16(sgiparam.sparecyl),
    1847             SGI_SSWAP16(sgiparam.ilfact),
    1848             (char *)sgilabel,
    1849             str_units(PLURAL), units_per_sector);
    1850     } else {
    1851         printf( _("\nDisk %s (SGI disk label): "
    1852             "%d heads, %d sectors, %d cylinders\n"
    1853             "Units = %s of %d * 512 bytes\n\n"),
    1854             disk_device, heads, sectors, cylinders,
    1855             str_units(PLURAL), units_per_sector );
    1856     }
    1857 
    1858     w = strlen(disk_device);
    1859     wd = strlen(_("Device"));
    1860     if (w < wd)
    1861     w = wd;
    1862 
    1863     printf(_("----- partitions -----\n"
    1864         "Pt# %*s  Info     Start       End   Sectors  Id  System\n"),
    1865         w + 2, _("Device"));
    1866     for (i = 0 ; i < partitions; i++) {
    1867         if( sgi_get_num_sectors(i) || debug ) {
    1868             uint32_t start = sgi_get_start_sector(i);
    1869             uint32_t len = sgi_get_num_sectors(i);
    1870             kpi++;              /* only count nonempty partitions */
    1871             printf(
    1872             "%2d: %s %4s %9ld %9ld %9ld  %2x  %s\n",
    1873 /* fdisk part number */ i+1,
    1874 /* device */            partname(disk_device, kpi, w+3),
    1875 /* flags */             (sgi_get_swappartition() == i) ? "swap" :
    1876 /* flags */             (sgi_get_bootpartition() == i) ? "boot" : "    ",
    1877 /* start */             (long) scround(start),
    1878 /* end */               (long) scround(start+len)-1,
    1879 /* no odd flag on end */(long) len,
    1880 /* type id */           sgi_get_sysid(i),
    1881 /* type name */         partition_type(sgi_get_sysid(i)));
    1882         }
    1883     }
    1884     printf(_("----- Bootinfo -----\nBootfile: %s\n"
    1885         "----- Directory Entries -----\n"),
    1886         sgilabel->boot_file);
    1887     for (i = 0 ; i < sgi_volumes; i++) {
    1888         if (sgilabel->directory[i].vol_file_size) {
    1889             uint32_t start = SGI_SSWAP32(sgilabel->directory[i].vol_file_start);
    1890             uint32_t len = SGI_SSWAP32(sgilabel->directory[i].vol_file_size);
    1891             unsigned char *name = sgilabel->directory[i].vol_file_name;
    1892 
    1893             printf(_("%2d: %-10s sector%5u size%8u\n"),
    1894                 i, (char*)name, (unsigned int) start, (unsigned int) len);
    1895         }
    1896     }
    1897 }
    1898 
    1899 static void
    1900 sgi_set_bootpartition(int i)
    1901 {
    1902     sgilabel->boot_part = SGI_SSWAP16(((short)i));
    1903 }
    1904 
    1905 static unsigned int
    1906 sgi_get_lastblock(void)
    1907 {
    1908     return heads * sectors * cylinders;
    1909 }
    1910 
    1911 static void
    1912 sgi_set_swappartition(int i)
    1913 {
    1914     sgilabel->swap_part = SGI_SSWAP16(((short)i));
    1915 }
    1916 
    1917 static int
    1918 sgi_check_bootfile(const char* aFile)
    1919 {
    1920     if (strlen(aFile) < 3) /* "/a\n" is minimum */ {
    1921         printf(_("\nInvalid Bootfile!\n"
    1922             "\tThe bootfile must be an absolute non-zero pathname,\n"
    1923             "\te.g. \"/unix\" or \"/unix.save\".\n"));
    1924         return 0;
    1925     } else {
    1926         if (strlen(aFile) > 16) {
    1927             printf(_("\n\tName of Bootfile too long:  "
    1928                 "16 bytes maximum.\n"));
    1929             return 0;
    1930         } else {
    1931             if (aFile[0] != '/') {
    1932                 printf(_("\n\tBootfile must have a "
    1933                     "fully qualified pathname.\n"));
    1934                 return 0;
    1935             }
    1936         }
    1937     }
    1938     if (strncmp(aFile, (char*)sgilabel->boot_file, 16)) {
    1939         printf(_("\n\tBe aware, that the bootfile is not checked for existence.\n\t"
    1940              "SGI's default is \"/unix\" and for backup \"/unix.save\".\n"));
    1941         /* filename is correct and did change */
    1942         return 1;
    1943     }
    1944     return 0;   /* filename did not change */
    1945 }
    1946 
    1947 static const char *
    1948 sgi_get_bootfile(void)
    1949 {
    1950     return (char*)sgilabel->boot_file;
    1951 }
    1952 
    1953 static void
    1954 sgi_set_bootfile(const char* aFile)
    1955 {
    1956     int i = 0;
    1957 
    1958     if (sgi_check_bootfile(aFile)) {
    1959         while (i < 16) {
    1960             if ((aFile[i] != '\n')  /* in principle caught again by next line */
    1961              && (strlen(aFile) > i))
    1962                 sgilabel->boot_file[i] = aFile[i];
    1963             else
    1964                 sgilabel->boot_file[i] = 0;
    1965             i++;
    1966         }
    1967         printf(_("\n\tBootfile is changed to \"%s\".\n"), sgilabel->boot_file);
    1968     }
    1969 }
    1970 
    1971 static void
    1972 create_sgiinfo(void)
    1973 {
    1974     /* I keep SGI's habit to write the sgilabel to the second block */
    1975     sgilabel->directory[0].vol_file_start = SGI_SSWAP32(2);
    1976     sgilabel->directory[0].vol_file_size = SGI_SSWAP32(sizeof(sgiinfo));
    1977     strcpy((char*)sgilabel->directory[0].vol_file_name, "sgilabel");
    1978 }
    1979 
    1980 static sgiinfo *fill_sgiinfo(void);
    1981 
    1982 static void
    1983 sgi_write_table(void)
    1984 {
    1985     sgilabel->csum = 0;
    1986     sgilabel->csum = SGI_SSWAP32(two_s_complement_32bit_sum(
    1987             (unsigned int*)sgilabel, sizeof(*sgilabel)));
    1988     assert(two_s_complement_32bit_sum(
    1989         (unsigned int*)sgilabel, sizeof(*sgilabel)) == 0);
    1990 
    1991     if (lseek(fd, 0, SEEK_SET) < 0)
    1992         fdisk_fatal(unable_to_seek);
    1993     if (write(fd, sgilabel, SECTOR_SIZE) != SECTOR_SIZE)
    1994         fdisk_fatal(unable_to_write);
    1995     if (!strncmp((char*)sgilabel->directory[0].vol_file_name, "sgilabel", 8)) {
    1996         /*
    1997          * keep this habit of first writing the "sgilabel".
    1998          * I never tested whether it works without (AN 981002).
    1999          */
    2000         sgiinfo *info = fill_sgiinfo();
    2001         int infostartblock = SGI_SSWAP32(sgilabel->directory[0].vol_file_start);
    2002         if (lseek(fd, infostartblock*SECTOR_SIZE, SEEK_SET) < 0)
    2003             fdisk_fatal(unable_to_seek);
    2004         if (write(fd, info, SECTOR_SIZE) != SECTOR_SIZE)
    2005             fdisk_fatal(unable_to_write);
    2006         free(info);
    2007     }
    2008 }
    2009 
    2010 static int
    2011 compare_start(int *x, int *y)
    2012 {
    2013     /*
    2014      * sort according to start sectors
    2015      * and prefers largest partition:
    2016      * entry zero is entire disk entry
    2017      */
    2018     unsigned int i = *x;
    2019     unsigned int j = *y;
    2020     unsigned int a = sgi_get_start_sector(i);
    2021     unsigned int b = sgi_get_start_sector(j);
    2022     unsigned int c = sgi_get_num_sectors(i);
    2023     unsigned int d = sgi_get_num_sectors(j);
    2024 
    2025     if (a == b)
    2026         return (d > c) ? 1 : (d == c) ? 0 : -1;
    2027     return (a > b) ? 1 : -1;
    2028 }
    2029 
    2030 
    2031 static int
    2032 verify_sgi(int verbose)
    2033 {
    2034     int Index[16];      /* list of valid partitions */
    2035     int sortcount = 0;  /* number of used partitions, i.e. non-zero lengths */
    2036     int entire = 0, i = 0;
    2037     unsigned int start = 0;
    2038     long long gap = 0;      /* count unused blocks */
    2039     unsigned int lastblock = sgi_get_lastblock();
    2040 
    2041     clearfreelist();
    2042     for (i = 0; i < 16; i++) {
    2043         if (sgi_get_num_sectors(i) != 0) {
    2044             Index[sortcount++] = i;
    2045             if (sgi_get_sysid(i) == ENTIRE_DISK) {
    2046                 if (entire++ == 1) {
    2047                     if (verbose)
    2048                         printf(_("More than one entire disk entry present.\n"));
    2049                 }
    2050             }
    2051         }
    2052     }
    2053     if (sortcount == 0) {
    2054         if (verbose)
    2055             printf(_("No partitions defined\n"));
    2056         return (lastblock > 0) ? 1 : (lastblock == 0) ? 0 : -1;
    2057     }
    2058     qsort(Index, sortcount, sizeof(Index[0]), (void*)compare_start);
    2059     if (sgi_get_sysid(Index[0]) == ENTIRE_DISK) {
    2060         if ((Index[0] != 10) && verbose)
    2061             printf(_("IRIX likes when Partition 11 covers the entire disk.\n"));
    2062         if ((sgi_get_start_sector(Index[0]) != 0) && verbose)
    2063             printf(_("The entire disk partition should start "
    2064                 "at block 0,\n"
    2065                 "not at diskblock %d.\n"),
    2066         sgi_get_start_sector(Index[0]));
    2067         if (debug)      /* I do not understand how some disks fulfil it */
    2068             if ((sgi_get_num_sectors(Index[0]) != lastblock) && verbose)
    2069                 printf(_("The entire disk partition is only %d diskblock large,\n"
    2070                     "but the disk is %d diskblocks long.\n"),
    2071         sgi_get_num_sectors(Index[0]), lastblock);
    2072         lastblock = sgi_get_num_sectors(Index[0]);
    2073     } else {
    2074         if (verbose)
    2075             printf(_("One Partition (#11) should cover the entire disk.\n"));
    2076         if (debug > 2)
    2077             printf("sysid=%d\tpartition=%d\n",
    2078                 sgi_get_sysid(Index[0]), Index[0]+1);
    2079     }
    2080     for (i = 1, start = 0; i < sortcount; i++) {
    2081         int cylsize = sgi_get_nsect() * sgi_get_ntrks();
    2082 
    2083         if ((sgi_get_start_sector(Index[i]) % cylsize) != 0) {
    2084             if (debug)      /* I do not understand how some disks fulfil it */
    2085                 if (verbose)
    2086                     printf(_("Partition %d does not start on cylinder boundary.\n"),
    2087                         Index[i]+1);
    2088         }
    2089         if (sgi_get_num_sectors(Index[i]) % cylsize != 0) {
    2090             if (debug)      /* I do not understand how some disks fulfil it */
    2091                 if (verbose)
    2092                     printf(_("Partition %d does not end on cylinder boundary.\n"),
    2093                         Index[i]+1);
    2094         }
    2095         /* We cannot handle several "entire disk" entries. */
    2096         if (sgi_get_sysid(Index[i]) == ENTIRE_DISK) continue;
    2097         if (start > sgi_get_start_sector(Index[i])) {
    2098             if (verbose)
    2099                 printf(_("The Partition %d and %d overlap by %d sectors.\n"),
    2100                     Index[i-1]+1, Index[i]+1,
    2101                     start - sgi_get_start_sector(Index[i]));
    2102             if (gap >  0) gap = -gap;
    2103             if (gap == 0) gap = -1;
    2104         }
    2105         if (start < sgi_get_start_sector(Index[i])) {
    2106             if (verbose)
    2107                 printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"),
    2108                     sgi_get_start_sector(Index[i]) - start,
    2109                     start, sgi_get_start_sector(Index[i])-1);
    2110             gap += sgi_get_start_sector(Index[i]) - start;
    2111             add2freelist(start, sgi_get_start_sector(Index[i]));
    2112         }
    2113         start = sgi_get_start_sector(Index[i])
    2114                + sgi_get_num_sectors(Index[i]);
    2115         if (debug > 1) {
    2116             if (verbose)
    2117                 printf("%2d:%12d\t%12d\t%12d\n", Index[i],
    2118                     sgi_get_start_sector(Index[i]),
    2119                     sgi_get_num_sectors(Index[i]),
    2120                     sgi_get_sysid(Index[i]));
    2121         }
    2122     }
    2123     if (start < lastblock) {
    2124         if (verbose)
    2125             printf(_("Unused gap of %8u sectors - sectors %8u-%u\n"),
    2126                 lastblock - start, start, lastblock-1);
    2127         gap += lastblock - start;
    2128         add2freelist(start, lastblock);
    2129     }
    2130     /*
    2131      * Done with arithmetics
    2132      * Go for details now
    2133      */
    2134     if (verbose) {
    2135         if (!sgi_get_num_sectors(sgi_get_bootpartition())) {
    2136             printf(_("\nThe boot partition does not exist.\n"));
    2137         }
    2138         if (!sgi_get_num_sectors(sgi_get_swappartition())) {
    2139             printf(_("\nThe swap partition does not exist.\n"));
    2140         } else {
    2141             if ((sgi_get_sysid(sgi_get_swappartition()) != SGI_SWAP)
    2142              && (sgi_get_sysid(sgi_get_swappartition()) != LINUX_SWAP))
    2143                 printf(_("\nThe swap partition has no swap type.\n"));
    2144         }
    2145         if (sgi_check_bootfile("/unix"))
    2146             printf(_("\tYou have chosen an unusual boot file name.\n"));
    2147     }
    2148     return (gap > 0) ? 1 : (gap == 0) ? 0 : -1;
    2149 }
    2150 
    2151 static int
    2152 sgi_gaps(void)
    2153 {
    2154     /*
    2155      * returned value is:
    2156      *  = 0 : disk is properly filled to the rim
    2157      *  < 0 : there is an overlap
    2158      *  > 0 : there is still some vacant space
    2159      */
    2160     return verify_sgi(0);
    2161 }
    2162 
    2163 static void
    2164 sgi_change_sysid(int i, int sys)
    2165 {
    2166     if( sgi_get_num_sectors(i) == 0 ) { /* caught already before, ... */
    2167         printf(_("Sorry You may change the Tag of non-empty partitions.\n"));
    2168         return;
    2169     }
    2170     if (((sys != ENTIRE_DISK ) && (sys != SGI_VOLHDR))
    2171      && (sgi_get_start_sector(i) < 1) ) {
    2172         read_chars(
    2173             _("It is highly recommended that the partition at offset 0\n"
    2174             "is of type \"SGI volhdr\", the IRIX system will rely on it to\n"
    2175             "retrieve from its directory standalone tools like sash and fx.\n"
    2176             "Only the \"SGI volume\" entire disk section may violate this.\n"
    2177             "Type YES if you are sure about tagging this partition differently.\n"));
    2178         if (strcmp(line_ptr, _("YES\n")))
    2179             return;
    2180     }
    2181     sgilabel->partitions[i].id = SGI_SSWAP32(sys);
    2182 }
    2183 
    2184 /* returns partition index of first entry marked as entire disk */
    2185 static int
    2186 sgi_entire(void)
    2187 {
    2188     int i;
    2189 
    2190     for (i = 0; i < 16; i++)
    2191         if (sgi_get_sysid(i) == SGI_VOLUME)
    2192             return i;
    2193     return -1;
    2194 }
    2195 
    2196 static void
    2197 sgi_set_partition(int i, unsigned int start, unsigned int length, int sys)
    2198 {
    2199     sgilabel->partitions[i].id = SGI_SSWAP32(sys);
    2200     sgilabel->partitions[i].num_sectors = SGI_SSWAP32(length);
    2201     sgilabel->partitions[i].start_sector = SGI_SSWAP32(start);
    2202     set_changed(i);
    2203     if (sgi_gaps() < 0)     /* rebuild freelist */
    2204         printf(_("Do You know, You got a partition overlap on the disk?\n"));
    2205 }
    2206 
    2207 static void
    2208 sgi_set_entire(void)
    2209 {
    2210     int n;
    2211 
    2212     for (n = 10; n < partitions; n++) {
    2213         if(!sgi_get_num_sectors(n) ) {
    2214             sgi_set_partition(n, 0, sgi_get_lastblock(), SGI_VOLUME);
    2215             break;
    2216         }
    2217     }
    2218 }
    2219 
    2220 static void
    2221 sgi_set_volhdr(void)
    2222 {
    2223     int n;
    2224 
    2225     for (n = 8; n < partitions; n++) {
    2226     if (!sgi_get_num_sectors(n)) {
    2227         /*
    2228          * 5 cylinders is an arbitrary value I like
    2229          * IRIX 5.3 stored files in the volume header
    2230          * (like sash, symmon, fx, ide) with ca. 3200
    2231          * sectors.
    2232          */
    2233         if (heads * sectors * 5 < sgi_get_lastblock())
    2234             sgi_set_partition(n, 0, heads * sectors * 5, SGI_VOLHDR);
    2235             break;
    2236         }
    2237     }
    2238 }
    2239 
    2240 static void
    2241 sgi_delete_partition(int i)
    2242 {
    2243     sgi_set_partition(i, 0, 0, 0);
    2244 }
    2245 
    2246 static void
    2247 sgi_add_partition(int n, int sys)
    2248 {
    2249     char mesg[256];
    2250     unsigned int first = 0, last = 0;
    2251 
    2252     if (n == 10) {
    2253         sys = SGI_VOLUME;
    2254     } else if (n == 8) {
    2255         sys = 0;
    2256     }
    2257     if(sgi_get_num_sectors(n)) {
    2258         printf(_("Partition %d is already defined.  Delete "
    2259             "it before re-adding it.\n"), n + 1);
    2260         return;
    2261     }
    2262     if ((sgi_entire() == -1) && (sys != SGI_VOLUME)) {
    2263         printf(_("Attempting to generate entire disk entry automatically.\n"));
    2264         sgi_set_entire();
    2265         sgi_set_volhdr();
    2266     }
    2267     if ((sgi_gaps() == 0) && (sys != SGI_VOLUME)) {
    2268         printf(_("The entire disk is already covered with partitions.\n"));
    2269         return;
    2270     }
    2271     if (sgi_gaps() < 0) {
    2272         printf(_("You got a partition overlap on the disk. Fix it first!\n"));
    2273         return;
    2274     }
    2275     snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
    2276     while (1) {
    2277         if(sys == SGI_VOLUME) {
    2278             last = sgi_get_lastblock();
    2279             first = read_int(0, 0, last-1, 0, mesg);
    2280             if (first != 0) {
    2281                 printf(_("It is highly recommended that eleventh partition\n"
    2282                         "covers the entire disk and is of type `SGI volume'\n"));
    2283             }
    2284         } else {
    2285             first = freelist[0].first;
    2286             last  = freelist[0].last;
    2287             first = read_int(scround(first), scround(first), scround(last)-1,
    2288                 0, mesg);
    2289         }
    2290         if (display_in_cyl_units)
    2291             first *= units_per_sector;
    2292         else
    2293             first = first; /* align to cylinder if you know how ... */
    2294         if(!last )
    2295             last = isinfreelist(first);
    2296         if(last == 0) {
    2297             printf(_("You will get a partition overlap on the disk. "
    2298                 "Fix it first!\n"));
    2299         } else
    2300             break;
    2301     }
    2302     snprintf(mesg, sizeof(mesg), _(" Last %s"), str_units(SINGULAR));
    2303     last = read_int(scround(first), scround(last)-1, scround(last)-1,
    2304             scround(first), mesg)+1;
    2305     if (display_in_cyl_units)
    2306         last *= units_per_sector;
    2307     else
    2308         last = last; /* align to cylinder if You know how ... */
    2309     if ( (sys == SGI_VOLUME) && (first != 0 || last != sgi_get_lastblock() ) )
    2310         printf(_("It is highly recommended that eleventh partition\n"
    2311             "covers the entire disk and is of type `SGI volume'\n"));
    2312     sgi_set_partition(n, first, last-first, sys);
    2313 }
    2314 
    2315 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
    2316 static void
    2317 create_sgilabel(void)
    2318 {
    2319     struct hd_geometry geometry;
    2320     struct {
    2321         unsigned int start;
    2322         unsigned int nsect;
    2323         int sysid;
    2324     } old[4];
    2325     int i = 0;
    2326     long longsectors;               /* the number of sectors on the device */
    2327     int res;                        /* the result from the ioctl */
    2328     int sec_fac;                    /* the sector factor */
    2329 
    2330     sec_fac = sector_size / 512;    /* determine the sector factor */
    2331 
    2332     fprintf( stderr,
    2333         _("Building a new SGI disklabel. Changes will remain in memory only,\n"
    2334         "until you decide to write them. After that, of course, the previous\n"
    2335         "content will be unrecoverably lost.\n\n"));
    2336 
    2337     sgi_other_endian = (BB_LITTLE_ENDIAN);
    2338     res = ioctl(fd, BLKGETSIZE, &longsectors);
    2339     if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
    2340         heads = geometry.heads;
    2341         sectors = geometry.sectors;
    2342         if (res == 0) {
    2343             /* the get device size ioctl was successful */
    2344             cylinders = longsectors / (heads * sectors);
    2345             cylinders /= sec_fac;
    2346         } else {
    2347             /* otherwise print error and use truncated version */
    2348             cylinders = geometry.cylinders;
    2349             fprintf(stderr,
    2350                 _("Warning:  BLKGETSIZE ioctl failed on %s.  "
    2351                 "Using geometry cylinder value of %d.\n"
    2352                 "This value may be truncated for devices"
    2353                 " > 33.8 GB.\n"), disk_device, cylinders);
    2354         }
    2355     }
    2356     for (i = 0; i < 4; i++) {
    2357         old[i].sysid = 0;
    2358         if (valid_part_table_flag(MBRbuffer)) {
    2359             if(get_part_table(i)->sys_ind) {
    2360                 old[i].sysid = get_part_table(i)->sys_ind;
    2361                 old[i].start = get_start_sect(get_part_table(i));
    2362                 old[i].nsect = get_nr_sects(get_part_table(i));
    2363                 printf(_("Trying to keep parameters of partition %d.\n"), i);
    2364                 if (debug)
    2365                     printf(_("ID=%02x\tSTART=%d\tLENGTH=%d\n"),
    2366                 old[i].sysid, old[i].start, old[i].nsect);
    2367             }
    2368         }
    2369     }
    2370 
    2371     memset(MBRbuffer, 0, sizeof(MBRbuffer));
    2372     sgilabel->magic = SGI_SSWAP32(SGI_LABEL_MAGIC);
    2373     sgilabel->boot_part = SGI_SSWAP16(0);
    2374     sgilabel->swap_part = SGI_SSWAP16(1);
    2375 
    2376     /* sizeof(sgilabel->boot_file) = 16 > 6 */
    2377     memset(sgilabel->boot_file, 0, 16);
    2378     strcpy((char*)sgilabel->boot_file, "/unix");
    2379 
    2380     sgilabel->devparam.skew                     = (0);
    2381     sgilabel->devparam.gap1                     = (0);
    2382     sgilabel->devparam.gap2                     = (0);
    2383     sgilabel->devparam.sparecyl                 = (0);
    2384     sgilabel->devparam.pcylcount                = SGI_SSWAP16(geometry.cylinders);
    2385     sgilabel->devparam.head_vol0                = SGI_SSWAP16(0);
    2386     sgilabel->devparam.ntrks                    = SGI_SSWAP16(geometry.heads);
    2387                         /* tracks/cylinder (heads) */
    2388     sgilabel->devparam.cmd_tag_queue_depth      = (0);
    2389     sgilabel->devparam.unused0                  = (0);
    2390     sgilabel->devparam.unused1                  = SGI_SSWAP16(0);
    2391     sgilabel->devparam.nsect                    = SGI_SSWAP16(geometry.sectors);
    2392                         /* sectors/track */
    2393     sgilabel->devparam.bytes                    = SGI_SSWAP16(512);
    2394     sgilabel->devparam.ilfact                   = SGI_SSWAP16(1);
    2395     sgilabel->devparam.flags                    = SGI_SSWAP32(TRACK_FWD|
    2396                             IGNORE_ERRORS|RESEEK);
    2397     sgilabel->devparam.datarate                 = SGI_SSWAP32(0);
    2398     sgilabel->devparam.retries_on_error         = SGI_SSWAP32(1);
    2399     sgilabel->devparam.ms_per_word              = SGI_SSWAP32(0);
    2400     sgilabel->devparam.xylogics_gap1            = SGI_SSWAP16(0);
    2401     sgilabel->devparam.xylogics_syncdelay       = SGI_SSWAP16(0);
    2402     sgilabel->devparam.xylogics_readdelay       = SGI_SSWAP16(0);
    2403     sgilabel->devparam.xylogics_gap2            = SGI_SSWAP16(0);
    2404     sgilabel->devparam.xylogics_readgate        = SGI_SSWAP16(0);
    2405     sgilabel->devparam.xylogics_writecont       = SGI_SSWAP16(0);
    2406     memset( &(sgilabel->directory), 0, sizeof(struct volume_directory)*15 );
    2407     memset( &(sgilabel->partitions), 0, sizeof(struct sgi_partition)*16 );
    2408     current_label_type = label_sgi;
    2409     partitions = 16;
    2410     sgi_volumes = 15;
    2411     sgi_set_entire();
    2412     sgi_set_volhdr();
    2413     for (i = 0; i < 4; i++) {
    2414         if(old[i].sysid) {
    2415             sgi_set_partition(i, old[i].start, old[i].nsect, old[i].sysid);
    2416         }
    2417     }
    2418 }
    2419 
    2420 static void
    2421 sgi_set_xcyl(void)
    2422 {
    2423     /* do nothing in the beginning */
    2424 }
    2425 #endif /* CONFIG_FEATURE_FDISK_ADVANCED */
    2426 
    2427 /* _____________________________________________________________
    2428  */
    2429 
    2430 static sgiinfo *
    2431 fill_sgiinfo(void)
    2432 {
    2433     sgiinfo *info = calloc(1, sizeof(sgiinfo));
    2434 
    2435     info->magic = SGI_SSWAP32(SGI_INFO_MAGIC);
    2436     info->b1 = SGI_SSWAP32(-1);
    2437     info->b2 = SGI_SSWAP16(-1);
    2438     info->b3 = SGI_SSWAP16(1);
    2439     /* You may want to replace this string !!!!!!! */
    2440     strcpy( (char*)info->scsi_string, "IBM OEM 0662S12         3 30" );
    2441     strcpy( (char*)info->serial, "0000" );
    2442     info->check1816 = SGI_SSWAP16(18*256 +16 );
    2443     strcpy( (char*)info->installer, "Sfx version 5.3, Oct 18, 1994" );
    2444     return info;
    2445 }
    2446 #endif /* SGI_LABEL */
    2447 
    2448 
    2449 #ifdef CONFIG_FEATURE_SUN_LABEL
    2450 /*
    2451  * fdisksunlabel.c
    2452  *
    2453  * I think this is mostly, or entirely, due to
    2454  *      Jakub Jelinek (jj@sunsite.mff.cuni.cz), July 1996
    2455  *
    2456  * Merged with fdisk for other architectures, aeb, June 1998.
    2457  *
    2458  * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
    2459  *      Internationalization
    2460  */
    2461 
    2462 
    2463 static int sun_other_endian;
    2464 static int scsi_disk;
    2465 static int floppy;
    2466 
    2467 #ifndef IDE0_MAJOR
    2468 #define IDE0_MAJOR 3
    2469 #endif
    2470 #ifndef IDE1_MAJOR
    2471 #define IDE1_MAJOR 22
    2472 #endif
    2473 
    2474 static void
    2475 guess_device_type(void)
    2476 {
    2477     struct stat bootstat;
    2478 
    2479     if (fstat(fd, &bootstat) < 0) {
    2480         scsi_disk = 0;
    2481         floppy = 0;
    2482     } else if (S_ISBLK(bootstat.st_mode)
    2483         && (major(bootstat.st_rdev) == IDE0_MAJOR ||
    2484             major(bootstat.st_rdev) == IDE1_MAJOR)) {
    2485         scsi_disk = 0;
    2486         floppy = 0;
    2487     } else if (S_ISBLK(bootstat.st_mode)
    2488         && major(bootstat.st_rdev) == FLOPPY_MAJOR) {
    2489         scsi_disk = 0;
    2490         floppy = 1;
    2491     } else {
    2492         scsi_disk = 1;
    2493         floppy = 0;
    2494     }
    2495 }
    2496 
    2497 static const struct systypes sun_sys_types[] = {
    2498     { "\x00" "Empty"        }, /* 0            */
    2499     { "\x01" "Boot"         }, /* 1            */
    2500     { "\x02" "SunOS root"   }, /* 2            */
    2501     { "\x03" "SunOS swap"   }, /* SUNOS_SWAP   */
    2502     { "\x04" "SunOS usr"    }, /* 4            */
    2503     { "\x05" "Whole disk"   }, /* WHOLE_DISK   */
    2504     { "\x06" "SunOS stand"  }, /* 6            */
    2505     { "\x07" "SunOS var"    }, /* 7            */
    2506     { "\x08" "SunOS home"   }, /* 8            */
    2507     { "\x82" "Linux swap"   }, /* LINUX_SWAP   */
    2508     { "\x83" "Linux native" }, /* LINUX_NATIVE */
    2509     { "\x8e" "Linux LVM"    }, /* 0x8e         */
    2510 /* New (2.2.x) raid partition with autodetect using persistent superblock */
    2511     { "\xfd" "Linux raid autodetect" }, /* 0xfd         */ 
    2512     { NULL }
    2513 };
    2514 
    2515 
    2516 static void
    2517 set_sun_partition(int i, uint start, uint stop, int sysid)
    2518 {
    2519     sunlabel->infos[i].id = sysid;
    2520     sunlabel->partitions[i].start_cylinder =
    2521         SUN_SSWAP32(start / (heads * sectors));
    2522     sunlabel->partitions[i].num_sectors =
    2523         SUN_SSWAP32(stop - start);
    2524     set_changed(i);
    2525 }
    2526 
    2527 static int
    2528 check_sun_label(void)
    2529 {
    2530     unsigned short *ush;
    2531     int csum;
    2532 
    2533     if (sunlabel->magic != SUN_LABEL_MAGIC
    2534      && sunlabel->magic != SUN_LABEL_MAGIC_SWAPPED) {
    2535         current_label_type = label_dos;
    2536         sun_other_endian = 0;
    2537         return 0;
    2538     }
    2539     sun_other_endian = (sunlabel->magic == SUN_LABEL_MAGIC_SWAPPED);
    2540     ush = ((unsigned short *) (sunlabel + 1)) - 1;
    2541     for (csum = 0; ush >= (unsigned short *)sunlabel;) csum ^= *ush--;
    2542     if (csum) {
    2543         fprintf(stderr,_("Detected sun disklabel with wrong checksum.\n"
    2544                 "Probably you'll have to set all the values,\n"
    2545                 "e.g. heads, sectors, cylinders and partitions\n"
    2546                 "or force a fresh label (s command in main menu)\n"));
    2547     } else {
    2548         heads = SUN_SSWAP16(sunlabel->ntrks);
    2549         cylinders = SUN_SSWAP16(sunlabel->ncyl);
    2550         sectors = SUN_SSWAP16(sunlabel->nsect);
    2551     }
    2552     update_units();
    2553     current_label_type = label_sun;
    2554     partitions = 8;
    2555     return 1;
    2556 }
    2557 
    2558 static const struct sun_predefined_drives {
    2559     const char *vendor;
    2560     const char *model;
    2561     unsigned short sparecyl;
    2562     unsigned short ncyl;
    2563     unsigned short nacyl;
    2564     unsigned short pcylcount;
    2565     unsigned short ntrks;
    2566     unsigned short nsect;
    2567     unsigned short rspeed;
    2568 } sun_drives[] = {
    2569     { "Quantum","ProDrive 80S",1,832,2,834,6,34,3662},
    2570     { "Quantum","ProDrive 105S",1,974,2,1019,6,35,3662},
    2571     { "CDC","Wren IV 94171-344",3,1545,2,1549,9,46,3600},
    2572     { "IBM","DPES-31080",0,4901,2,4903,4,108,5400},
    2573     { "IBM","DORS-32160",0,1015,2,1017,67,62,5400},
    2574     { "IBM","DNES-318350",0,11199,2,11474,10,320,7200},
    2575     { "SEAGATE","ST34371",0,3880,2,3882,16,135,7228},
    2576     { "","SUN0104",1,974,2,1019,6,35,3662},
    2577     { "","SUN0207",4,1254,2,1272,9,36,3600},
    2578     { "","SUN0327",3,1545,2,1549,9,46,3600},
    2579     { "","SUN0340",0,1538,2,1544,6,72,4200},
    2580     { "","SUN0424",2,1151,2,2500,9,80,4400},
    2581     { "","SUN0535",0,1866,2,2500,7,80,5400},
    2582     { "","SUN0669",5,1614,2,1632,15,54,3600},
    2583     { "","SUN1.0G",5,1703,2,1931,15,80,3597},
    2584     { "","SUN1.05",0,2036,2,2038,14,72,5400},
    2585     { "","SUN1.3G",6,1965,2,3500,17,80,5400},
    2586     { "","SUN2.1G",0,2733,2,3500,19,80,5400},
    2587     { "IOMEGA","Jaz",0,1019,2,1021,64,32,5394},
    2588 };
    2589 
    2590 static const struct sun_predefined_drives *
    2591 sun_autoconfigure_scsi(void)
    2592 {
    2593     const struct sun_predefined_drives *p = NULL;
    2594 
    2595 #ifdef SCSI_IOCTL_GET_IDLUN
    2596     unsigned int id[2];
    2597     char buffer[2048];
    2598     char buffer2[2048];
    2599     FILE *pfd;
    2600     char *vendor;
    2601     char *model;
    2602     char *q;
    2603     int i;
    2604 
    2605     if (!ioctl(fd, SCSI_IOCTL_GET_IDLUN, &id)) {
    2606         sprintf(buffer,
    2607             "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n",
    2608 #if 0
    2609             ((id[0]>>24)&0xff)-/*PROC_SCSI_SCSI+PROC_SCSI_FILE*/33,
    2610 #else
    2611             /* This is very wrong (works only if you have one HBA),
    2612                but I haven't found a way how to get hostno
    2613                from the current kernel */
    2614             0,
    2615 #endif
    2616             (id[0]>>16) & 0xff,
    2617             id[0] & 0xff,
    2618             (id[0]>>8) & 0xff
    2619         );
    2620         pfd = fopen("/proc/scsi/scsi","r");
    2621         if (pfd) {
    2622             while (fgets(buffer2, 2048, pfd)) {
    2623                 if (!strcmp(buffer, buffer2)) {
    2624                     if (fgets(buffer2,2048,pfd)) {
    2625                         q = strstr(buffer2,"Vendor: ");
    2626                         if (q) {
    2627                             q += 8;
    2628                             vendor = q;
    2629                             q = strstr(q," ");
    2630                             *q++ = 0;   /* truncate vendor name */
    2631                             q = strstr(q,"Model: ");
    2632                             if (q) {
    2633                                 *q = 0;
    2634                                 q += 7;
    2635                                 model = q;
    2636                                 q = strstr(q," Rev: ");
    2637                                 if (q) {
    2638                                     *q = 0;
    2639                                     for (i = 0; i < SIZE(sun_drives); i++) {
    2640                                         if (*sun_drives[i].vendor && strcasecmp(sun_drives[i].vendor, vendor))
    2641                                             continue;
    2642                                         if (!strstr(model, sun_drives[i].model))
    2643                                             continue;
    2644                                         printf(_("Autoconfigure found a %s%s%s\n"),sun_drives[i].vendor,(*sun_drives[i].vendor) ? " " : "",sun_drives[i].model);
    2645                                         p = sun_drives + i;
    2646                                         break;
    2647                                     }
    2648                                 }
    2649                             }
    2650                         }
    2651                     }
    2652                     break;
    2653                 }
    2654             }
    2655             fclose(pfd);
    2656         }
    2657     }
    2658 #endif
    2659     return p;
    2660 }
    2661 
    2662 static void
    2663 create_sunlabel(void)
    2664 {
    2665     struct hd_geometry geometry;
    2666     unsigned int ndiv;
    2667     int i;
    2668     unsigned char c;
    2669     const struct sun_predefined_drives *p = NULL;
    2670 
    2671     fprintf(stderr,
    2672         _("Building a new sun disklabel. Changes will remain in memory only,\n"
    2673         "until you decide to write them. After that, of course, the previous\n"
    2674         "content won't be recoverable.\n\n"));
    2675     sun_other_endian = BB_LITTLE_ENDIAN;
    2676     memset(MBRbuffer, 0, sizeof(MBRbuffer));
    2677     sunlabel->magic = SUN_SSWAP16(SUN_LABEL_MAGIC);
    2678     if (!floppy) {
    2679         puts(_("Drive type\n"
    2680          "   ?   auto configure\n"
    2681          "   0   custom (with hardware detected defaults)"));
    2682         for (i = 0; i < SIZE(sun_drives); i++) {
    2683             printf("   %c   %s%s%s\n",
    2684                 i + 'a', sun_drives[i].vendor,
    2685                 (*sun_drives[i].vendor) ? " " : "",
    2686                 sun_drives[i].model);
    2687         }
    2688         while (1) {
    2689             c = read_char(_("Select type (? for auto, 0 for custom): "));
    2690             if (c >= 'a' && c < 'a' + SIZE(sun_drives)) {
    2691                 p = sun_drives + c - 'a';
    2692                 break;
    2693             } else if (c >= 'A' && c < 'A' + SIZE(sun_drives)) {
    2694                 p = sun_drives + c - 'A';
    2695                 break;
    2696             } else if (c == '0') {
    2697                 break;
    2698             } else if (c == '?' && scsi_disk) {
    2699                 p = sun_autoconfigure_scsi();
    2700                 if (!p)
    2701                 printf(_("Autoconfigure failed.\n"));
    2702                 else
    2703                 break;
    2704             }
    2705         }
    2706     }
    2707     if (!p || floppy) {
    2708         if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
    2709             heads = geometry.heads;
    2710             sectors = geometry.sectors;
    2711             cylinders = geometry.cylinders;
    2712         } else {
    2713             heads = 0;
    2714             sectors = 0;
    2715             cylinders = 0;
    2716         }
    2717         if (floppy) {
    2718             sunlabel->nacyl = 0;
    2719             sunlabel->pcylcount = SUN_SSWAP16(cylinders);
    2720             sunlabel->rspeed = SUN_SSWAP16(300);
    2721             sunlabel->ilfact = SUN_SSWAP16(1);
    2722             sunlabel->sparecyl = 0;
    2723         } else {
    2724             heads = read_int(1,heads,1024,0,_("Heads"));
    2725             sectors = read_int(1,sectors,1024,0,_("Sectors/track"));
    2726         if (cylinders)
    2727             cylinders = read_int(1,cylinders-2,65535,0,_("Cylinders"));
    2728         else
    2729             cylinders = read_int(1,0,65535,0,_("Cylinders"));
    2730             sunlabel->nacyl = SUN_SSWAP16(read_int(0,2,65535,0, _("Alternate cylinders")));
    2731             sunlabel->pcylcount = SUN_SSWAP16(read_int(0,cylinders+SUN_SSWAP16(sunlabel->nacyl), 65535,0, _("Physical cylinders")));
    2732             sunlabel->rspeed = SUN_SSWAP16(read_int(1,5400,100000,0, _("Rotation speed (rpm)")));
    2733             sunlabel->ilfact = SUN_SSWAP16(read_int(1,1,32,0, _("Interleave factor")));
    2734             sunlabel->sparecyl = SUN_SSWAP16(read_int(0,0,sectors,0, _("Extra sectors per cylinder")));
    2735         }
    2736     } else {
    2737         sunlabel->sparecyl = SUN_SSWAP16(p->sparecyl);
    2738         sunlabel->ncyl = SUN_SSWAP16(p->ncyl);
    2739         sunlabel->nacyl = SUN_SSWAP16(p->nacyl);
    2740         sunlabel->pcylcount = SUN_SSWAP16(p->pcylcount);
    2741         sunlabel->ntrks = SUN_SSWAP16(p->ntrks);
    2742         sunlabel->nsect = SUN_SSWAP16(p->nsect);
    2743         sunlabel->rspeed = SUN_SSWAP16(p->rspeed);
    2744         sunlabel->ilfact = SUN_SSWAP16(1);
    2745         cylinders = p->ncyl;
    2746         heads = p->ntrks;
    2747         sectors = p->nsect;
    2748         puts(_("You may change all the disk params from the x menu"));
    2749     }
    2750 
    2751     snprintf((char *)(sunlabel->info), sizeof(sunlabel->info),
    2752         "%s%s%s cyl %d alt %d hd %d sec %d",
    2753         p ? p->vendor : "", (p && *p->vendor) ? " " : "",
    2754         p ? p->model : (floppy ? _("3,5\" floppy") : _("Linux custom")),
    2755         cylinders, SUN_SSWAP16(sunlabel->nacyl), heads, sectors);
    2756 
    2757     sunlabel->ntrks = SUN_SSWAP16(heads);
    2758     sunlabel->nsect = SUN_SSWAP16(sectors);
    2759     sunlabel->ncyl = SUN_SSWAP16(cylinders);
    2760     if (floppy)
    2761         set_sun_partition(0, 0, cylinders * heads * sectors, LINUX_NATIVE);
    2762     else {
    2763         if (cylinders * heads * sectors >= 150 * 2048) {
    2764             ndiv = cylinders - (50 * 2048 / (heads * sectors)); /* 50M swap */
    2765         } else
    2766             ndiv = cylinders * 2 / 3;
    2767         set_sun_partition(0, 0, ndiv * heads * sectors, LINUX_NATIVE);
    2768         set_sun_partition(1, ndiv * heads * sectors, cylinders * heads * sectors, LINUX_SWAP);
    2769         sunlabel->infos[1].flags |= 0x01; /* Not mountable */
    2770     }
    2771     set_sun_partition(2, 0, cylinders * heads * sectors, WHOLE_DISK);
    2772     {
    2773         unsigned short *ush = (unsigned short *)sunlabel;
    2774         unsigned short csum = 0;
    2775         while (ush < (unsigned short *)(&sunlabel->csum))
    2776             csum ^= *ush++;
    2777         sunlabel->csum = csum;
    2778     }
    2779 
    2780     set_all_unchanged();
    2781     set_changed(0);
    2782     get_boot(create_empty_sun);
    2783 }
    2784 
    2785 static void
    2786 toggle_sunflags(int i, unsigned char mask)
    2787 {
    2788     if (sunlabel->infos[i].flags & mask)
    2789         sunlabel->infos[i].flags &= ~mask;
    2790     else
    2791         sunlabel->infos[i].flags |= mask;
    2792     set_changed(i);
    2793 }
    2794 
    2795 static void
    2796 fetch_sun(uint *starts, uint *lens, uint *start, uint *stop)
    2797 {
    2798     int i, continuous = 1;
    2799 
    2800     *start = 0;
    2801     *stop = cylinders * heads * sectors;
    2802     for (i = 0; i < partitions; i++) {
    2803         if (sunlabel->partitions[i].num_sectors
    2804          && sunlabel->infos[i].id
    2805          && sunlabel->infos[i].id != WHOLE_DISK) {
    2806             starts[i] = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
    2807             lens[i] = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
    2808             if (continuous) {
    2809                 if (starts[i] == *start)
    2810                     *start += lens[i];
    2811                 else if (starts[i] + lens[i] >= *stop)
    2812                     *stop = starts[i];
    2813                 else
    2814                     continuous = 0;
    2815                     /* There will be probably more gaps
    2816                       than one, so lets check afterwards */
    2817             }
    2818         } else {
    2819             starts[i] = 0;
    2820             lens[i] = 0;
    2821         }
    2822     }
    2823 }
    2824 
    2825 static uint *verify_sun_starts;
    2826 
    2827 static int
    2828 verify_sun_cmp(int *a, int *b)
    2829 {
    2830     if (*a == -1) return 1;
    2831     if (*b == -1) return -1;
    2832     if (verify_sun_starts[*a] > verify_sun_starts[*b]) return 1;
    2833     return -1;
    2834 }
    2835 
    2836 static void
    2837 verify_sun(void)
    2838 {
    2839     uint starts[8], lens[8], start, stop;
    2840     int i,j,k,starto,endo;
    2841     int array[8];
    2842 
    2843     verify_sun_starts = starts;
    2844     fetch_sun(starts,lens,&start,&stop);
    2845     for (k = 0; k < 7; k++) {
    2846         for (i = 0; i < 8; i++) {
    2847             if (k && (lens[i] % (heads * sectors))) {
    2848                 printf(_("Partition %d doesn't end on cylinder boundary\n"), i+1);
    2849             }
    2850             if (lens[i]) {
    2851                 for (j = 0; j < i; j++)
    2852                     if (lens[j]) {
    2853                         if (starts[j] == starts[i]+lens[i]) {
    2854                             starts[j] = starts[i]; lens[j] += lens[i];
    2855                             lens[i] = 0;
    2856                         } else if (starts[i] == starts[j]+lens[j]){
    2857                             lens[j] += lens[i];
    2858                             lens[i] = 0;
    2859                         } else if (!k) {
    2860                             if (starts[i] < starts[j]+lens[j]
    2861                              && starts[j] < starts[i]+lens[i]) {
    2862                                 starto = starts[i];
    2863                                 if (starts[j] > starto)
    2864                                     starto = starts[j];
    2865                                 endo = starts[i]+lens[i];
    2866                                 if (starts[j]+lens[j] < endo)
    2867                                     endo = starts[j]+lens[j];
    2868                                 printf(_("Partition %d overlaps with others in "
    2869                                     "sectors %d-%d\n"), i+1, starto, endo);
    2870                             }
    2871                         }
    2872                     }
    2873             }
    2874         }
    2875     }
    2876     for (i = 0; i < 8; i++) {
    2877         if (lens[i])
    2878             array[i] = i;
    2879         else
    2880             array[i] = -1;
    2881     }
    2882     qsort(array,SIZE(array),sizeof(array[0]),
    2883         (int (*)(const void *,const void *)) verify_sun_cmp);
    2884     if (array[0] == -1) {
    2885         printf(_("No partitions defined\n"));
    2886         return;
    2887     }
    2888     stop = cylinders * heads * sectors;
    2889     if (starts[array[0]])
    2890         printf(_("Unused gap - sectors 0-%d\n"),starts[array[0]]);
    2891     for (i = 0; i < 7 && array[i+1] != -1; i++) {
    2892         printf(_("Unused gap - sectors %d-%d\n"),starts[array[i]]+lens[array[i]],starts[array[i+1]]);
    2893     }
    2894     start = starts[array[i]] + lens[array[i]];
    2895     if (start < stop)
    2896         printf(_("Unused gap - sectors %d-%d\n"),start,stop);
    2897 }
    2898 
    2899 static void
    2900 add_sun_partition(int n, int sys)
    2901 {
    2902     uint start, stop, stop2;
    2903     uint starts[8], lens[8];
    2904     int whole_disk = 0;
    2905 
    2906     char mesg[256];
    2907     int i, first, last;
    2908 
    2909     if (sunlabel->partitions[n].num_sectors && sunlabel->infos[n].id) {
    2910         printf(_("Partition %d is already defined.  Delete "
    2911             "it before re-adding it.\n"), n + 1);
    2912         return;
    2913     }
    2914 
    2915     fetch_sun(starts,lens,&start,&stop);
    2916     if (stop <= start) {
    2917         if (n == 2)
    2918             whole_disk = 1;
    2919         else {
    2920             printf(_("Other partitions already cover the whole disk.\nDelete "
    2921                    "some/shrink them before retry.\n"));
    2922             return;
    2923         }
    2924     }
    2925     snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
    2926     while (1) {
    2927         if (whole_disk)
    2928             first = read_int(0, 0, 0, 0, mesg);
    2929         else
    2930             first = read_int(scround(start), scround(stop)+1,
    2931                      scround(stop), 0, mesg);
    2932         if (display_in_cyl_units)
    2933             first *= units_per_sector;
    2934         else
    2935             /* Starting sector has to be properly aligned */
    2936             first = (first + heads * sectors - 1) / (heads * sectors);
    2937         if (n == 2 && first != 0)
    2938             printf("\
    2939 It is highly recommended that the third partition covers the whole disk\n\
    2940 and is of type `Whole disk'\n");
    2941         /* ewt asks to add: "don't start a partition at cyl 0"
    2942            However, edmundo@rano.demon.co.uk writes:
    2943            "In addition to having a Sun partition table, to be able to
    2944            boot from the disc, the first partition, /dev/sdX1, must
    2945            start at cylinder 0. This means that /dev/sdX1 contains
    2946            the partition table and the boot block, as these are the
    2947            first two sectors of the disc. Therefore you must be
    2948            careful what you use /dev/sdX1 for. In particular, you must
    2949            not use a partition starting at cylinder 0 for Linux swap,
    2950            as that would overwrite the partition table and the boot
    2951            block. You may, however, use such a partition for a UFS
    2952            or EXT2 file system, as these file systems leave the first
    2953            1024 bytes undisturbed. */
    2954         /* On the other hand, one should not use partitions
    2955            starting at block 0 in an md, or the label will
    2956            be trashed. */
    2957         for (i = 0; i < partitions; i++)
    2958             if (lens[i] && starts[i] <= first && starts[i] + lens[i] > first)
    2959                 break;
    2960         if (i < partitions && !whole_disk) {
    2961             if (n == 2 && !first) {
    2962                 whole_disk = 1;
    2963                 break;
    2964             }
    2965             printf(_("Sector %d is already allocated\n"), first);
    2966         } else
    2967             break;
    2968     }
    2969     stop = cylinders * heads * sectors;
    2970     stop2 = stop;
    2971     for (i = 0; i < partitions; i++) {
    2972         if (starts[i] > first && starts[i] < stop)
    2973             stop = starts[i];
    2974     }
    2975     snprintf(mesg, sizeof(mesg),
    2976         _("Last %s or +size or +sizeM or +sizeK"),
    2977         str_units(SINGULAR));
    2978     if (whole_disk)
    2979         last = read_int(scround(stop2), scround(stop2), scround(stop2),
    2980                 0, mesg);
    2981     else if (n == 2 && !first)
    2982         last = read_int(scround(first), scround(stop2), scround(stop2),
    2983                 scround(first), mesg);
    2984     else
    2985         last = read_int(scround(first), scround(stop), scround(stop),
    2986                 scround(first), mesg);
    2987     if (display_in_cyl_units)
    2988         last *= units_per_sector;
    2989     if (n == 2 && !first) {
    2990         if (last >= stop2) {
    2991             whole_disk = 1;
    2992             last = stop2;
    2993         } else if (last > stop) {
    2994             printf(_("You haven't covered the whole disk with "
    2995                 "the 3rd partition, but your value\n"
    2996                 "%d %s covers some other partition. "
    2997                 "Your entry has been changed\n"
    2998                 "to %d %s\n"),
    2999                 scround(last), str_units(SINGULAR),
    3000                 scround(stop), str_units(SINGULAR));
    3001             last = stop;
    3002         }
    3003     } else if (!whole_disk && last > stop)
    3004         last = stop;
    3005 
    3006     if (whole_disk)
    3007         sys = WHOLE_DISK;
    3008     set_sun_partition(n, first, last, sys);
    3009 }
    3010 
    3011 static void
    3012 sun_delete_partition(int i)
    3013 {
    3014     unsigned int nsec;
    3015 
    3016     if (i == 2
    3017      && sunlabel->infos[i].id == WHOLE_DISK
    3018      && !sunlabel->partitions[i].start_cylinder
    3019      && (nsec = SUN_SSWAP32(sunlabel->partitions[i].num_sectors)) == heads * sectors * cylinders)
    3020         printf(_("If you want to maintain SunOS/Solaris compatibility, "
    3021             "consider leaving this\n"
    3022             "partition as Whole disk (5), starting at 0, with %u "
    3023             "sectors\n"), nsec);
    3024     sunlabel->infos[i].id = 0;
    3025     sunlabel->partitions[i].num_sectors = 0;
    3026 }
    3027 
    3028 static void
    3029 sun_change_sysid(int i, int sys)
    3030 {
    3031     if (sys == LINUX_SWAP && !sunlabel->partitions[i].start_cylinder) {
    3032         read_chars(
    3033             _("It is highly recommended that the partition at offset 0\n"
    3034             "is UFS, EXT2FS filesystem or SunOS swap. Putting Linux swap\n"
    3035             "there may destroy your partition table and bootblock.\n"
    3036             "Type YES if you're very sure you would like that partition\n"
    3037             "tagged with 82 (Linux swap): "));
    3038         if (strcmp (line_ptr, _("YES\n")))
    3039             return;
    3040     }
    3041     switch (sys) {
    3042     case SUNOS_SWAP:
    3043     case LINUX_SWAP:
    3044         /* swaps are not mountable by default */
    3045         sunlabel->infos[i].flags |= 0x01;
    3046         break;
    3047     default:
    3048         /* assume other types are mountable;
    3049            user can change it anyway */
    3050         sunlabel->infos[i].flags &= ~0x01;
    3051         break;
    3052     }
    3053     sunlabel->infos[i].id = sys;
    3054 }
    3055 
    3056 static void
    3057 sun_list_table(int xtra)
    3058 {
    3059     int i, w;
    3060 
    3061     w = strlen(disk_device);
    3062     if (xtra)
    3063         printf(
    3064         _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d rpm\n"
    3065         "%d cylinders, %d alternate cylinders, %d physical cylinders\n"
    3066         "%d extra sects/cyl, interleave %d:1\n"
    3067         "%s\n"
    3068         "Units = %s of %d * 512 bytes\n\n"),
    3069             disk_device, heads, sectors, SUN_SSWAP16(sunlabel->rspeed),
    3070             cylinders, SUN_SSWAP16(sunlabel->nacyl),
    3071             SUN_SSWAP16(sunlabel->pcylcount),
    3072             SUN_SSWAP16(sunlabel->sparecyl),
    3073             SUN_SSWAP16(sunlabel->ilfact),
    3074             (char *)sunlabel,
    3075             str_units(PLURAL), units_per_sector);
    3076     else
    3077         printf(
    3078     _("\nDisk %s (Sun disk label): %d heads, %d sectors, %d cylinders\n"
    3079     "Units = %s of %d * 512 bytes\n\n"),
    3080             disk_device, heads, sectors, cylinders,
    3081             str_units(PLURAL), units_per_sector);
    3082 
    3083     printf(_("%*s Flag    Start       End    Blocks   Id  System\n"),
    3084         w + 1, _("Device"));
    3085     for (i = 0 ; i < partitions; i++) {
    3086         if (sunlabel->partitions[i].num_sectors) {
    3087             uint32_t start = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
    3088             uint32_t len = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
    3089             printf("%s %c%c %9ld %9ld %9ld%c  %2x  %s\n",
    3090                 partname(disk_device, i+1, w),          /* device */           
    3091                 (sunlabel->infos[i].flags & 0x01) ? 'u' : ' ',  /* flags */             
    3092                 (sunlabel->infos[i].flags & 0x10) ? 'r' : ' ',             
    3093                 (long) scround(start),                          /* start */             
    3094                 (long) scround(start+len),                      /* end */               
    3095                 (long) len / 2, len & 1 ? '+' : ' ',            /* odd flag on end */   
    3096                 sunlabel->infos[i].id,                          /* type id */           
    3097                 partition_type(sunlabel->infos[i].id));         /* type name */         
    3098         }
    3099     }
    3100 }
    3101 
    3102 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
    3103 
    3104 static void
    3105 sun_set_alt_cyl(void)
    3106 {
    3107     sunlabel->nacyl =
    3108         SUN_SSWAP16(read_int(0,SUN_SSWAP16(sunlabel->nacyl), 65535, 0,
    3109                 _("Number of alternate cylinders")));
    3110 }
    3111 
    3112 static void
    3113 sun_set_ncyl(int cyl)
    3114 {
    3115     sunlabel->ncyl = SUN_SSWAP16(cyl);
    3116 }
    3117 
    3118 static void
    3119 sun_set_xcyl(void)
    3120 {
    3121     sunlabel->sparecyl =
    3122         SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->sparecyl), sectors, 0,
    3123                 _("Extra sectors per cylinder")));
    3124 }
    3125 
    3126 static void
    3127 sun_set_ilfact(void)
    3128 {
    3129     sunlabel->ilfact =
    3130         SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->ilfact), 32, 0,
    3131                 _("Interleave factor")));
    3132 }
    3133 
    3134 static void
    3135 sun_set_rspeed(void)
    3136 {
    3137     sunlabel->rspeed =
    3138         SUN_SSWAP16(read_int(1, SUN_SSWAP16(sunlabel->rspeed), 100000, 0,
    3139                 _("Rotation speed (rpm)")));
    3140 }
    3141 
    3142 static void
    3143 sun_set_pcylcount(void)
    3144 {
    3145     sunlabel->pcylcount =
    3146         SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->pcylcount), 65535, 0,
    3147                 _("Number of physical cylinders")));
    3148 }
    3149 #endif /* CONFIG_FEATURE_FDISK_ADVANCED */
    3150 
    3151 static void
    3152 sun_write_table(void)
    3153 {
    3154     unsigned short *ush = (unsigned short *)sunlabel;
    3155     unsigned short csum = 0;
    3156 
    3157     while (ush < (unsigned short *)(&sunlabel->csum))
    3158         csum ^= *ush++;
    3159     sunlabel->csum = csum;
    3160     if (lseek(fd, 0, SEEK_SET) < 0)
    3161         fdisk_fatal(unable_to_seek);
    3162     if (write(fd, sunlabel, SECTOR_SIZE) != SECTOR_SIZE)
    3163         fdisk_fatal(unable_to_write);
    3164 }
    3165 #endif /* SUN_LABEL */
    3166 
    3167 /* DOS partition types */
    3168 
    3169 static const struct systypes i386_sys_types[] = {
    3170     { "\x00" "Empty" },
    3171     { "\x01" "FAT12" },
    3172     { "\x04" "FAT16 <32M" },
    3173     { "\x05" "Extended" },         /* DOS 3.3+ extended partition */
    3174     { "\x06" "FAT16" },            /* DOS 16-bit >=32M */
    3175     { "\x07" "HPFS/NTFS" },        /* OS/2 IFS, eg, HPFS or NTFS or QNX */
    3176     { "\x0a" "OS/2 Boot Manager" },/* OS/2 Boot Manager */
    3177     { "\x0b" "Win95 FAT32" },
    3178     { "\x0c" "Win95 FAT32 (LBA)" },/* LBA really is `Extended Int 13h' */
    3179     { "\x0e" "Win95 FAT16 (LBA)" },
    3180     { "\x0f" "Win95 Ext'd (LBA)" },
    3181     { "\x11" "Hidden FAT12" },
    3182     { "\x12" "Compaq diagnostics" },
    3183     { "\x14" "Hidden FAT16 <32M" },
    3184     { "\x16" "Hidden FAT16" },
    3185     { "\x17" "Hidden HPFS/NTFS" },
    3186     { "\x1b" "Hidden Win95 FAT32" },
    3187     { "\x1c" "Hidden Win95 FAT32 (LBA)" },
    3188     { "\x1e" "Hidden Win95 FAT16 (LBA)" },
    3189     { "\x3c" "PartitionMagic recovery" },
    3190     { "\x41" "PPC PReP Boot" },
    3191     { "\x42" "SFS" },
    3192     { "\x63" "GNU HURD or SysV" }, /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */
    3193     { "\x80" "Old Minix" },        /* Minix 1.4a and earlier */
    3194     { "\x81" "Minix / old Linux" },/* Minix 1.4b and later */
    3195     { "\x82" "Linux swap" },       /* also Solaris */
    3196     { "\x83" "Linux" },
    3197     { "\x84" "OS/2 hidden C: drive" },
    3198     { "\x85" "Linux extended" },
    3199     { "\x86" "NTFS volume set" },
    3200     { "\x87" "NTFS volume set" },
    3201     { "\x8e" "Linux LVM" },
    3202     { "\x9f" "BSD/OS" },           /* BSDI */
    3203     { "\xa0" "IBM Thinkpad hibernation" },
    3204     { "\xa5" "FreeBSD" },          /* various BSD flavours */
    3205     { "\xa6" "OpenBSD" },
    3206     { "\xa8" "Darwin UFS" },
    3207     { "\xa9" "NetBSD" },
    3208     { "\xab" "Darwin boot" },
    3209     { "\xb7" "BSDI fs" },
    3210     { "\xb8" "BSDI swap" },
    3211     { "\xbe" "Solaris boot" },
    3212     { "\xeb" "BeOS fs" },
    3213     { "\xee" "EFI GPT" },          /* Intel EFI GUID Partition Table */
    3214     { "\xef" "EFI (FAT-12/16/32)" },/* Intel EFI System Partition */
    3215     { "\xf0" "Linux/PA-RISC boot" },/* Linux/PA-RISC boot loader */
    3216     { "\xf2" "DOS secondary" },    /* DOS 3.3+ secondary */
    3217     { "\xfd" "Linux raid autodetect" },/* New (2.2.x) raid partition with
    3218                         autodetect using persistent
    3219                         superblock */
    3220 #ifdef CONFIG_WEIRD_PARTITION_TYPES
    3221     { "\x02" "XENIX root" },
    3222     { "\x03" "XENIX usr" },
    3223     { "\x08" "AIX" },              /* AIX boot (AIX -- PS/2 port) or SplitDrive */
    3224     { "\x09" "AIX bootable" },     /* AIX data or Coherent */
    3225     { "\x10" "OPUS" },
    3226     { "\x18" "AST SmartSleep" },
    3227     { "\x24" "NEC DOS" },
    3228     { "\x39" "Plan 9" },
    3229     { "\x40" "Venix 80286" },
    3230     { "\x4d" "QNX4.x" },
    3231     { "\x4e" "QNX4.x 2nd part" },
    3232     { "\x4f" "QNX4.x 3rd part" },
    3233     { "\x50" "OnTrack DM" },
    3234     { "\x51" "OnTrack DM6 Aux1" }, /* (or Novell) */
    3235     { "\x52" "CP/M" },             /* CP/M or Microport SysV/AT */
    3236     { "\x53" "OnTrack DM6 Aux3" },
    3237     { "\x54" "OnTrackDM6" },
    3238     { "\x55" "EZ-Drive" },
    3239     { "\x56" "Golden Bow" },
    3240     { "\x5c" "Priam Edisk" },
    3241     { "\x61" "SpeedStor" },
    3242     { "\x64" "Novell Netware 286" },
    3243     { "\x65" "Novell Netware 386" },
    3244     { "\x70" "DiskSecure Multi-Boot" },
    3245     { "\x75" "PC/IX" },
    3246     { "\x93" "Amoeba" },
    3247     { "\x94" "Amoeba BBT" },       /* (bad block table) */
    3248     { "\xa7" "NeXTSTEP" },
    3249     { "\xbb" "Boot Wizard hidden" },
    3250     { "\xc1" "DRDOS/sec (FAT-12)" },
    3251     { "\xc4" "DRDOS/sec (FAT-16 < 32M)" },
    3252     { "\xc6" "DRDOS/sec (FAT-16)" },
    3253     { "\xc7" "Syrinx" },
    3254     { "\xda" "Non-FS data" },
    3255     { "\xdb" "CP/M / CTOS / ..." },/* CP/M or Concurrent CP/M or
    3256                     Concurrent DOS or CTOS */
    3257     { "\xde" "Dell Utility" },     /* Dell PowerEdge Server utilities */
    3258     { "\xdf" "BootIt" },           /* BootIt EMBRM */
    3259     { "\xe1" "DOS access" },       /* DOS access or SpeedStor 12-bit FAT
    3260                     extended partition */
    3261     { "\xe3" "DOS R/O" },          /* DOS R/O or SpeedStor */
    3262     { "\xe4" "SpeedStor" },        /* SpeedStor 16-bit FAT extended
    3263                     partition < 1024 cyl. */
    3264     { "\xf1" "SpeedStor" },
    3265     { "\xf4" "SpeedStor" },        /* SpeedStor large partition */
    3266     { "\xfe" "LANstep" },          /* SpeedStor >1024 cyl. or LANstep */
    3267     { "\xff" "BBT" },              /* Xenix Bad Block Table */
    3268 #endif
    3269     { 0 }
    3270 };
    3271 
    3272 
    3273 
    3274 /* A valid partition table sector ends in 0x55 0xaa */
    3275 static unsigned int
    3276 part_table_flag(const char *b)
    3277 {
    3278     return ((uint) b[510]) + (((uint) b[511]) << 8);
    3279 }
    3280 
    3281 
    3282 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
    3283 static void
    3284 write_part_table_flag(char *b)
    3285 {
    3286     b[510] = 0x55;
    3287     b[511] = 0xaa;
    3288 }
    3289 
     505STATIC_OSF void bsd_select(void);
     506STATIC_OSF void xbsd_print_disklabel(int);
     507#include "fdisk_osf.c"
     508
     509#if ENABLE_FEATURE_SGI_LABEL || ENABLE_FEATURE_SUN_LABEL
     510static uint16_t
     511fdisk_swap16(uint16_t x)
     512{
     513    return (x << 8) | (x >> 8);
     514}
     515
     516static uint32_t
     517fdisk_swap32(uint32_t x)
     518{
     519    return (x << 24) |
     520           ((x & 0xFF00) << 8) |
     521           ((x & 0xFF0000) >> 8) |
     522           (x >> 24);
     523}
     524#endif
     525
     526STATIC_SGI const char *const sgi_sys_types[];
     527STATIC_SGI unsigned sgi_get_num_sectors(int i);
     528STATIC_SGI int sgi_get_sysid(int i);
     529STATIC_SGI void sgi_delete_partition(int i);
     530STATIC_SGI void sgi_change_sysid(int i, int sys);
     531STATIC_SGI void sgi_list_table(int xtra);
     532#if ENABLE_FEATURE_FDISK_ADVANCED
     533STATIC_SGI void sgi_set_xcyl(void);
     534#endif
     535STATIC_SGI int verify_sgi(int verbose);
     536STATIC_SGI void sgi_add_partition(int n, int sys);
     537STATIC_SGI void sgi_set_swappartition(int i);
     538STATIC_SGI const char *sgi_get_bootfile(void);
     539STATIC_SGI void sgi_set_bootfile(const char* aFile);
     540STATIC_SGI void create_sgiinfo(void);
     541STATIC_SGI void sgi_write_table(void);
     542STATIC_SGI void sgi_set_bootpartition(int i);
     543#include "fdisk_sgi.c"
     544
     545STATIC_SUN const char *const sun_sys_types[];
     546STATIC_SUN void sun_delete_partition(int i);
     547STATIC_SUN void sun_change_sysid(int i, int sys);
     548STATIC_SUN void sun_list_table(int xtra);
     549STATIC_SUN void add_sun_partition(int n, int sys);
     550#if ENABLE_FEATURE_FDISK_ADVANCED
     551STATIC_SUN void sun_set_alt_cyl(void);
     552STATIC_SUN void sun_set_ncyl(int cyl);
     553STATIC_SUN void sun_set_xcyl(void);
     554STATIC_SUN void sun_set_ilfact(void);
     555STATIC_SUN void sun_set_rspeed(void);
     556STATIC_SUN void sun_set_pcylcount(void);
     557#endif
     558STATIC_SUN void toggle_sunflags(int i, unsigned char mask);
     559STATIC_SUN void verify_sun(void);
     560STATIC_SUN void sun_write_table(void);
     561#include "fdisk_sun.c"
     562
     563#if ENABLE_FEATURE_FDISK_WRITABLE
    3290564/* start_sect and nr_sects are stored little endian on all machines */
    3291565/* moreover, they are not aligned correctly */
    3292566static void
    3293 store4_little_endian(unsigned char *cp, unsigned int val)
    3294 {
    3295     cp[0] = (val & 0xff);
    3296     cp[1] = ((val >> 8) & 0xff);
    3297     cp[2] = ((val >> 16) & 0xff);
    3298     cp[3] = ((val >> 24) & 0xff);
    3299 }
    3300 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
    3301 
    3302 static unsigned int
     567store4_little_endian(unsigned char *cp, unsigned val)
     568{
     569    cp[0] = val;
     570    cp[1] = val >> 8;
     571    cp[2] = val >> 16;
     572    cp[3] = val >> 24;
     573}
     574#endif /* FEATURE_FDISK_WRITABLE */
     575
     576static unsigned
    3303577read4_little_endian(const unsigned char *cp)
    3304578{
    3305     return (uint)(cp[0]) + ((uint)(cp[1]) << 8)
    3306         + ((uint)(cp[2]) << 16) + ((uint)(cp[3]) << 24);
    3307 }
    3308 
    3309 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
    3310 static void
    3311 set_start_sect(struct partition *p, unsigned int start_sect)
     579    return cp[0] + (cp[1] << 8) + (cp[2] << 16) + (cp[3] << 24);
     580}
     581
     582#if ENABLE_FEATURE_FDISK_WRITABLE
     583static void
     584set_start_sect(struct partition *p, unsigned start_sect)
    3312585{
    3313586    store4_little_endian(p->start4, start_sect);
     
    3315588#endif
    3316589
    3317 static int32_t
     590static unsigned
    3318591get_start_sect(const struct partition *p)
    3319592{
     
    3321594}
    3322595
    3323 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
    3324 static void
    3325 set_nr_sects(struct partition *p, int32_t nr_sects)
     596#if ENABLE_FEATURE_FDISK_WRITABLE
     597static void
     598set_nr_sects(struct partition *p, unsigned nr_sects)
    3326599{
    3327600    store4_little_endian(p->size4, nr_sects);
     
    3329602#endif
    3330603
    3331 static int32_t
     604static unsigned
    3332605get_nr_sects(const struct partition *p)
    3333606{
     
    3338611static int type_open = O_RDWR;
    3339612
    3340 
    3341613static int ext_index;               /* the prime extended partition */
    3342 static int listing;                    /* no aborts for fdisk -l */
     614static int listing;                 /* no aborts for fdisk -l */
    3343615static int dos_compatible_flag = ~0;
    3344 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
     616#if ENABLE_FEATURE_FDISK_WRITABLE
    3345617static int dos_changed;
    3346618static int nowarn;            /* no warnings for fdisk -l/-s */
    3347619#endif
    3348620
    3349 
    3350 
    3351 static uint user_cylinders, user_heads, user_sectors;
    3352 static uint pt_heads, pt_sectors;
    3353 static uint kern_heads, kern_sectors;
    3354 
    3355 static off_t extended_offset;            /* offset of link pointers */
    3356 
    3357 static unsigned long long total_number_of_sectors;
    3358 
    3359 
    3360 static jmp_buf listingbuf;
    3361 
    3362 static void fdisk_fatal(enum failure why)
    3363 {
    3364     const char *message;
    3365 
     621static unsigned user_cylinders, user_heads, user_sectors;
     622static unsigned pt_heads, pt_sectors;
     623static unsigned kern_heads, kern_sectors;
     624
     625static ullong extended_offset;            /* offset of link pointers */
     626static ullong total_number_of_sectors;
     627
     628static void fdisk_fatal(const char *why)
     629{
    3366630    if (listing) {
    3367631        close(fd);
    3368632        longjmp(listingbuf, 1);
    3369633    }
    3370 
    3371     switch (why) {
    3372     case unable_to_open:
    3373         message = "Unable to open %s\n";
    3374         break;
    3375     case unable_to_read:
    3376         message = "Unable to read %s\n";
    3377         break;
    3378     case unable_to_seek:
    3379         message = "Unable to seek on %s\n";
    3380         break;
    3381     case unable_to_write:
    3382         message = "Unable to write %s\n";
    3383         break;
    3384     case ioctl_error:
    3385         message = "BLKGETSIZE ioctl failed on %s\n";
    3386         break;
    3387     default:
    3388         message = "Fatal error\n";
    3389     }
    3390 
    3391     fputc('\n', stderr);
    3392     fprintf(stderr, message, disk_device);
    3393     exit(1);
    3394 }
    3395 
    3396 static void
    3397 seek_sector(off_t secno)
    3398 {
    3399     off_t offset = secno * sector_size;
    3400     if (lseek(fd, offset, SEEK_SET) == (off_t) -1)
     634    bb_error_msg_and_die(why, disk_device);
     635}
     636
     637static void
     638seek_sector(ullong secno)
     639{
     640    secno *= sector_size;
     641#if ENABLE_FDISK_SUPPORT_LARGE_DISKS
     642    if (lseek64(fd, (off64_t)secno, SEEK_SET) == (off64_t) -1)
    3401643        fdisk_fatal(unable_to_seek);
    3402 }
    3403 
    3404 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
    3405 static void
    3406 write_sector(off_t secno, char *buf)
     644#else
     645    if (secno > MAXINT(off_t)
     646     || lseek(fd, (off_t)secno, SEEK_SET) == (off_t) -1
     647    ) {
     648        fdisk_fatal(unable_to_seek);
     649    }
     650#endif
     651}
     652
     653#if ENABLE_FEATURE_FDISK_WRITABLE
     654static void
     655write_sector(ullong secno, char *buf)
    3407656{
    3408657    seek_sector(secno);
     
    3414663/* Allocate a buffer and read a partition table sector */
    3415664static void
    3416 read_pte(struct pte *pe, off_t offset)
     665read_pte(struct pte *pe, ullong offset)
    3417666{
    3418667    pe->offset = offset;
    3419     pe->sectorbuffer = (char *) xmalloc(sector_size);
     668    pe->sectorbuffer = xmalloc(sector_size);
    3420669    seek_sector(offset);
    3421670    if (read(fd, pe->sectorbuffer, sector_size) != sector_size)
    3422671        fdisk_fatal(unable_to_read);
    3423 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
     672#if ENABLE_FEATURE_FDISK_WRITABLE
    3424673    pe->changed = 0;
    3425674#endif
     
    3427676}
    3428677
    3429 static unsigned int
     678static unsigned
    3430679get_partition_start(const struct pte *pe)
    3431680{
     
    3433682}
    3434683
    3435 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
     684#if ENABLE_FEATURE_FDISK_WRITABLE
    3436685/*
    3437686 * Avoid warning about DOS partitions when no DOS partition was changed.
     
    3453702menu(void)
    3454703{
    3455 #ifdef CONFIG_FEATURE_SUN_LABEL
    3456     if (label_sun == current_label_type) {
    3457         puts(_("Command action"));
    3458         puts(_("\ta\ttoggle a read only flag"));           /* sun */
    3459         puts(_("\tb\tedit bsd disklabel"));
    3460         puts(_("\tc\ttoggle the mountable flag"));         /* sun */
    3461         puts(_("\td\tdelete a partition"));
    3462         puts(_("\tl\tlist known partition types"));
    3463         puts(_("\tm\tprint this menu"));
    3464         puts(_("\tn\tadd a new partition"));
    3465         puts(_("\to\tcreate a new empty DOS partition table"));
    3466         puts(_("\tp\tprint the partition table"));
    3467         puts(_("\tq\tquit without saving changes"));
    3468         puts(_("\ts\tcreate a new empty Sun disklabel"));  /* sun */
    3469         puts(_("\tt\tchange a partition's system id"));
    3470         puts(_("\tu\tchange display/entry units"));
    3471         puts(_("\tv\tverify the partition table"));
    3472         puts(_("\tw\twrite table to disk and exit"));
    3473 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
    3474         puts(_("\tx\textra functionality (experts only)"));
    3475 #endif
    3476     } else
    3477 #endif
    3478 #ifdef CONFIG_FEATURE_SGI_LABEL
    3479     if (label_sgi == current_label_type) {
    3480         puts(_("Command action"));
    3481         puts(_("\ta\tselect bootable partition"));    /* sgi flavour */
    3482         puts(_("\tb\tedit bootfile entry"));          /* sgi */
    3483         puts(_("\tc\tselect sgi swap partition"));    /* sgi flavour */
    3484         puts(_("\td\tdelete a partition"));
    3485         puts(_("\tl\tlist known partition types"));
    3486         puts(_("\tm\tprint this menu"));
    3487         puts(_("\tn\tadd a new partition"));
    3488         puts(_("\to\tcreate a new empty DOS partition table"));
    3489         puts(_("\tp\tprint the partition table"));
    3490         puts(_("\tq\tquit without saving changes"));
    3491         puts(_("\ts\tcreate a new empty Sun disklabel"));  /* sun */
    3492         puts(_("\tt\tchange a partition's system id"));
    3493         puts(_("\tu\tchange display/entry units"));
    3494         puts(_("\tv\tverify the partition table"));
    3495         puts(_("\tw\twrite table to disk and exit"));
    3496     } else
    3497 #endif
    3498 #ifdef CONFIG_FEATURE_AIX_LABEL
    3499     if (label_aix == current_label_type) {
    3500         puts(_("Command action"));
    3501         puts(_("\tm\tprint this menu"));
    3502         puts(_("\to\tcreate a new empty DOS partition table"));
    3503         puts(_("\tq\tquit without saving changes"));
    3504         puts(_("\ts\tcreate a new empty Sun disklabel"));  /* sun */
    3505     } else
    3506 #endif
    3507     {
    3508         puts(_("Command action"));
    3509         puts(_("\ta\ttoggle a bootable flag"));
    3510         puts(_("\tb\tedit bsd disklabel"));
    3511         puts(_("\tc\ttoggle the dos compatibility flag"));
    3512         puts(_("\td\tdelete a partition"));
    3513         puts(_("\tl\tlist known partition types"));
    3514         puts(_("\tm\tprint this menu"));
    3515         puts(_("\tn\tadd a new partition"));
    3516         puts(_("\to\tcreate a new empty DOS partition table"));
    3517         puts(_("\tp\tprint the partition table"));
    3518         puts(_("\tq\tquit without saving changes"));
    3519         puts(_("\ts\tcreate a new empty Sun disklabel"));  /* sun */
    3520         puts(_("\tt\tchange a partition's system id"));
    3521         puts(_("\tu\tchange display/entry units"));
    3522         puts(_("\tv\tverify the partition table"));
    3523         puts(_("\tw\twrite table to disk and exit"));
    3524 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
    3525         puts(_("\tx\textra functionality (experts only)"));
    3526 #endif
    3527     }
    3528 }
    3529 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
    3530 
    3531 
    3532 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
     704    puts("Command Action");
     705    if (LABEL_IS_SUN) {
     706        puts("a\ttoggle a read only flag");           /* sun */
     707        puts("b\tedit bsd disklabel");
     708        puts("c\ttoggle the mountable flag");         /* sun */
     709        puts("d\tdelete a partition");
     710        puts("l\tlist known partition types");
     711        puts("n\tadd a new partition");
     712        puts("o\tcreate a new empty DOS partition table");
     713        puts("p\tprint the partition table");
     714        puts("q\tquit without saving changes");
     715        puts("s\tcreate a new empty Sun disklabel");  /* sun */
     716        puts("t\tchange a partition's system id");
     717        puts("u\tchange display/entry units");
     718        puts("v\tverify the partition table");
     719        puts("w\twrite table to disk and exit");
     720#if ENABLE_FEATURE_FDISK_ADVANCED
     721        puts("x\textra functionality (experts only)");
     722#endif
     723    } else if (LABEL_IS_SGI) {
     724        puts("a\tselect bootable partition");    /* sgi flavour */
     725        puts("b\tedit bootfile entry");          /* sgi */
     726        puts("c\tselect sgi swap partition");    /* sgi flavour */
     727        puts("d\tdelete a partition");
     728        puts("l\tlist known partition types");
     729        puts("n\tadd a new partition");
     730        puts("o\tcreate a new empty DOS partition table");
     731        puts("p\tprint the partition table");
     732        puts("q\tquit without saving changes");
     733        puts("s\tcreate a new empty Sun disklabel");  /* sun */
     734        puts("t\tchange a partition's system id");
     735        puts("u\tchange display/entry units");
     736        puts("v\tverify the partition table");
     737        puts("w\twrite table to disk and exit");
     738    } else if (LABEL_IS_AIX) {
     739        puts("o\tcreate a new empty DOS partition table");
     740        puts("q\tquit without saving changes");
     741        puts("s\tcreate a new empty Sun disklabel");  /* sun */
     742    } else {
     743        puts("a\ttoggle a bootable flag");
     744        puts("b\tedit bsd disklabel");
     745        puts("c\ttoggle the dos compatibility flag");
     746        puts("d\tdelete a partition");
     747        puts("l\tlist known partition types");
     748        puts("n\tadd a new partition");
     749        puts("o\tcreate a new empty DOS partition table");
     750        puts("p\tprint the partition table");
     751        puts("q\tquit without saving changes");
     752        puts("s\tcreate a new empty Sun disklabel");  /* sun */
     753        puts("t\tchange a partition's system id");
     754        puts("u\tchange display/entry units");
     755        puts("v\tverify the partition table");
     756        puts("w\twrite table to disk and exit");
     757#if ENABLE_FEATURE_FDISK_ADVANCED
     758        puts("x\textra functionality (experts only)");
     759#endif
     760    }
     761}
     762#endif /* FEATURE_FDISK_WRITABLE */
     763
     764
     765#if ENABLE_FEATURE_FDISK_ADVANCED
    3533766static void
    3534767xmenu(void)
    3535768{
    3536 #ifdef CONFIG_FEATURE_SUN_LABEL
    3537     if (label_sun == current_label_type) {
    3538     puts(_("Command action"));
    3539     puts(_("\ta\tchange number of alternate cylinders"));      /*sun*/
    3540     puts(_("\tc\tchange number of cylinders"));
    3541     puts(_("\td\tprint the raw data in the partition table"));
    3542     puts(_("\te\tchange number of extra sectors per cylinder"));/*sun*/
    3543     puts(_("\th\tchange number of heads"));
    3544     puts(_("\ti\tchange interleave factor"));                  /*sun*/
    3545     puts(_("\to\tchange rotation speed (rpm)"));               /*sun*/
    3546     puts(_("\tm\tprint this menu"));
    3547     puts(_("\tp\tprint the partition table"));
    3548     puts(_("\tq\tquit without saving changes"));
    3549     puts(_("\tr\treturn to main menu"));
    3550     puts(_("\ts\tchange number of sectors/track"));
    3551     puts(_("\tv\tverify the partition table"));
    3552     puts(_("\tw\twrite table to disk and exit"));
    3553     puts(_("\ty\tchange number of physical cylinders"));       /*sun*/
    3554     }  else
    3555 #endif
    3556 #ifdef CONFIG_FEATURE_SGI_LABEL
    3557     if (label_sgi == current_label_type) {
    3558         puts(_("Command action"));
    3559         puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
    3560         puts(_("\tc\tchange number of cylinders"));
    3561         puts(_("\td\tprint the raw data in the partition table"));
    3562         puts(_("\te\tlist extended partitions"));          /* !sun */
    3563         puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
    3564         puts(_("\th\tchange number of heads"));
    3565         puts(_("\tm\tprint this menu"));
    3566         puts(_("\tp\tprint the partition table"));
    3567         puts(_("\tq\tquit without saving changes"));
    3568         puts(_("\tr\treturn to main menu"));
    3569         puts(_("\ts\tchange number of sectors/track"));
    3570         puts(_("\tv\tverify the partition table"));
    3571         puts(_("\tw\twrite table to disk and exit"));
    3572     } else
    3573 #endif
    3574 #ifdef CONFIG_FEATURE_AIX_LABEL
    3575     if (label_aix == current_label_type) {
    3576         puts(_("Command action"));
    3577         puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
    3578         puts(_("\tc\tchange number of cylinders"));
    3579         puts(_("\td\tprint the raw data in the partition table"));
    3580         puts(_("\te\tlist extended partitions"));          /* !sun */
    3581         puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
    3582         puts(_("\th\tchange number of heads"));
    3583         puts(_("\tm\tprint this menu"));
    3584         puts(_("\tp\tprint the partition table"));
    3585         puts(_("\tq\tquit without saving changes"));
    3586         puts(_("\tr\treturn to main menu"));
    3587         puts(_("\ts\tchange number of sectors/track"));
    3588         puts(_("\tv\tverify the partition table"));
    3589         puts(_("\tw\twrite table to disk and exit"));
    3590     }  else
    3591 #endif
    3592     {
    3593         puts(_("Command action"));
    3594         puts(_("\tb\tmove beginning of data in a partition")); /* !sun */
    3595         puts(_("\tc\tchange number of cylinders"));
    3596         puts(_("\td\tprint the raw data in the partition table"));
    3597         puts(_("\te\tlist extended partitions"));          /* !sun */
    3598         puts(_("\tf\tfix partition order"));               /* !sun, !aix, !sgi */
    3599 #ifdef CONFIG_FEATURE_SGI_LABEL
    3600         puts(_("\tg\tcreate an IRIX (SGI) partition table"));/* sgi */
    3601 #endif
    3602         puts(_("\th\tchange number of heads"));
    3603         puts(_("\tm\tprint this menu"));
    3604         puts(_("\tp\tprint the partition table"));
    3605         puts(_("\tq\tquit without saving changes"));
    3606         puts(_("\tr\treturn to main menu"));
    3607         puts(_("\ts\tchange number of sectors/track"));
    3608         puts(_("\tv\tverify the partition table"));
    3609         puts(_("\tw\twrite table to disk and exit"));
     769    puts("Command Action");
     770    if (LABEL_IS_SUN) {
     771        puts("a\tchange number of alternate cylinders");      /*sun*/
     772        puts("c\tchange number of cylinders");
     773        puts("d\tprint the raw data in the partition table");
     774        puts("e\tchange number of extra sectors per cylinder");/*sun*/
     775        puts("h\tchange number of heads");
     776        puts("i\tchange interleave factor");                  /*sun*/
     777        puts("o\tchange rotation speed (rpm)");               /*sun*/
     778        puts("p\tprint the partition table");
     779        puts("q\tquit without saving changes");
     780        puts("r\treturn to main menu");
     781        puts("s\tchange number of sectors/track");
     782        puts("v\tverify the partition table");
     783        puts("w\twrite table to disk and exit");
     784        puts("y\tchange number of physical cylinders");       /*sun*/
     785    } else if (LABEL_IS_SGI) {
     786        puts("b\tmove beginning of data in a partition"); /* !sun */
     787        puts("c\tchange number of cylinders");
     788        puts("d\tprint the raw data in the partition table");
     789        puts("e\tlist extended partitions");          /* !sun */
     790        puts("g\tcreate an IRIX (SGI) partition table");/* sgi */
     791        puts("h\tchange number of heads");
     792        puts("p\tprint the partition table");
     793        puts("q\tquit without saving changes");
     794        puts("r\treturn to main menu");
     795        puts("s\tchange number of sectors/track");
     796        puts("v\tverify the partition table");
     797        puts("w\twrite table to disk and exit");
     798    } else if (LABEL_IS_AIX) {
     799        puts("b\tmove beginning of data in a partition"); /* !sun */
     800        puts("c\tchange number of cylinders");
     801        puts("d\tprint the raw data in the partition table");
     802        puts("e\tlist extended partitions");          /* !sun */
     803        puts("g\tcreate an IRIX (SGI) partition table");/* sgi */
     804        puts("h\tchange number of heads");
     805        puts("p\tprint the partition table");
     806        puts("q\tquit without saving changes");
     807        puts("r\treturn to main menu");
     808        puts("s\tchange number of sectors/track");
     809        puts("v\tverify the partition table");
     810        puts("w\twrite table to disk and exit");
     811    } else {
     812        puts("b\tmove beginning of data in a partition"); /* !sun */
     813        puts("c\tchange number of cylinders");
     814        puts("d\tprint the raw data in the partition table");
     815        puts("e\tlist extended partitions");          /* !sun */
     816        puts("f\tfix partition order");               /* !sun, !aix, !sgi */
     817#if ENABLE_FEATURE_SGI_LABEL
     818        puts("g\tcreate an IRIX (SGI) partition table");/* sgi */
     819#endif
     820        puts("h\tchange number of heads");
     821        puts("p\tprint the partition table");
     822        puts("q\tquit without saving changes");
     823        puts("r\treturn to main menu");
     824        puts("s\tchange number of sectors/track");
     825        puts("v\tverify the partition table");
     826        puts("w\twrite table to disk and exit");
    3610827    }
    3611828}
    3612829#endif /* ADVANCED mode */
    3613830
    3614 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
    3615 static const struct systypes *
     831#if ENABLE_FEATURE_FDISK_WRITABLE
     832static const char *const *
    3616833get_sys_types(void)
    3617834{
    3618835    return (
    3619 #ifdef CONFIG_FEATURE_SUN_LABEL
    3620         label_sun == current_label_type ? sun_sys_types :
    3621 #endif
    3622 #ifdef CONFIG_FEATURE_SGI_LABEL
    3623         label_sgi == current_label_type ? sgi_sys_types :
    3624 #endif
     836        LABEL_IS_SUN ? sun_sys_types :
     837        LABEL_IS_SGI ? sgi_sys_types :
    3625838        i386_sys_types);
    3626839}
    3627840#else
    3628841#define get_sys_types() i386_sys_types
    3629 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
    3630 
    3631 static const char *partition_type(unsigned char type)
     842#endif /* FEATURE_FDISK_WRITABLE */
     843
     844static const char *
     845partition_type(unsigned char type)
    3632846{
    3633847    int i;
    3634     const struct systypes *types = get_sys_types();
    3635 
    3636     for (i = 0; types[i].name; i++)
    3637         if ((unsigned char )types[i].name[0] == type)
    3638             return types[i].name + 1;
    3639 
    3640     return _("Unknown");
    3641 }
    3642 
    3643 
    3644 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
     848    const char *const *types = get_sys_types();
     849
     850    for (i = 0; types[i]; i++)
     851        if ((unsigned char)types[i][0] == type)
     852            return types[i] + 1;
     853
     854    return "Unknown";
     855}
     856
     857
     858#if ENABLE_FEATURE_FDISK_WRITABLE
    3645859static int
    3646860get_sysid(int i)
    3647861{
    3648     return (
    3649 #ifdef CONFIG_FEATURE_SUN_LABEL
    3650         label_sun == current_label_type ? sunlabel->infos[i].id :
    3651 #endif
    3652 #ifdef CONFIG_FEATURE_SGI_LABEL
    3653         label_sgi == current_label_type ? sgi_get_sysid(i) :
    3654 #endif
    3655         ptes[i].part_table->sys_ind);
    3656 }
    3657 
    3658 void list_types(const struct systypes *sys)
    3659 {
    3660     uint last[4], done = 0, next = 0, size;
     862    return LABEL_IS_SUN ? sunlabel->infos[i].id :
     863            (LABEL_IS_SGI ? sgi_get_sysid(i) :
     864                ptes[i].part_table->sys_ind);
     865}
     866
     867static void
     868list_types(const char *const *sys)
     869{
     870    enum { COLS = 3 };
     871
     872    unsigned last[COLS];
     873    unsigned done, next, size;
    3661874    int i;
    3662875
    3663     for (i = 0; sys[i].name; i++);
    3664     size = i;
    3665 
    3666     for (i = 3; i >= 0; i--)
    3667         last[3 - i] = done += (size + i - done) / (i + 1);
    3668     i = done = 0;
    3669 
     876    for (size = 0; sys[size]; size++) /* */;
     877
     878    done = 0;
     879    for (i = COLS-1; i >= 0; i--) {
     880        done += (size + i - done) / (i + 1);
     881        last[COLS-1 - i] = done;
     882    }
     883
     884    i = done = next = 0;
    3670885    do {
    3671         printf("%c%2x  %-15.15s", i ? ' ' : '\n',
    3672             (unsigned char)sys[next].name[0],
    3673             partition_type((unsigned char)sys[next].name[0]));
     886        printf("%c%2x %-22.22s", i ? ' ' : '\n',
     887            (unsigned char)sys[next][0],
     888            sys[next] + 1);
    3674889        next = last[i++] + done;
    3675         if (i > 3 || next >= last[i]) {
     890        if (i >= COLS || next >= last[i]) {
    3676891            i = 0;
    3677892            next = ++done;
     
    3680895    putchar('\n');
    3681896}
    3682 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
     897#endif /* FEATURE_FDISK_WRITABLE */
    3683898
    3684899static int
     
    3698913}
    3699914
    3700 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
    3701 static void
    3702 set_partition(int i, int doext, off_t start, off_t stop, int sysid)
     915#if ENABLE_FEATURE_FDISK_WRITABLE
     916static void
     917set_partition(int i, int doext, ullong start, ullong stop, int sysid)
    3703918{
    3704919    struct partition *p;
    3705     off_t offset;
     920    ullong offset;
    3706921
    3707922    if (doext) {
     
    3727942
    3728943static int
    3729 test_c(const char **m, const char *mesg)
    3730 {
    3731     int val = 0;
    3732     if (!*m)
    3733         fprintf(stderr, _("You must set"));
    3734     else {
    3735         fprintf(stderr, " %s", *m);
    3736         val = 1;
    3737     }
    3738     *m = mesg;
    3739     return val;
    3740 }
    3741 
    3742 static int
    3743944warn_geometry(void)
    3744945{
    3745     const char *m = NULL;
    3746     int prev = 0;
    3747 
     946    if (heads && sectors && cylinders)
     947        return 0;
     948
     949    printf("Unknown value(s) for:");
    3748950    if (!heads)
    3749         prev = test_c(&m, _("heads"));
     951        printf(" heads");
    3750952    if (!sectors)
    3751         prev = test_c(&m, _("sectors"));
     953        printf(" sectors");
    3752954    if (!cylinders)
    3753         prev = test_c(&m, _("cylinders"));
    3754     if (!m)
    3755         return 0;
    3756 
    3757     fprintf(stderr, "%s%s.\n"
    3758 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
    3759             "You can do this from the extra functions menu.\n"
    3760 #endif
    3761         , prev ? _(" and ") : " ", m);
    3762 
     955        printf(" cylinders");
     956    printf(
     957#if ENABLE_FEATURE_FDISK_WRITABLE
     958        " (settable in the extra functions menu)"
     959#endif
     960        "\n");
    3763961    return 1;
    3764962}
    3765963
    3766 static void update_units(void)
     964static void
     965update_units(void)
    3767966{
    3768967    int cyl_units = heads * sectors;
     
    3774973}
    3775974
    3776 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
     975#if ENABLE_FEATURE_FDISK_WRITABLE
    3777976static void
    3778977warn_cylinders(void)
    3779978{
    3780     if (label_dos == current_label_type && cylinders > 1024 && !nowarn)
    3781         fprintf(stderr, _("\n"
     979    if (LABEL_IS_DOS && cylinders > 1024 && !nowarn)
     980        printf("\n"
    3782981"The number of cylinders for this disk is set to %d.\n"
    3783982"There is nothing wrong with that, but this is larger than 1024,\n"
     
    3785984"1) software that runs at boot time (e.g., old versions of LILO)\n"
    3786985"2) booting and partitioning software from other OSs\n"
    3787 "   (e.g., DOS FDISK, OS/2 FDISK)\n"),
     986"   (e.g., DOS FDISK, OS/2 FDISK)\n",
    3788987            cylinders);
    3789988}
     
    38031002    p = pex->part_table;
    38041003    if (!get_start_sect(p)) {
    3805         fprintf(stderr,
    3806             _("Bad offset in primary extended partition\n"));
     1004        printf("Bad offset in primary extended partition\n");
    38071005        return;
    38081006    }
     
    38141012            /* This is not a Linux restriction, but
    38151013               this program uses arrays of size MAXIMUM_PARTS.
    3816                Do not try to `improve' this test. */
     1014               Do not try to 'improve' this test. */
    38171015            struct pte *pre = &ptes[partitions-1];
    3818 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
    3819             fprintf(stderr,
    3820                 _("Warning: deleting partitions after %d\n"),
     1016#if ENABLE_FEATURE_FDISK_WRITABLE
     1017            printf("Warning: deleting partitions after %d\n",
    38211018                partitions);
    38221019            pre->changed = 1;
     
    38351032            if (IS_EXTENDED(p->sys_ind)) {
    38361033                if (pe->ext_pointer)
    3837                     fprintf(stderr,
    3838                         _("Warning: extra link "
    3839                           "pointer in partition table"
    3840                           " %d\n"), partitions + 1);
     1034                    printf("Warning: extra link "
     1035                        "pointer in partition table"
     1036                        " %d\n", partitions + 1);
    38411037                else
    38421038                    pe->ext_pointer = p;
    38431039            } else if (p->sys_ind) {
    38441040                if (pe->part_table)
    3845                     fprintf(stderr,
    3846                         _("Warning: ignoring extra "
     1041                    printf("Warning: ignoring extra "
    38471042                          "data in partition table"
    3848                           " %d\n"), partitions + 1);
     1043                          " %d\n", partitions + 1);
    38491044                else
    38501045                    pe->part_table = p;
     
    38701065    }
    38711066
    3872 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
     1067#if ENABLE_FEATURE_FDISK_WRITABLE
    38731068    /* remove empty links */
    38741069 remove:
     
    38761071        struct pte *pe = &ptes[i];
    38771072
    3878         if (!get_nr_sects(pe->part_table) &&
    3879             (partitions > 5 || ptes[4].part_table->sys_ind)) {
    3880             printf("omitting empty partition (%d)\n", i+1);
     1073        if (!get_nr_sects(pe->part_table)
     1074         && (partitions > 5 || ptes[4].part_table->sys_ind)
     1075        ) {
     1076            printf("Omitting empty partition (%d)\n", i+1);
    38811077            delete_partition(i);
    38821078            goto remove;    /* numbering changed */
     
    38861082}
    38871083
    3888 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
     1084#if ENABLE_FEATURE_FDISK_WRITABLE
    38891085static void
    38901086create_doslabel(void)
     
    38921088    int i;
    38931089
    3894     fprintf(stderr,
    3895     _("Building a new DOS disklabel. Changes will remain in memory only,\n"
    3896       "until you decide to write them. After that, of course, the previous\n"
    3897       "content won't be recoverable.\n\n"));
     1090    printf(msg_building_new_label, "DOS disklabel");
    38981091
    38991092    current_label_type = label_dos;
    39001093
    3901 #ifdef CONFIG_FEATURE_OSF_LABEL
     1094#if ENABLE_FEATURE_OSF_LABEL
    39021095    possibly_osf_label = 0;
    39031096#endif
     
    39121105    get_boot(create_empty_dos);
    39131106}
    3914 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
     1107#endif /* FEATURE_FDISK_WRITABLE */
    39151108
    39161109static void
     
    39221115            sector_size = arg;
    39231116        if (sector_size != DEFAULT_SECTOR_SIZE)
    3924             printf(_("Note: sector size is %d (not %d)\n"),
     1117            printf("Note: sector size is %d (not %d)\n",
    39251118                   sector_size, DEFAULT_SECTOR_SIZE);
    39261119    }
    39271120}
    39281121
    3929 static inline void
     1122static void
    39301123get_kernel_geometry(void)
    39311124{
     
    39761169{
    39771170    int sec_fac;
    3978     unsigned long long bytes;       /* really u64 */
     1171    uint64_t v64;
    39791172
    39801173    get_sectorsize();
    39811174    sec_fac = sector_size / 512;
    3982 #ifdef CONFIG_FEATURE_SUN_LABEL
     1175#if ENABLE_FEATURE_SUN_LABEL
    39831176    guess_device_type();
    39841177#endif
     
    39961189        pt_sectors ? pt_sectors :
    39971190        kern_sectors ? kern_sectors : 63;
    3998     if (ioctl(fd, BLKGETSIZE64, &bytes) == 0) {
    3999         /* got bytes */
     1191    if (ioctl(fd, BLKGETSIZE64, &v64) == 0) {
     1192        /* got bytes, convert to 512 byte sectors */
     1193        total_number_of_sectors = (v64 >> 9);
    40001194    } else {
    4001         unsigned long longsectors;
    4002 
    4003     if (ioctl(fd, BLKGETSIZE, &longsectors))
    4004         longsectors = 0;
    4005             bytes = ((unsigned long long) longsectors) << 9;
    4006     }
    4007 
    4008     total_number_of_sectors = (bytes >> 9);
     1195        unsigned long longsectors; /* need temp of type long */
     1196        if (ioctl(fd, BLKGETSIZE, &longsectors))
     1197            longsectors = 0;
     1198        total_number_of_sectors = longsectors;
     1199    }
    40091200
    40101201    sector_offset = 1;
     
    40371228        pe->offset = 0;
    40381229        pe->sectorbuffer = MBRbuffer;
    4039 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
     1230#if ENABLE_FEATURE_FDISK_WRITABLE
    40401231        pe->changed = (what == create_empty_dos);
    40411232#endif
    40421233    }
    40431234
    4044 #ifdef CONFIG_FEATURE_SUN_LABEL
     1235#if ENABLE_FEATURE_SUN_LABEL
    40451236    if (what == create_empty_sun && check_sun_label())
    40461237        return 0;
     
    40491240    memset(MBRbuffer, 0, 512);
    40501241
    4051 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
     1242#if ENABLE_FEATURE_FDISK_WRITABLE
    40521243    if (what == create_empty_dos)
    40531244        goto got_dos_table;             /* skip reading disk */
    40541245
    4055     if ((fd = open(disk_device, type_open)) < 0) {
    4056         if ((fd = open(disk_device, O_RDONLY)) < 0) {
     1246    fd = open(disk_device, type_open);
     1247    if (fd < 0) {
     1248        fd = open(disk_device, O_RDONLY);
     1249        if (fd < 0) {
    40571250            if (what == try_only)
    40581251                return 1;
    40591252            fdisk_fatal(unable_to_open);
    40601253        } else
    4061             printf(_("You will not be able to write "
    4062                 "the partition table.\n"));
     1254            printf("You will not be able to write "
     1255                "the partition table\n");
    40631256    }
    40641257
     
    40691262    }
    40701263#else
    4071     if ((fd = open(disk_device, O_RDONLY)) < 0)
     1264    fd = open(disk_device, O_RDONLY);
     1265    if (fd < 0)
    40721266        return 1;
    40731267    if (512 != read(fd, MBRbuffer, 512))
     
    40791273    update_units();
    40801274
    4081 #ifdef CONFIG_FEATURE_SUN_LABEL
     1275#if ENABLE_FEATURE_SUN_LABEL
    40821276    if (check_sun_label())
    40831277        return 0;
    40841278#endif
    40851279
    4086 #ifdef CONFIG_FEATURE_SGI_LABEL
     1280#if ENABLE_FEATURE_SGI_LABEL
    40871281    if (check_sgi_label())
    40881282        return 0;
    40891283#endif
    40901284
    4091 #ifdef CONFIG_FEATURE_AIX_LABEL
     1285#if ENABLE_FEATURE_AIX_LABEL
    40921286    if (check_aix_label())
    40931287        return 0;
    40941288#endif
    40951289
    4096 #ifdef CONFIG_FEATURE_OSF_LABEL
     1290#if ENABLE_FEATURE_OSF_LABEL
    40971291    if (check_osf_label()) {
    40981292        possibly_osf_label = 1;
     
    41011295            return 0;
    41021296        }
    4103         printf(_("This disk has both DOS and BSD magic.\n"
    4104              "Give the 'b' command to go to BSD mode.\n"));
    4105     }
    4106 #endif
    4107 
    4108 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
     1297        printf("This disk has both DOS and BSD magic.\n"
     1298             "Give the 'b' command to go to BSD mode.\n");
     1299    }
     1300#endif
     1301
     1302#if ENABLE_FEATURE_FDISK_WRITABLE
    41091303 got_dos_table:
    41101304#endif
    41111305
    41121306    if (!valid_part_table_flag(MBRbuffer)) {
    4113 #ifndef CONFIG_FEATURE_FDISK_WRITABLE
     1307#if !ENABLE_FEATURE_FDISK_WRITABLE
    41141308        return -1;
    41151309#else
    41161310        switch (what) {
    41171311        case fdisk:
    4118             fprintf(stderr,
    4119                 _("Device contains neither a valid DOS "
     1312            printf("Device contains neither a valid DOS "
    41201313                  "partition table, nor Sun, SGI or OSF "
    4121                   "disklabel\n"));
     1314                  "disklabel\n");
    41221315#ifdef __sparc__
    4123 #ifdef CONFIG_FEATURE_SUN_LABEL
     1316#if ENABLE_FEATURE_SUN_LABEL
    41241317            create_sunlabel();
    41251318#endif
     
    41311324            return -1;
    41321325        case create_empty_dos:
    4133 #ifdef CONFIG_FEATURE_SUN_LABEL
     1326#if ENABLE_FEATURE_SUN_LABEL
    41341327        case create_empty_sun:
    41351328#endif
    41361329            break;
    41371330        default:
    4138             fprintf(stderr, _("Internal error\n"));
    4139             exit(1);
    4140         }
    4141 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
    4142     }
    4143 
    4144 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
     1331            bb_error_msg_and_die("internal error");
     1332        }
     1333#endif /* FEATURE_FDISK_WRITABLE */
     1334    }
     1335
     1336#if ENABLE_FEATURE_FDISK_WRITABLE
    41451337    warn_cylinders();
    41461338#endif
     
    41521344        if (IS_EXTENDED(pe->part_table->sys_ind)) {
    41531345            if (partitions != 4)
    4154                 fprintf(stderr, _("Ignoring extra extended "
    4155                     "partition %d\n"), i + 1);
     1346                printf("Ignoring extra extended "
     1347                    "partition %d\n", i + 1);
    41561348            else
    41571349                read_extended(i);
     
    41631355
    41641356        if (!valid_part_table_flag(pe->sectorbuffer)) {
    4165             fprintf(stderr,
    4166                 _("Warning: invalid flag 0x%04x of partition "
    4167                 "table %d will be corrected by w(rite)\n"),
    4168                 part_table_flag(pe->sectorbuffer), i + 1);
    4169 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
     1357            printf("Warning: invalid flag 0x%02x,0x%02x of partition "
     1358                "table %d will be corrected by w(rite)\n",
     1359                pe->sectorbuffer[510],
     1360                pe->sectorbuffer[511],
     1361                i + 1);
     1362#if ENABLE_FEATURE_FDISK_WRITABLE
    41701363            pe->changed = 1;
    41711364#endif
     
    41761369}
    41771370
    4178 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
     1371#if ENABLE_FEATURE_FDISK_WRITABLE
    41791372/*
    41801373 * Print the message MESG, then read an integer between LOW and HIGH (inclusive).
     
    41841377 * There is no default if DFLT is not between LOW and HIGH.
    41851378 */
    4186 static uint
    4187 read_int(uint low, uint dflt, uint high, uint base, char *mesg)
    4188 {
    4189     uint i;
     1379static unsigned
     1380read_int(unsigned low, unsigned dflt, unsigned high, unsigned base, const char *mesg)
     1381{
     1382    unsigned i;
    41901383    int default_ok = 1;
    4191     static char *ms = NULL;
    4192     static int mslen = 0;
    4193 
    4194     if (!ms || strlen(mesg)+100 > mslen) {
    4195         mslen = strlen(mesg)+200;
    4196         ms = xrealloc(ms,mslen);
    4197     }
    4198 
    4199     if (dflt < low || dflt > high)
     1384    const char *fmt = "%s (%u-%u, default %u): ";
     1385
     1386    if (dflt < low || dflt > high) {
     1387        fmt = "%s (%u-%u): ";
    42001388        default_ok = 0;
    4201 
    4202     if (default_ok)
    4203         snprintf(ms, mslen, _("%s (%u-%u, default %u): "),
    4204              mesg, low, high, dflt);
    4205     else
    4206         snprintf(ms, mslen, "%s (%u-%u): ", mesg, low, high);
     1389    }
    42071390
    42081391    while (1) {
     
    42101393
    42111394        /* ask question and read answer */
    4212         while (read_chars(ms) != '\n' && !isdigit(*line_ptr)
    4213          && *line_ptr != '-' && *line_ptr != '+')
    4214             continue;
     1395        do {
     1396            printf(fmt, mesg, low, high, dflt);
     1397            read_maybe_empty("");
     1398        } while (*line_ptr != '\n' && !isdigit(*line_ptr)
     1399         && *line_ptr != '-' && *line_ptr != '+');
    42151400
    42161401        if (*line_ptr == '+' || *line_ptr == '-') {
     
    42181403            int absolute = 0;
    42191404
    4220             i = atoi(line_ptr+1);
     1405            i = atoi(line_ptr + 1);
    42211406
    42221407            while (isdigit(*++line_ptr))
     
    42471432            }
    42481433            if (absolute) {
    4249                 unsigned long long bytes;
     1434                ullong bytes;
    42501435                unsigned long unit;
    42511436
    4252                 bytes = (unsigned long long) i * absolute;
     1437                bytes = (ullong) i * absolute;
    42531438                unit = sector_size * units_per_sector;
    42541439                bytes += unit/2; /* round */
     
    42661451            }
    42671452        }
    4268         if (use_default)
    4269             printf(_("Using default value %u\n"), i = dflt);
     1453        if (use_default) {
     1454            i = dflt;
     1455            printf("Using default value %u\n", i);
     1456        }
    42701457        if (i >= low && i <= high)
    42711458            break;
    4272         else
    4273             printf(_("Value out of range.\n"));
     1459        printf("Value is out of range\n");
    42741460    }
    42751461    return i;
     
    42821468    int i;
    42831469
    4284     i = read_int(1, 0, max, 0, _("Partition number")) - 1;
     1470    i = read_int(1, 0, max, 0, "Partition number") - 1;
    42851471    pe = &ptes[i];
    42861472
    42871473    if (warn) {
    4288         if (
    4289             (
    4290                 label_sun != current_label_type &&
    4291                 label_sgi != current_label_type &&
    4292                 !pe->part_table->sys_ind
    4293             )
    4294 #ifdef CONFIG_FEATURE_SUN_LABEL
    4295             || (
    4296                 label_sun == current_label_type &&
    4297                 (
    4298                     !sunlabel->partitions[i].num_sectors
    4299                     || !sunlabel->infos[i].id
    4300                 )
    4301             )
    4302 #endif
    4303 #ifdef CONFIG_FEATURE_SGI_LABEL
    4304             || (
    4305                 label_sgi == current_label_type &&
    4306                  !sgi_get_num_sectors(i)
    4307             )
    4308 #endif
    4309         ){
    4310             fprintf(stderr,
    4311                 _("Warning: partition %d has empty type\n"),
    4312                 i+1
    4313             );
     1474        if ((!LABEL_IS_SUN && !LABEL_IS_SGI && !pe->part_table->sys_ind)
     1475         || (LABEL_IS_SUN && (!sunlabel->partitions[i].num_sectors || !sunlabel->infos[i].id))
     1476         || (LABEL_IS_SGI && !sgi_get_num_sectors(i))
     1477        ) {
     1478            printf("Warning: partition %d has empty type\n", i+1);
    43141479        }
    43151480    }
     
    43341499    }
    43351500    if (pno >= 0) {
    4336         printf(_("Selected partition %d\n"), pno+1);
     1501        printf("Selected partition %d\n", pno+1);
    43371502        return pno;
    43381503    }
    4339     printf(_("No partition is defined yet!\n"));
     1504    printf("No partition is defined yet!\n");
    43401505    return -1;
    43411506
     
    43611526    }
    43621527    if (pno >= 0) {
    4363         printf(_("Selected partition %d\n"), pno+1);
     1528        printf("Selected partition %d\n", pno+1);
    43641529        return pno;
    43651530    }
    4366     printf(_("All primary partitions have been defined already!\n"));
     1531    printf("All primary partitions have been defined already!\n");
    43671532    return -1;
    43681533
     
    43721537
    43731538
    4374 void change_units(void)
     1539static void
     1540change_units(void)
    43751541{
    43761542    display_in_cyl_units = !display_in_cyl_units;
    43771543    update_units();
    4378     printf(_("Changing display/entry units to %s\n"),
     1544    printf("Changing display/entry units to %s\n",
    43791545        str_units(PLURAL));
    43801546}
     
    43871553
    43881554    if (IS_EXTENDED(p->sys_ind) && !p->boot_ind)
    4389         fprintf(stderr,
    4390             _("WARNING: Partition %d is an extended partition\n"),
    4391             i + 1);
     1555        printf("WARNING: Partition %d is an extended partition\n", i + 1);
    43921556    p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG);
    43931557    pe->changed = 1;
     
    44001564    if (dos_compatible_flag) {
    44011565        sector_offset = sectors;
    4402         printf(_("DOS Compatibility flag is set\n"));
    4403     }
    4404     else {
     1566        printf("DOS Compatibility flag is set\n");
     1567    } else {
    44051568        sector_offset = 1;
    4406         printf(_("DOS Compatibility flag is not set\n"));
     1569        printf("DOS Compatibility flag is not set\n");
    44071570    }
    44081571}
     
    44231586    pe->changed = 1;
    44241587
    4425 #ifdef CONFIG_FEATURE_SUN_LABEL
    4426     if (label_sun == current_label_type) {
     1588    if (LABEL_IS_SUN) {
    44271589        sun_delete_partition(i);
    44281590        return;
    44291591    }
    4430 #endif
    4431 #ifdef CONFIG_FEATURE_SGI_LABEL
    4432     if (label_sgi == current_label_type) {
     1592    if (LABEL_IS_SGI) {
    44331593        sgi_delete_partition(i);
    44341594        return;
    44351595    }
    4436 #endif
    44371596
    44381597    if (i < 4) {
     
    44911650    struct partition *p;
    44921651
    4493 #ifdef CONFIG_FEATURE_SGI_LABEL
    44941652    /* If sgi_label then don't use get_existing_partition,
    44951653       let the user select a partition, since get_existing_partition()
    44961654       only works for Linux like partition tables. */
    4497     if (label_sgi != current_label_type) {
     1655    if (!LABEL_IS_SGI) {
    44981656        i = get_existing_partition(0, partitions);
    44991657    } else {
    45001658        i = get_partition(0, partitions);
    45011659    }
    4502 #else
    4503     i = get_existing_partition(0, partitions);
    4504 #endif
    45051660    if (i == -1)
    45061661        return;
     
    45101665    /* if changing types T to 0 is allowed, then
    45111666       the reverse change must be allowed, too */
    4512     if (!sys && label_sgi != current_label_type &&
    4513         label_sun != current_label_type && !get_nr_sects(p))
    4514     {
    4515         printf(_("Partition %d does not exist yet!\n"), i + 1);
    4516     }else{
    4517         while (1) {
    4518         sys = read_hex (get_sys_types());
    4519 
    4520         if (!sys && label_sgi != current_label_type &&
    4521             label_sun != current_label_type)
    4522         {
    4523             printf(_("Type 0 means free space to many systems\n"
     1667    if (!sys && !LABEL_IS_SGI && !LABEL_IS_SUN && !get_nr_sects(p)) {
     1668        printf("Partition %d does not exist yet!\n", i + 1);
     1669        return;
     1670    }
     1671    while (1) {
     1672        sys = read_hex(get_sys_types());
     1673
     1674        if (!sys && !LABEL_IS_SGI && !LABEL_IS_SUN) {
     1675            printf("Type 0 means free space to many systems\n"
    45241676                   "(but not to Linux). Having partitions of\n"
    4525                    "type 0 is probably unwise. You can delete\n"
    4526                    "a partition using the `d' command.\n"));
     1677                   "type 0 is probably unwise.\n");
    45271678            /* break; */
    45281679        }
    45291680
    4530         if (label_sun != current_label_type && label_sgi != current_label_type) {
     1681        if (!LABEL_IS_SUN && !LABEL_IS_SGI) {
    45311682            if (IS_EXTENDED(sys) != IS_EXTENDED(p->sys_ind)) {
    4532                 printf(_("You cannot change a partition into"
    4533                        " an extended one or vice versa\n"
    4534                        "Delete it first.\n"));
     1683                printf("You cannot change a partition into"
     1684                       " an extended one or vice versa\n");
    45351685                break;
    45361686            }
     
    45381688
    45391689        if (sys < 256) {
    4540 #ifdef CONFIG_FEATURE_SUN_LABEL
    4541             if (label_sun == current_label_type && i == 2 && sys != WHOLE_DISK)
    4542                 printf(_("Consider leaving partition 3 "
     1690#if ENABLE_FEATURE_SUN_LABEL
     1691            if (LABEL_IS_SUN && i == 2 && sys != SUN_WHOLE_DISK)
     1692                printf("Consider leaving partition 3 "
    45431693                       "as Whole disk (5),\n"
    45441694                       "as SunOS/Solaris expects it and "
    4545                        "even Linux likes it.\n\n"));
    4546 #endif
    4547 #ifdef CONFIG_FEATURE_SGI_LABEL
    4548             if (label_sgi == current_label_type &&
     1695                       "even Linux likes it\n\n");
     1696#endif
     1697#if ENABLE_FEATURE_SGI_LABEL
     1698            if (LABEL_IS_SGI &&
    45491699                (
    4550                     (i == 10 && sys != ENTIRE_DISK) ||
     1700                    (i == 10 && sys != SGI_ENTIRE_DISK) ||
    45511701                    (i == 8 && sys != 0)
    45521702                )
    4553             ){
    4554                 printf(_("Consider leaving partition 9 "
     1703            ) {
     1704                printf("Consider leaving partition 9 "
    45551705                       "as volume header (0),\nand "
    45561706                       "partition 11 as entire volume (6)"
    4557                        "as IRIX expects it.\n\n"));
     1707                       "as IRIX expects it\n\n");
    45581708            }
    45591709#endif
    45601710            if (sys == origsys)
    45611711                break;
    4562 #ifdef CONFIG_FEATURE_SUN_LABEL
    4563             if (label_sun == current_label_type) {
     1712            if (LABEL_IS_SUN) {
    45641713                sun_change_sysid(i, sys);
    4565             } else
    4566 #endif
    4567 #ifdef CONFIG_FEATURE_SGI_LABEL
    4568             if (label_sgi == current_label_type) {
     1714            } else if (LABEL_IS_SGI) {
    45691715                sgi_change_sysid(i, sys);
    45701716            } else
    4571 #endif
    45721717                p->sys_ind = sys;
    45731718
    4574             printf(_("Changed system type of partition %d "
    4575                 "to %x (%s)\n"), i + 1, sys,
     1719            printf("Changed system type of partition %d "
     1720                "to %x (%s)\n", i + 1, sys,
    45761721                partition_type(sys));
    45771722            ptes[i].changed = 1;
     
    45811726            break;
    45821727        }
    4583         }
    4584     }
    4585 }
    4586 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
    4587 
    4588 
    4589 /* check_consistency() and long2chs() added Sat Mar 6 12:28:16 1993,
     1728    }
     1729}
     1730#endif /* FEATURE_FDISK_WRITABLE */
     1731
     1732
     1733/* check_consistency() and linear2chs() added Sat Mar 6 12:28:16 1993,
    45901734 * faith@cs.unc.edu, based on code fragments from pfdisk by Gordon W. Ross,
    45911735 * Jan.  1990 (version 1.2.1 by Gordon W. Ross Aug. 1990; Modified by S.
     
    45931737
    45941738static void
    4595 long2chs(ulong ls, uint *c, uint *h, uint *s)
     1739linear2chs(unsigned ls, unsigned *c, unsigned *h, unsigned *s)
    45961740{
    45971741    int spc = heads * sectors;
     
    46061750check_consistency(const struct partition *p, int partition)
    46071751{
    4608     uint pbc, pbh, pbs;          /* physical beginning c, h, s */
    4609     uint pec, peh, pes;          /* physical ending c, h, s */
    4610     uint lbc, lbh, lbs;          /* logical beginning c, h, s */
    4611     uint lec, leh, les;          /* logical ending c, h, s */
     1752    unsigned pbc, pbh, pbs;          /* physical beginning c, h, s */
     1753    unsigned pec, peh, pes;          /* physical ending c, h, s */
     1754    unsigned lbc, lbh, lbs;          /* logical beginning c, h, s */
     1755    unsigned lec, leh, les;          /* logical ending c, h, s */
    46121756
    46131757    if (!heads || !sectors || (partition >= 4))
     
    46251769
    46261770/* compute logical beginning (c, h, s) */
    4627     long2chs(get_start_sect(p), &lbc, &lbh, &lbs);
     1771    linear2chs(get_start_sect(p), &lbc, &lbh, &lbs);
    46281772
    46291773/* compute logical ending (c, h, s) */
    4630     long2chs(get_start_sect(p) + get_nr_sects(p) - 1, &lec, &leh, &les);
     1774    linear2chs(get_start_sect(p) + get_nr_sects(p) - 1, &lec, &leh, &les);
    46311775
    46321776/* Same physical / logical beginning? */
    46331777    if (cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) {
    4634         printf(_("Partition %d has different physical/logical "
    4635             "beginnings (non-Linux?):\n"), partition + 1);
    4636         printf(_("     phys=(%d, %d, %d) "), pbc, pbh, pbs);
    4637         printf(_("logical=(%d, %d, %d)\n"),lbc, lbh, lbs);
     1778        printf("Partition %d has different physical/logical "
     1779            "beginnings (non-Linux?):\n", partition + 1);
     1780        printf("     phys=(%d, %d, %d) ", pbc, pbh, pbs);
     1781        printf("logical=(%d, %d, %d)\n",lbc, lbh, lbs);
    46381782    }
    46391783
    46401784/* Same physical / logical ending? */
    46411785    if (cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) {
    4642         printf(_("Partition %d has different physical/logical "
    4643             "endings:\n"), partition + 1);
    4644         printf(_("     phys=(%d, %d, %d) "), pec, peh, pes);
    4645         printf(_("logical=(%d, %d, %d)\n"),lec, leh, les);
    4646     }
    4647 
    4648 #if 0
    4649 /* Beginning on cylinder boundary? */
    4650     if (pbh != !pbc || pbs != 1) {
    4651         printf(_("Partition %i does not start on cylinder "
    4652             "boundary:\n"), partition + 1);
    4653         printf(_("     phys=(%d, %d, %d) "), pbc, pbh, pbs);
    4654         printf(_("should be (%d, %d, 1)\n"), pbc, !pbc);
    4655     }
    4656 #endif
     1786        printf("Partition %d has different physical/logical "
     1787            "endings:\n", partition + 1);
     1788        printf("     phys=(%d, %d, %d) ", pec, peh, pes);
     1789        printf("logical=(%d, %d, %d)\n", lec, leh, les);
     1790    }
    46571791
    46581792/* Ending on cylinder boundary? */
    46591793    if (peh != (heads - 1) || pes != sectors) {
    4660         printf(_("Partition %i does not end on cylinder boundary.\n"),
     1794        printf("Partition %i does not end on cylinder boundary\n",
    46611795            partition + 1);
    4662 #if 0
    4663         printf(_("     phys=(%d, %d, %d) "), pec, peh, pes);
    4664         printf(_("should be (%d, %d, %d)\n"),
    4665         pec, heads - 1, sectors);
    4666 #endif
    46671796    }
    46681797}
     
    46751804
    46761805    if (megabytes < 10000)
    4677         printf(_("\nDisk %s: %ld MB, %lld bytes\n"),
     1806        printf("\nDisk %s: %ld MB, %lld bytes\n",
    46781807               disk_device, megabytes, bytes);
    46791808    else
    4680         printf(_("\nDisk %s: %ld.%ld GB, %lld bytes\n"),
     1809        printf("\nDisk %s: %ld.%ld GB, %lld bytes\n",
    46811810               disk_device, megabytes/1000, (megabytes/100)%10, bytes);
    4682     printf(_("%d heads, %d sectors/track, %d cylinders"),
     1811    printf("%d heads, %d sectors/track, %d cylinders",
    46831812           heads, sectors, cylinders);
    46841813    if (units_per_sector == 1)
    4685         printf(_(", total %llu sectors"),
     1814        printf(", total %llu sectors",
    46861815               total_number_of_sectors / (sector_size/512));
    4687     printf(_("\nUnits = %s of %d * %d = %d bytes\n\n"),
     1816    printf("\nUnits = %s of %d * %d = %d bytes\n\n",
    46881817           str_units(PLURAL),
    46891818           units_per_sector, sector_size, units_per_sector * sector_size);
     
    47001829    const struct pte *pe;
    47011830    const struct partition *p;
    4702     off_t last_p_start_pos = 0, p_start_pos;
     1831    ullong last_p_start_pos = 0, p_start_pos;
    47031832    int i, last_i = 0;
    47041833
    4705     for (i = 0 ; i < partitions; i++) {
     1834    for (i = 0; i < partitions; i++) {
    47061835        if (i == 4) {
    47071836            last_i = 4;
     
    47251854}
    47261855
    4727 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
     1856#if ENABLE_FEATURE_FDISK_ADVANCED
    47281857/*
    47291858 * Fix the chain of logicals.
     
    47981927
    47991928    if (!wrong_p_order(NULL)) {
    4800         printf(_("Nothing to do. Ordering is correct already.\n\n"));
     1929        printf("Ordering is already correct\n\n");
    48011930        return;
    48021931    }
     
    48371966    int i, w;
    48381967
    4839 #ifdef CONFIG_FEATURE_SUN_LABEL
    4840     if (label_sun == current_label_type) {
     1968    if (LABEL_IS_SUN) {
    48411969        sun_list_table(xtra);
    48421970        return;
    48431971    }
    4844 #endif
    4845 
    4846 #ifdef CONFIG_FEATURE_SGI_LABEL
    4847     if (label_sgi == current_label_type) {
     1972    if (LABEL_IS_SUN) {
    48481973        sgi_list_table(xtra);
    48491974        return;
    48501975    }
    4851 #endif
    48521976
    48531977    list_disk_geometry();
    48541978
    4855 #ifdef CONFIG_FEATURE_OSF_LABEL
    4856     if (label_osf == current_label_type) {
     1979    if (LABEL_IS_OSF) {
    48571980        xbsd_print_disklabel(xtra);
    48581981        return;
    48591982    }
    4860 #endif
    48611983
    48621984    /* Heuristic: we list partition 3 of /dev/foo as /dev/foo3,
     
    48691991        w = 5;
    48701992
    4871     printf(_("%*s Boot    Start       End    Blocks   Id  System\n"),
    4872            w+1, _("Device"));
     1993    //            1 12345678901 12345678901 12345678901  12
     1994    printf("%*s Boot      Start         End      Blocks  Id System\n",
     1995           w+1, "Device");
    48731996
    48741997    for (i = 0; i < partitions; i++) {
    48751998        const struct pte *pe = &ptes[i];
     1999        ullong psects;
     2000        ullong pblocks;
     2001        unsigned podd;
    48762002
    48772003        p = pe->part_table;
    4878         if (p && !is_cleared_partition(p)) {
    4879             off_t psects = get_nr_sects(p);
    4880             off_t pblocks = psects;
    4881             unsigned int podd = 0;
    4882 
    4883             if (sector_size < 1024) {
    4884                 pblocks /= (1024 / sector_size);
    4885                 podd = psects % (1024 / sector_size);
    4886             }
    4887             if (sector_size > 1024)
    4888                 pblocks *= (sector_size / 1024);
    4889             printf(
    4890                 "%s  %c %11llu %11llu %11llu%c  %2x  %s\n",
     2004        if (!p || is_cleared_partition(p))
     2005            continue;
     2006
     2007        psects = get_nr_sects(p);
     2008        pblocks = psects;
     2009        podd = 0;
     2010
     2011        if (sector_size < 1024) {
     2012            pblocks /= (1024 / sector_size);
     2013            podd = psects % (1024 / sector_size);
     2014        }
     2015        if (sector_size > 1024)
     2016            pblocks *= (sector_size / 1024);
     2017
     2018        printf("%s  %c %11llu %11llu %11llu%c %2x %s\n",
    48912019            partname(disk_device, i+1, w+2),
    4892 /* boot flag */         !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG
    4893             ? '*' : '?',
    4894 /* start */             (unsigned long long) cround(get_partition_start(pe)),
    4895 /* end */               (unsigned long long) cround(get_partition_start(pe) + psects
     2020            !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG /* boot flag */
     2021                ? '*' : '?',
     2022            (ullong) cround(get_partition_start(pe)),           /* start */
     2023            (ullong) cround(get_partition_start(pe) + psects    /* end */
    48962024                - (psects ? 1 : 0)),
    4897 /* odd flag on end */   (unsigned long long) pblocks, podd ? '+' : ' ',
    4898 /* type id */           p->sys_ind,
    4899 /* type name */         partition_type(p->sys_ind));
    4900             check_consistency(p, i);
    4901         }
     2025            (ullong) pblocks, podd ? '+' : ' ', /* odd flag on end */
     2026            p->sys_ind,                                     /* type id */
     2027            partition_type(p->sys_ind));                    /* type name */
     2028
     2029        check_consistency(p, i);
    49022030    }
    49032031
     
    49052033    /* partition table entries are not checked for correct order if this
    49062034       is a sgi, sun or aix labeled disk... */
    4907     if (label_dos == current_label_type && wrong_p_order(NULL)) {
     2035    if (LABEL_IS_DOS && wrong_p_order(NULL)) {
    49082036        /* FIXME */
    4909         printf(_("\nPartition table entries are not in disk order\n"));
    4910     }
    4911 }
    4912 
    4913 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
     2037        printf("\nPartition table entries are not in disk order\n");
     2038    }
     2039}
     2040
     2041#if ENABLE_FEATURE_FDISK_ADVANCED
    49142042static void
    49152043x_list_table(int extend)
     
    49192047    int i;
    49202048
    4921     printf(_("\nDisk %s: %d heads, %d sectors, %d cylinders\n\n"),
     2049    printf("\nDisk %s: %d heads, %d sectors, %d cylinders\n\n",
    49222050        disk_device, heads, sectors, cylinders);
    4923     printf(_("Nr AF  Hd Sec  Cyl  Hd Sec  Cyl    Start     Size ID\n"));
    4924     for (i = 0 ; i < partitions; i++) {
     2051    printf("Nr AF  Hd Sec  Cyl  Hd Sec  Cyl      Start       Size ID\n");
     2052    for (i = 0; i < partitions; i++) {
    49252053        pe = &ptes[i];
    49262054        p = (extend ? pe->ext_pointer : pe->part_table);
     
    49402068#endif
    49412069
    4942 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
    4943 static void
    4944 fill_bounds(off_t *first, off_t *last)
     2070#if ENABLE_FEATURE_FDISK_WRITABLE
     2071static void
     2072fill_bounds(ullong *first, ullong *last)
    49452073{
    49462074    int i;
     
    49612089
    49622090static void
    4963 check(int n, uint h, uint s, uint c, off_t start)
    4964 {
    4965     off_t total, real_s, real_c;
     2091check(int n, unsigned h, unsigned s, unsigned c, ullong start)
     2092{
     2093    ullong total, real_s, real_c;
    49662094
    49672095    real_s = sector(s) - 1;
     
    49692097    total = (real_c * sectors + real_s) * heads + h;
    49702098    if (!total)
    4971         fprintf(stderr, _("Warning: partition %d contains sector 0\n"), n);
     2099        printf("Partition %d contains sector 0\n", n);
    49722100    if (h >= heads)
    4973         fprintf(stderr,
    4974             _("Partition %d: head %d greater than maximum %d\n"),
     2101        printf("Partition %d: head %d greater than maximum %d\n",
    49752102            n, h + 1, heads);
    49762103    if (real_s >= sectors)
    4977         fprintf(stderr, _("Partition %d: sector %d greater than "
    4978             "maximum %d\n"), n, s, sectors);
     2104        printf("Partition %d: sector %d greater than "
     2105            "maximum %d\n", n, s, sectors);
    49792106    if (real_c >= cylinders)
    4980         fprintf(stderr, _("Partitions %d: cylinder %llu greater than "
    4981             "maximum %d\n"), n, (unsigned long long)real_c + 1, cylinders);
     2107        printf("Partition %d: cylinder %llu greater than "
     2108            "maximum %d\n", n, real_c + 1, cylinders);
    49822109    if (cylinders <= 1024 && start != total)
    4983         fprintf(stderr,
    4984             _("Partition %d: previous sectors %llu disagrees with "
    4985             "total %llu\n"), n, (unsigned long long)start, (unsigned long long)total);
     2110        printf("Partition %d: previous sectors %llu disagrees with "
     2111            "total %llu\n", n, start, total);
    49862112}
    49872113
     
    49902116{
    49912117    int i, j;
    4992     uint total = 1;
    4993     off_t first[partitions], last[partitions];
     2118    unsigned total = 1;
     2119    ullong first[partitions], last[partitions];
    49942120    struct partition *p;
    49952121
     
    49972123        return;
    49982124
    4999 #ifdef CONFIG_FEATURE_SUN_LABEL
    5000     if (label_sun == current_label_type) {
     2125    if (LABEL_IS_SUN) {
    50012126        verify_sun();
    50022127        return;
    50032128    }
    5004 #endif
    5005 #ifdef CONFIG_FEATURE_SGI_LABEL
    5006     if (label_sgi == current_label_type) {
     2129    if (LABEL_IS_SGI) {
    50072130        verify_sgi(1);
    50082131        return;
    50092132    }
    5010 #endif
    50112133
    50122134    fill_bounds(first, last);
     
    50182140            check_consistency(p, i);
    50192141            if (get_partition_start(pe) < first[i])
    5020                 printf(_("Warning: bad start-of-data in "
    5021                     "partition %d\n"), i + 1);
     2142                printf("Warning: bad start-of-data in "
     2143                    "partition %d\n", i + 1);
    50222144            check(i + 1, p->end_head, p->end_sector, p->end_cyl,
    50232145                last[i]);
    50242146            total += last[i] + 1 - first[i];
    5025             for (j = 0; j < i; j++)
    5026             if ((first[i] >= first[j] && first[i] <= last[j])
    5027              || ((last[i] <= last[j] && last[i] >= first[j]))) {
    5028                 printf(_("Warning: partition %d overlaps "
    5029                     "partition %d.\n"), j + 1, i + 1);
    5030                 total += first[i] >= first[j] ?
    5031                     first[i] : first[j];
    5032                 total -= last[i] <= last[j] ?
    5033                     last[i] : last[j];
     2147            for (j = 0; j < i; j++) {
     2148                if ((first[i] >= first[j] && first[i] <= last[j])
     2149                 || ((last[i] <= last[j] && last[i] >= first[j]))) {
     2150                    printf("Warning: partition %d overlaps "
     2151                        "partition %d\n", j + 1, i + 1);
     2152                    total += first[i] >= first[j] ?
     2153                        first[i] : first[j];
     2154                    total -= last[i] <= last[j] ?
     2155                        last[i] : last[j];
     2156                }
    50342157            }
    50352158        }
     
    50382161    if (extended_offset) {
    50392162        struct pte *pex = &ptes[ext_index];
    5040         off_t e_last = get_start_sect(pex->part_table) +
     2163        ullong e_last = get_start_sect(pex->part_table) +
    50412164            get_nr_sects(pex->part_table) - 1;
    50422165
     
    50462169            if (!p->sys_ind) {
    50472170                if (i != 4 || i + 1 < partitions)
    5048                     printf(_("Warning: partition %d "
    5049                         "is empty\n"), i + 1);
     2171                    printf("Warning: partition %d "
     2172                        "is empty\n", i + 1);
     2173            } else if (first[i] < extended_offset || last[i] > e_last) {
     2174                printf("Logical partition %d not entirely in "
     2175                    "partition %d\n", i + 1, ext_index + 1);
    50502176            }
    5051             else if (first[i] < extended_offset ||
    5052                     last[i] > e_last)
    5053                 printf(_("Logical partition %d not entirely in "
    5054                     "partition %d\n"), i + 1, ext_index + 1);
    50552177        }
    50562178    }
    50572179
    50582180    if (total > heads * sectors * cylinders)
    5059         printf(_("Total allocated sectors %d greater than the maximum "
    5060             "%d\n"), total, heads * sectors * cylinders);
    5061     else if ((total = heads * sectors * cylinders - total) != 0)
    5062         printf(_("%d unallocated sectors\n"), total);
     2181        printf("Total allocated sectors %d greater than the maximum "
     2182            "%d\n", total, heads * sectors * cylinders);
     2183    else {
     2184        total = heads * sectors * cylinders - total;
     2185        if (total != 0)
     2186            printf("%d unallocated sectors\n", total);
     2187    }
    50632188}
    50642189
     
    50702195    struct partition *p = ptes[n].part_table;
    50712196    struct partition *q = ptes[ext_index].part_table;
    5072     long long llimit;
    5073     off_t start, stop = 0, limit, temp,
    5074         first[partitions], last[partitions];
     2197    ullong limit, temp;
     2198    ullong start, stop = 0;
     2199    ullong first[partitions], last[partitions];
    50752200
    50762201    if (p && p->sys_ind) {
    5077         printf(_("Partition %d is already defined.  Delete "
    5078              "it before re-adding it.\n"), n + 1);
     2202        printf(msg_part_already_defined, n + 1);
    50792203        return;
    50802204    }
     
    50832207        start = sector_offset;
    50842208        if (display_in_cyl_units || !total_number_of_sectors)
    5085             llimit = heads * sectors * cylinders - 1;
     2209            limit = (ullong) heads * sectors * cylinders - 1;
    50862210        else
    5087             llimit = total_number_of_sectors - 1;
    5088         limit = llimit;
    5089         if (limit != llimit)
    5090             limit = 0x7fffffff;
     2211            limit = total_number_of_sectors - 1;
    50912212        if (extended_offset) {
    50922213            first[ext_index] = extended_offset;
     
    51022223            first[i] = (cround(first[i]) - 1) * units_per_sector;
    51032224
    5104     snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR));
     2225    snprintf(mesg, sizeof(mesg), "First %s", str_units(SINGULAR));
    51052226    do {
    51062227        temp = start;
     
    51172238            break;
    51182239        if (start >= temp+units_per_sector && num_read) {
    5119             printf(_("Sector %llu is already allocated\n"), (unsigned long long)temp);
     2240            printf("Sector %lld is already allocated\n", temp);
    51202241            temp = start;
    51212242            num_read = 0;
    51222243        }
    51232244        if (!num_read && start == temp) {
    5124             off_t saved_start;
     2245            ullong saved_start;
    51252246
    51262247            saved_start = start;
     
    51542275    }
    51552276    if (start > limit) {
    5156         printf(_("No free sectors available\n"));
     2277        printf("No free sectors available\n");
    51572278        if (n > 4)
    51582279            partitions--;
     
    51632284    } else {
    51642285        snprintf(mesg, sizeof(mesg),
    5165              _("Last %s or +size or +sizeM or +sizeK"),
     2286             "Last %s or +size or +sizeM or +sizeK",
    51662287             str_units(SINGULAR));
    51672288        stop = read_int(cround(start), cround(limit), cround(limit),
     
    51852306        pen->ext_pointer = p;
    51862307        pe4->offset = extended_offset = start;
    5187         pe4->sectorbuffer = xcalloc(1, sector_size);
     2308        pe4->sectorbuffer = xzalloc(sector_size);
    51882309        pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
    51892310        pe4->ext_pointer = pe4->part_table + 1;
     
    51992320        struct pte *pe = &ptes[partitions];
    52002321
    5201         pe->sectorbuffer = xcalloc(1, sector_size);
     2322        pe->sectorbuffer = xzalloc(sector_size);
    52022323        pe->part_table = pt_offset(pe->sectorbuffer, 0);
    52032324        pe->ext_pointer = pe->part_table + 1;
     
    52172338        return;
    52182339
    5219 #ifdef CONFIG_FEATURE_SUN_LABEL
    5220     if (label_sun == current_label_type) {
     2340    if (LABEL_IS_SUN) {
    52212341        add_sun_partition(get_partition(0, partitions), LINUX_NATIVE);
    52222342        return;
    52232343    }
    5224 #endif
    5225 #ifdef CONFIG_FEATURE_SGI_LABEL
    5226     if (label_sgi == current_label_type) {
     2344    if (LABEL_IS_SGI) {
    52272345        sgi_add_partition(get_partition(0, partitions), LINUX_NATIVE);
    52282346        return;
    52292347    }
    5230 #endif
    5231 #ifdef CONFIG_FEATURE_AIX_LABEL
    5232     if (label_aix == current_label_type) {
    5233         printf(_("\tSorry - this fdisk cannot handle AIX disk labels."
    5234              "\n\tIf you want to add DOS-type partitions, create"
    5235              "\n\ta new empty DOS partition table first. (Use o.)"
    5236              "\n\tWARNING: "
    5237              "This will destroy the present disk contents.\n"));
     2348    if (LABEL_IS_AIX) {
     2349        printf("Sorry - this fdisk cannot handle AIX disk labels.\n"
     2350"If you want to add DOS-type partitions, create a new empty DOS partition\n"
     2351"table first (use 'o'). This will destroy the present disk contents.\n");
    52382352        return;
    52392353    }
    5240 #endif
    52412354
    52422355    for (i = 0; i < 4; i++)
     
    52442357
    52452358    if (!free_primary && partitions >= MAXIMUM_PARTS) {
    5246         printf(_("The maximum number of partitions has been created\n"));
     2359        printf("The maximum number of partitions has been created\n");
    52472360        return;
    52482361    }
     
    52522365            add_logical();
    52532366        else
    5254             printf(_("You must delete some partition and add "
    5255                  "an extended partition first\n"));
     2367            printf("You must delete some partition and add "
     2368                 "an extended partition first\n");
    52562369    } else {
    5257         char c, line[LINE_LENGTH];
    5258         snprintf(line, sizeof(line), "%s\n   %s\n   p   primary "
    5259                         "partition (1-4)\n",
    5260              "Command action", (extended_offset ?
    5261              "l   logical (5 or over)" : "e   extended"));
     2370        char c, line[80];
     2371        snprintf(line, sizeof(line),
     2372            "Command action\n"
     2373            "   %s\n"
     2374            "   p   primary partition (1-4)\n",
     2375            (extended_offset ?
     2376            "l   logical (5 or over)" : "e   extended"));
    52622377        while (1) {
    5263             if ((c = read_char(line)) == 'p' || c == 'P') {
     2378            c = read_nonempty(line);
     2379            if (c == 'p' || c == 'P') {
    52642380                i = get_nonexisting_partition(0, 4);
    52652381                if (i >= 0)
     
    52672383                return;
    52682384            }
    5269             else if (c == 'l' && extended_offset) {
     2385            if (c == 'l' && extended_offset) {
    52702386                add_logical();
    52712387                return;
    52722388            }
    5273             else if (c == 'e' && !extended_offset) {
     2389            if (c == 'e' && !extended_offset) {
    52742390                i = get_nonexisting_partition(0, 4);
    52752391                if (i >= 0)
     
    52772393                return;
    52782394            }
    5279             else
    5280                 printf(_("Invalid partition number "
    5281                      "for type `%c'\n"), c);
     2395            printf("Invalid partition number "
     2396                     "for type '%c'\n", c);
    52822397        }
    52832398    }
     
    52892404    int i;
    52902405
    5291     if (label_dos == current_label_type) {
     2406    if (LABEL_IS_DOS) {
    52922407        for (i = 0; i < 3; i++)
    52932408            if (ptes[i].changed)
     
    53022417        }
    53032418    }
    5304 #ifdef CONFIG_FEATURE_SGI_LABEL
    5305     else if (label_sgi == current_label_type) {
     2419    else if (LABEL_IS_SGI) {
    53062420        /* no test on change? the printf below might be mistaken */
    53072421        sgi_write_table();
    53082422    }
    5309 #endif
    5310 #ifdef CONFIG_FEATURE_SUN_LABEL
    5311     else if (label_sun == current_label_type) {
     2423    else if (LABEL_IS_SUN) {
    53122424        int needw = 0;
    53132425
     
    53182430            sun_write_table();
    53192431    }
    5320 #endif
    5321 
    5322     printf(_("The partition table has been altered!\n\n"));
     2432
     2433    printf("The partition table has been altered!\n\n");
    53232434    reread_partition_table(1);
    53242435}
     
    53272438reread_partition_table(int leave)
    53282439{
    5329     int error = 0;
    53302440    int i;
    53312441
    5332     printf(_("Calling ioctl() to re-read partition table.\n"));
     2442    printf("Calling ioctl() to re-read partition table\n");
    53332443    sync();
    5334     sleep(2);
    5335     if ((i = ioctl(fd, BLKRRPART)) != 0) {
    5336         error = errno;
    5337     } else {
    5338         /* some kernel versions (1.2.x) seem to have trouble
    5339            rereading the partition table, but if asked to do it
    5340            twice, the second time works. - biro@yggdrasil.com */
    5341         sync();
    5342         sleep(2);
    5343         if ((i = ioctl(fd, BLKRRPART)) != 0)
    5344             error = errno;
    5345     }
    5346 
    5347     if (i) {
    5348         printf(_("\nWARNING: Re-reading the partition table "
    5349              "failed with error %d: %s.\n"
    5350              "The kernel still uses the old table.\n"
    5351              "The new table will be used "
    5352              "at the next reboot.\n"),
    5353             error, strerror(error));
    5354     }
    5355 
     2444    /* sleep(2); Huh? */
     2445    i = ioctl_or_perror(fd, BLKRRPART, NULL,
     2446            "WARNING: rereading partition table "
     2447            "failed, kernel still uses old table");
     2448#if 0
    53562449    if (dos_changed)
    53572450        printf(
    5358         _("\nWARNING: If you have created or modified any DOS 6.x\n"
     2451        "\nWARNING: If you have created or modified any DOS 6.x\n"
    53592452        "partitions, please see the fdisk manual page for additional\n"
    5360         "information.\n"));
     2453        "information\n");
     2454#endif
    53612455
    53622456    if (leave) {
    5363         close(fd);
    5364 
    5365         printf(_("Syncing disks.\n"));
    5366         sync();
    5367         sleep(4);               /* for sync() */
    5368         exit(!!i);
    5369     }
    5370 }
    5371 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
    5372 
    5373 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
     2457        if (ENABLE_FEATURE_CLEAN_UP)
     2458            close(fd);
     2459        exit(i != 0);
     2460    }
     2461}
     2462#endif /* FEATURE_FDISK_WRITABLE */
     2463
     2464#if ENABLE_FEATURE_FDISK_ADVANCED
    53742465#define MAX_PER_LINE    16
    53752466static void
     
    53832474        printf(" %02X", (unsigned char) pbuffer[i]);
    53842475        if (l == MAX_PER_LINE - 1) {
    5385             printf("\n");
     2476            puts("");
    53862477            l = -1;
    53872478        }
    53882479    }
    53892480    if (l > 0)
    5390         printf("\n");
    5391     printf("\n");
    5392 }
    5393 
     2481        puts("");
     2482    puts("");
     2483}
    53942484
    53952485static void
     
    53982488    int i;
    53992489
    5400     printf(_("Device: %s\n"), disk_device);
    5401 #if defined(CONFIG_FEATURE_SGI_LABEL) || defined(CONFIG_FEATURE_SUN_LABEL)
    5402     if (label_sun == current_label_type || label_sgi == current_label_type)
     2490    printf("Device: %s\n", disk_device);
     2491    if (LABEL_IS_SGI || LABEL_IS_SUN)
    54032492        print_buffer(MBRbuffer);
    5404     else
    5405 #endif
     2493    else {
    54062494        for (i = 3; i < partitions; i++)
    54072495            print_buffer(ptes[i].sectorbuffer);
     2496    }
    54082497}
    54092498
     
    54132502    struct pte *pe = &ptes[i];
    54142503    struct partition *p = pe->part_table;
    5415     off_t new, first;
     2504    ullong new, first;
    54162505
    54172506    if (warn_geometry())
    54182507        return;
    54192508    if (!p->sys_ind || !get_nr_sects(p) || IS_EXTENDED(p->sys_ind)) {
    5420         printf(_("Partition %d has no data area\n"), i + 1);
     2509        printf("Partition %d has no data area\n", i + 1);
    54212510        return;
    54222511    }
    54232512    first = get_partition_start(pe);
    54242513    new = read_int(first, first, first + get_nr_sects(p) - 1, first,
    5425                _("New beginning of data")) - pe->offset;
     2514               "New beginning of data") - pe->offset;
    54262515
    54272516    if (new != get_nr_sects(p)) {
     
    54402529    while (1) {
    54412530        putchar('\n');
    5442         c = tolower(read_char(_("Expert command (m for help): ")));
     2531        c = tolower(read_nonempty("Expert command (m for help): "));
    54432532        switch (c) {
    54442533        case 'a':
    5445 #ifdef CONFIG_FEATURE_SUN_LABEL
    5446             if (label_sun == current_label_type)
     2534            if (LABEL_IS_SUN)
    54472535                sun_set_alt_cyl();
    5448 #endif
    54492536            break;
    54502537        case 'b':
    5451             if (label_dos == current_label_type)
     2538            if (LABEL_IS_DOS)
    54522539                move_begin(get_partition(0, partitions));
    54532540            break;
     
    54552542            user_cylinders = cylinders =
    54562543                read_int(1, cylinders, 1048576, 0,
    5457                     _("Number of cylinders"));
    5458 #ifdef CONFIG_FEATURE_SUN_LABEL
    5459             if (label_sun == current_label_type)
     2544                    "Number of cylinders");
     2545            if (LABEL_IS_SUN)
    54602546                sun_set_ncyl(cylinders);
    5461 #endif
    5462             if (label_dos == current_label_type)
     2547            if (LABEL_IS_DOS)
    54632548                warn_cylinders();
    54642549            break;
     
    54672552            break;
    54682553        case 'e':
    5469 #ifdef CONFIG_FEATURE_SGI_LABEL
    5470             if (label_sgi == current_label_type)
     2554            if (LABEL_IS_SGI)
    54712555                sgi_set_xcyl();
    5472             else
    5473 #endif
    5474 #ifdef CONFIG_FEATURE_SUN_LABEL
    5475              if (label_sun == current_label_type)
     2556            else if (LABEL_IS_SUN)
    54762557                sun_set_xcyl();
    5477              else
    5478 #endif
    5479             if (label_dos == current_label_type)
     2558            else if (LABEL_IS_DOS)
    54802559                x_list_table(1);
    54812560            break;
    54822561        case 'f':
    5483             if (label_dos == current_label_type)
     2562            if (LABEL_IS_DOS)
    54842563                fix_partition_table_order();
    54852564            break;
    54862565        case 'g':
    5487 #ifdef CONFIG_FEATURE_SGI_LABEL
     2566#if ENABLE_FEATURE_SGI_LABEL
    54882567            create_sgilabel();
    54892568#endif
     
    54912570        case 'h':
    54922571            user_heads = heads = read_int(1, heads, 256, 0,
    5493                     _("Number of heads"));
     2572                    "Number of heads");
    54942573            update_units();
    54952574            break;
    54962575        case 'i':
    5497 #ifdef CONFIG_FEATURE_SUN_LABEL
    5498             if (label_sun == current_label_type)
     2576            if (LABEL_IS_SUN)
    54992577                sun_set_ilfact();
    5500 #endif
    55012578            break;
    55022579        case 'o':
    5503 #ifdef CONFIG_FEATURE_SUN_LABEL
    5504             if (label_sun == current_label_type)
     2580            if (LABEL_IS_SUN)
    55052581                sun_set_rspeed();
    5506 #endif
    55072582            break;
    55082583        case 'p':
    5509 #ifdef CONFIG_FEATURE_SUN_LABEL
    5510             if (label_sun == current_label_type)
     2584            if (LABEL_IS_SUN)
    55112585                list_table(1);
    55122586            else
    5513 #endif
    55142587                x_list_table(0);
    55152588            break;
    55162589        case 'q':
    55172590            close(fd);
    5518             printf("\n");
     2591            puts("");
    55192592            exit(0);
    55202593        case 'r':
     
    55222595        case 's':
    55232596            user_sectors = sectors = read_int(1, sectors, 63, 0,
    5524                        _("Number of sectors"));
     2597                       "Number of sectors");
    55252598            if (dos_compatible_flag) {
    55262599                sector_offset = sectors;
    5527                 fprintf(stderr, _("Warning: setting "
    5528                     "sector offset for DOS "
    5529                     "compatiblity\n"));
     2600                printf("Warning: setting sector offset for DOS "
     2601                    "compatiblity\n");
    55302602            }
    55312603            update_units();
     
    55382610            break;
    55392611        case 'y':
    5540 #ifdef CONFIG_FEATURE_SUN_LABEL
    5541             if (label_sun == current_label_type)
     2612            if (LABEL_IS_SUN)
    55422613                sun_set_pcylcount();
    5543 #endif
    55442614            break;
    55452615        default:
     
    55862656
    55872657static void
    5588 try(const char *device, int user_specified)
     2658trydev(const char *device, int user_specified)
    55892659{
    55902660    int gb;
     
    55962666        if (is_ide_cdrom_or_tape(device))
    55972667            return;
    5598     if ((fd = open(disk_device, type_open)) >= 0) {
     2668    fd = open(disk_device, type_open);
     2669    if (fd >= 0) {
    55992670        gb = get_boot(try_only);
    56002671        if (gb > 0) {   /* I/O error */
     
    56022673        } else if (gb < 0) { /* no DOS signature */
    56032674            list_disk_geometry();
    5604             if (label_aix == current_label_type){
     2675            if (LABEL_IS_AIX) {
    56052676                return;
    56062677            }
    5607 #ifdef CONFIG_FEATURE_OSF_LABEL
    5608             if (btrydev(device) < 0)
    5609 #endif
    5610                 fprintf(stderr,
    5611                     _("Disk %s doesn't contain a valid "
    5612                     "partition table\n"), device);
     2678#if ENABLE_FEATURE_OSF_LABEL
     2679            if (bsd_trydev(device) < 0)
     2680#endif
     2681                printf("Disk %s doesn't contain a valid "
     2682                    "partition table\n", device);
    56132683            close(fd);
    56142684        } else {
    56152685            close(fd);
    56162686            list_table(0);
    5617 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
    5618             if (label_sun != current_label_type && partitions > 4){
     2687#if ENABLE_FEATURE_FDISK_WRITABLE
     2688            if (!LABEL_IS_SUN && partitions > 4){
    56192689                delete_partition(ext_index);
    56202690            }
     
    56262696           installed on the system. */
    56272697        if (errno == EACCES) {
    5628             fprintf(stderr, _("Cannot open %s\n"), device);
     2698            printf("Cannot open %s\n", device);
    56292699            return;
    56302700        }
     
    56412711    int ma, mi, sz;
    56422712
    5643     procpt = bb_wfopen(PROC_PARTITIONS, "r");
     2713    procpt = fopen_or_warn("/proc/partitions", "r");
    56442714
    56452715    while (fgets(line, sizeof(line), procpt)) {
     
    56512721            continue;
    56522722        sprintf(devname, "/dev/%s", ptname);
    5653         try(devname, 0);
    5654     }
    5655 #ifdef CONFIG_FEATURE_CLEAN_UP
     2723        trydev(devname, 0);
     2724    }
     2725#if ENABLE_FEATURE_CLEAN_UP
    56562726    fclose(procpt);
    56572727#endif
    56582728}
    56592729
    5660 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
     2730#if ENABLE_FEATURE_FDISK_WRITABLE
    56612731static void
    56622732unknown_command(int c)
    56632733{
    5664     printf(_("%c: unknown command\n"), c);
    5665 }
    5666 #endif
    5667 
     2734    printf("%c: unknown command\n", c);
     2735}
     2736#endif
     2737
     2738int fdisk_main(int argc, char **argv);
    56682739int fdisk_main(int argc, char **argv)
    56692740{
    5670     int c;
    5671 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
    5672     int optl = 0;
    5673 #endif
    5674 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
    5675     int opts = 0;
    5676 #endif
     2741    char *str_b, *str_C, *str_H, *str_S;
     2742    unsigned opt;
    56772743    /*
    5678      * Calls:
    56792744     *  fdisk -v
    56802745     *  fdisk -l [-b sectorsize] [-u] device ...
     
    56832748     *
    56842749     * Options -C, -H, -S set the geometry.
    5685      *
    56862750     */
    5687     while ((c = getopt(argc, argv, "b:C:H:lS:uvV"
    5688 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
    5689                     "s"
    5690 #endif
    5691                         )) != -1) {
    5692         switch (c) {
    5693         case 'b':
    5694             /* Ugly: this sector size is really per device,
    5695                so cannot be combined with multiple disks,
    5696                and te same goes for the C/H/S options.
    5697             */
    5698             sector_size = atoi(optarg);
    5699             if (sector_size != 512 && sector_size != 1024 &&
    5700                 sector_size != 2048)
    5701                 bb_show_usage();
    5702             sector_offset = 2;
    5703             user_set_sector_size = 1;
    5704             break;
    5705         case 'C':
    5706             user_cylinders = atoi(optarg);
    5707             break;
    5708         case 'H':
    5709             user_heads = atoi(optarg);
    5710             if (user_heads <= 0 || user_heads >= 256)
    5711                 user_heads = 0;
    5712             break;
    5713         case 'S':
    5714             user_sectors = atoi(optarg);
    5715             if (user_sectors <= 0 || user_sectors >= 64)
    5716                 user_sectors = 0;
    5717             break;
    5718         case 'l':
    5719 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
    5720             optl = 1;
    5721 #endif
    5722             break;
    5723 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
    5724         case 's':
    5725             opts = 1;
    5726             break;
    5727 #endif
    5728         case 'u':
    5729             display_in_cyl_units = 0;
    5730             break;
    5731         case 'V':
    5732         case 'v':
    5733             printf("fdisk v" UTIL_LINUX_VERSION "\n");
    5734             return 0;
    5735         default:
     2751    enum {
     2752        OPT_b = 1 << 0,
     2753        OPT_C = 1 << 1,
     2754        OPT_H = 1 << 2,
     2755        OPT_l = 1 << 3,
     2756        OPT_S = 1 << 4,
     2757        OPT_u = 1 << 5,
     2758        OPT_s = (1 << 6) * ENABLE_FEATURE_FDISK_BLKSIZE,
     2759    };
     2760
     2761    PTR_TO_GLOBALS = xzalloc(sizeof(G));
     2762
     2763    opt = getopt32(argv, "b:C:H:lS:u" USE_FEATURE_FDISK_BLKSIZE("s"),
     2764                &str_b, &str_C, &str_H, &str_S);
     2765    argc -= optind;
     2766    argv += optind;
     2767    if (opt & OPT_b) { // -b
     2768        /* Ugly: this sector size is really per device,
     2769           so cannot be combined with multiple disks,
     2770           and the same goes for the C/H/S options.
     2771        */
     2772        sector_size = xatoi_u(str_b);
     2773        if (sector_size != 512 && sector_size != 1024 &&
     2774            sector_size != 2048)
    57362775            bb_show_usage();
    5737         }
    5738     }
    5739 
    5740 #if 0
    5741     printf(_("This kernel finds the sector size itself - "
    5742          "-b option ignored\n"));
    5743 #else
    5744     if (user_set_sector_size && argc-optind != 1)
    5745         printf(_("Warning: the -b (set sector size) option should"
    5746              " be used with one specified device\n"));
    5747 #endif
    5748 
    5749 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
    5750     if (optl) {
     2776        sector_offset = 2;
     2777        user_set_sector_size = 1;
     2778    }
     2779    if (opt & OPT_C) user_cylinders = xatoi_u(str_C); // -C
     2780    if (opt & OPT_H) { // -H
     2781        user_heads = xatoi_u(str_H);
     2782        if (user_heads <= 0 || user_heads >= 256)
     2783            user_heads = 0;
     2784    }
     2785    //if (opt & OPT_l) // -l
     2786    if (opt & OPT_S) { // -S
     2787        user_sectors = xatoi_u(str_S);
     2788        if (user_sectors <= 0 || user_sectors >= 64)
     2789            user_sectors = 0;
     2790    }
     2791    if (opt & OPT_u) display_in_cyl_units = 0; // -u
     2792    //if (opt & OPT_s) // -s
     2793
     2794    if (user_set_sector_size && argc != 1)
     2795        printf("Warning: the -b (set sector size) option should"
     2796             " be used with one specified device\n");
     2797
     2798#if ENABLE_FEATURE_FDISK_WRITABLE
     2799    if (opt & OPT_l) {
    57512800        nowarn = 1;
    57522801#endif
    57532802        type_open = O_RDONLY;
    5754         if (argc > optind) {
     2803        if (argc > 0) {
    57552804            int k;
    5756 #if __GNUC__
     2805#if defined(__GNUC__)
    57572806            /* avoid gcc warning:
    57582807               variable `k' might be clobbered by `longjmp' */
     
    57602809#endif
    57612810            listing = 1;
    5762             for (k = optind; k < argc; k++)
    5763                 try(argv[k], 1);
     2811            for (k = 0; k < argc; k++)
     2812                trydev(argv[k], 1);
    57642813        } else {
    57652814            /* we no longer have default device names */
     
    57682817        }
    57692818        return 0;
    5770 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
    5771     }
    5772 #endif
    5773 
    5774 #ifdef CONFIG_FEATURE_FDISK_BLKSIZE
    5775     if (opts) {
     2819#if ENABLE_FEATURE_FDISK_WRITABLE
     2820    }
     2821#endif
     2822
     2823#if ENABLE_FEATURE_FDISK_BLKSIZE
     2824    if (opt & OPT_s) {
    57762825        long size;
    57772826        int j;
     
    57802829        type_open = O_RDONLY;
    57812830
    5782         opts = argc - optind;
    5783         if (opts <= 0)
     2831        if (argc <= 0)
    57842832            bb_show_usage();
    57852833
    5786         for (j = optind; j < argc; j++) {
     2834        for (j = 0; j < argc; j++) {
    57872835            disk_device = argv[j];
    5788             if ((fd = open(disk_device, type_open)) < 0)
     2836            fd = open(disk_device, type_open);
     2837            if (fd < 0)
    57892838                fdisk_fatal(unable_to_open);
    57902839            if (ioctl(fd, BLKGETSIZE, &size))
    57912840                fdisk_fatal(ioctl_error);
    57922841            close(fd);
    5793             if (opts == 1)
     2842            if (argc == 1)
    57942843                printf("%ld\n", size/2);
    57952844            else
     
    58002849#endif
    58012850
    5802 #ifdef CONFIG_FEATURE_FDISK_WRITABLE
    5803     if (argc-optind == 1)
    5804         disk_device = argv[optind];
    5805     else
     2851#if ENABLE_FEATURE_FDISK_WRITABLE
     2852    if (argc != 1)
    58062853        bb_show_usage();
    58072854
     2855    disk_device = argv[0];
    58082856    get_boot(fdisk);
    58092857
    5810 #ifdef CONFIG_FEATURE_OSF_LABEL
    5811     if (label_osf == current_label_type) {
     2858    if (LABEL_IS_OSF) {
    58122859        /* OSF label, and no DOS label */
    5813         printf(_("Detected an OSF/1 disklabel on %s, entering "
    5814              "disklabel mode.\n"),
    5815                disk_device);
    5816         bselect();
     2860        printf("Detected an OSF/1 disklabel on %s, entering "
     2861            "disklabel mode\n", disk_device);
     2862        bsd_select();
    58172863        /*Why do we do this?  It seems to be counter-intuitive*/
    58182864        current_label_type = label_dos;
    58192865        /* If we return we may want to make an empty DOS label? */
    58202866    }
    5821 #endif
    58222867
    58232868    while (1) {
     2869        int c;
    58242870        putchar('\n');
    5825         c = tolower(read_char(_("Command (m for help): ")));
     2871        c = tolower(read_nonempty("Command (m for help): "));
    58262872        switch (c) {
    58272873        case 'a':
    5828             if (label_dos == current_label_type)
     2874            if (LABEL_IS_DOS)
    58292875                toggle_active(get_partition(1, partitions));
    5830 #ifdef CONFIG_FEATURE_SUN_LABEL
    5831             else if (label_sun == current_label_type)
     2876            else if (LABEL_IS_SUN)
    58322877                toggle_sunflags(get_partition(1, partitions),
    58332878                        0x01);
    5834 #endif
    5835 #ifdef CONFIG_FEATURE_SGI_LABEL
    5836             else if (label_sgi == current_label_type)
     2879            else if (LABEL_IS_SGI)
    58372880                sgi_set_bootpartition(
    58382881                    get_partition(1, partitions));
    5839 #endif
    58402882            else
    58412883                unknown_command(c);
    58422884            break;
    58432885        case 'b':
    5844 #ifdef CONFIG_FEATURE_SGI_LABEL
    5845             if (label_sgi == current_label_type) {
    5846                 printf(_("\nThe current boot file is: %s\n"),
     2886            if (LABEL_IS_SGI) {
     2887                printf("\nThe current boot file is: %s\n",
    58472888                    sgi_get_bootfile());
    5848                 if (read_chars(_("Please enter the name of the "
    5849                            "new boot file: ")) == '\n')
    5850                     printf(_("Boot file unchanged\n"));
     2889                if (read_maybe_empty("Please enter the name of the "
     2890                           "new boot file: ") == '\n')
     2891                    printf("Boot file unchanged\n");
    58512892                else
    58522893                    sgi_set_bootfile(line_ptr);
    5853             } else
    5854 #endif
    5855 #ifdef CONFIG_FEATURE_OSF_LABEL
    5856                 bselect();
     2894            }
     2895#if ENABLE_FEATURE_OSF_LABEL
     2896            else
     2897                bsd_select();
    58572898#endif
    58582899            break;
    58592900        case 'c':
    5860             if (label_dos == current_label_type)
     2901            if (LABEL_IS_DOS)
    58612902                toggle_dos_compatibility_flag();
    5862 #ifdef CONFIG_FEATURE_SUN_LABEL
    5863             else if (label_sun == current_label_type)
     2903            else if (LABEL_IS_SUN)
    58642904                toggle_sunflags(get_partition(1, partitions),
    58652905                        0x10);
    5866 #endif
    5867 #ifdef CONFIG_FEATURE_SGI_LABEL
    5868             else if (label_sgi == current_label_type)
     2906            else if (LABEL_IS_SGI)
    58692907                sgi_set_swappartition(
    58702908                        get_partition(1, partitions));
    5871 #endif
    58722909            else
    58732910                unknown_command(c);
     
    58762913            {
    58772914                int j;
    5878 #ifdef CONFIG_FEATURE_SGI_LABEL
    58792915            /* If sgi_label then don't use get_existing_partition,
    58802916               let the user select a partition, since
    58812917               get_existing_partition() only works for Linux-like
    58822918               partition tables */
    5883                 if (label_sgi != current_label_type) {
     2919                if (!LABEL_IS_SGI) {
    58842920                    j = get_existing_partition(1, partitions);
    58852921                } else {
    58862922                    j = get_partition(1, partitions);
    58872923                }
    5888 #else
    5889                 j = get_existing_partition(1, partitions);
    5890 #endif
    58912924                if (j >= 0)
    58922925                    delete_partition(j);
     
    58942927            break;
    58952928        case 'i':
    5896 #ifdef CONFIG_FEATURE_SGI_LABEL
    5897             if (label_sgi == current_label_type)
     2929            if (LABEL_IS_SGI)
    58982930                create_sgiinfo();
    58992931            else
    5900 #endif
    59012932                unknown_command(c);
    59022933        case 'l':
     
    59172948        case 'q':
    59182949            close(fd);
    5919             printf("\n");
     2950            puts("");
    59202951            return 0;
    59212952        case 's':
    5922 #ifdef CONFIG_FEATURE_SUN_LABEL
     2953#if ENABLE_FEATURE_SUN_LABEL
    59232954            create_sunlabel();
    59242955#endif
     
    59362967            write_table();          /* does not return */
    59372968            break;
    5938 #ifdef CONFIG_FEATURE_FDISK_ADVANCED
     2969#if ENABLE_FEATURE_FDISK_ADVANCED
    59392970        case 'x':
    5940 #ifdef CONFIG_FEATURE_SGI_LABEL
    5941             if (label_sgi == current_label_type) {
    5942                 fprintf(stderr,
    5943                     _("\n\tSorry, no experts menu for SGI "
    5944                     "partition tables available.\n\n"));
     2971            if (LABEL_IS_SGI) {
     2972                printf("\n\tSorry, no experts menu for SGI "
     2973                    "partition tables available\n\n");
    59452974            } else
    5946 #endif
    5947 
    59482975                xselect();
    59492976            break;
     
    59552982    }
    59562983    return 0;
    5957 #endif /* CONFIG_FEATURE_FDISK_WRITABLE */
    5958 }
     2984#endif /* FEATURE_FDISK_WRITABLE */
     2985}
Note: See TracChangeset for help on using the changeset viewer.