Changeset 1765 in MondoRescue for branches/2.2.5/mindi-busybox/util-linux


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

Update to busybox 1.7.2

Location:
branches/2.2.5/mindi-busybox/util-linux
Files:
6 added
4 deleted
25 edited

Legend:

Unmodified
Added
Removed
  • branches/2.2.5/mindi-busybox/util-linux/Config.in

    r821 r1765  
    66menu "Linux System Utilities"
    77
    8 config CONFIG_DMESG
     8config DMESG
    99    bool "dmesg"
    1010    default n
     
    1818      wish to enable the 'dmesg' utility.
    1919
    20 config CONFIG_FBSET
     20config FEATURE_DMESG_PRETTY
     21    bool "pretty dmesg output"
     22    default y
     23    depends on DMESG
     24    help
     25      If you wish to scrub the syslog level from the output, say 'Y' here.
     26      The syslog level is a string prefixed to every line with the form "<#>".
     27
     28      With this option you will see:
     29        # dmesg
     30        Linux version 2.6.17.4 .....
     31        BIOS-provided physical RAM map:
     32         BIOS-e820: 0000000000000000 - 000000000009f000 (usable)
     33
     34      Without this option you will see:
     35        # dmesg
     36        <5>Linux version 2.6.17.4 .....
     37        <6>BIOS-provided physical RAM map:
     38        <6> BIOS-e820: 0000000000000000 - 000000000009f000 (usable)
     39
     40config FBSET
    2141    bool "fbset"
    2242    default n
     
    2747      if you wish to enable the 'fbset' utility.
    2848
    29 config CONFIG_FEATURE_FBSET_FANCY
     49config FEATURE_FBSET_FANCY
    3050    bool "Turn on extra fbset options"
    3151    default n
    32     depends on CONFIG_FBSET
     52    depends on FBSET
    3353    help
    3454      This option enables extended fbset options, allowing one to set the
     
    3757      options.
    3858
    39 config CONFIG_FEATURE_FBSET_READMODE
     59config FEATURE_FBSET_READMODE
    4060    bool "Turn on fbset readmode support"
    4161    default n
    42     depends on CONFIG_FBSET
     62    depends on FBSET
    4363    help
    4464      This option allows fbset to read the video mode database stored by
     
    4666      device to pre-defined video modes.
    4767
    48 config CONFIG_FDFLUSH
     68config FDFLUSH
    4969    bool "fdflush"
    5070    default n
     
    5878      leave this disabled.
    5979
    60 config CONFIG_FDFORMAT
     80config FDFORMAT
    6181    bool "fdformat"
    6282    default n
     
    6484      fdformat is used to low-level format a floppy disk.
    6585
    66 config CONFIG_FDISK
     86config FDISK
    6787    bool "fdisk"
    6888    default n
     
    7696    bool "support over 4GB disks"
    7797    default y
    78     depends on CONFIG_FDISK
     98    depends on FDISK
    7999    help
    80100      Enable this option to support large disks > 4GB.
    81101
    82 config CONFIG_FEATURE_FDISK_WRITABLE
     102config FEATURE_FDISK_WRITABLE
    83103    bool "Write support"
    84104    default y
    85     depends on CONFIG_FDISK
     105    depends on FDISK
    86106    help
    87107      Enabling this option allows you to create or change a partition table
     
    89109      disabled, you will only be able to view the partition table.
    90110
    91 config CONFIG_FEATURE_AIX_LABEL
     111config FEATURE_AIX_LABEL
    92112    bool "Support AIX disklabels"
    93113    default n
    94     depends on CONFIG_FDISK && CONFIG_FEATURE_FDISK_WRITABLE
     114    depends on FDISK && FEATURE_FDISK_WRITABLE
    95115    help
    96116      Enabling this option allows you to create or change AIX disklabels.
    97117      Most people can safely leave this option disabled.
    98118
    99 config CONFIG_FEATURE_SGI_LABEL
     119config FEATURE_SGI_LABEL
    100120    bool "Support SGI disklabels"
    101121    default n
    102     depends on CONFIG_FDISK && CONFIG_FEATURE_FDISK_WRITABLE
     122    depends on FDISK && FEATURE_FDISK_WRITABLE
    103123    help
    104124      Enabling this option allows you to create or change SGI disklabels.
    105125      Most people can safely leave this option disabled.
    106126
    107 config CONFIG_FEATURE_SUN_LABEL
     127config FEATURE_SUN_LABEL
    108128    bool "Support SUN disklabels"
    109129    default n
    110     depends on CONFIG_FDISK && CONFIG_FEATURE_FDISK_WRITABLE
     130    depends on FDISK && FEATURE_FDISK_WRITABLE
    111131    help
    112132      Enabling this option allows you to create or change SUN disklabels.
    113133      Most people can safely leave this option disabled.
    114134
    115 config CONFIG_FEATURE_OSF_LABEL
     135config FEATURE_OSF_LABEL
    116136    bool "Support BSD disklabels"
    117137    default n
    118     depends on CONFIG_FDISK && CONFIG_FEATURE_FDISK_WRITABLE
     138    depends on FDISK && FEATURE_FDISK_WRITABLE
    119139    help
    120140      Enabling this option allows you to create or change BSD disklabels
    121141      and define and edit BSD disk slices.
    122142
    123 config CONFIG_FEATURE_FDISK_ADVANCED
     143config FEATURE_FDISK_ADVANCED
    124144    bool "Support expert mode"
    125145    default n
    126     depends on CONFIG_FDISK && CONFIG_FEATURE_FDISK_WRITABLE
     146    depends on FDISK && FEATURE_FDISK_WRITABLE
    127147    help
    128148      Enabling this option allows you to do terribly unsafe things like
     
    131151      reason you would be wise to leave this disabled.
    132152
    133 config CONFIG_FREERAMDISK
     153config FREERAMDISK
    134154    bool "freeramdisk"
    135155    default n
     
    142162      this disabled.
    143163
    144 config CONFIG_FSCK_MINIX
     164config FSCK_MINIX
    145165    bool "fsck_minix"
    146166    default n
     
    153173      filesystem.
    154174
    155 config CONFIG_MKFS_MINIX
     175config MKFS_MINIX
    156176    bool "mkfs_minix"
    157177    default n
     
    162182
    163183comment "Minix filesystem support"
    164     depends on CONFIG_FSCK_MINIX || CONFIG_MKFS_MINIX
    165 
    166 config CONFIG_FEATURE_MINIX2
     184    depends on FSCK_MINIX || MKFS_MINIX
     185
     186config FEATURE_MINIX2
    167187    bool "Support Minix fs v2 (fsck_minix/mkfs_minix)"
    168188    default y
    169     depends on CONFIG_FSCK_MINIX || CONFIG_MKFS_MINIX
     189    depends on FSCK_MINIX || MKFS_MINIX
    170190    help
    171191      If you wish to be able to create version 2 minix filesystems, enable this.
     
    173193      version 2 filesystem support.
    174194
    175 config CONFIG_GETOPT
     195config GETOPT
    176196    bool "getopt"
    177197    default n
     
    184204      wisely leave this disabled.
    185205
    186 config CONFIG_HEXDUMP
     206config HEXDUMP
    187207    bool "hexdump"
    188208    default n
     
    191211      way that is comparable to the output from most hex editors.
    192212
    193 config CONFIG_HWCLOCK
     213config HWCLOCK
    194214    bool "hwclock"
    195215    default n
     
    200220      correct time when Linux is _not_ running.
    201221
    202 config CONFIG_FEATURE_HWCLOCK_LONG_OPTIONS
     222config FEATURE_HWCLOCK_LONG_OPTIONS
    203223    bool "Support long options (--hctosys,...)"
    204224    default n
    205     depends on CONFIG_HWCLOCK && CONFIG_GETOPT_LONG
     225    depends on HWCLOCK && GETOPT_LONG
    206226    help
    207227      By default, the hwclock utility only uses short options.  If you
     
    209229      then enable this option.
    210230
    211 config CONFIG_FEATURE_HWCLOCK_ADJTIME_FHS
     231config FEATURE_HWCLOCK_ADJTIME_FHS
    212232    bool "Use FHS /var/lib/hwclock/adjtime"
    213233    default y
    214     depends on CONFIG_HWCLOCK
     234    depends on HWCLOCK
    215235    help
    216236      Starting with FHS 2.3, the adjtime state file is supposed to exist
     
    221241      http://www.pathname.com/fhs/pub/fhs-2.3.html#VARLIBHWCLOCKSTATEDIRECTORYFORHWCLO
    222242
    223 config CONFIG_IPCRM
     243config IPCRM
    224244    bool "ipcrm"
    225245    default n
    226     select CONFIG_FEATURE_SUID
     246    select FEATURE_SUID
    227247    help
    228248      The ipcrm utility allows the removal of System V interprocess
     
    230250      from the system.
    231251
    232 config CONFIG_IPCS
     252config IPCS
    233253    bool "ipcs"
    234254    default n
    235     select CONFIG_FEATURE_SUID
     255    select FEATURE_SUID
    236256    help
    237257      The ipcs utility is used to provide information on the currently
    238258      allocated System V interprocess (IPC) objects in the system.
    239259
    240 config CONFIG_LOSETUP
     260config LOSETUP
    241261    bool "losetup"
    242262    default n
     
    246266      version does not currently support enabling data encryption.
    247267
    248 config CONFIG_MDEV
     268config MDEV
    249269    bool "mdev"
    250270    default n
    251271    help
    252       mdev is a mini-udev implementation: call it with -s to populate
    253       /dev from /sys, then "echo /sbin/mdev > /proc/sys/kernel/hotplug" to
    254       have it handle hotplug events afterwards.  Device names are taken
    255       from sysfs.
    256 
    257 config CONFIG_FEATURE_MDEV_CONF
     272      mdev is a mini-udev implementation for dynamically creating device
     273      nodes in the /dev directory.
     274
     275      For more information, please see docs/mdev.txt
     276
     277config FEATURE_MDEV_CONF
    258278    bool "Support /etc/mdev.conf"
    259279    default n
    260     depends on CONFIG_MDEV
    261     help
    262       The mdev config file contains lines that look like:
    263 
    264         hd[a-z][0-9]* 0:3 660
    265 
    266       That's device name (with regex match), uid:gid, and permissions.
    267 
    268       Config file parsing stops on the first matching line.  If no config
    269       entry is matched, devices are created with default 0:0 660.  (Make
    270       the last line match .* to override this.)
    271 
    272 config CONFIG_FEATURE_MDEV_EXEC
     280    depends on MDEV
     281    help
     282      Add support for the mdev config file to control ownership and
     283      permissions of the device nodes.
     284
     285      For more information, please see docs/mdev.txt
     286
     287config FEATURE_MDEV_EXEC
    273288    bool "Support command execution at device addition/removal"
    274289    default n
    275     depends on CONFIG_FEATURE_MDEV_CONF
    276     help
    277       This adds support for an optional field to /etc/mdev.conf, consisting
    278       of a special character and a command line to run after creating the
    279       corresponding device(s) and before removing, ala:
    280 
    281         hdc root:cdrom 660  *ln -s $MDEV cdrom
    282 
    283       The $MDEV environment variable is set to the name of the device.
    284 
    285       The special characters and their meanings are:
    286         @ Run after creating the device.
    287         $ Run before removing the device.
    288         * Run both after creating and before removing the device.
    289 
    290       Commands are executed via system() so you need /bin/sh, meaning you
    291       probably want to select a default shell in the Shells menu.
    292 
    293 config CONFIG_MKSWAP
     290    depends on FEATURE_MDEV_CONF
     291    help
     292      This adds support for an optional field to /etc/mdev.conf for
     293      executing commands when devices are created/removed.
     294
     295      For more information, please see docs/mdev.txt
     296
     297config FEATURE_MDEV_LOAD_FIRMWARE
     298    bool "Support loading of firmwares"
     299    default n
     300    depends on MDEV
     301    help
     302      Some devices need to load firmware before they can be usable.
     303
     304      These devices will request userspace look up the files in
     305      /lib/firmware/ and if it exists, send it to the kernel for
     306      loading into the hardware.
     307
     308config MKSWAP
    294309    bool "mkswap"
    295310    default n
     
    304319      the swap space using the 'swapon' utility.
    305320
    306 config CONFIG_FEATURE_MKSWAP_V0
     321config FEATURE_MKSWAP_V0
    307322    bool "version 0 support"
    308323    default n
    309     depends on CONFIG_MKSWAP
    310 #   depends on CONFIG_MKSWAP && CONFIG_DEPRECATED
     324    depends on MKSWAP
     325#   depends on MKSWAP && DEPRECATED
    311326    help
    312327      Enable support for the old v0 style.
     
    314329      only option.
    315330
    316 config CONFIG_MORE
     331config MORE
    317332    bool "more"
    318333    default n
     
    324339      any need to reading text files, you can leave this disabled.
    325340
    326 config CONFIG_FEATURE_USE_TERMIOS
     341config FEATURE_USE_TERMIOS
    327342    bool "Use termios to manipulate the screen"
    328343    default y
    329     depends on CONFIG_MORE
     344    depends on MORE
    330345    help
    331346      This option allows utilities such as 'more' and 'top' to determine
     
    335350      unable to move the cursor.
    336351
    337 config CONFIG_MOUNT
     352config MOUNT
    338353    bool "mount"
    339354    default n
     
    346361      the 'mount' utility.
    347362
    348 config CONFIG_FEATURE_MOUNT_NFS
     363config FEATURE_MOUNT_NFS
    349364    bool "Support mounting NFS file systems"
    350365    default n
    351     depends on CONFIG_MOUNT
    352     help
    353      Enable mounting of NFS file systems.
    354 
    355 config CONFIG_PIVOT_ROOT
     366    depends on MOUNT
     367    select FEATURE_HAVE_RPC
     368    select FEATURE_SYSLOG
     369    help
     370      Enable mounting of NFS file systems.
     371
     372config FEATURE_MOUNT_CIFS
     373    bool "Support mounting CIFS/SMB file systems"
     374    default n
     375    depends on MOUNT
     376    help
     377      Enable support for samba mounts.
     378
     379config FEATURE_MOUNT_FLAGS
     380    depends on MOUNT
     381    bool "Support lots of -o flags in mount"
     382    default y
     383    help
     384      Without this, mount only supports ro/rw/remount.  With this, it
     385      supports nosuid, suid, dev, nodev, exec, noexec, sync, async, atime,
     386      noatime, diratime, nodiratime, loud, bind, move, shared, slave,
     387      private, unbindable, rshared, rslave, rprivate, and runbindable.
     388
     389config FEATURE_MOUNT_FSTAB
     390    depends on MOUNT
     391    bool "Support /etc/fstab and -a"
     392    default y
     393    help
     394      Support mount all and looking for files in /etc/fstab.
     395
     396config PIVOT_ROOT
    356397    bool "pivot_root"
    357398    default n
     
    365406      in linux 2.6) use switch_root instead.
    366407
    367 config CONFIG_RDATE
     408config RDATE
    368409    bool "rdate"
    369410    default n
     
    374415      systems.
    375416
    376 config CONFIG_READPROFILE
     417config READPROFILE
    377418    bool "readprofile"
    378419    default n
     
    380421      This allows you to parse /proc/profile for basic profiling.
    381422
    382 config CONFIG_SETARCH
     423config SETARCH
    383424    bool "setarch"
    384425    default n
     
    389430      (like amd64/x86, ppc64/ppc, sparc64/sparc, etc...).
    390431
    391 config CONFIG_SWAPONOFF
     432config SWAPONOFF
    392433    bool "swaponoff"
    393434    default n
     
    400441      option disabled.
    401442
    402 config CONFIG_SWITCH_ROOT
     443config SWITCH_ROOT
    403444    bool "switch_root"
    404445    default n
     
    419460      list of active mount points.  That's why.
    420461
    421 config CONFIG_UMOUNT
     462config UMOUNT
    422463    bool "umount"
    423464    default n
     
    428469      also want to enable 'umount'.
    429470
    430 config CONFIG_FEATURE_UMOUNT_ALL
     471config FEATURE_UMOUNT_ALL
    431472    bool "umount -a option"
    432473    default n
    433     depends on CONFIG_UMOUNT
     474    depends on UMOUNT
    434475    help
    435476      Support -a option to unmount all currently mounted filesystems.
    436477
    437478comment "Common options for mount/umount"
    438     depends on CONFIG_MOUNT || CONFIG_UMOUNT
    439 
    440 config CONFIG_FEATURE_MOUNT_LOOP
     479    depends on MOUNT || UMOUNT
     480
     481config FEATURE_MOUNT_LOOP
    441482    bool "Support loopback mounts"
    442483    default n
    443     depends on CONFIG_MOUNT || CONFIG_UMOUNT
     484    depends on MOUNT || UMOUNT
    444485    help
    445486      Enabling this feature allows automatic mounting of files (containing
     
    450491
    451492      You can still use the 'losetup' utility (to manually associate files
    452           with loop devices) if you need to do something advanced, such as
     493      with loop devices) if you need to do something advanced, such as
    453494      specify an offset or cryptographic options to the loopback device.
    454495      (If you don't want umount to free the loop device, use "umount -D".)
    455496
    456 config CONFIG_FEATURE_MTAB_SUPPORT
     497config FEATURE_MTAB_SUPPORT
    457498    bool "Support for the old /etc/mtab file"
    458499    default n
    459     depends on CONFIG_MOUNT || CONFIG_UMOUNT
     500    depends on MOUNT || UMOUNT
    460501    help
    461502      Historically, Unix systems kept track of the currently mounted
  • branches/2.2.5/mindi-busybox/util-linux/dmesg.c

    r821 r1765  
    1 /* vi: set ts=4:
    2  *
     1/* vi: set sw=4 ts=4: */
     2/*
     3 *
    34 * dmesg - display/control kernel ring buffer.
    45 *
    5  * Copyring 2006 Rob Landley <rob@landley.net>
     6 * Copyright 2006 Rob Landley <rob@landley.net>
     7 * Copyright 2006 Bernhard Fischer <rep.nop@aon.at>
    68 *
    7  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     9 * Licensed under GPLv2, see file LICENSE in this tarball for details.
    810 */
    911
    10 #include "busybox.h"
    11 #include <unistd.h>
    1212#include <sys/klog.h>
     13#include "libbb.h"
    1314
    14 int dmesg_main(int argc, char *argv[])
     15int dmesg_main(int argc, char **argv);
     16int dmesg_main(int argc, char **argv)
    1517{
    1618    char *size, *level;
    17     int flags = bb_getopt_ulflags(argc, argv, "cs:n:", &size, &level);
     19    int flags = getopt32(argv, "cs:n:", &size, &level);
    1820
    1921    if (flags & 4) {
    20         if(klogctl(8, NULL, bb_xgetlarg(level, 10, 0, 10)))
     22        if (klogctl(8, NULL, xatoul_range(level, 0, 10)))
    2123            bb_perror_msg_and_die("klogctl");
    2224    } else {
     
    2426        char *buf;
    2527
    26         len = (flags & 2) ? bb_xgetlarg(size, 10, 2, INT_MAX) : 16384;
     28        len = (flags & 2) ? xatoul_range(size, 2, INT_MAX) : 16384;
    2729        buf = xmalloc(len);
    2830        if (0 > (len = klogctl(3 + (flags & 1), buf, len)))
    2931            bb_perror_msg_and_die("klogctl");
    30         write(1,buf,len);
    31         if (len && buf[len-1]!='\n') putchar('\n');
     32
     33        // Skip <#> at the start of lines, and make sure we end with a newline.
     34
     35        if (ENABLE_FEATURE_DMESG_PRETTY) {
     36            int last = '\n';
     37            int in;
     38
     39            for (in = 0; in<len;) {
     40                if (last == '\n' && buf[in] == '<') in += 3;
     41                else putchar(last = buf[in++]);
     42            }
     43            if (last != '\n') putchar('\n');
     44        } else {
     45            write(1,buf,len);
     46            if (len && buf[len-1]!='\n') putchar('\n');
     47        }
     48
     49        if (ENABLE_FEATURE_CLEAN_UP) free(buf);
    3250    }
    3351
  • branches/2.2.5/mindi-busybox/util-linux/fbset.c

    r821 r1765  
    1313 */
    1414
    15 #include <stdio.h>
    16 #include <stdlib.h>
    17 #include <unistd.h>
    18 #include <fcntl.h>
    19 #include <errno.h>
    20 #include <ctype.h>
    21 #include <string.h>
    22 #include <stdint.h>
    23 #include <sys/ioctl.h>
    24 #include "busybox.h"
     15#include "libbb.h"
    2516
    2617#define DEFAULTFBDEV  FB_0
     
    3122    OPT_INFO     = (1 << 1),
    3223    OPT_READMODE = (1 << 2),
     24    OPT_ALL      = (1 << 9),
    3325
    3426    CMD_FB = 1,
     
    4638    CMD_CHANGE = 13,
    4739
    48 #ifdef CONFIG_FEATURE_FBSET_FANCY
     40#if ENABLE_FEATURE_FBSET_FANCY
    4941    CMD_XRES = 100,
    5042    CMD_YRES = 101,
     
    7062};
    7163
    72 static unsigned int g_options = 0;
     64static unsigned g_options;
    7365
    7466/* Stuff stolen from the kernel's fb.h */
     67#define FB_ACTIVATE_ALL 64
    7568enum {
    7669    FBIOGET_VSCREENINFO = 0x4600,
     
    7871};
    7972struct fb_bitfield {
    80     uint32_t offset;            /* beginning of bitfield    */
    81     uint32_t length;            /* length of bitfield       */
    82     uint32_t msb_right;     /* != 0 : Most significant bit is */
    83                     /* right */
     73    uint32_t offset;                /* beginning of bitfield */
     74    uint32_t length;        /* length of bitfield */
     75    uint32_t msb_right;             /* !=0: Most significant bit is right */
    8476};
    8577struct fb_var_screeninfo {
    86     uint32_t xres;          /* visible resolution       */
     78    uint32_t xres;                  /* visible resolution */
    8779    uint32_t yres;
    88     uint32_t xres_virtual;      /* virtual resolution       */
     80    uint32_t xres_virtual;          /* virtual resolution */
    8981    uint32_t yres_virtual;
    90     uint32_t xoffset;           /* offset from virtual to visible */
    91     uint32_t yoffset;           /* resolution           */
    92 
    93     uint32_t bits_per_pixel;        /* guess what           */
    94     uint32_t grayscale;     /* != 0 Graylevels instead of colors */
    95 
    96     struct fb_bitfield red;     /* bitfield in fb mem if true color, */
    97     struct fb_bitfield green;   /* else only length is significant */
     82    uint32_t xoffset;               /* offset from virtual to visible */
     83    uint32_t yoffset;               /* resolution */
     84
     85    uint32_t bits_per_pixel;
     86    uint32_t grayscale;             /* !=0 Graylevels instead of colors */
     87
     88    struct fb_bitfield red;         /* bitfield in fb mem if true color, */
     89    struct fb_bitfield green;       /* else only length is significant */
    9890    struct fb_bitfield blue;
    99     struct fb_bitfield transp;  /* transparency         */
    100 
    101     uint32_t nonstd;            /* != 0 Non standard pixel format */
    102 
    103     uint32_t activate;          /* see FB_ACTIVATE_*        */
    104 
    105     uint32_t height;            /* height of picture in mm    */
    106     uint32_t width;         /* width of picture in mm    */
     91    struct fb_bitfield transp;      /* transparency */
     92
     93    uint32_t nonstd;                /* !=0 Non standard pixel format */
     94
     95    uint32_t activate;              /* see FB_ACTIVATE_x */
     96
     97    uint32_t height;                /* height of picture in mm */
     98    uint32_t width;                 /* width of picture in mm */
    10799
    108100    uint32_t accel_flags;       /* acceleration flags (hints)   */
    109101
    110102    /* Timing: All values in pixclocks, except pixclock (of course) */
    111     uint32_t pixclock;          /* pixel clock in ps (pico seconds) */
    112     uint32_t left_margin;       /* time from sync to picture    */
    113     uint32_t right_margin;      /* time from picture to sync    */
    114     uint32_t upper_margin;      /* time from sync to picture    */
     103    uint32_t pixclock;              /* pixel clock in ps (pico seconds) */
     104    uint32_t left_margin;           /* time from sync to picture */
     105    uint32_t right_margin;          /* time from picture to sync */
     106    uint32_t upper_margin;          /* time from sync to picture */
    115107    uint32_t lower_margin;
    116     uint32_t hsync_len;     /* length of horizontal sync    */
    117     uint32_t vsync_len;     /* length of vertical sync  */
    118     uint32_t sync;          /* see FB_SYNC_*        */
    119     uint32_t vmode;         /* see FB_VMODE_*       */
    120     uint32_t reserved[6];       /* Reserved for future compatibility */
     108    uint32_t hsync_len;             /* length of horizontal sync */
     109    uint32_t vsync_len;             /* length of vertical sync */
     110    uint32_t sync;                  /* see FB_SYNC_x */
     111    uint32_t vmode;                 /* see FB_VMODE_x */
     112    uint32_t reserved[6];           /* Reserved for future compatibility */
    121113};
    122114
    123115
    124116static const struct cmdoptions_t {
    125     const char *name;
     117    const char name[10];
    126118    const unsigned char param_count;
    127119    const unsigned char code;
    128120} g_cmdoptions[] = {
    129     {
    130     "-fb", 1, CMD_FB}, {
    131     "-db", 1, CMD_DB}, {
    132     "-a", 0, CMD_ALL}, {
    133     "-i", 0, CMD_INFO}, {
    134     "-g", 5, CMD_GEOMETRY}, {
    135     "-t", 7, CMD_TIMING}, {
    136     "-accel", 1, CMD_ACCEL}, {
    137     "-hsync", 1, CMD_HSYNC}, {
    138     "-vsync", 1, CMD_VSYNC}, {
    139     "-laced", 1, CMD_LACED}, {
    140     "-double", 1, CMD_DOUBLE}, {
    141     "-n", 0, CMD_CHANGE}, {
    142 #ifdef CONFIG_FEATURE_FBSET_FANCY
    143     "-all", 0, CMD_ALL}, {
    144     "-xres", 1, CMD_XRES}, {
    145     "-yres", 1, CMD_YRES}, {
    146     "-vxres", 1, CMD_VXRES}, {
    147     "-vyres", 1, CMD_VYRES}, {
    148     "-depth", 1, CMD_DEPTH}, {
    149     "-match", 0, CMD_MATCH}, {
    150     "-geometry", 5, CMD_GEOMETRY}, {
    151     "-pixclock", 1, CMD_PIXCLOCK}, {
    152     "-left", 1, CMD_LEFT}, {
    153     "-right", 1, CMD_RIGHT}, {
    154     "-upper", 1, CMD_UPPER}, {
    155     "-lower", 1, CMD_LOWER}, {
    156     "-hslen", 1, CMD_HSLEN}, {
    157     "-vslen", 1, CMD_VSLEN}, {
    158     "-timings", 7, CMD_TIMING}, {
    159     "-csync", 1, CMD_CSYNC}, {
    160     "-gsync", 1, CMD_GSYNC}, {
    161     "-extsync", 1, CMD_EXTSYNC}, {
    162     "-bcast", 1, CMD_BCAST}, {
    163     "-rgba", 1, CMD_RGBA}, {
    164     "-step", 1, CMD_STEP}, {
    165     "-move", 1, CMD_MOVE}, {
    166 #endif
    167     0, 0, 0}
    168 };
    169 
    170 #ifdef CONFIG_FEATURE_FBSET_READMODE
     121    { "-fb", 1, CMD_FB },
     122    { "-db", 1, CMD_DB },
     123    { "-a", 0, CMD_ALL },
     124    { "-i", 0, CMD_INFO },
     125    { "-g", 5, CMD_GEOMETRY },
     126    { "-t", 7, CMD_TIMING },
     127    { "-accel", 1, CMD_ACCEL },
     128    { "-hsync", 1, CMD_HSYNC },
     129    { "-vsync", 1, CMD_VSYNC },
     130    { "-laced", 1, CMD_LACED },
     131    { "-double", 1, CMD_DOUBLE },
     132    { "-n", 0, CMD_CHANGE },
     133#if ENABLE_FEATURE_FBSET_FANCY
     134    { "-all", 0, CMD_ALL },
     135    { "-xres", 1, CMD_XRES },
     136    { "-yres", 1, CMD_YRES },
     137    { "-vxres", 1, CMD_VXRES },
     138    { "-vyres", 1, CMD_VYRES },
     139    { "-depth", 1, CMD_DEPTH },
     140    { "-match", 0, CMD_MATCH },
     141    { "-geometry", 5, CMD_GEOMETRY },
     142    { "-pixclock", 1, CMD_PIXCLOCK },
     143    { "-left", 1, CMD_LEFT },
     144    { "-right", 1, CMD_RIGHT },
     145    { "-upper", 1, CMD_UPPER },
     146    { "-lower", 1, CMD_LOWER },
     147    { "-hslen", 1, CMD_HSLEN },
     148    { "-vslen", 1, CMD_VSLEN },
     149    { "-timings", 7, CMD_TIMING },
     150    { "-csync", 1, CMD_CSYNC },
     151    { "-gsync", 1, CMD_GSYNC },
     152    { "-extsync", 1, CMD_EXTSYNC },
     153    { "-bcast", 1, CMD_BCAST },
     154    { "-rgba", 1, CMD_RGBA },
     155    { "-step", 1, CMD_STEP },
     156    { "-move", 1, CMD_MOVE },
     157#endif
     158    { "", 0, 0 }
     159};
     160
     161#if ENABLE_FEATURE_FBSET_READMODE
    171162/* taken from linux/fb.h */
    172163enum {
     
    179170};
    180171#endif
     172
    181173static int readmode(struct fb_var_screeninfo *base, const char *fn,
    182174                    const char *mode)
    183175{
    184 #ifdef CONFIG_FEATURE_FBSET_READMODE
     176#if ENABLE_FEATURE_FBSET_READMODE
    185177    FILE *f;
    186178    char buf[256];
    187179    char *p = buf;
    188180
    189     f = bb_xfopen(fn, "r");
     181    f = xfopen(fn, "r");
    190182    while (!feof(f)) {
    191183        fgets(buf, sizeof(buf), f);
    192         if ((p = strstr(buf, "mode ")) || (p = strstr(buf, "mode\t"))) {
    193             p += 5;
    194             if ((p = strstr(buf, mode))) {
    195                 p += strlen(mode);
    196                 if (!isspace(*p) && (*p != 0) && (*p != '"')
    197                     && (*p != '\r') && (*p != '\n'))
    198                     continue;   /* almost, but not quite */
    199                 while (!feof(f)) {
    200                     fgets(buf, sizeof(buf), f);
    201 
    202             if ((p = strstr(buf, "geometry "))) {
    203             p += 9;
    204 
    205             sscanf(p, "%d %d %d %d %d",
    206                 &(base->xres), &(base->yres),
    207                 &(base->xres_virtual), &(base->yres_virtual),
    208                 &(base->bits_per_pixel));
    209             } else if ((p = strstr(buf, "timings "))) {
    210             p += 8;
    211 
    212             sscanf(p, "%d %d %d %d %d %d %d",
    213                 &(base->pixclock),
    214                 &(base->left_margin), &(base->right_margin),
    215                 &(base->upper_margin), &(base->lower_margin),
    216                 &(base->hsync_len), &(base->vsync_len));
    217             } else if ((p = strstr(buf, "laced "))) {
    218             p += 6;
    219 
    220             if (strstr(buf, "false")) {
    221                 base->vmode &= ~FB_VMODE_INTERLACED;
    222             } else {
    223                 base->vmode |= FB_VMODE_INTERLACED;
     184        if (!(p = strstr(buf, "mode ")) && !(p = strstr(buf, "mode\t")))
     185            continue;
     186        p += 5;
     187        if (!(p = strstr(buf, mode)))
     188            continue;
     189        p += strlen(mode);
     190        if (!isspace(*p) && (*p != 0) && (*p != '"')
     191                && (*p != '\r') && (*p != '\n'))
     192            continue;   /* almost, but not quite */
     193
     194        while (!feof(f)) {
     195            fgets(buf, sizeof(buf), f);
     196            if ((p = strstr(buf, "geometry "))) {
     197                p += 9;
     198                /* FIXME: catastrophic on arches with 64bit ints */
     199                sscanf(p, "%d %d %d %d %d",
     200                    &(base->xres), &(base->yres),
     201                    &(base->xres_virtual), &(base->yres_virtual),
     202                    &(base->bits_per_pixel));
     203            } else if ((p = strstr(buf, "timings "))) {
     204                p += 8;
     205                sscanf(p, "%d %d %d %d %d %d %d",
     206                    &(base->pixclock),
     207                    &(base->left_margin), &(base->right_margin),
     208                    &(base->upper_margin), &(base->lower_margin),
     209                    &(base->hsync_len), &(base->vsync_len));
     210            } else if ((p = strstr(buf, "laced "))) {
     211                //p += 6;
     212                if (strstr(buf, "false")) {
     213                    base->vmode &= ~FB_VMODE_INTERLACED;
     214                } else {
     215                    base->vmode |= FB_VMODE_INTERLACED;
     216                }
     217            } else if ((p = strstr(buf, "double "))) {
     218                //p += 7;
     219                if (strstr(buf, "false")) {
     220                    base->vmode &= ~FB_VMODE_DOUBLE;
     221                } else {
     222                    base->vmode |= FB_VMODE_DOUBLE;
     223                }
     224            } else if ((p = strstr(buf, "vsync "))) {
     225                //p += 6;
     226                if (strstr(buf, "low")) {
     227                    base->sync &= ~FB_SYNC_VERT_HIGH_ACT;
     228                } else {
     229                    base->sync |= FB_SYNC_VERT_HIGH_ACT;
     230                }
     231            } else if ((p = strstr(buf, "hsync "))) {
     232                //p += 6;
     233                if (strstr(buf, "low")) {
     234                    base->sync &= ~FB_SYNC_HOR_HIGH_ACT;
     235                } else {
     236                    base->sync |= FB_SYNC_HOR_HIGH_ACT;
     237                }
     238            } else if ((p = strstr(buf, "csync "))) {
     239                //p += 6;
     240                if (strstr(buf, "low")) {
     241                    base->sync &= ~FB_SYNC_COMP_HIGH_ACT;
     242                } else {
     243                    base->sync |= FB_SYNC_COMP_HIGH_ACT;
     244                }
     245            } else if ((p = strstr(buf, "extsync "))) {
     246                //p += 8;
     247                if (strstr(buf, "false")) {
     248                    base->sync &= ~FB_SYNC_EXT;
     249                } else {
     250                    base->sync |= FB_SYNC_EXT;
     251                }
    224252            }
    225             } else if ((p = strstr(buf, "double "))) {
    226             p += 7;
    227 
    228             if (strstr(buf, "false")) {
    229                 base->vmode &= ~FB_VMODE_DOUBLE;
    230             } else {
    231                 base->vmode |= FB_VMODE_DOUBLE;
    232             }
    233             } else if ((p = strstr(buf, "vsync "))) {
    234             p += 6;
    235 
    236             if (strstr(buf, "low")) {
    237                 base->sync &= ~FB_SYNC_VERT_HIGH_ACT;
    238             } else {
    239                 base->sync |= FB_SYNC_VERT_HIGH_ACT;
    240             }
    241             } else if ((p = strstr(buf, "hsync "))) {
    242             p += 6;
    243 
    244             if (strstr(buf, "low")) {
    245                 base->sync &= ~FB_SYNC_HOR_HIGH_ACT;
    246             } else {
    247                 base->sync |= FB_SYNC_HOR_HIGH_ACT;
    248             }
    249             } else if ((p = strstr(buf, "csync "))) {
    250             p += 6;
    251 
    252             if (strstr(buf, "low")) {
    253                 base->sync &= ~FB_SYNC_COMP_HIGH_ACT;
    254             } else {
    255                 base->sync |= FB_SYNC_COMP_HIGH_ACT;
    256             }
    257             } else if ((p = strstr(buf, "extsync "))) {
    258             p += 8;
    259 
    260             if (strstr(buf, "false")) {
    261                 base->sync &= ~FB_SYNC_EXT;
    262             } else {
    263                 base->sync |= FB_SYNC_EXT;
    264             }
    265             }
    266 
    267                     if (strstr(buf, "endmode"))
    268                         return 1;
    269                 }
    270             }
     253
     254            if (strstr(buf, "endmode"))
     255                return 1;
    271256        }
    272257    }
    273258#else
    274     bb_error_msg( "mode reading not compiled in");
     259    bb_error_msg("mode reading not compiled in");
    275260#endif
    276261    return 0;
     
    298283    if (v->pixclock) {
    299284        drate = 1e12 / v->pixclock;
    300         hrate =
    301             drate / (v->left_margin + v->xres + v->right_margin +
    302                      v->hsync_len);
    303         vrate =
    304             hrate / (v->upper_margin + v->yres + v->lower_margin +
    305                      v->vsync_len);
     285        hrate = drate / (v->left_margin + v->xres + v->right_margin + v->hsync_len);
     286        vrate = hrate / (v->upper_margin + v->yres + v->lower_margin + v->vsync_len);
    306287    }
    307288    printf("\nmode \"%ux%u-%u\"\n"
    308 #ifdef CONFIG_FEATURE_FBSET_FANCY
     289#if ENABLE_FEATURE_FBSET_FANCY
    309290    "\t# D: %.3f MHz, H: %.3f kHz, V: %.3f Hz\n"
    310291#endif
    311     "\tgeometry %u %u %u %u %u\n\ttimings %u %u %u %u %u %u %u\n\taccel %s\n\trgba %u/%u,%u/%u,%u/%u,%u/%u\nendmode\n\n",
    312            v->xres, v->yres, (int) (vrate + 0.5),
    313 #ifdef CONFIG_FEATURE_FBSET_FANCY
    314            drate / 1e6, hrate / 1e3, vrate,
    315 #endif
    316            v->xres, v->yres, v->xres_virtual, v->yres_virtual,
    317            v->bits_per_pixel, v->pixclock, v->left_margin,
    318            v->right_margin, v->upper_margin, v->lower_margin, v->hsync_len,
    319            v->vsync_len, (v->accel_flags > 0 ? "true" : "false"), v->red.length,
    320            v->red.offset, v->green.length, v->green.offset, v->blue.length,
    321            v->blue.offset, v->transp.length, v->transp.offset);
     292    "\tgeometry %u %u %u %u %u\n"
     293    "\ttimings %u %u %u %u %u %u %u\n"
     294    "\taccel %s\n"
     295    "\trgba %u/%u,%u/%u,%u/%u,%u/%u\n"
     296    "endmode\n\n",
     297        v->xres, v->yres, (int) (vrate + 0.5),
     298#if ENABLE_FEATURE_FBSET_FANCY
     299        drate / 1e6, hrate / 1e3, vrate,
     300#endif
     301        v->xres, v->yres, v->xres_virtual, v->yres_virtual, v->bits_per_pixel,
     302        v->pixclock, v->left_margin, v->right_margin, v->upper_margin, v->lower_margin,
     303            v->hsync_len, v->vsync_len,
     304        (v->accel_flags > 0 ? "true" : "false"),
     305        v->red.length, v->red.offset, v->green.length, v->green.offset,
     306            v->blue.length, v->blue.offset, v->transp.length, v->transp.offset);
    322307}
    323308
     
    325310int main(int argc, char **argv)
    326311#else
     312int fbset_main(int argc, char **argv);
    327313int fbset_main(int argc, char **argv)
    328314#endif
     
    330316    struct fb_var_screeninfo var, varset;
    331317    int fh, i;
    332     char *fbdev = DEFAULTFBDEV;
    333     char *modefile = DEFAULTFBMODE;
     318    const char *fbdev = DEFAULTFBDEV;
     319    const char *modefile = DEFAULTFBMODE;
    334320    char *thisarg, *mode = NULL;
    335321
     
    340326    argc--;
    341327    for (; argc > 0 && (thisarg = *argv); argc--, argv++) {
    342         for (i = 0; g_cmdoptions[i].name; i++) {
    343             if (!strcmp(thisarg, g_cmdoptions[i].name)) {
    344                 if (argc - 1 < g_cmdoptions[i].param_count)
    345                     bb_show_usage();
    346                 switch (g_cmdoptions[i].code) {
    347                 case CMD_FB:
    348                     fbdev = argv[1];
    349                     break;
    350                 case CMD_DB:
    351                     modefile = argv[1];
    352                     break;
    353                 case CMD_GEOMETRY:
    354                     varset.xres = strtoul(argv[1], 0, 0);
    355                     varset.yres = strtoul(argv[2], 0, 0);
    356                     varset.xres_virtual = strtoul(argv[3], 0, 0);
    357                     varset.yres_virtual = strtoul(argv[4], 0, 0);
    358                     varset.bits_per_pixel = strtoul(argv[5], 0, 0);
    359                     break;
    360                 case CMD_TIMING:
    361                     varset.pixclock = strtoul(argv[1], 0, 0);
    362                     varset.left_margin = strtoul(argv[2], 0, 0);
    363                     varset.right_margin = strtoul(argv[3], 0, 0);
    364                     varset.upper_margin = strtoul(argv[4], 0, 0);
    365                     varset.lower_margin = strtoul(argv[5], 0, 0);
    366                     varset.hsync_len = strtoul(argv[6], 0, 0);
    367                     varset.vsync_len = strtoul(argv[7], 0, 0);
    368                     break;
    369         case CMD_CHANGE:
    370             g_options |= OPT_CHANGE;
    371             break;
    372 #ifdef CONFIG_FEATURE_FBSET_FANCY
    373                 case CMD_XRES:
    374                     varset.xres = strtoul(argv[1], 0, 0);
    375                     break;
    376                 case CMD_YRES:
    377                     varset.yres = strtoul(argv[1], 0, 0);
    378                     break;
    379                case CMD_DEPTH:
    380                     varset.bits_per_pixel = strtoul(argv[1], 0, 0);
    381                     break;
    382 #endif
    383                 }
    384                 argc -= g_cmdoptions[i].param_count;
    385                 argv += g_cmdoptions[i].param_count;
    386                 break;
     328        for (i = 0; g_cmdoptions[i].name[0]; i++) {
     329            if (strcmp(thisarg, g_cmdoptions[i].name))
     330                continue;
     331            if (argc-1 < g_cmdoptions[i].param_count)
     332                bb_show_usage();
     333
     334            switch (g_cmdoptions[i].code) {
     335            case CMD_FB:
     336                fbdev = argv[1];
     337                break;
     338            case CMD_DB:
     339                modefile = argv[1];
     340                break;
     341            case CMD_GEOMETRY:
     342                varset.xres = xatou32(argv[1]);
     343                varset.yres = xatou32(argv[2]);
     344                varset.xres_virtual = xatou32(argv[3]);
     345                varset.yres_virtual = xatou32(argv[4]);
     346                varset.bits_per_pixel = xatou32(argv[5]);
     347                break;
     348            case CMD_TIMING:
     349                varset.pixclock = xatou32(argv[1]);
     350                varset.left_margin = xatou32(argv[2]);
     351                varset.right_margin = xatou32(argv[3]);
     352                varset.upper_margin = xatou32(argv[4]);
     353                varset.lower_margin = xatou32(argv[5]);
     354                varset.hsync_len = xatou32(argv[6]);
     355                varset.vsync_len = xatou32(argv[7]);
     356                break;
     357            case CMD_ALL:
     358                g_options |= OPT_ALL;
     359                break;
     360            case CMD_CHANGE:
     361                g_options |= OPT_CHANGE;
     362                break;
     363#if ENABLE_FEATURE_FBSET_FANCY
     364            case CMD_XRES:
     365                varset.xres = xatou32(argv[1]);
     366                break;
     367            case CMD_YRES:
     368                varset.yres = xatou32(argv[1]);
     369                break;
     370            case CMD_DEPTH:
     371                varset.bits_per_pixel = xatou32(argv[1]);
     372                break;
     373#endif
    387374            }
     375            argc -= g_cmdoptions[i].param_count;
     376            argv += g_cmdoptions[i].param_count;
     377            break;
    388378        }
    389         if (!g_cmdoptions[i].name) {
    390             if (argc == 1) {
    391                 mode = *argv;
    392                 g_options |= OPT_READMODE;
    393             } else {
     379        if (!g_cmdoptions[i].name[0]) {
     380            if (argc != 1)
    394381                bb_show_usage();
    395             }
     382            mode = *argv;
     383            g_options |= OPT_READMODE;
    396384        }
    397385    }
    398386
    399     fh = bb_xopen(fbdev, O_RDONLY);
    400     if (ioctl(fh, FBIOGET_VSCREENINFO, &var))
    401         bb_perror_msg_and_die("fbset(ioctl)");
     387    fh = xopen(fbdev, O_RDONLY);
     388    xioctl(fh, FBIOGET_VSCREENINFO, &var);
    402389    if (g_options & OPT_READMODE) {
    403390        if (!readmode(&var, modefile, mode)) {
    404             bb_error_msg("Unknown video mode `%s'", mode);
    405             return EXIT_FAILURE;
     391            bb_error_msg_and_die("unknown video mode '%s'", mode);
    406392        }
    407393    }
    408394
    409395    setmode(&var, &varset);
    410     if (g_options & OPT_CHANGE)
    411         if (ioctl(fh, FBIOPUT_VSCREENINFO, &var))
    412             bb_perror_msg_and_die("fbset(ioctl)");
     396    if (g_options & OPT_CHANGE) {
     397        if (g_options & OPT_ALL)
     398            var.activate = FB_ACTIVATE_ALL;
     399        xioctl(fh, FBIOPUT_VSCREENINFO, &var);
     400    }
    413401    showmode(&var);
    414402    /* Don't close the file, as exiting will take care of that */
  • branches/2.2.5/mindi-busybox/util-linux/fdformat.c

    r821 r1765  
     1/* vi: set sw=4 ts=4: */
    12/* fdformat.c  -  Low-level formats a floppy disk - Werner Almesberger */
    23
     
    910 */
    1011
    11 #include <stdio.h>
    12 #include <string.h>
    13 #include <fcntl.h>
    14 #include <errno.h>
    15 #include <unistd.h>
    16 #include <stdlib.h>
    17 #include <sys/stat.h>
    18 #include <sys/ioctl.h>
    19 #include "busybox.h"
     12#include "libbb.h"
    2013
    2114
     
    5346#define FD_FILL_BYTE 0xF6 /* format fill byte. */
    5447
    55 static void print_and_flush(const char * __restrict format, ...)
    56 {
    57     va_list arg;
    58 
    59     va_start(arg, format);
    60     bb_vfprintf(stdout, format, arg);
    61     va_end(arg);
    62     bb_xfflush_stdout();
    63 }
    64 
    65 static void bb_xioctl(int fd, int request, void *argp, const char *string)
    66 {
    67     if (ioctl (fd, request, argp) < 0) {
    68         bb_perror_msg_and_die(string);
    69     }
    70 }
    71 
     48int fdformat_main(int argc,char **argv);
    7249int fdformat_main(int argc,char **argv)
    7350{
     
    8158        bb_show_usage();
    8259    }
    83     verify = !bb_getopt_ulflags(argc, argv, "n");
     60    verify = !getopt32(argv, "n");
    8461    argv += optind;
    8562
    86     /* R_OK is needed for verifying */
    87     if (stat(*argv,&st) < 0 || access(*argv,W_OK | R_OK ) < 0) {
    88         bb_perror_msg_and_die("%s",*argv);
    89     }
     63    xstat(*argv, &st);
    9064    if (!S_ISBLK(st.st_mode)) {
    91         bb_error_msg_and_die("%s: not a block device",*argv);
     65        bb_error_msg_and_die("%s: not a block device", *argv);
    9266        /* do not test major - perhaps this was an USB floppy */
    9367    }
    9468
     69    /* O_RDWR for formatting and verifying */
     70    fd = xopen(*argv, O_RDWR);
    9571
    96     /* O_RDWR for formatting and verifying */
    97     fd = bb_xopen(*argv,O_RDWR );
     72    /* original message was: "Could not determine current format type" */
     73    xioctl(fd, FDGETPRM, &param);
    9874
    99     bb_xioctl(fd, FDGETPRM, &param, "FDGETPRM");/*original message was: "Could not determine current format type" */
    100 
    101     print_and_flush("%s-sided, %d tracks, %d sec/track. Total capacity %d kB.\n",
     75    printf("%s-sided, %d tracks, %d sec/track. Total capacity %d kB\n",
    10276        (param.head == 2) ? "Double" : "Single",
    10377        param.track, param.sect, param.size >> 1);
    10478
    10579    /* FORMAT */
    106     print_and_flush("Formatting ... ", NULL);
    107     bb_xioctl(fd, FDFMTBEG,NULL,"FDFMTBEG");
     80    printf("Formatting... ");
     81    xioctl(fd, FDFMTBEG, NULL);
    10882
    10983    /* n == track */
    110     for (n = 0; n < param.track; n++)
    111     {
    112         descr.head = 0;
    113         descr.track = n;
    114         bb_xioctl(fd, FDFMTTRK,&descr,"FDFMTTRK");
    115         print_and_flush("%3d\b\b\b", n);
    116         if (param.head == 2) {
    117         descr.head = 1;
    118         bb_xioctl(fd, FDFMTTRK,&descr,"FDFMTTRK");
    119         }
     84    for (n = 0; n < param.track; n++) {
     85        descr.head = 0;
     86        descr.track = n;
     87        xioctl(fd, FDFMTTRK, &descr);
     88        printf("%3d\b\b\b", n);
     89        if (param.head == 2) {
     90            descr.head = 1;
     91            xioctl(fd, FDFMTTRK, &descr);
     92        }
    12093    }
    12194
    122     bb_xioctl(fd,FDFMTEND,NULL,"FDFMTEND");
    123     print_and_flush("done\n", NULL);
     95    xioctl(fd, FDFMTEND, NULL);
     96    printf("done\n");
    12497
    12598    /* VERIFY */
    126     if(verify) {
     99    if (verify) {
    127100        /* n == cyl_size */
    128101        n = param.sect*param.head*512;
    129102
    130103        data = xmalloc(n);
    131         print_and_flush("Verifying ... ", NULL);
     104        printf("Verifying... ");
    132105        for (cyl = 0; cyl < param.track; cyl++) {
    133             print_and_flush("%3d\b\b\b", cyl);
    134             if((read_bytes = safe_read(fd,data,n))!= n ) {
    135                 if(read_bytes < 0) {
     106            printf("%3d\b\b\b", cyl);
     107            read_bytes = safe_read(fd, data, n);
     108            if (read_bytes != n) {
     109                if (read_bytes < 0) {
    136110                    bb_perror_msg(bb_msg_read_error);
    137111                }
    138                 bb_error_msg_and_die("Problem reading cylinder %d, expected %d, read %d", cyl, n, read_bytes);
     112                bb_error_msg_and_die("problem reading cylinder %d, "
     113                    "expected %d, read %d", cyl, n, read_bytes);
     114                // FIXME: maybe better seek & continue??
    139115            }
    140116            /* Check backwards so we don't need a counter */
    141             while(--read_bytes>=0) {
    142                 if( data[read_bytes] != FD_FILL_BYTE) {
    143                      print_and_flush("bad data in cyl %d\nContinuing ... ",cyl);
     117            while (--read_bytes >= 0) {
     118                if (data[read_bytes] != FD_FILL_BYTE) {
     119                     printf("bad data in cyl %d\nContinuing... ",cyl);
    144120                }
    145121            }
     
    151127        if (ENABLE_FEATURE_CLEAN_UP) free(data);
    152128
    153         print_and_flush("done\n", NULL);
     129        printf("done\n");
    154130    }
    155131
  • 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}
  • branches/2.2.5/mindi-busybox/util-linux/freeramdisk.c

    r821 r1765  
    77 * Unified with fdflush by Tito Ragusa <farmatito@tiscali.it>
    88 *
    9  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     9 * Licensed under GPLv2, see file LICENSE in this tarball for details.
    1010 */
    1111
    12 #include <stdio.h>
    13 #include <string.h>
    14 #include <sys/types.h>
    15 #include <fcntl.h>
    16 #include <sys/ioctl.h>
    17 #include <stdlib.h>
    18 #include <unistd.h>
    19 #include "busybox.h"
     12#include "libbb.h"
    2013
    2114/* From <linux/fd.h> */
    2215#define FDFLUSH  _IO(2,0x4b)
    2316
     17int freeramdisk_main(int argc, char **argv);
    2418int freeramdisk_main(int argc, char **argv)
    2519{
    26     int result;
    2720    int fd;
    2821
    2922    if (argc != 2) bb_show_usage();
    3023
    31     fd = bb_xopen(argv[1], O_RDWR);
     24    fd = xopen(argv[1], O_RDWR);
    3225
    3326    // Act like freeramdisk, fdflush, or both depending on configuration.
    34     result = ioctl(fd, (ENABLE_FREERAMDISK && bb_applet_name[1]=='r')
    35             || !ENABLE_FDFLUSH ? BLKFLSBUF : FDFLUSH);
     27    ioctl_or_perror_and_die(fd, (ENABLE_FREERAMDISK && applet_name[1]=='r')
     28            || !ENABLE_FDFLUSH ? BLKFLSBUF : FDFLUSH, NULL, "%s", argv[1]);
    3629
    3730    if (ENABLE_FEATURE_CLEAN_UP) close(fd);
    3831
    39     if (result) bb_perror_msg_and_die("%s", argv[1]);
    4032    return EXIT_SUCCESS;
    4133}
  • branches/2.2.5/mindi-busybox/util-linux/fsck_minix.c

    r821 r1765  
    33 * fsck.c - a file system consistency checker for Linux.
    44 *
    5  * (C) 1991, 1992 Linus Torvalds. This file may be redistributed
    6  * as per the GNU copyleft.
     5 * (C) 1991, 1992 Linus Torvalds.
     6 *
     7 * Licensed under GPLv2, see file LICENSE in this tarball for details.
    78 */
    89
     
    8788 */
    8889
    89 #include <stdio.h>
    90 #include <errno.h>
    91 #include <unistd.h>
    92 #include <string.h>
    93 #include <fcntl.h>
    94 #include <ctype.h>
    95 #include <stdlib.h>
    96 #include <termios.h>
    9790#include <mntent.h>
    98 #include <sys/param.h>
    99 #include "busybox.h"
    100 
    101 /*
    102  * This is the original minix inode layout on disk.
    103  * Note the 8-bit gid and atime and ctime.
    104  */
    105 struct minix_inode {
    106     uint16_t i_mode;
    107     uint16_t i_uid;
    108     uint32_t i_size;
    109     uint32_t i_time;
    110     uint8_t  i_gid;
    111     uint8_t  i_nlinks;
    112     uint16_t i_zone[9];
    113 };
    114 
    115 /*
    116  * The new minix inode has all the time entries, as well as
    117  * long block numbers and a third indirect block (7+1+1+1
    118  * instead of 7+1+1). Also, some previously 8-bit values are
    119  * now 16-bit. The inode is now 64 bytes instead of 32.
    120  */
    121 struct minix2_inode {
    122     uint16_t i_mode;
    123     uint16_t i_nlinks;
    124     uint16_t i_uid;
    125     uint16_t i_gid;
    126     uint32_t i_size;
    127     uint32_t i_atime;
    128     uint32_t i_mtime;
    129     uint32_t i_ctime;
    130     uint32_t i_zone[10];
    131 };
     91#include "libbb.h"
     92#include "minix.h"
     93
     94#ifndef BLKGETSIZE
     95#define BLKGETSIZE _IO(0x12,96)    /* return device size */
     96#endif
    13297
    13398enum {
    134     MINIX_ROOT_INO = 1,
    135     MINIX_LINK_MAX = 250,
     99#ifdef UNUSED
     100    MINIX1_LINK_MAX = 250,
    136101    MINIX2_LINK_MAX = 65530,
    137 
    138102    MINIX_I_MAP_SLOTS = 8,
    139103    MINIX_Z_MAP_SLOTS = 64,
    140     MINIX_SUPER_MAGIC = 0x137F,     /* original minix fs */
    141     MINIX_SUPER_MAGIC2 = 0x138F,        /* minix fs, 30 char names */
    142     MINIX2_SUPER_MAGIC = 0x2468,        /* minix V2 fs */
    143     MINIX2_SUPER_MAGIC2 = 0x2478,       /* minix V2 fs, 30 char names */
    144     MINIX_VALID_FS = 0x0001,        /* Clean fs. */
    145     MINIX_ERROR_FS = 0x0002,        /* fs has errors. */
    146 
    147     MINIX_INODES_PER_BLOCK = ((BLOCK_SIZE)/(sizeof (struct minix_inode))),
    148     MINIX2_INODES_PER_BLOCK = ((BLOCK_SIZE)/(sizeof (struct minix2_inode))),
    149 
    150     MINIX_V1 = 0x0001,      /* original minix fs */
    151     MINIX_V2 = 0x0002       /* minix V2 fs */
     104    MINIX_V1 = 0x0001,      /* original minix fs */
     105    MINIX_V2 = 0x0002,      /* minix V2 fs */
     106#endif
     107    MINIX_NAME_MAX = 255,         /* # chars in a file name */
    152108};
    153109
    154 #define INODE_VERSION(inode)    inode->i_sb->u.minix_sb.s_version
    155 
    156 /*
    157  * minix super-block data on disk
    158  */
    159 struct minix_super_block {
    160     uint16_t s_ninodes;
    161     uint16_t s_nzones;
    162     uint16_t s_imap_blocks;
    163     uint16_t s_zmap_blocks;
    164     uint16_t s_firstdatazone;
    165     uint16_t s_log_zone_size;
    166     uint32_t s_max_size;
    167     uint16_t s_magic;
    168     uint16_t s_state;
    169     uint32_t s_zones;
     110#if !ENABLE_FEATURE_MINIX2
     111enum { version2 = 0 };
     112#endif
     113
     114enum { MAX_DEPTH = 32 };
     115
     116struct globals {
     117    int dev_fd;
     118#if ENABLE_FEATURE_MINIX2
     119    smallint version2;
     120#endif
     121    smallint repair, automatic, verbose, list, show, warn_mode, force;
     122    smallint changed;  /* is filesystem modified? */
     123    smallint errors_uncorrected;  /* flag if some error was not corrected */
     124    smallint termios_set;
     125    smallint dirsize;
     126    smallint namelen;
     127    char *device_name;
     128    int directory, regular, blockdev, chardev, links, symlinks, total;
     129    char *inode_buffer;
     130
     131    char *inode_map;
     132    char *zone_map;
     133
     134    unsigned char *inode_count;
     135    unsigned char *zone_count;
     136
     137    /* File-name data */
     138    int name_depth;
     139    char *name_component[MAX_DEPTH+1];
     140
     141    /* Bigger stuff */
     142    struct termios sv_termios;
     143    char super_block_buffer[BLOCK_SIZE];
     144    char add_zone_ind_blk[BLOCK_SIZE];
     145    char add_zone_dind_blk[BLOCK_SIZE];
     146    USE_FEATURE_MINIX2(char add_zone_tind_blk[BLOCK_SIZE];)
     147    char check_file_blk[BLOCK_SIZE];
     148
     149    /* File-name data */
     150    char current_name[MAX_DEPTH * MINIX_NAME_MAX];
    170151};
    171152
    172 struct minix_dir_entry {
    173     uint16_t inode;
    174     char name[0];
    175 };
    176 
    177 
    178 #define NAME_MAX         255   /* # chars in a file name */
    179 
    180 #define MINIX_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix_inode)))
    181 
    182 #ifndef BLKGETSIZE
    183 #define BLKGETSIZE _IO(0x12,96)    /* return device size */
    184 #endif
    185 
    186 #ifndef __linux__
    187 #define volatile
    188 #endif
    189 
    190 enum { ROOT_INO = 1 };
    191 
    192 #define UPPER(size,n) ((size+((n)-1))/(n))
    193 #define INODE_SIZE (sizeof(struct minix_inode))
    194 #ifdef CONFIG_FEATURE_MINIX2
    195 #define INODE_SIZE2 (sizeof(struct minix2_inode))
    196 #define INODE_BLOCKS UPPER(INODES, (version2 ? MINIX2_INODES_PER_BLOCK \
    197                     : MINIX_INODES_PER_BLOCK))
     153#define G (*ptr_to_globals)
     154#define dev_fd             (G.dev_fd             )
     155#if ENABLE_FEATURE_MINIX2
     156#define version2           (G.version2           )
     157#endif
     158#define repair             (G.repair             )
     159#define automatic          (G.automatic          )
     160#define verbose            (G.verbose            )
     161#define list               (G.list               )
     162#define show               (G.show               )
     163#define warn_mode          (G.warn_mode          )
     164#define force              (G.force              )
     165#define changed            (G.changed            )
     166#define errors_uncorrected (G.errors_uncorrected )
     167#define termios_set        (G.termios_set        )
     168#define dirsize            (G.dirsize            )
     169#define namelen            (G.namelen            )
     170#define device_name        (G.device_name        )
     171#define directory          (G.directory          )
     172#define regular            (G.regular            )
     173#define blockdev           (G.blockdev           )
     174#define chardev            (G.chardev            )
     175#define links              (G.links              )
     176#define symlinks           (G.symlinks           )
     177#define total              (G.total              )
     178#define inode_buffer       (G.inode_buffer       )
     179#define inode_map          (G.inode_map          )
     180#define zone_map           (G.zone_map           )
     181#define inode_count        (G.inode_count        )
     182#define zone_count         (G.zone_count         )
     183#define name_depth         (G.name_depth         )
     184#define name_component     (G.name_component     )
     185#define sv_termios         (G.sv_termios         )
     186#define super_block_buffer (G.super_block_buffer )
     187#define add_zone_ind_blk   (G.add_zone_ind_blk   )
     188#define add_zone_dind_blk  (G.add_zone_dind_blk  )
     189#define add_zone_tind_blk  (G.add_zone_tind_blk  )
     190#define check_file_blk     (G.check_file_blk     )
     191#define current_name       (G.current_name       )
     192#define INIT_G() do { \
     193    PTR_TO_GLOBALS = xzalloc(sizeof(G)); \
     194    dirsize = 16; \
     195    namelen = 14; \
     196    current_name[0] = '/'; \
     197    /*current_name[1] = '\0';*/ \
     198    name_component[0] = &current_name[0]; \
     199} while (0)
     200
     201#define Inode1 (((struct minix1_inode *) inode_buffer)-1)
     202#define Inode2 (((struct minix2_inode *) inode_buffer)-1)
     203
     204#define Super (*(struct minix_super_block *)(super_block_buffer))
     205
     206#if ENABLE_FEATURE_MINIX2
     207# define ZONES    ((unsigned)(version2 ? Super.s_zones : Super.s_nzones))
    198208#else
    199 #define INODE_BLOCKS UPPER(INODES, (MINIX_INODES_PER_BLOCK))
    200 #endif
     209# define ZONES    ((unsigned)(Super.s_nzones))
     210#endif
     211#define INODES    ((unsigned)Super.s_ninodes)
     212#define IMAPS     ((unsigned)Super.s_imap_blocks)
     213#define ZMAPS     ((unsigned)Super.s_zmap_blocks)
     214#define FIRSTZONE ((unsigned)Super.s_firstdatazone)
     215#define ZONESIZE  ((unsigned)Super.s_log_zone_size)
     216#define MAXSIZE   ((unsigned)Super.s_max_size)
     217#define MAGIC     (Super.s_magic)
     218
     219/* gcc likes this more (code is smaller) than macro variant */
     220static ALWAYS_INLINE unsigned div_roundup(unsigned size, unsigned n)
     221{
     222    return (size + n-1) / n;
     223}
     224
     225#if ENABLE_FEATURE_MINIX2
     226#define INODE_BLOCKS div_roundup(INODES, (version2 ? MINIX2_INODES_PER_BLOCK \
     227                    : MINIX1_INODES_PER_BLOCK))
     228#else
     229#define INODE_BLOCKS div_roundup(INODES, MINIX1_INODES_PER_BLOCK)
     230#endif
     231
    201232#define INODE_BUFFER_SIZE (INODE_BLOCKS * BLOCK_SIZE)
    202 
    203 #define BITS_PER_BLOCK (BLOCK_SIZE<<3)
    204 
    205 static char *program_version = "1.2 - 11/11/96";
    206 static char *device_name;
    207 static int IN;
    208 static int repair, automatic, verbose, list, show, warn_mode, force;
    209 static int directory, regular, blockdev, chardev, links, symlinks, total;
    210 
    211 static int changed;         /* flags if the filesystem has been changed */
    212 static int errors_uncorrected;  /* flag if some error was not corrected */
    213 static int dirsize = 16;
    214 static int namelen = 14;
    215 static struct termios termios;
    216 static int termios_set;
    217 
    218 static char *inode_buffer;
    219 #define Inode (((struct minix_inode *) inode_buffer)-1)
    220 #define Inode2 (((struct minix2_inode *) inode_buffer)-1)
    221 static char super_block_buffer[BLOCK_SIZE];
    222 
    223 #define Super (*(struct minix_super_block *)super_block_buffer)
    224 #define INODES ((unsigned long)Super.s_ninodes)
    225 #ifdef CONFIG_FEATURE_MINIX2
    226 static int version2;
    227 #define ZONES ((unsigned long)(version2 ? Super.s_zones : Super.s_nzones))
    228 #else
    229 #define ZONES ((unsigned long)(Super.s_nzones))
    230 #endif
    231 #define IMAPS ((unsigned long)Super.s_imap_blocks)
    232 #define ZMAPS ((unsigned long)Super.s_zmap_blocks)
    233 #define FIRSTZONE ((unsigned long)Super.s_firstdatazone)
    234 #define ZONESIZE ((unsigned long)Super.s_log_zone_size)
    235 #define MAXSIZE ((unsigned long)Super.s_max_size)
    236 #define MAGIC (Super.s_magic)
    237 #define NORM_FIRSTZONE (2+IMAPS+ZMAPS+INODE_BLOCKS)
    238 
    239 static char *inode_map;
    240 static char *zone_map;
    241 
    242 static unsigned char *inode_count;
    243 static unsigned char *zone_count;
    244 
    245 static void recursive_check(unsigned int ino);
    246 #ifdef CONFIG_FEATURE_MINIX2
    247 static void recursive_check2(unsigned int ino);
    248 #endif
    249 
    250 static inline int bit(char *a, unsigned int i)
    251 {
    252       return (a[i >> 3] & (1<<(i & 7))) != 0;
    253 }
    254 #define inode_in_use(x) (bit(inode_map,(x)))
    255 #define zone_in_use(x) (bit(zone_map,(x)-FIRSTZONE+1))
    256 
    257 #define mark_inode(x) (setbit(inode_map,(x)),changed=1)
    258 #define unmark_inode(x) (clrbit(inode_map,(x)),changed=1)
    259 
    260 #define mark_zone(x) (setbit(zone_map,(x)-FIRSTZONE+1),changed=1)
    261 #define unmark_zone(x) (clrbit(zone_map,(x)-FIRSTZONE+1),changed=1)
    262 
    263 static void leave(int) ATTRIBUTE_NORETURN;
    264 static void leave(int status)
     233#define NORM_FIRSTZONE    (2 + IMAPS + ZMAPS + INODE_BLOCKS)
     234
     235/* Before you ask "where they come from?": */
     236/* setbit/clrbit are supplied by sys/param.h */
     237
     238static int minix_bit(const char *a, unsigned i)
     239{
     240    return (a[i >> 3] & (1<<(i & 7)));
     241}
     242
     243static void minix_setbit(char *a, unsigned i)
     244{
     245    setbit(a, i);
     246    changed = 1;
     247}
     248static void minix_clrbit(char *a, unsigned i)
     249{
     250    clrbit(a, i);
     251    changed = 1;
     252}
     253
     254/* Note: do not assume 0/1, it is 0/nonzero */
     255#define zone_in_use(x)  (minix_bit(zone_map,(x)-FIRSTZONE+1))
     256#define inode_in_use(x) (minix_bit(inode_map,(x)))
     257
     258#define mark_inode(x)   (minix_setbit(inode_map,(x)))
     259#define unmark_inode(x) (minix_clrbit(inode_map,(x)))
     260
     261#define mark_zone(x)    (minix_setbit(zone_map,(x)-FIRSTZONE+1))
     262#define unmark_zone(x)  (minix_clrbit(zone_map,(x)-FIRSTZONE+1))
     263
     264
     265static void recursive_check(unsigned ino);
     266#if ENABLE_FEATURE_MINIX2
     267static void recursive_check2(unsigned ino);
     268#endif
     269
     270static void die(const char *str) ATTRIBUTE_NORETURN;
     271static void die(const char *str)
    265272{
    266273    if (termios_set)
    267         tcsetattr(0, TCSANOW, &termios);
    268     exit(status);
    269 }
    270 
    271 static void die(const char *str)
    272 {
    273     bb_error_msg("%s", str);
    274     leave(8);
    275 }
    276 
    277 /* File-name data */
    278 enum { MAX_DEPTH = 32 };
    279 static int name_depth;
    280 static char *current_name;
    281 static char *name_component[MAX_DEPTH+1];
    282 
    283 /* Wed Feb  9 15:17:06 MST 2000 */
    284 /* dynamically allocate name_list (instead of making it static) */
    285 static inline void alloc_current_name(void)
    286 {
    287     current_name = xmalloc(MAX_DEPTH * (BUFSIZ + 1));
    288     current_name[0] = '/';
    289     current_name[1] = '\0';
    290     name_component[0] = &current_name[0];
    291 }
    292 
    293 #ifdef CONFIG_FEATURE_CLEAN_UP
    294 /* execute this atexit() to deallocate name_list[] */
    295 /* piptigger was here */
    296 static inline void free_current_name(void)
    297 {
    298     free(current_name);
    299 }
    300 #endif
     274        tcsetattr(0, TCSANOW, &sv_termios);
     275    bb_error_msg_and_die("%s", str);
     276}
    301277
    302278static void push_filename(const char *name)
     
    315291}
    316292
    317 static void pop_filename(void) {
     293static void pop_filename(void)
     294{
    318295    name_depth--;
    319296    if (name_depth < MAX_DEPTH) {
     
    331308
    332309    if (!repair) {
    333         printf("\n");
     310        puts("");
    334311        errors_uncorrected = 1;
    335312        return 0;
    336313    }
    337314    if (automatic) {
    338         printf("\n");
     315        puts("");
    339316        if (!def)
    340317            errors_uncorrected = 1;
     
    344321    for (;;) {
    345322        fflush(stdout);
    346         if ((c = getchar()) == EOF) {
     323        c = getchar();
     324        if (c == EOF) {
    347325            if (!def)
    348326                errors_uncorrected = 1;
     
    380358    int fd;
    381359
    382     if ((f = setmntent(MOUNTED, "r")) == NULL)
     360    f = setmntent(MOUNTED, "r");
     361    if (f == NULL)
    383362        return;
    384363    while ((mnt = getmntent(f)) != NULL)
     
    397376    if (fd < 0 && errno == EROFS)
    398377        return;
    399     else
    400         close(fd);
     378    close(fd);
    401379
    402380    printf("%s is mounted. ", device_name);
     
    408386        exit(0);
    409387    }
    410     return;
    411388}
    412389
     
    417394 * or a bad zone-number).
    418395 */
    419 static int check_zone_nr2(uint32_t *nr, int *corrected)
     396static int check_zone_nr2(uint32_t *nr, smallint *corrected)
    420397{
    421398    const char *msg;
     
    436413}
    437414
    438 static int check_zone_nr(uint16_t *nr, int *corrected)
     415static int check_zone_nr(uint16_t *nr, smallint *corrected)
    439416{
    440417    uint32_t nr32 = *nr;
     
    447424 * read-block reads block nr into the buffer at addr.
    448425 */
    449 static void read_block(unsigned int nr, char *addr)
     426static void read_block(unsigned nr, char *addr)
    450427{
    451428    if (!nr) {
     
    453430        return;
    454431    }
    455     if (BLOCK_SIZE * nr != lseek(IN, BLOCK_SIZE * nr, SEEK_SET)) {
    456         printf("%s: unable to seek to block in file '%s'\n",
     432    if (BLOCK_SIZE * nr != lseek(dev_fd, BLOCK_SIZE * nr, SEEK_SET)) {
     433        printf("%s: cannot seek to block in file '%s'\n",
    457434                bb_msg_read_error, current_name);
    458435        errors_uncorrected = 1;
    459436        memset(addr, 0, BLOCK_SIZE);
    460     } else if (BLOCK_SIZE != read(IN, addr, BLOCK_SIZE)) {
     437    } else if (BLOCK_SIZE != read(dev_fd, addr, BLOCK_SIZE)) {
    461438        printf("%s: bad block in file '%s'\n",
    462439                bb_msg_read_error, current_name);
     
    469446 * write_block writes block nr to disk.
    470447 */
    471 static void write_block(unsigned int nr, char *addr)
     448static void write_block(unsigned nr, char *addr)
    472449{
    473450    if (!nr)
     
    479456        return;
    480457    }
    481     if (BLOCK_SIZE * nr != lseek(IN, BLOCK_SIZE * nr, SEEK_SET))
    482         die("Seek failed in write_block");
    483     if (BLOCK_SIZE != write(IN, addr, BLOCK_SIZE)) {
     458    if (BLOCK_SIZE * nr != lseek(dev_fd, BLOCK_SIZE * nr, SEEK_SET))
     459        die("seek failed in write_block");
     460    if (BLOCK_SIZE != write(dev_fd, addr, BLOCK_SIZE)) {
    484461        printf("%s: bad block in file '%s'\n",
    485462                bb_msg_write_error, current_name);
     
    493470 * any indirect blocks with errors.
    494471 */
    495 static int map_block(struct minix_inode *inode, unsigned int blknr)
     472static int map_block(struct minix1_inode *inode, unsigned blknr)
    496473{
    497474    uint16_t ind[BLOCK_SIZE >> 1];
    498475    uint16_t dind[BLOCK_SIZE >> 1];
    499     int blk_chg, block, result;
     476    int block, result;
     477    smallint blk_chg;
    500478
    501479    if (blknr < 7)
     
    527505}
    528506
    529 #ifdef CONFIG_FEATURE_MINIX2
    530 static int map_block2(struct minix2_inode *inode, unsigned int blknr)
     507#if ENABLE_FEATURE_MINIX2
     508static int map_block2(struct minix2_inode *inode, unsigned blknr)
    531509{
    532510    uint32_t ind[BLOCK_SIZE >> 2];
    533511    uint32_t dind[BLOCK_SIZE >> 2];
    534512    uint32_t tind[BLOCK_SIZE >> 2];
    535     int blk_chg, block, result;
     513    int block, result;
     514    smallint blk_chg;
    536515
    537516    if (blknr < 7)
     
    593572     * unconditionally set if we get this far.
    594573     */
    595     Super.s_state |= MINIX_VALID_FS;
    596     if (errors_uncorrected)
    597         Super.s_state |= MINIX_ERROR_FS;
    598     else
     574    Super.s_state |= MINIX_VALID_FS | MINIX_ERROR_FS;
     575    if (!errors_uncorrected)
    599576        Super.s_state &= ~MINIX_ERROR_FS;
    600577
    601     if (BLOCK_SIZE != lseek(IN, BLOCK_SIZE, SEEK_SET))
    602         die("Seek failed in write_super_block");
    603     if (BLOCK_SIZE != write(IN, super_block_buffer, BLOCK_SIZE))
    604         die("Unable to write super-block");
     578    if (BLOCK_SIZE != lseek(dev_fd, BLOCK_SIZE, SEEK_SET))
     579        die("seek failed in write_super_block");
     580    if (BLOCK_SIZE != write(dev_fd, super_block_buffer, BLOCK_SIZE))
     581        die("cannot write super-block");
    605582}
    606583
     
    609586    write_super_block();
    610587
    611     if (IMAPS * BLOCK_SIZE != write(IN, inode_map, IMAPS * BLOCK_SIZE))
    612         die("Unable to write inode map");
    613     if (ZMAPS * BLOCK_SIZE != write(IN, zone_map, ZMAPS * BLOCK_SIZE))
    614         die("Unable to write zone map");
    615     if (INODE_BUFFER_SIZE != write(IN, inode_buffer, INODE_BUFFER_SIZE))
    616         die("Unable to write inodes");
     588    if (IMAPS * BLOCK_SIZE != write(dev_fd, inode_map, IMAPS * BLOCK_SIZE))
     589        die("cannot write inode map");
     590    if (ZMAPS * BLOCK_SIZE != write(dev_fd, zone_map, ZMAPS * BLOCK_SIZE))
     591        die("cannot write zone map");
     592    if (INODE_BUFFER_SIZE != write(dev_fd, inode_buffer, INODE_BUFFER_SIZE))
     593        die("cannot write inodes");
    617594}
    618595
     
    623600    int size;
    624601
    625 #ifdef CONFIG_FEATURE_MINIX2
     602#if ENABLE_FEATURE_MINIX2
    626603    if (version2)
    627         block = Inode2[ROOT_INO].i_zone[0];
     604        block = Inode2[MINIX_ROOT_INO].i_zone[0];
    628605    else
    629606#endif
    630         block = Inode[ROOT_INO].i_zone[0];
     607        block = Inode1[MINIX_ROOT_INO].i_zone[0];
    631608    read_block(block, blk);
    632609    for (size = 16; size < BLOCK_SIZE; size <<= 1) {
     
    642619static void read_superblock(void)
    643620{
    644     if (BLOCK_SIZE != lseek(IN, BLOCK_SIZE, SEEK_SET))
    645         die("Seek failed");
    646     if (BLOCK_SIZE != read(IN, super_block_buffer, BLOCK_SIZE))
    647         die("Unable to read super block");
     621    if (BLOCK_SIZE != lseek(dev_fd, BLOCK_SIZE, SEEK_SET))
     622        die("seek failed");
     623    if (BLOCK_SIZE != read(dev_fd, super_block_buffer, BLOCK_SIZE))
     624        die("cannot read super block");
    648625    /* already initialized to:
    649626    namelen = 14;
     
    651628    version2 = 0;
    652629    */
    653     if (MAGIC == MINIX_SUPER_MAGIC) {
    654     } else if (MAGIC == MINIX_SUPER_MAGIC2) {
     630    if (MAGIC == MINIX1_SUPER_MAGIC) {
     631    } else if (MAGIC == MINIX1_SUPER_MAGIC2) {
    655632        namelen = 30;
    656633        dirsize = 32;
    657 #ifdef CONFIG_FEATURE_MINIX2
     634#if ENABLE_FEATURE_MINIX2
    658635    } else if (MAGIC == MINIX2_SUPER_MAGIC) {
    659636        version2 = 1;
     
    664641#endif
    665642    } else
    666         die("Bad magic number in super-block");
     643        die("bad magic number in super-block");
    667644    if (ZONESIZE != 0 || BLOCK_SIZE != 1024)
    668         die("Only 1k blocks/zones supported");
     645        die("only 1k blocks/zones supported");
    669646    if (IMAPS * BLOCK_SIZE * 8 < INODES + 1)
    670         die("Bad s_imap_blocks field in super-block");
     647        die("bad s_imap_blocks field in super-block");
    671648    if (ZMAPS * BLOCK_SIZE * 8 < ZONES - FIRSTZONE + 1)
    672         die("Bad s_zmap_blocks field in super-block");
     649        die("bad s_zmap_blocks field in super-block");
    673650}
    674651
     
    680657    inode_count = xmalloc(INODES + 1);
    681658    zone_count = xmalloc(ZONES);
    682     if (IMAPS * BLOCK_SIZE != read(IN, inode_map, IMAPS * BLOCK_SIZE))
    683         die("Unable to read inode map");
    684     if (ZMAPS * BLOCK_SIZE != read(IN, zone_map, ZMAPS * BLOCK_SIZE))
    685         die("Unable to read zone map");
    686     if (INODE_BUFFER_SIZE != read(IN, inode_buffer, INODE_BUFFER_SIZE))
    687         die("Unable to read inodes");
     659    if (IMAPS * BLOCK_SIZE != read(dev_fd, inode_map, IMAPS * BLOCK_SIZE))
     660        die("cannot read inode map");
     661    if (ZMAPS * BLOCK_SIZE != read(dev_fd, zone_map, ZMAPS * BLOCK_SIZE))
     662        die("cannot read zone map");
     663    if (INODE_BUFFER_SIZE != read(dev_fd, inode_buffer, INODE_BUFFER_SIZE))
     664        die("cannot read inodes");
    688665    if (NORM_FIRSTZONE != FIRSTZONE) {
    689         printf("Warning: Firstzone!=Norm_firstzone\n");
     666        printf("warning: firstzone!=norm_firstzone\n");
    690667        errors_uncorrected = 1;
    691668    }
    692669    get_dirsize();
    693670    if (show) {
    694         printf("%ld inodes\n"
    695             "%ld blocks\n"
    696             "Firstdatazone=%ld (%ld)\n"
    697             "Zonesize=%d\n"
    698             "Maxsize=%ld\n"
    699             "Filesystem state=%d\n"
    700             "namelen=%d\n\n",
     671        printf("%u inodes\n"
     672            "%u blocks\n"
     673            "Firstdatazone=%u (%u)\n"
     674            "Zonesize=%u\n"
     675            "Maxsize=%u\n"
     676            "Filesystem state=%u\n"
     677            "namelen=%u\n\n",
    701678            INODES,
    702679            ZONES,
     
    709686}
    710687
    711 static struct minix_inode *get_inode(unsigned int nr)
    712 {
    713     struct minix_inode *inode;
     688static struct minix1_inode *get_inode(unsigned nr)
     689{
     690    struct minix1_inode *inode;
    714691
    715692    if (!nr || nr > INODES)
    716693        return NULL;
    717694    total++;
    718     inode = Inode + nr;
     695    inode = Inode1 + nr;
    719696    if (!inode_count[nr]) {
    720697        if (!inode_in_use(nr)) {
     
    724701                if (ask("Mark as 'in use'", 1))
    725702                    mark_inode(nr);
    726             } else {
    727                 errors_uncorrected = 1;
     703                else
     704                    errors_uncorrected = 1;
    728705            }
    729706        }
     
    754731}
    755732
    756 #ifdef CONFIG_FEATURE_MINIX2
    757 static struct minix2_inode *get_inode2(unsigned int nr)
     733#if ENABLE_FEATURE_MINIX2
     734static struct minix2_inode *get_inode2(unsigned nr)
    758735{
    759736    struct minix2_inode *inode;
     
    802779static void check_root(void)
    803780{
    804     struct minix_inode *inode = Inode + ROOT_INO;
     781    struct minix1_inode *inode = Inode1 + MINIX_ROOT_INO;
    805782
    806783    if (!inode || !S_ISDIR(inode->i_mode))
    807         die("Root inode isn't a directory");
    808 }
    809 
    810 #ifdef CONFIG_FEATURE_MINIX2
     784        die("root inode isn't a directory");
     785}
     786
     787#if ENABLE_FEATURE_MINIX2
    811788static void check_root2(void)
    812789{
    813     struct minix2_inode *inode = Inode2 + ROOT_INO;
     790    struct minix2_inode *inode = Inode2 + MINIX_ROOT_INO;
    814791
    815792    if (!inode || !S_ISDIR(inode->i_mode))
    816         die("Root inode isn't a directory");
    817 }
    818 #endif
    819 
    820 static int add_zone(uint16_t *znr, int *corrected)
     793        die("root inode isn't a directory");
     794}
     795#else
     796void check_root2(void);
     797#endif
     798
     799static int add_zone(uint16_t *znr, smallint *corrected)
    821800{
    822801    int result;
     
    848827}
    849828
    850 #ifdef CONFIG_FEATURE_MINIX2
    851 static int add_zone2(uint32_t *znr, int *corrected)
     829#if ENABLE_FEATURE_MINIX2
     830static int add_zone2(uint32_t *znr, smallint *corrected)
    852831{
    853832    int result;
     
    880859#endif
    881860
    882 static void add_zone_ind(uint16_t *znr, int *corrected)
    883 {
    884     static char blk[BLOCK_SIZE];
    885     int i, chg_blk = 0;
     861static void add_zone_ind(uint16_t *znr, smallint *corrected)
     862{
     863    int i;
    886864    int block;
     865    smallint chg_blk = 0;
    887866
    888867    block = add_zone(znr, corrected);
    889868    if (!block)
    890869        return;
    891     read_block(block, blk);
     870    read_block(block, add_zone_ind_blk);
    892871    for (i = 0; i < (BLOCK_SIZE >> 1); i++)
    893         add_zone(i + (uint16_t *) blk, &chg_blk);
     872        add_zone(i + (uint16_t *) add_zone_ind_blk, &chg_blk);
    894873    if (chg_blk)
    895         write_block(block, blk);
    896 }
    897 
    898 #ifdef CONFIG_FEATURE_MINIX2
    899 static void add_zone_ind2(uint32_t *znr, int *corrected)
    900 {
    901     static char blk[BLOCK_SIZE];
    902     int i, chg_blk = 0;
     874        write_block(block, add_zone_ind_blk);
     875}
     876
     877#if ENABLE_FEATURE_MINIX2
     878static void add_zone_ind2(uint32_t *znr, smallint *corrected)
     879{
     880    int i;
    903881    int block;
     882    smallint chg_blk = 0;
    904883
    905884    block = add_zone2(znr, corrected);
    906885    if (!block)
    907886        return;
    908     read_block(block, blk);
     887    read_block(block, add_zone_ind_blk);
    909888    for (i = 0; i < BLOCK_SIZE >> 2; i++)
    910         add_zone2(i + (uint32_t *) blk, &chg_blk);
     889        add_zone2(i + (uint32_t *) add_zone_ind_blk, &chg_blk);
    911890    if (chg_blk)
    912         write_block(block, blk);
    913 }
    914 #endif
    915 
    916 static void add_zone_dind(uint16_t *znr, int *corrected)
    917 {
    918     static char blk[BLOCK_SIZE];
    919     int i, blk_chg = 0;
     891        write_block(block, add_zone_ind_blk);
     892}
     893#endif
     894
     895static void add_zone_dind(uint16_t *znr, smallint *corrected)
     896{
     897    int i;
    920898    int block;
     899    smallint chg_blk = 0;
    921900
    922901    block = add_zone(znr, corrected);
    923902    if (!block)
    924903        return;
    925     read_block(block, blk);
     904    read_block(block, add_zone_dind_blk);
    926905    for (i = 0; i < (BLOCK_SIZE >> 1); i++)
    927         add_zone_ind(i + (uint16_t *) blk, &blk_chg);
    928     if (blk_chg)
    929         write_block(block, blk);
    930 }
    931 
    932 #ifdef CONFIG_FEATURE_MINIX2
    933 static void add_zone_dind2(uint32_t *znr, int *corrected)
    934 {
    935     static char blk[BLOCK_SIZE];
    936     int i, blk_chg = 0;
     906        add_zone_ind(i + (uint16_t *) add_zone_dind_blk, &chg_blk);
     907    if (chg_blk)
     908        write_block(block, add_zone_dind_blk);
     909}
     910
     911#if ENABLE_FEATURE_MINIX2
     912static void add_zone_dind2(uint32_t *znr, smallint *corrected)
     913{
     914    int i;
    937915    int block;
     916    smallint chg_blk = 0;
    938917
    939918    block = add_zone2(znr, corrected);
    940919    if (!block)
    941920        return;
    942     read_block(block, blk);
     921    read_block(block, add_zone_dind_blk);
    943922    for (i = 0; i < BLOCK_SIZE >> 2; i++)
    944         add_zone_ind2(i + (uint32_t *) blk, &blk_chg);
    945     if (blk_chg)
    946         write_block(block, blk);
    947 }
    948 
    949 static void add_zone_tind2(uint32_t *znr, int *corrected)
    950 {
    951     static char blk[BLOCK_SIZE];
    952     int i, blk_chg = 0;
     923        add_zone_ind2(i + (uint32_t *) add_zone_dind_blk, &chg_blk);
     924    if (chg_blk)
     925        write_block(block, add_zone_dind_blk);
     926}
     927
     928static void add_zone_tind2(uint32_t *znr, smallint *corrected)
     929{
     930    int i;
    953931    int block;
     932    smallint chg_blk = 0;
    954933
    955934    block = add_zone2(znr, corrected);
    956935    if (!block)
    957936        return;
    958     read_block(block, blk);
     937    read_block(block, add_zone_tind_blk);
    959938    for (i = 0; i < BLOCK_SIZE >> 2; i++)
    960         add_zone_dind2(i + (uint32_t *) blk, &blk_chg);
    961     if (blk_chg)
    962         write_block(block, blk);
    963 }
    964 #endif
    965 
    966 static void check_zones(unsigned int i)
    967 {
    968     struct minix_inode *inode;
     939        add_zone_dind2(i + (uint32_t *) add_zone_tind_blk, &chg_blk);
     940    if (chg_blk)
     941        write_block(block, add_zone_tind_blk);
     942}
     943#endif
     944
     945static void check_zones(unsigned i)
     946{
     947    struct minix1_inode *inode;
    969948
    970949    if (!i || i > INODES)
     
    972951    if (inode_count[i] > 1)     /* have we counted this file already? */
    973952        return;
    974     inode = Inode + i;
     953    inode = Inode1 + i;
    975954    if (!S_ISDIR(inode->i_mode) && !S_ISREG(inode->i_mode) &&
    976955        !S_ISLNK(inode->i_mode)) return;
     
    981960}
    982961
    983 #ifdef CONFIG_FEATURE_MINIX2
    984 static void check_zones2(unsigned int i)
     962#if ENABLE_FEATURE_MINIX2
     963static void check_zones2(unsigned i)
    985964{
    986965    struct minix2_inode *inode;
     
    1002981#endif
    1003982
    1004 static void check_file(struct minix_inode *dir, unsigned int offset)
    1005 {
    1006     static char blk[BLOCK_SIZE];
    1007     struct minix_inode *inode;
     983static void check_file(struct minix1_inode *dir, unsigned offset)
     984{
     985    struct minix1_inode *inode;
    1008986    int ino;
    1009987    char *name;
     
    1011989
    1012990    block = map_block(dir, offset / BLOCK_SIZE);
    1013     read_block(block, blk);
    1014     name = blk + (offset % BLOCK_SIZE) + 2;
     991    read_block(block, check_file_blk);
     992    name = check_file_blk + (offset % BLOCK_SIZE) + 2;
    1015993    ino = *(uint16_t *) (name - 2);
    1016994    if (ino > INODES) {
     
    1019997        if (ask("Remove", 1)) {
    1020998            *(uint16_t *) (name - 2) = 0;
    1021             write_block(block, blk);
     999            write_block(block, check_file_blk);
    10221000        }
    10231001        ino = 0;
     
    10271005    pop_filename();
    10281006    if (!offset) {
    1029         if (!inode || strcmp(".", name)) {
    1030             printf("%s: bad directory: '.' isn't first\n", current_name);
    1031             errors_uncorrected = 1;
    1032         } else
     1007        if (inode && LONE_CHAR(name, '.'))
    10331008            return;
     1009        printf("%s: bad directory: '.' isn't first\n", current_name);
     1010        errors_uncorrected = 1;
    10341011    }
    10351012    if (offset == dirsize) {
    1036         if (!inode || strcmp("..", name)) {
    1037             printf("%s: bad directory: '..' isn't second\n", current_name);
    1038             errors_uncorrected = 1;
    1039         } else
     1013        if (inode && strcmp("..", name) == 0)
    10401014            return;
     1015        printf("%s: bad directory: '..' isn't second\n", current_name);
     1016        errors_uncorrected = 1;
    10411017    }
    10421018    if (!inode)
     
    10521028        recursive_check(ino);
    10531029    pop_filename();
    1054     return;
    1055 }
    1056 
    1057 #ifdef CONFIG_FEATURE_MINIX2
    1058 static void check_file2(struct minix2_inode *dir, unsigned int offset)
    1059 {
    1060     static char blk[BLOCK_SIZE];
     1030}
     1031
     1032#if ENABLE_FEATURE_MINIX2
     1033static void check_file2(struct minix2_inode *dir, unsigned offset)
     1034{
    10611035    struct minix2_inode *inode;
    10621036    int ino;
     
    10651039
    10661040    block = map_block2(dir, offset / BLOCK_SIZE);
    1067     read_block(block, blk);
    1068     name = blk + (offset % BLOCK_SIZE) + 2;
     1041    read_block(block, check_file_blk);
     1042    name = check_file_blk + (offset % BLOCK_SIZE) + 2;
    10691043    ino = *(uint16_t *) (name - 2);
    10701044    if (ino > INODES) {
     
    10731047        if (ask("Remove", 1)) {
    10741048            *(uint16_t *) (name - 2) = 0;
    1075             write_block(block, blk);
     1049            write_block(block, check_file_blk);
    10761050        }
    10771051        ino = 0;
     
    10811055    pop_filename();
    10821056    if (!offset) {
    1083         if (!inode || strcmp(".", name)) {
    1084             printf("%s: bad directory: '.' isn't first\n", current_name);
    1085             errors_uncorrected = 1;
    1086         } else
     1057        if (inode && LONE_CHAR(name, '.'))
    10871058            return;
     1059        printf("%s: bad directory: '.' isn't first\n", current_name);
     1060        errors_uncorrected = 1;
    10881061    }
    10891062    if (offset == dirsize) {
    1090         if (!inode || strcmp("..", name)) {
    1091             printf("%s: bad directory: '..' isn't second\n", current_name);
    1092             errors_uncorrected = 1;
    1093         } else
     1063        if (inode && strcmp("..", name) == 0)
    10941064            return;
     1065        printf("%s: bad directory: '..' isn't second\n", current_name);
     1066        errors_uncorrected = 1;
    10951067    }
    10961068    if (!inode)
     
    11061078        recursive_check2(ino);
    11071079    pop_filename();
    1108     return;
    1109 }
    1110 #endif
    1111 
    1112 static void recursive_check(unsigned int ino)
    1113 {
    1114     struct minix_inode *dir;
    1115     unsigned int offset;
    1116 
    1117     dir = Inode + ino;
     1080}
     1081#endif
     1082
     1083static void recursive_check(unsigned ino)
     1084{
     1085    struct minix1_inode *dir;
     1086    unsigned offset;
     1087
     1088    dir = Inode1 + ino;
    11181089    if (!S_ISDIR(dir->i_mode))
    1119         die("Internal error");
     1090        die("internal error");
    11201091    if (dir->i_size < 2 * dirsize) {
    11211092        printf("%s: bad directory: size<32", current_name);
     
    11261097}
    11271098
    1128 #ifdef CONFIG_FEATURE_MINIX2
    1129 static void recursive_check2(unsigned int ino)
     1099#if ENABLE_FEATURE_MINIX2
     1100static void recursive_check2(unsigned ino)
    11301101{
    11311102    struct minix2_inode *dir;
    1132     unsigned int offset;
     1103    unsigned offset;
    11331104
    11341105    dir = Inode2 + ino;
    11351106    if (!S_ISDIR(dir->i_mode))
    1136         die("Internal error");
     1107        die("internal error");
    11371108    if (dir->i_size < 2 * dirsize) {
    11381109        printf("%s: bad directory: size<32", current_name);
     
    11461117static int bad_zone(int i)
    11471118{
    1148     char buffer[1024];
    1149 
    1150     if (BLOCK_SIZE * i != lseek(IN, BLOCK_SIZE * i, SEEK_SET))
    1151         die("Seek failed in bad_zone");
    1152     return (BLOCK_SIZE != read(IN, buffer, BLOCK_SIZE));
     1119    char buffer[BLOCK_SIZE];
     1120
     1121    if (BLOCK_SIZE * i != lseek(dev_fd, BLOCK_SIZE * i, SEEK_SET))
     1122        die("seek failed in bad_zone");
     1123    return (BLOCK_SIZE != read(dev_fd, buffer, BLOCK_SIZE));
    11531124}
    11541125
     
    11581129
    11591130    for (i = 1; i <= INODES; i++) {
    1160         if (warn_mode && Inode[i].i_mode && !inode_in_use(i)) {
     1131        if (warn_mode && Inode1[i].i_mode && !inode_in_use(i)) {
    11611132            printf("Inode %d has non-zero mode. ", i);
    11621133            if (ask("Clear", 1)) {
    1163                 Inode[i].i_mode = 0;
     1134                Inode1[i].i_mode = 0;
    11641135                changed = 1;
    11651136            }
     
    11781149                mark_inode(i);
    11791150        }
    1180         if (Inode[i].i_nlinks != inode_count[i]) {
     1151        if (Inode1[i].i_nlinks != inode_count[i]) {
    11811152            printf("Inode %d (mode=%07o), i_nlinks=%d, counted=%d. ",
    1182                    i, Inode[i].i_mode, Inode[i].i_nlinks, inode_count[i]);
     1153                i, Inode1[i].i_mode, Inode1[i].i_nlinks,
     1154                inode_count[i]);
    11831155            if (ask("Set i_nlinks to count", 1)) {
    1184                 Inode[i].i_nlinks = inode_count[i];
     1156                Inode1[i].i_nlinks = inode_count[i];
    11851157                changed = 1;
    11861158            }
     
    11881160    }
    11891161    for (i = FIRSTZONE; i < ZONES; i++) {
    1190         if (zone_in_use(i) == zone_count[i])
     1162        if ((zone_in_use(i) != 0) == zone_count[i])
    11911163            continue;
    11921164        if (!zone_count[i]) {
     
    12031175}
    12041176
    1205 #ifdef CONFIG_FEATURE_MINIX2
     1177#if ENABLE_FEATURE_MINIX2
    12061178static void check_counts2(void)
    12071179{
     
    12311203        if (Inode2[i].i_nlinks != inode_count[i]) {
    12321204            printf("Inode %d (mode=%07o), i_nlinks=%d, counted=%d. ",
    1233                    i, Inode2[i].i_mode, Inode2[i].i_nlinks,
    1234                    inode_count[i]);
     1205                i, Inode2[i].i_mode, Inode2[i].i_nlinks,
     1206                inode_count[i]);
    12351207            if (ask("Set i_nlinks to count", 1)) {
    12361208                Inode2[i].i_nlinks = inode_count[i];
     
    12401212    }
    12411213    for (i = FIRSTZONE; i < ZONES; i++) {
    1242         if (zone_in_use(i) == zone_count[i])
     1214        if ((zone_in_use(i) != 0) == zone_count[i])
    12431215            continue;
    12441216        if (!zone_count[i]) {
     
    12601232    memset(inode_count, 0, (INODES + 1) * sizeof(*inode_count));
    12611233    memset(zone_count, 0, ZONES * sizeof(*zone_count));
    1262     check_zones(ROOT_INO);
    1263     recursive_check(ROOT_INO);
     1234    check_zones(MINIX_ROOT_INO);
     1235    recursive_check(MINIX_ROOT_INO);
    12641236    check_counts();
    12651237}
    12661238
    1267 #ifdef CONFIG_FEATURE_MINIX2
     1239#if ENABLE_FEATURE_MINIX2
    12681240static void check2(void)
    12691241{
    12701242    memset(inode_count, 0, (INODES + 1) * sizeof(*inode_count));
    12711243    memset(zone_count, 0, ZONES * sizeof(*zone_count));
    1272     check_zones2(ROOT_INO);
    1273     recursive_check2(ROOT_INO);
     1244    check_zones2(MINIX_ROOT_INO);
     1245    recursive_check2(MINIX_ROOT_INO);
    12741246    check_counts2();
    12751247}
    1276 #endif
    1277 
     1248#else
     1249void check2(void);
     1250#endif
     1251
     1252int fsck_minix_main(int argc, char **argv);
    12781253int fsck_minix_main(int argc, char **argv)
    12791254{
     
    12811256    int retcode = 0;
    12821257
    1283     alloc_current_name();
    1284 #ifdef CONFIG_FEATURE_CLEAN_UP
    1285     /* Don't bother to free memory.  Exit does
    1286      * that automagically, so we can save a few bytes */
    1287     atexit(free_current_name);
    1288 #endif
    1289 
    1290     if (INODE_SIZE * MINIX_INODES_PER_BLOCK != BLOCK_SIZE)
    1291         die("Bad inode size");
    1292 #ifdef CONFIG_FEATURE_MINIX2
     1258    xfunc_error_retval = 8;
     1259
     1260    INIT_G();
     1261
     1262    if (INODE_SIZE1 * MINIX1_INODES_PER_BLOCK != BLOCK_SIZE)
     1263        die("bad inode size");
     1264#if ENABLE_FEATURE_MINIX2
    12931265    if (INODE_SIZE2 * MINIX2_INODES_PER_BLOCK != BLOCK_SIZE)
    1294         die("Bad v2 inode size");
    1295 #endif
    1296     while (argc-- > 1) {
     1266        die("bad v2 inode size");
     1267#endif
     1268    while (--argc != 0) {
    12971269        argv++;
    12981270        if (argv[0][0] != '-') {
    12991271            if (device_name)
    13001272                bb_show_usage();
    1301             else
    1302                 device_name = argv[0];
    1303         } else
    1304             while (*++argv[0])
     1273            device_name = argv[0];
     1274        } else {
     1275            while (*++argv[0]) {
    13051276                switch (argv[0][0]) {
    13061277                case 'l':
     
    13301301                    bb_show_usage();
    13311302                }
     1303            }
     1304        }
    13321305    }
    13331306    if (!device_name)
    13341307        bb_show_usage();
     1308
    13351309    check_mount();              /* trying to check a mounted filesystem? */
    13361310    if (repair && !automatic) {
    13371311        if (!isatty(0) || !isatty(1))
    1338             die("Need terminal for interactive repairs");
    1339     }
    1340     IN = open(device_name, repair ? O_RDWR : O_RDONLY);
    1341     if (IN < 0){
    1342         printf("Unable to open device '%s'\n", device_name);
    1343         leave(8);
    1344     }
    1345     sync(); /* paranoia? */
     1312            die("need terminal for interactive repairs");
     1313    }
     1314    dev_fd = xopen(device_name, repair ? O_RDWR : O_RDONLY);
     1315
     1316    /*sync(); paranoia? */
    13461317    read_superblock();
    13471318
     
    13521323     * command line.
    13531324     */
    1354     printf("%s, %s\n", bb_applet_name, program_version);
    1355     if (!(Super.s_state & MINIX_ERROR_FS) &&
    1356         (Super.s_state & MINIX_VALID_FS) && !force) {
     1325    printf("%s: %s\n", applet_name, bb_banner);
     1326
     1327    if (!(Super.s_state & MINIX_ERROR_FS)
     1328     && (Super.s_state & MINIX_VALID_FS) && !force
     1329    ) {
    13571330        if (repair)
    13581331            printf("%s is clean, check is skipped\n", device_name);
    1359         return retcode;
     1332        return 0;
    13601333    } else if (force)
    13611334        printf("Forcing filesystem check on %s\n", device_name);
     
    13671340
    13681341    if (repair && !automatic) {
    1369         tcgetattr(0, &termios);
    1370         tmp = termios;
     1342        tcgetattr(0, &sv_termios);
     1343        tmp = sv_termios;
    13711344        tmp.c_lflag &= ~(ICANON | ECHO);
    13721345        tcsetattr(0, TCSANOW, &tmp);
    13731346        termios_set = 1;
    13741347    }
    1375 #ifdef CONFIG_FEATURE_MINIX2
     1348
    13761349    if (version2) {
    13771350        check_root2();
    13781351        check2();
    1379     } else
    1380 #endif
    1381     {
     1352    } else {
    13821353        check_root();
    13831354        check();
    13841355    }
     1356
    13851357    if (verbose) {
    13861358        int i, free_cnt;
     
    13891361            if (!inode_in_use(i))
    13901362                free_cnt++;
    1391         printf("\n%6ld inodes used (%ld%%)\n", (INODES - free_cnt),
     1363        printf("\n%6u inodes used (%u%%)\n", (INODES - free_cnt),
    13921364               100 * (INODES - free_cnt) / INODES);
    13931365        for (i = FIRSTZONE, free_cnt = 0; i < ZONES; i++)
    13941366            if (!zone_in_use(i))
    13951367                free_cnt++;
    1396         printf("%6ld zones used (%ld%%)\n\n"
    1397                "%6d regular files\n"
    1398                "%6d directories\n"
    1399                "%6d character device files\n"
    1400                "%6d block device files\n"
    1401                "%6d links\n"
    1402                "%6d symbolic links\n"
     1368        printf("%6u zones used (%u%%)\n\n"
     1369               "%6u regular files\n"
     1370               "%6u directories\n"
     1371               "%6u character device files\n"
     1372               "%6u block device files\n"
     1373               "%6u links\n"
     1374               "%6u symbolic links\n"
    14031375               "------\n"
    1404                "%6d files\n",
     1376               "%6u files\n",
    14051377               (ZONES - free_cnt), 100 * (ZONES - free_cnt) / ZONES,
    14061378               regular, directory, chardev, blockdev,
     
    14161388
    14171389    if (repair && !automatic)
    1418         tcsetattr(0, TCSANOW, &termios);
     1390        tcsetattr(0, TCSANOW, &sv_termios);
    14191391
    14201392    if (changed)
  • branches/2.2.5/mindi-busybox/util-linux/getopt.c

    r821 r1765  
     1/* vi: set sw=4 ts=4: */
    12/*
    23 * getopt.c - Enhanced implementation of BSD getopt(1)
     
    3132 */
    3233
    33 #include <stdio.h>
    34 #include <stdlib.h>
    35 #include <string.h>
    36 #include <unistd.h>
    37 #include <ctype.h>
    3834#include <getopt.h>
    39 
    40 #include "busybox.h"
     35#include "libbb.h"
    4136
    4237/* NON_OPT is the code that is returned when a non-option is found in '+'
     
    4439enum {
    4540    NON_OPT = 1,
     41#if ENABLE_GETOPT_LONG
    4642/* LONG_OPT is the code that is returned when a long option is found. */
    4743    LONG_OPT = 2
     44#endif
    4845};
    4946
    50 /* The shells recognized. */
    51 typedef enum {BASH,TCSH} shell_t;
    52 
    53 
    54 /* Some global variables that tells us how to parse. */
    55 static shell_t shell=BASH; /* The shell we generate output for. */
    56 static int quiet_errors; /* 0 is not quiet. */
    57 static int quiet_output; /* 0 is not quiet. */
    58 static int quote=1; /* 1 is do quote. */
    59 static int alternative; /* 0 is getopt_long, 1 is getopt_long_only */
    60 
    61 /* Function prototypes */
    62 static const char *normalize(const char *arg);
    63 static int generate_output(char * argv[],int argc,const char *optstr,
    64             const struct option *longopts);
    65 static void add_long_options(char *options);
    66 static void add_longopt(const char *name,int has_arg);
    67 static void set_shell(const char *new_shell);
    68 
     47/* For finding activated option flags. Must match getopt32 call! */
     48enum {
     49    OPT_o   = 0x1,  // -o
     50    OPT_n   = 0x2,  // -n
     51    OPT_q   = 0x4,  // -q
     52    OPT_Q   = 0x8,  // -Q
     53    OPT_s   = 0x10, // -s
     54    OPT_T   = 0x20, // -T
     55    OPT_u   = 0x40, // -u
     56#if ENABLE_GETOPT_LONG
     57    OPT_a   = 0x80, // -a
     58    OPT_l   = 0x100, // -l
     59#endif
     60    SHELL_IS_TCSH = 0x8000, /* hijack this bit for other purposes */
     61};
     62
     63/* 0 is getopt_long, 1 is getopt_long_only */
     64#define alternative  (option_mask32 & OPT_a)
     65
     66#define quiet_errors (option_mask32 & OPT_q)
     67#define quiet_output (option_mask32 & OPT_Q)
     68#define quote        (!(option_mask32 & OPT_u))
     69#define shell_TCSH   (option_mask32 & SHELL_IS_TCSH)
    6970
    7071/*
     
    7778 * each call.
    7879 */
    79 const char *normalize(const char *arg)
    80 {
    81     static char *BUFFER=NULL;
    82     const char *argptr=arg;
     80static const char *normalize(const char *arg)
     81{
    8382    char *bufptr;
    84 
     83#if ENABLE_FEATURE_CLEAN_UP
     84    static char *BUFFER = NULL;
    8585    free(BUFFER);
     86#else
     87    char *BUFFER;
     88#endif
    8689
    8790    if (!quote) { /* Just copy arg */
    88            BUFFER=bb_xstrdup(arg);
     91        BUFFER = xstrdup(arg);
    8992        return BUFFER;
    9093    }
     
    9497       opening quote! We need also the global opening and closing quote,
    9598       and one extra character for '\0'. */
    96     BUFFER=xmalloc(strlen(arg)*4+3);
    97 
    98     bufptr=BUFFER;
    99     *bufptr++='\'';
    100 
    101     while (*argptr) {
    102         if (*argptr == '\'') {
     99    BUFFER = xmalloc(strlen(arg)*4 + 3);
     100
     101    bufptr = BUFFER;
     102    *bufptr ++= '\'';
     103
     104    while (*arg) {
     105        if (*arg == '\'') {
    103106            /* Quote: replace it with: '\'' */
    104             *bufptr++='\'';
    105             *bufptr++='\\';
    106             *bufptr++='\'';
    107             *bufptr++='\'';
    108         } else if (shell==TCSH && *argptr=='!') {
     107            *bufptr ++= '\'';
     108            *bufptr ++= '\\';
     109            *bufptr ++= '\'';
     110            *bufptr ++= '\'';
     111        } else if (shell_TCSH && *arg == '!') {
    109112            /* Exclamation mark: replace it with: \! */
    110             *bufptr++='\'';
    111             *bufptr++='\\';
    112             *bufptr++='!';
    113             *bufptr++='\'';
    114         } else if (shell==TCSH && *argptr=='\n') {
     113            *bufptr ++= '\'';
     114            *bufptr ++= '\\';
     115            *bufptr ++= '!';
     116            *bufptr ++= '\'';
     117        } else if (shell_TCSH && *arg == '\n') {
    115118            /* Newline: replace it with: \n */
    116             *bufptr++='\\';
    117             *bufptr++='n';
    118         } else if (shell==TCSH && isspace(*argptr)) {
     119            *bufptr ++= '\\';
     120            *bufptr ++= 'n';
     121        } else if (shell_TCSH && isspace(*arg)) {
    119122            /* Non-newline whitespace: replace it with \<ws> */
    120             *bufptr++='\'';
    121             *bufptr++='\\';
    122             *bufptr++=*argptr;
    123             *bufptr++='\'';
     123            *bufptr ++= '\'';
     124            *bufptr ++= '\\';
     125            *bufptr ++= *arg;
     126            *bufptr ++= '\'';
    124127        } else
    125128            /* Just copy */
    126             *bufptr++=*argptr;
    127         argptr++;
    128     }
    129     *bufptr++='\'';
    130     *bufptr++='\0';
     129            *bufptr ++= *arg;
     130        arg++;
     131    }
     132    *bufptr ++= '\'';
     133    *bufptr ++= '\0';
    131134    return BUFFER;
    132135}
     
    139142 * Other settings are found in global variables.
    140143 */
    141 int generate_output(char * argv[],int argc,const char *optstr,
    142             const struct option *longopts)
     144#if !ENABLE_GETOPT_LONG
     145#define generate_output(argv,argc,optstr,longopts) generate_output(argv,argc,optstr)
     146#endif
     147static int generate_output(char **argv, int argc, const char *optstr, const struct option *longopts)
    143148{
    144149    int exit_code = 0; /* We assume everything will be OK */
    145     int opt;
     150    unsigned opt;
     151#if ENABLE_GETOPT_LONG
    146152    int longindex;
     153#endif
    147154    const char *charptr;
    148155
    149156    if (quiet_errors) /* No error reporting from getopt(3) */
    150         opterr=0;
    151     optind=0; /* Reset getopt(3) */
    152 
    153     while ((opt = (alternative?
    154                getopt_long_only(argc,argv,optstr,longopts,&longindex):
    155                getopt_long(argc,argv,optstr,longopts,&longindex)))
    156            != EOF)
     157        opterr = 0;
     158    optind = 0; /* Reset getopt(3) */
     159
     160    while (1) {
     161        opt =
     162#if ENABLE_GETOPT_LONG
     163            alternative ?
     164            getopt_long_only(argc, argv, optstr, longopts, &longindex) :
     165            getopt_long(argc, argv, optstr, longopts, &longindex);
     166#else
     167            getopt(argc, argv, optstr);
     168#endif
     169        if (opt == EOF)
     170            break;
    157171        if (opt == '?' || opt == ':' )
    158172            exit_code = 1;
    159173        else if (!quiet_output) {
     174#if ENABLE_GETOPT_LONG
    160175            if (opt == LONG_OPT) {
    161                 printf(" --%s",longopts[longindex].name);
     176                printf(" --%s", longopts[longindex].name);
    162177                if (longopts[longindex].has_arg)
    163178                    printf(" %s",
    164                            normalize(optarg?optarg:""));
    165             } else if (opt == NON_OPT)
    166                 printf(" %s",normalize(optarg));
     179                        normalize(optarg ? optarg : ""));
     180            } else
     181#endif
     182            if (opt == NON_OPT)
     183                printf(" %s", normalize(optarg));
    167184            else {
    168                 printf(" -%c",opt);
     185                printf(" -%c", opt);
    169186                charptr = strchr(optstr,opt);
    170187                if (charptr != NULL && *++charptr == ':')
    171188                    printf(" %s",
    172                            normalize(optarg?optarg:""));
     189                        normalize(optarg ? optarg : ""));
    173190            }
    174191        }
    175 
    176     if (! quiet_output) {
     192    }
     193
     194    if (!quiet_output) {
    177195        printf(" --");
    178196        while (optind < argc)
    179             printf(" %s",normalize(argv[optind++]));
    180         printf("\n");
     197            printf(" %s", normalize(argv[optind++]));
     198        puts("");
    181199    }
    182200    return exit_code;
    183201}
    184202
    185 static struct option *long_options;
    186 static int long_options_length; /* Length of array */
    187 static int long_options_nr; /* Nr of used elements in array */
    188 enum { LONG_OPTIONS_INCR = 10 };
    189 #define init_longopt() add_longopt(NULL,0)
    190 
    191 /* Register a long option. The contents of name is copied. */
    192 void add_longopt(const char *name,int has_arg)
    193 {
    194     if (!name) { /* init */
    195         free(long_options);
    196         long_options=NULL;
    197         long_options_length=0;
    198         long_options_nr=0;
    199     }
    200 
    201     if (long_options_nr == long_options_length) {
    202         long_options_length += LONG_OPTIONS_INCR;
    203         long_options=xrealloc(long_options,
    204                      sizeof(struct option) *
    205                      long_options_length);
    206     }
    207 
    208     long_options[long_options_nr].name=NULL;
    209     long_options[long_options_nr].has_arg=0;
    210     long_options[long_options_nr].flag=NULL;
    211     long_options[long_options_nr].val=0;
    212 
    213     if (long_options_nr) { /* Not for init! */
    214         long_options[long_options_nr-1].has_arg=has_arg;
    215         long_options[long_options_nr-1].flag=NULL;
    216         long_options[long_options_nr-1].val=LONG_OPT;
    217            long_options[long_options_nr-1].name=bb_xstrdup(name);
    218     }
    219     long_options_nr++;
    220 }
    221 
    222 
     203#if ENABLE_GETOPT_LONG
    223204/*
    224205 * Register several long options. options is a string of long options,
     
    226207 * This nukes options!
    227208 */
    228 void add_long_options(char *options)
    229 {
     209static struct option *add_long_options(struct option *long_options, char *options)
     210{
     211    int long_nr = 0;
    230212    int arg_opt, tlen;
    231     char *tokptr=strtok(options,", \t\n");
     213    char *tokptr = strtok(options, ", \t\n");
     214
     215    if (long_options)
     216        while (long_options[long_nr].name)
     217            long_nr++;
     218
    232219    while (tokptr) {
    233         arg_opt=no_argument;
    234         tlen=strlen(tokptr);
    235         if (tlen > 0) {
    236             if (tokptr[tlen-1] == ':') {
    237                 if (tlen > 1 && tokptr[tlen-2] == ':') {
    238                     tokptr[tlen-2]='\0';
    239                     tlen -= 2;
    240                     arg_opt=optional_argument;
    241                 } else {
    242                     tokptr[tlen-1]='\0';
    243                     tlen -= 1;
    244                     arg_opt=required_argument;
     220        arg_opt = no_argument;
     221        tlen = strlen(tokptr);
     222        if (tlen) {
     223            tlen--;
     224            if (tokptr[tlen] == ':') {
     225                arg_opt = required_argument;
     226                if (tlen && tokptr[tlen-1] == ':') {
     227                    tlen--;
     228                    arg_opt = optional_argument;
    245229                }
     230                tokptr[tlen] = '\0';
    246231                if (tlen == 0)
    247                     bb_error_msg("empty long option after -l or --long argument");
     232                    bb_error_msg_and_die("empty long option specified");
    248233            }
    249             add_longopt(tokptr,arg_opt);
     234            long_options = xrealloc(long_options,
     235                    sizeof(long_options[0]) * (long_nr+2));
     236            long_options[long_nr].has_arg = arg_opt;
     237            long_options[long_nr].flag = NULL;
     238            long_options[long_nr].val = LONG_OPT;
     239            long_options[long_nr].name = xstrdup(tokptr);
     240            long_nr++;
     241            memset(&long_options[long_nr], 0, sizeof(long_options[0]));
    250242        }
    251         tokptr=strtok(NULL,", \t\n");
    252     }
    253 }
    254 
    255 void set_shell(const char *new_shell)
    256 {
    257     if (!strcmp(new_shell,"bash"))
    258         shell=BASH;
    259     else if (!strcmp(new_shell,"tcsh"))
    260         shell=TCSH;
    261     else if (!strcmp(new_shell,"sh"))
    262         shell=BASH;
    263     else if (!strcmp(new_shell,"csh"))
    264         shell=TCSH;
     243        tokptr = strtok(NULL, ", \t\n");
     244    }
     245    return long_options;
     246}
     247#endif
     248
     249static void set_shell(const char *new_shell)
     250{
     251    if (!strcmp(new_shell,"bash") || !strcmp(new_shell,"sh"))
     252        return;
     253    if (!strcmp(new_shell,"tcsh") || !strcmp(new_shell,"csh"))
     254        option_mask32 |= SHELL_IS_TCSH;
    265255    else
    266         bb_error_msg("unknown shell after -s or --shell argument");
     256        bb_error_msg("unknown shell '%s', assuming bash", new_shell);
    267257}
    268258
     
    276266 */
    277267
    278 static const struct option longopts[]=
    279 {
    280     {"options",required_argument,NULL,'o'},
    281     {"longoptions",required_argument,NULL,'l'},
    282     {"quiet",no_argument,NULL,'q'},
    283     {"quiet-output",no_argument,NULL,'Q'},
    284     {"shell",required_argument,NULL,'s'},
    285     {"test",no_argument,NULL,'T'},
    286     {"unquoted",no_argument,NULL,'u'},
    287     {"alternative",no_argument,NULL,'a'},
    288     {"name",required_argument,NULL,'n'},
    289     {NULL,0,NULL,0}
    290 };
    291 
    292 /* Stop scanning as soon as a non-option argument is found! */
    293 static const char shortopts[]="+ao:l:n:qQs:Tu";
    294 
    295 
     268#if ENABLE_GETOPT_LONG
     269static const char getopt_longopts[] ALIGN1 =
     270    "options\0"      Required_argument "o"
     271    "longoptions\0"  Required_argument "l"
     272    "quiet\0"        No_argument       "q"
     273    "quiet-output\0" No_argument       "Q"
     274    "shell\0"        Required_argument "s"
     275    "test\0"         No_argument       "T"
     276    "unquoted\0"     No_argument       "u"
     277    "alternative\0"  No_argument       "a"
     278    "name\0"         Required_argument "n"
     279    ;
     280#endif
     281
     282int getopt_main(int argc, char *argv[]);
    296283int getopt_main(int argc, char *argv[])
    297284{
    298     const char *optstr = NULL;
     285    char *optstr = NULL;
    299286    char *name = NULL;
    300     int opt;
    301     int compatible=0;
    302 
    303     init_longopt();
    304 
    305     if (getenv("GETOPT_COMPATIBLE"))
    306         compatible=1;
     287    unsigned opt;
     288    const char *compatible;
     289    char *s_arg;
     290#if ENABLE_GETOPT_LONG
     291    struct option *long_options = NULL;
     292    llist_t *l_arg = NULL;
     293#endif
     294
     295    compatible = getenv("GETOPT_COMPATIBLE"); /* used as yes/no flag */
    307296
    308297    if (argc == 1) {
     
    311300               when there were no arguments. */
    312301            printf(" --\n");
    313                return 0;
    314         } else
    315             bb_error_msg_and_die("missing optstring argument");
     302            return 0;
     303        }
     304        bb_error_msg_and_die("missing optstring argument");
    316305    }
    317306
     
    319308        char *s;
    320309
    321         quote=0;
    322         s=xmalloc(strlen(argv[1])+1);
    323         strcpy(s,argv[1]+strspn(argv[1],"-+"));
    324         argv[1]=argv[0];
    325            return (generate_output(argv+1,argc-1,s,long_options));
    326     }
    327 
    328     while ((opt=getopt_long(argc,argv,shortopts,longopts,NULL)) != EOF)
    329         switch (opt) {
    330         case 'a':
    331             alternative=1;
    332             break;
    333         case 'o':
    334                optstr = optarg;
    335             break;
    336         case 'l':
    337             add_long_options(optarg);
    338             break;
    339         case 'n':
    340                name = optarg;
    341             break;
    342         case 'q':
    343             quiet_errors=1;
    344             break;
    345         case 'Q':
    346             quiet_output=1;
    347             break;
    348         case 's':
    349             set_shell(optarg);
    350             break;
    351         case 'T':
    352                return 4;
    353         case 'u':
    354             quote=0;
    355             break;
    356         default:
    357             bb_show_usage();
    358         }
    359 
     310        option_mask32 |= OPT_u; /* quoting off */
     311        s = xstrdup(argv[1] + strspn(argv[1], "-+"));
     312        argv[1] = argv[0];
     313        return generate_output(argv+1, argc-1, s, long_options);
     314    }
     315
     316#if !ENABLE_GETOPT_LONG
     317    opt = getopt32(argv, "+o:n:qQs:Tu", &optstr, &name, &s_arg);
     318#else
     319    applet_long_options = getopt_longopts;
     320    opt_complementary = "l::";
     321    opt = getopt32(argv, "+o:n:qQs:Tual:",
     322                    &optstr, &name, &s_arg, &l_arg);
     323    /* Effectuate the read options for the applet itself */
     324    while (l_arg) {
     325        long_options = add_long_options(long_options, l_arg->data);
     326        l_arg = l_arg->link;
     327    }
     328#endif
     329
     330    if (opt & OPT_s) {
     331        set_shell(s_arg);
     332    }
     333
     334    if (opt & OPT_T) {
     335        return 4;
     336    }
     337
     338    /* All options controlling the applet have now been parsed */
    360339    if (!optstr) {
    361340        if (optind >= argc)
    362341            bb_error_msg_and_die("missing optstring argument");
    363         else optstr=argv[optind++];
    364     }
    365     if (name)
    366         argv[optind-1]=name;
    367     else
    368         argv[optind-1]=argv[0];
    369        return (generate_output(argv+optind-1,argc-optind+1,optstr,long_options));
    370 }
     342        optstr = argv[optind++];
     343    }
     344
     345    argv[optind-1] = name ? name : argv[0];
     346    return generate_output(argv+optind-1, argc-optind+1, optstr, long_options);
     347}
  • branches/2.2.5/mindi-busybox/util-linux/hexdump.c

    r821 r1765  
     1/* vi: set sw=4 ts=4: */
    12/*
    23 * hexdump implementation for busybox
     
    910 */
    1011
    11 #include "busybox.h"
    1212#include <getopt.h>
    13 #include <string.h>
     13#include "libbb.h"
    1414#include "dump.h"
     15
     16/* This is a NOEXEC applet. Be very careful! */
     17
    1518
    1619static void bb_dump_addfile(char *name)
    1720{
    18     register char *p;
     21    char *p;
    1922    FILE *fp;
    2023    char *buf;
    2124
    22     fp = bb_xfopen(name, "r");
     25    fp = xfopen(name, "r");
    2326
    24     while ((buf = bb_get_chomped_line_from_file(fp)) != NULL) {
     27    while ((buf = xmalloc_getline(fp)) != NULL) {
    2528        p = skip_whitespace(buf);
    2629
     
    3336}
    3437
    35 static const char * const add_strings[] = {
    36             "\"%07.7_ax \" 16/1 \"%03o \" \"\\n\"",     /* b */
    37             "\"%07.7_ax \" 16/1 \"%3_c \" \"\\n\"",     /* c */
    38             "\"%07.7_ax \" 8/2 \"  %05u \" \"\\n\"",    /* d */
    39             "\"%07.7_ax \" 8/2 \" %06o \" \"\\n\"",     /* o */
    40             "\"%07.7_ax \" 8/2 \"   %04x \" \"\\n\"",   /* x */
     38static const char *const add_strings[] = {
     39    "\"%07.7_ax \" 16/1 \"%03o \" \"\\n\"",     /* b */
     40    "\"%07.7_ax \" 16/1 \"%3_c \" \"\\n\"",     /* c */
     41    "\"%07.7_ax \" 8/2 \"  %05u \" \"\\n\"",    /* d */
     42    "\"%07.7_ax \" 8/2 \" %06o \" \"\\n\"",     /* o */
     43    "\"%07.7_ax \" 8/2 \"   %04x \" \"\\n\"",   /* x */
    4144};
    4245
    43 static const char add_first[] = "\"%07.7_Ax\n\"";
     46static const char add_first[] ALIGN1 = "\"%07.7_Ax\n\"";
    4447
    45 static const char hexdump_opts[] = "bcdoxCe:f:n:s:v";
     48static const char hexdump_opts[] ALIGN1 = "bcdoxCe:f:n:s:v";
    4649
    4750static const struct suffix_mult suffixes[] = {
    48     {"b", 512 },
    49     {"k", 1024 },
    50     {"m", 1024*1024 },
    51     {NULL, 0 }
     51    { "b", 512 },
     52    { "k", 1024 },
     53    { "m", 1024*1024 },
     54    { }
    5255};
    5356
     57int hexdump_main(int argc, char **argv);
    5458int hexdump_main(int argc, char **argv)
    5559{
    56 //  register FS *tfs;
    5760    const char *p;
    5861    int ch;
     
    6265
    6366    while ((ch = getopt(argc, argv, hexdump_opts)) > 0) {
    64         if ((p = strchr(hexdump_opts, ch)) != NULL) {
    65             if ((p - hexdump_opts) < 5) {
    66                 bb_dump_add(add_first);
    67                 bb_dump_add(add_strings[(int)(p - hexdump_opts)]);
    68             } else if (ch == 'C') {
    69                     bb_dump_add("\"%08.8_Ax\n\"");
    70                 bb_dump_add("\"%08.8_ax  \" 8/1 \"%02x \" \"  \" 8/1 \"%02x \" ");
    71                     bb_dump_add("\"  |\" 16/1 \"%_p\" \"|\\n\"");
    72             } else {
    73                 /* Sae a little bit of space below by omitting the 'else's. */
    74                 if (ch == 'e') {
    75                     bb_dump_add(optarg);
    76                 } /* else */
    77                 if (ch == 'f') {
    78                     bb_dump_addfile(optarg);
    79                 } /* else */
    80                 if (ch == 'n') {
    81                     bb_dump_length = bb_xgetularg10_bnd(optarg, 0, INT_MAX);
    82                 } /* else */
    83                 if (ch == 's') {
    84                     bb_dump_skip = bb_xgetularg_bnd_sfx(optarg, 10, 0, LONG_MAX, suffixes);
    85                 } /* else */
    86                 if (ch == 'v') {
    87                     bb_dump_vflag = ALL;
    88                 }
     67        p = strchr(hexdump_opts, ch);
     68        if (!p)
     69            bb_show_usage();
     70        if ((p - hexdump_opts) < 5) {
     71            bb_dump_add(add_first);
     72            bb_dump_add(add_strings[(int)(p - hexdump_opts)]);
     73        } else if (ch == 'C') {
     74            bb_dump_add("\"%08.8_Ax\n\"");
     75            bb_dump_add("\"%08.8_ax  \" 8/1 \"%02x \" \"  \" 8/1 \"%02x \" ");
     76            bb_dump_add("\"  |\" 16/1 \"%_p\" \"|\\n\"");
     77        } else {
     78            /* Save a little bit of space below by omitting the 'else's. */
     79            if (ch == 'e') {
     80                bb_dump_add(optarg);
     81            } /* else */
     82            if (ch == 'f') {
     83                bb_dump_addfile(optarg);
     84            } /* else */
     85            if (ch == 'n') {
     86                bb_dump_length = xatoi_u(optarg);
     87            } /* else */
     88            if (ch == 's') {
     89                bb_dump_skip = xatoul_range_sfx(optarg, 0, LONG_MAX, suffixes);
     90            } /* else */
     91            if (ch == 'v') {
     92                bb_dump_vflag = ALL;
    8993            }
    90         } else {
    91             bb_show_usage();
    9294        }
    9395    }
     
    100102    argv += optind;
    101103
    102     return(bb_dump_dump(argv));
     104    return bb_dump_dump(argv);
    103105}
  • branches/2.2.5/mindi-busybox/util-linux/hwclock.c

    r821 r1765  
    88*/
    99
    10 
    11 #include <sys/ioctl.h>
    1210#include <sys/utsname.h>
    13 #include <ctype.h>
    14 #include <fcntl.h>
    1511#include <getopt.h>
    16 #include <stdlib.h>
    17 #include <string.h>
    18 #include <syslog.h>
    19 #include <time.h>
    20 #include <unistd.h>
    21 #include "busybox.h"
     12#include "libbb.h"
    2213
    2314/* Copied from linux/rtc.h to eliminate the kernel dependency */
     
    4334#endif
    4435
     36static const char *rtcname;
     37
     38static int xopen_rtc(int flags)
     39{
     40    int rtc;
     41
     42    if (!rtcname) {
     43        rtc = open("/dev/rtc", flags);
     44        if (rtc >= 0)
     45            return rtc;
     46        rtc = open("/dev/rtc0", flags);
     47        if (rtc >= 0)
     48            return rtc;
     49        rtcname = "/dev/misc/rtc";
     50    }
     51    return xopen(rtcname, flags);
     52}
     53
    4554static time_t read_rtc(int utc)
    4655{
    47     int rtc;
    4856    struct tm tm;
    4957    char *oldtz = 0;
    5058    time_t t = 0;
    51 
    52     if (( rtc = open ( "/dev/rtc", O_RDONLY )) < 0 ) {
    53         if (( rtc = open ( "/dev/misc/rtc", O_RDONLY )) < 0 )
    54             bb_perror_msg_and_die ( "Could not access RTC" );
    55     }
    56     memset ( &tm, 0, sizeof( struct tm ));
    57     if ( ioctl ( rtc, RTC_RD_TIME, &tm ) < 0 )
    58         bb_perror_msg_and_die ( "Could not read time from RTC" );
     59    int rtc = xopen_rtc(O_RDONLY);
     60
     61    memset(&tm, 0, sizeof(struct tm));
     62    xioctl(rtc, RTC_RD_TIME, &tm);
    5963    tm.tm_isdst = -1; /* not known */
    6064
    61     close ( rtc );
    62 
    63     if ( utc ) {
    64         oldtz = getenv ( "TZ" );
    65         setenv ( "TZ", "UTC 0", 1 );
    66         tzset ( );
    67     }
    68 
    69     t = mktime ( &tm );
    70 
    71     if ( utc ) {
    72         if ( oldtz )
    73             setenv ( "TZ", oldtz, 1 );
    74         else
    75             unsetenv ( "TZ" );
    76         tzset ( );
     65    close(rtc);
     66
     67    if (utc) {
     68        oldtz = getenv("TZ");
     69        putenv((char*)"TZ=UTC0");
     70        tzset();
     71    }
     72
     73    t = mktime(&tm);
     74
     75    if (utc) {
     76        unsetenv("TZ");
     77        if (oldtz)
     78            putenv(oldtz - 3);
     79        tzset();
    7780    }
    7881    return t;
     
    8184static void write_rtc(time_t t, int utc)
    8285{
    83     int rtc;
    8486    struct tm tm;
    85 
    86     if (( rtc = open ( "/dev/rtc", O_WRONLY )) < 0 ) {
    87         if (( rtc = open ( "/dev/misc/rtc", O_WRONLY )) < 0 )
    88             bb_perror_msg_and_die ( "Could not access RTC" );
    89     }
    90 
    91     tm = *( utc ? gmtime ( &t ) : localtime ( &t ));
     87    int rtc = xopen_rtc(O_WRONLY);
     88
     89    tm = *(utc ? gmtime(&t) : localtime(&t));
    9290    tm.tm_isdst = 0;
    9391
    94     if ( ioctl ( rtc, RTC_SET_TIME, &tm ) < 0 )
    95         bb_perror_msg_and_die ( "Could not set the RTC time" );
    96 
    97     close ( rtc );
    98 }
    99 
    100 static int show_clock(int utc)
    101 {
    102     struct tm *ptm;
     92    xioctl(rtc, RTC_SET_TIME, &tm);
     93
     94    close(rtc);
     95}
     96
     97static void show_clock(int utc)
     98{
     99    //struct tm *ptm;
    103100    time_t t;
    104     RESERVE_CONFIG_BUFFER(buffer, 64);
    105 
    106     t = read_rtc ( utc );
    107     ptm = localtime ( &t );  /* Sets 'tzname[]' */
    108 
    109     safe_strncpy ( buffer, ctime ( &t ), 64);
    110     if ( buffer [0] )
    111         buffer [strlen ( buffer ) - 1] = 0;
    112 
    113     //printf ( "%s  %.6f seconds %s\n", buffer, 0.0, utc ? "" : ( ptm-> tm_isdst ? tzname [1] : tzname [0] ));
    114     printf ( "%s  %.6f seconds\n", buffer, 0.0 );
    115     RELEASE_CONFIG_BUFFER(buffer);
    116 
    117     return 0;
    118 }
    119 
    120 static int to_sys_clock(int utc)
    121 {
    122     struct timeval tv = { 0, 0 };
     101    char *cp;
     102
     103    t = read_rtc(utc);
     104    //ptm = localtime(&t);  /* Sets 'tzname[]' */
     105
     106    cp = ctime(&t);
     107    if (cp[0])
     108        cp[strlen(cp) - 1] = '\0';
     109
     110    //printf("%s  %.6f seconds %s\n", cp, 0.0, utc ? "" : (ptm->tm_isdst ? tzname[1] : tzname[0]));
     111    printf("%s  0.000000 seconds\n", cp);
     112}
     113
     114static void to_sys_clock(int utc)
     115{
     116    struct timeval tv;
    123117    const struct timezone tz = { timezone/60 - 60*daylight, 0 };
    124118
    125     tv.tv_sec = read_rtc ( utc );
    126 
    127     if ( settimeofday ( &tv, &tz ))
    128         bb_perror_msg_and_die ( "settimeofday() failed" );
    129 
    130     return 0;
    131 }
    132 
    133 static int from_sys_clock(int utc)
    134 {
    135     struct timeval tv = { 0, 0 };
    136     struct timezone tz = { 0, 0 };
    137 
    138     if ( gettimeofday ( &tv, &tz ))
    139         bb_perror_msg_and_die ( "gettimeofday() failed" );
    140 
    141     write_rtc ( tv.tv_sec, utc );
    142     return 0;
    143 }
    144 
    145 #ifdef CONFIG_FEATURE_HWCLOCK_ADJTIME_FHS
     119    tv.tv_sec = read_rtc(utc);
     120    tv.tv_usec = 0;
     121    if (settimeofday(&tv, &tz))
     122        bb_perror_msg_and_die("settimeofday() failed");
     123}
     124
     125static void from_sys_clock(int utc)
     126{
     127    struct timeval tv;
     128
     129    gettimeofday(&tv, NULL);
     130    //if (gettimeofday(&tv, NULL))
     131    //  bb_perror_msg_and_die("gettimeofday() failed");
     132    write_rtc(tv.tv_sec, utc);
     133}
     134
     135#if ENABLE_FEATURE_HWCLOCK_ADJTIME_FHS
    146136# define ADJTIME_PATH "/var/lib/hwclock/adjtime"
    147137#else
     
    151141{
    152142    int utc = 0;
    153     FILE *f = fopen ( ADJTIME_PATH, "r" );
    154 
    155     if ( f ) {
     143    FILE *f = fopen(ADJTIME_PATH, "r");
     144
     145    if (f) {
    156146        RESERVE_CONFIG_BUFFER(buffer, 128);
    157147
    158         while ( fgets ( buffer, sizeof( buffer ), f )) {
    159             int len = strlen ( buffer );
    160 
    161             while ( len && isspace ( buffer [len - 1] ))
     148        while (fgets(buffer, sizeof(buffer), f)) {
     149            int len = strlen(buffer);
     150
     151            while (len && isspace(buffer[len - 1]))
    162152                len--;
    163153
    164             buffer [len] = 0;
    165 
    166             if ( strncmp ( buffer, "UTC", 3 ) == 0 ) {
     154            buffer[len] = 0;
     155
     156            if (strncmp(buffer, "UTC", 3) == 0) {
    167157                utc = 1;
    168158                break;
    169159            }
    170160        }
    171         fclose ( f );
     161        fclose(f);
    172162        RELEASE_CONFIG_BUFFER(buffer);
    173163    }
     
    175165}
    176166
    177 #define HWCLOCK_OPT_LOCALTIME   0x01
    178 #define HWCLOCK_OPT_UTC         0x02
    179 #define HWCLOCK_OPT_SHOW        0x04
    180 #define HWCLOCK_OPT_HCTOSYS     0x08
    181 #define HWCLOCK_OPT_SYSTOHC     0x10
    182 
    183 int hwclock_main ( int argc, char **argv )
    184 {
    185     unsigned long opt;
     167#define HWCLOCK_OPT_LOCALTIME   0x01
     168#define HWCLOCK_OPT_UTC         0x02
     169#define HWCLOCK_OPT_SHOW        0x04
     170#define HWCLOCK_OPT_HCTOSYS     0x08
     171#define HWCLOCK_OPT_SYSTOHC     0x10
     172#define HWCLOCK_OPT_RTCFILE     0x20
     173
     174int hwclock_main(int argc, char **argv);
     175int hwclock_main(int argc, char **argv)
     176{
     177    unsigned opt;
    186178    int utc;
    187179
    188180#if ENABLE_FEATURE_HWCLOCK_LONG_OPTIONS
    189 static const struct option hwclock_long_options[] = {
    190         { "localtime", 0, 0, 'l' },
    191         { "utc",       0, 0, 'u' },
    192         { "show",      0, 0, 'r' },
    193         { "hctosys",   0, 0, 's' },
    194         { "systohc",   0, 0, 'w' },
    195         { 0,           0, 0, 0 }
    196     };
    197     bb_applet_long_options = hwclock_long_options;
     181    static const char hwclock_longopts[] ALIGN1 =
     182        "localtime\0" No_argument "l"
     183        "utc\0"       No_argument "u"
     184        "show\0"      No_argument "r"
     185        "hctosys\0"   No_argument "s"
     186        "systohc\0"   No_argument "w"
     187        "file\0"      Required_argument "f"
     188        ;
     189    applet_long_options = hwclock_longopts;
    198190#endif
    199 
    200     bb_opt_complementally = "?:r--ws:w--rs:s--wr:l--u:u--l";
    201     opt = bb_getopt_ulflags(argc, argv, "lursw");
     191    opt_complementary = "r--ws:w--rs:s--wr:l--u:u--l";
     192    opt = getopt32(argv, "lurswf:", &rtcname);
    202193
    203194    /* If -u or -l wasn't given check if we are using utc */
     
    208199
    209200    if (opt & HWCLOCK_OPT_HCTOSYS) {
    210         return to_sys_clock ( utc );
    211     }
    212     else if (opt & HWCLOCK_OPT_SYSTOHC) {
    213         return from_sys_clock ( utc );
    214     } else {
    215         /* default HWCLOCK_OPT_SHOW */
    216         return show_clock ( utc );
    217     }
    218 }
     201        to_sys_clock(utc);
     202        return 0;
     203    }
     204    if (opt & HWCLOCK_OPT_SYSTOHC) {
     205        from_sys_clock(utc);
     206        return 0;
     207    }
     208    /* default HWCLOCK_OPT_SHOW */
     209    show_clock(utc);
     210    return 0;
     211}
  • branches/2.2.5/mindi-busybox/util-linux/ipcrm.c

    r821 r1765  
     1/* vi: set sw=4 ts=4: */
    12/*
    2  * ipcrm.c -- utility to allow removal of IPC objects and data structures.
     3 * ipcrm.c - utility to allow removal of IPC objects and data structures.
    34 *
    45 * 01 Sept 2004 - Rodney Radford <rradford@mindspring.com>
    56 * Adapted for busybox from util-linux-2.12a.
    67 *
    7  * This program is free software; you can redistribute it and/or modify
    8  * it under the terms of the GNU General Public License as published by
    9  * the Free Software Foundation; either version 2 of the License, or
    10  * (at your option) any later version.
    11  *
    12  * This program is distributed in the hope that it will be useful,
    13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    15  * General Public License for more details.
    16  *
    17  * You should have received a copy of the GNU General Public License
    18  * along with this program; if not, write to the Free Software
    19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    20  *
    21  * --- Pre-busybox history from util-linux-2.12a ------------------------
    22  *
    23  * 1999-04-02 frank zago
    24  * - can now remove several id's in the same call
    25  *
    26  * 1999-02-22 Arkadiusz Miÿkiewicz <misiek@pld.ORG.PL>
    27  * - added Native Language Support
    28  *
    29  * Original author - krishna balasubramanian 1993
     8 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
    309 */
    3110
    32 #include <stdio.h>
    33 #include <stdlib.h>
    34 #include <string.h>
    35 #include <errno.h>
    36 
    37 #include <sys/types.h>
     11#include "libbb.h"
     12
     13/* X/OPEN tells us to use <sys/{types,ipc,sem}.h> for semctl() */
     14/* X/OPEN tells us to use <sys/{types,ipc,msg}.h> for msgctl() */
    3815#include <sys/ipc.h>
    3916#include <sys/shm.h>
     
    4118#include <sys/sem.h>
    4219
    43 /* X/OPEN tells us to use <sys/{types,ipc,sem}.h> for semctl() */
    44 /* X/OPEN tells us to use <sys/{types,ipc,msg}.h> for msgctl() */
    45 /* for getopt */
    46 #include <unistd.h>
    47 
    48 /* for tolower and isupper */
    49 #include <ctype.h>
    50 
    51 #include "busybox.h"
    52 
    53 #if defined (__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
     20#if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
    5421/* union semun is defined by including <sys/sem.h> */
    5522#else
     
    6330#endif
    6431
     32#define IPCRM_LEGACY 1
     33
     34
     35#if IPCRM_LEGACY
     36
    6537typedef enum type_id {
    6638    SHM,
     
    6941} type_id;
    7042
    71 static int
    72 remove_ids(type_id type, int argc, char **argv) {
    73     int id;
    74     int ret = 0;        /* for gcc */
    75     char *end;
     43static int remove_ids(type_id type, int argc, char **argv)
     44{
     45    unsigned long id;
     46    int ret = 0;        /* silence gcc */
    7647    int nb_errors = 0;
    7748    union semun arg;
     
    7950    arg.val = 0;
    8051
    81     while(argc) {
    82 
    83         id = strtoul(argv[0], &end, 10);
    84 
    85         if (*end != 0) {
    86             bb_printf ("invalid id: %s\n", argv[0]);
    87             nb_errors ++;
     52    while (argc) {
     53        id = bb_strtoul(argv[0], NULL, 10);
     54        if (errno || id > INT_MAX) {
     55            bb_error_msg("invalid id: %s", argv[0]);
     56            nb_errors++;
    8857        } else {
    89             switch(type) {
    90             case SEM:
    91                 ret = semctl (id, 0, IPC_RMID, arg);
    92                 break;
    93 
    94             case MSG:
    95                 ret = msgctl (id, IPC_RMID, NULL);
    96                 break;
    97 
    98             case SHM:
    99                 ret = shmctl (id, IPC_RMID, NULL);
    100                 break;
    101             }
     58            if (type == SEM)
     59                ret = semctl(id, 0, IPC_RMID, arg);
     60            else if (type == MSG)
     61                ret = msgctl(id, IPC_RMID, NULL);
     62            else if (type ==  SHM)
     63                ret = shmctl(id, IPC_RMID, NULL);
    10264
    10365            if (ret) {
    104                 bb_printf ("cannot remove id %s (%s)\n",
    105                     argv[0], strerror(errno));
    106                 nb_errors ++;
     66                bb_perror_msg("cannot remove id %s", argv[0]);
     67                nb_errors++;
    10768            }
    10869        }
     
    11172    }
    11273
    113     return(nb_errors);
     74    return nb_errors;
    11475}
    115 
    116 static int deprecated_main(int argc, char **argv)
    117 {
    118     if (argc < 3) {
    119         bb_show_usage();
    120         bb_fflush_stdout_and_exit(1);
    121     }
    122 
    123     if (!strcmp(argv[1], "shm")) {
    124         if (remove_ids(SHM, argc-2, &argv[2]))
    125             bb_fflush_stdout_and_exit(1);
    126     }
    127     else if (!strcmp(argv[1], "msg")) {
    128         if (remove_ids(MSG, argc-2, &argv[2]))
    129             bb_fflush_stdout_and_exit(1);
    130     }
    131     else if (!strcmp(argv[1], "sem")) {
    132         if (remove_ids(SEM, argc-2, &argv[2]))
    133             bb_fflush_stdout_and_exit(1);
    134     }
    135     else {
    136         bb_printf ("unknown resource type: %s\n", argv[1]);
    137         bb_show_usage();
    138         bb_fflush_stdout_and_exit(1);
    139     }
    140 
    141     bb_printf ("resource(s) deleted\n");
    142     return 0;
    143 }
    144 
    145 
     76#endif /* IPCRM_LEGACY */
     77
     78
     79int ipcrm_main(int argc, char **argv);
    14680int ipcrm_main(int argc, char **argv)
    14781{
    148     int   c;
    149     int   error = 0;
    150     char *prog = argv[0];
     82    int c;
     83    int error = 0;
    15184
    15285    /* if the command is executed without parameters, do nothing */
    15386    if (argc == 1)
    15487        return 0;
    155 
     88#if IPCRM_LEGACY
    15689    /* check to see if the command is being invoked in the old way if so
    157        then run the old code */
    158     if (strcmp(argv[1], "shm") == 0 ||
    159         strcmp(argv[1], "msg") == 0 ||
    160         strcmp(argv[1], "sem") == 0)
    161         return deprecated_main(argc, argv);
     90       then run the old code. Valid commands are msg, shm, sem. */
     91    {
     92        type_id what = 0; /* silence gcc */
     93        char w;
     94
     95        w=argv[1][0];
     96        if ( ((w == 'm' && argv[1][1] == 's' && argv[1][2] == 'g')
     97               || (argv[1][0] == 's'
     98                   && ((w=argv[1][1]) == 'h' || w == 'e')
     99                   && argv[1][2] == 'm')
     100             ) && argv[1][3] == '\0'
     101        ) {
     102
     103            if (argc < 3)
     104                bb_show_usage();
     105
     106            if (w == 'h')
     107                what = SHM;
     108            else if (w == 'm')
     109                what = MSG;
     110            else if (w == 'e')
     111                what = SEM;
     112
     113            if (remove_ids(what, argc-2, &argv[2]))
     114                fflush_stdout_and_exit(1);
     115            printf("resource(s) deleted\n");
     116            return 0;
     117        }
     118    }
     119#endif /* IPCRM_LEGACY */
    162120
    163121    /* process new syntax to conform with SYSV ipcrm */
     
    165123        int result;
    166124        int id = 0;
    167         int iskey = isupper(c);
     125        int iskey = (isupper)(c);
    168126
    169127        /* needed to delete semaphores */
    170128        union semun arg;
     129
    171130        arg.val = 0;
    172131
    173         if ((c == '?') || (c == 'h'))
    174         {
     132        if ((c == '?') || (c == 'h')) {
    175133            bb_show_usage();
    176             return 0;
    177134        }
    178135
     
    180137        c = tolower(c);
    181138
    182         /* make sure the option is in range */
     139        /* make sure the option is in range: allowed are q, m, s */
    183140        if (c != 'q' && c != 'm' && c != 's') {
    184141            bb_show_usage();
    185             error++;
    186             return error;
    187142        }
    188143
    189144        if (iskey) {
    190145            /* keys are in hex or decimal */
    191             key_t key = strtoul(optarg, NULL, 0);
     146            key_t key = xstrtoul(optarg, 0);
     147
    192148            if (key == IPC_PRIVATE) {
    193149                error++;
    194                 bb_fprintf(stderr, "%s: illegal key (%s)\n",
    195                     prog, optarg);
     150                bb_error_msg("illegal key (%s)", optarg);
    196151                continue;
    197152            }
     
    199154            /* convert key to id */
    200155            id = ((c == 'q') ? msgget(key, 0) :
    201                   (c == 'm') ? shmget(key, 0, 0) :
    202                   semget(key, 0, 0));
     156                  (c == 'm') ? shmget(key, 0, 0) : semget(key, 0, 0));
    203157
    204158            if (id < 0) {
    205                 char *errmsg;
     159                const char *errmsg;
     160
    206161                error++;
    207                 switch(errno) {
     162                switch (errno) {
    208163                case EACCES:
    209                     errmsg = "permission denied for key";
     164                    errmsg = "permission denied for";
    210165                    break;
    211166                case EIDRM:
    212                     errmsg = "already removed key";
     167                    errmsg = "already removed";
    213168                    break;
    214169                case ENOENT:
    215                     errmsg = "invalid key";
     170                    errmsg = "invalid";
    216171                    break;
    217172                default:
    218                     errmsg = "unknown error in key";
     173                    errmsg = "unknown error in";
    219174                    break;
    220175                }
    221                 bb_fprintf(stderr, "%s: %s (%s)\n",
    222                     prog, errmsg, optarg);
     176                bb_error_msg("%s %s (%s)", errmsg, "key", optarg);
    223177                continue;
    224178            }
    225179        } else {
    226180            /* ids are in decimal */
    227             id = strtoul(optarg, NULL, 10);
     181            id = xatoul(optarg);
    228182        }
    229183
    230184        result = ((c == 'q') ? msgctl(id, IPC_RMID, NULL) :
    231               (c == 'm') ? shmctl(id, IPC_RMID, NULL) :
    232               semctl(id, 0, IPC_RMID, arg));
    233 
    234         if (result < 0) {
    235             char *errmsg;
     185                  (c == 'm') ? shmctl(id, IPC_RMID, NULL) :
     186                  semctl(id, 0, IPC_RMID, arg));
     187
     188        if (result) {
     189            const char *errmsg;
     190            const char *const what = iskey ? "key" : "id";
     191
    236192            error++;
    237             switch(errno) {
     193            switch (errno) {
    238194            case EACCES:
    239195            case EPERM:
    240                 errmsg = iskey
    241                     ? "permission denied for key"
    242                     : "permission denied for id";
     196                errmsg = "permission denied for";
    243197                break;
    244198            case EINVAL:
    245                 errmsg = iskey
    246                     ? "invalid key"
    247                     : "invalid id";
     199                errmsg = "invalid";
    248200                break;
    249201            case EIDRM:
    250                 errmsg = iskey
    251                     ? "already removed key"
    252                     : "already removed id";
     202                errmsg = "already removed";
    253203                break;
    254204            default:
    255                 errmsg = iskey
    256                     ? "unknown error in key"
    257                     : "unknown error in id";
    258                 break;
    259             }
    260             bb_fprintf(stderr, "%s: %s (%s)\n",
    261                 prog, errmsg, optarg);
     205                errmsg = "unknown error in";
     206                break;
     207            }
     208            bb_error_msg("%s %s (%s)", errmsg, what, optarg);
    262209            continue;
    263210        }
  • branches/2.2.5/mindi-busybox/util-linux/ipcs.c

    r821 r1765  
     1/* vi: set sw=4 ts=4: */
    12/*
    23 * ipcs.c -- provides information on allocated ipc resources.
     
    89 */
    910
    10 #include <stdio.h>
    11 #include <stdlib.h>
    12 #include <getopt.h>
    13 #include <errno.h>
    14 #include <time.h>
    15 #include <pwd.h>
    16 #include <grp.h>
    17 
    1811/* X/OPEN tells us to use <sys/{types,ipc,sem}.h> for semctl() */
    1912/* X/OPEN tells us to use <sys/{types,ipc,msg}.h> for msgctl() */
     
    2518#include <sys/shm.h>
    2619
    27 #include "busybox.h"
     20#include "libbb.h"
    2821
    2922/*-------------------------------------------------------------------*/
     
    3225#ifndef SHM_DEST
    3326/* shm_mode upper byte flags */
    34 #define SHM_DEST        01000   /* segment will be destroyed on last detach */
    35 #define SHM_LOCKED      02000   /* segment will not be swapped */
     27#define SHM_DEST        01000   /* segment will be destroyed on last detach */
     28#define SHM_LOCKED      02000   /* segment will not be swapped */
    3629#endif
    3730
     
    4639#define SHM_INFO        14
    4740struct shm_info {
    48      int  used_ids;
    49      ulong shm_tot; /* total allocated shm */
    50      ulong shm_rss; /* total resident shm */
    51      ulong shm_swp; /* total swapped shm */
    52      ulong swap_attempts;
    53      ulong swap_successes;
     41    int used_ids;
     42    ulong shm_tot;      /* total allocated shm */
     43    ulong shm_rss;      /* total resident shm */
     44    ulong shm_swp;      /* total swapped shm */
     45    ulong swap_attempts;
     46    ulong swap_successes;
    5447};
    5548#endif
     
    6962   X/OPEN tells us to define it ourselves, but until recently
    7063   Linux include files would also define it. */
    71 #if defined (__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
     64#if defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED)
    7265/* union semun is defined by including <sys/sem.h> */
    7366#else
     
    8679   glibc-1.09 has no support for sysv ipc.
    8780   glibc 2 uses __key, __seq */
    88 #if defined (__GNU_LIBRARY__) && __GNU_LIBRARY__ > 1
     81#if defined(__GNU_LIBRARY__) && __GNU_LIBRARY__ > 1
    8982#define KEY __key
    9083#else
     
    9891#define PID 5
    9992
    100 
    101 static void print_perms (int id, struct ipc_perm *ipcp) {
     93static char format;
     94
     95static void print_perms(int id, struct ipc_perm *ipcp)
     96{
    10297    struct passwd *pw;
    10398    struct group *gr;
    10499
    105     bb_printf ("%-10d %-10o", id, ipcp->mode & 0777);
     100    printf("%-10d %-10o", id, ipcp->mode & 0777);
    106101
    107102    if ((pw = getpwuid(ipcp->cuid)))
    108         bb_printf(" %-10s", pw->pw_name);
     103        printf(" %-10s", pw->pw_name);
    109104    else
    110         bb_printf(" %-10d", ipcp->cuid);
     105        printf(" %-10d", ipcp->cuid);
    111106    if ((gr = getgrgid(ipcp->cgid)))
    112         bb_printf(" %-10s", gr->gr_name);
     107        printf(" %-10s", gr->gr_name);
    113108    else
    114         bb_printf(" %-10d", ipcp->cgid);
     109        printf(" %-10d", ipcp->cgid);
    115110
    116111    if ((pw = getpwuid(ipcp->uid)))
    117         bb_printf(" %-10s", pw->pw_name);
     112        printf(" %-10s", pw->pw_name);
    118113    else
    119         bb_printf(" %-10d", ipcp->uid);
     114        printf(" %-10d", ipcp->uid);
    120115    if ((gr = getgrgid(ipcp->gid)))
    121         bb_printf(" %-10s\n", gr->gr_name);
     116        printf(" %-10s\n", gr->gr_name);
    122117    else
    123         bb_printf(" %-10d\n", ipcp->gid);
    124 }
    125 
    126 
    127 static void do_shm (char format)
     118        printf(" %-10d\n", ipcp->gid);
     119}
     120
     121
     122static void do_shm(void)
    128123{
    129124    int maxid, shmid, id;
     
    134129    struct passwd *pw;
    135130
    136     maxid = shmctl (0, SHM_INFO, (struct shmid_ds *) (void *) &shm_info);
     131    maxid = shmctl(0, SHM_INFO, (struct shmid_ds *) (void *) &shm_info);
    137132    if (maxid < 0) {
    138         bb_printf ("kernel not configured for shared memory\n");
     133        printf("kernel not configured for %s\n", "shared memory");
    139134        return;
    140135    }
     
    142137    switch (format) {
    143138    case LIMITS:
    144         bb_printf ("------ Shared Memory Limits --------\n");
    145         if ((shmctl (0, IPC_INFO, (struct shmid_ds *) (void *) &shminfo)) < 0 )
     139        printf("------ Shared Memory %s --------\n", "Limits");
     140        if ((shmctl(0, IPC_INFO, (struct shmid_ds *) (void *) &shminfo)) < 0)
    146141            return;
    147142        /* glibc 2.1.3 and all earlier libc's have ints as fields
    148143           of struct shminfo; glibc 2.1.91 has unsigned long; ach */
    149         bb_printf ("max number of segments = %lu\n"
    150             "max seg size (kbytes) = %lu\n"
    151             "max total shared memory (pages) = %lu\n"
    152             "min seg size (bytes) = %lu\n",
    153             (unsigned long) shminfo.shmmni,
    154             (unsigned long) (shminfo.shmmax >> 10),
    155             (unsigned long) shminfo.shmall,
    156             (unsigned long) shminfo.shmmin);
     144        printf("max number of segments = %lu\n"
     145                  "max seg size (kbytes) = %lu\n"
     146                  "max total shared memory (pages) = %lu\n"
     147                  "min seg size (bytes) = %lu\n",
     148                  (unsigned long) shminfo.shmmni,
     149                  (unsigned long) (shminfo.shmmax >> 10),
     150                  (unsigned long) shminfo.shmall,
     151                  (unsigned long) shminfo.shmmin);
    157152        return;
    158153
    159154    case STATUS:
    160         bb_printf ("------ Shared Memory Status --------\n"
    161             "segments allocated %d\n"
    162             "pages allocated %ld\n"
    163             "pages resident  %ld\n"
    164             "pages swapped   %ld\n"
    165             "Swap performance: %ld attempts\t %ld successes\n",
    166             shm_info.used_ids,
    167             shm_info.shm_tot,
    168             shm_info.shm_rss,
    169             shm_info.shm_swp,
    170             shm_info.swap_attempts, shm_info.swap_successes);
     155        printf("------ Shared Memory %s --------\n", "Status");
     156        printf(   "segments allocated %d\n"
     157                  "pages allocated %ld\n"
     158                  "pages resident  %ld\n"
     159                  "pages swapped   %ld\n"
     160                  "Swap performance: %ld attempts\t%ld successes\n",
     161                  shm_info.used_ids,
     162                  shm_info.shm_tot,
     163                  shm_info.shm_rss,
     164                  shm_info.shm_swp,
     165                  shm_info.swap_attempts, shm_info.swap_successes);
    171166        return;
    172167
    173168    case CREATOR:
    174         bb_printf ("------ Shared Memory Segment Creators/Owners --------\n"
    175             "%-10s %-10s %-10s %-10s %-10s %-10s\n",
    176             "shmid","perms","cuid","cgid","uid","gid");
     169        printf("------ Shared Memory %s --------\n", "Segment Creators/Owners");
     170        printf(   "%-10s %-10s %-10s %-10s %-10s %-10s\n",
     171                  "shmid", "perms", "cuid", "cgid", "uid", "gid");
    177172        break;
    178173
    179174    case TIME:
    180         bb_printf ("------ Shared Memory Attach/Detach/Change Times --------\n"
    181             "%-10s %-10s %-20s %-20s %-20s\n",
    182             "shmid","owner","attached","detached","changed");
     175        printf("------ Shared Memory %s --------\n", "Attach/Detach/Change Times");
     176        printf(   "%-10s %-10s %-20s %-20s %-20s\n",
     177                  "shmid", "owner", "attached", "detached", "changed");
    183178        break;
    184179
    185180    case PID:
    186         bb_printf ("------ Shared Memory Creator/Last-op --------\n"
    187             "%-10s %-10s %-10s %-10s\n",
    188             "shmid","owner","cpid","lpid");
     181        printf("------ Shared Memory %s --------\n", "Creator/Last-op");
     182        printf(   "%-10s %-10s %-10s %-10s\n",
     183                  "shmid", "owner", "cpid", "lpid");
    189184        break;
    190185
    191186    default:
    192         bb_printf ("------ Shared Memory Segments --------\n"
    193             "%-10s %-10s %-10s %-10s %-10s %-10s %-12s\n",
    194             "key","shmid","owner","perms","bytes","nattch","status");
     187        printf("------ Shared Memory %s --------\n", "Segments");
     188        printf(   "%-10s %-10s %-10s %-10s %-10s %-10s %-12s\n",
     189                  "key", "shmid", "owner", "perms", "bytes", "nattch",
     190                  "status");
    195191        break;
    196192    }
    197193
    198194    for (id = 0; id <= maxid; id++) {
    199         shmid = shmctl (id, SHM_STAT, &shmseg);
     195        shmid = shmctl(id, SHM_STAT, &shmseg);
    200196        if (shmid < 0)
    201197            continue;
    202         if (format == CREATOR)  {
    203             print_perms (shmid, ipcp);
     198        if (format == CREATOR) {
     199            print_perms(shmid, ipcp);
    204200            continue;
    205201        }
     
    208204        case TIME:
    209205            if (pw)
    210                 bb_printf ("%-10d %-10.10s", shmid, pw->pw_name);
    211             else
    212                 bb_printf ("%-10d %-10d", shmid, ipcp->uid);
     206                printf("%-10d %-10.10s", shmid, pw->pw_name);
     207            else
     208                printf("%-10d %-10d", shmid, ipcp->uid);
    213209            /* ctime uses static buffer: use separate calls */
    214             bb_printf(" %-20.16s", shmseg.shm_atime
    215                    ? ctime(&shmseg.shm_atime) + 4 : "Not set");
    216             bb_printf(" %-20.16s", shmseg.shm_dtime
    217                    ? ctime(&shmseg.shm_dtime) + 4 : "Not set");
    218             bb_printf(" %-20.16s\n", shmseg.shm_ctime
    219                    ? ctime(&shmseg.shm_ctime) + 4 : "Not set");
     210            printf(" %-20.16s", shmseg.shm_atime
     211                      ? ctime(&shmseg.shm_atime) + 4 : "Not set");
     212            printf(" %-20.16s", shmseg.shm_dtime
     213                      ? ctime(&shmseg.shm_dtime) + 4 : "Not set");
     214            printf(" %-20.16s\n", shmseg.shm_ctime
     215                      ? ctime(&shmseg.shm_ctime) + 4 : "Not set");
    220216            break;
    221217        case PID:
    222218            if (pw)
    223                 bb_printf ("%-10d %-10.10s", shmid, pw->pw_name);
    224             else
    225                 bb_printf ("%-10d %-10d", shmid, ipcp->uid);
    226             bb_printf (" %-10d %-10d\n",
    227                 shmseg.shm_cpid, shmseg.shm_lpid);
     219                printf("%-10d %-10.10s", shmid, pw->pw_name);
     220            else
     221                printf("%-10d %-10d", shmid, ipcp->uid);
     222            printf(" %-10d %-10d\n", shmseg.shm_cpid, shmseg.shm_lpid);
    228223            break;
    229224
    230225        default:
    231                 bb_printf("0x%08x ",ipcp->KEY );
    232             if (pw)
    233                 bb_printf ("%-10d %-10.10s", shmid, pw->pw_name);
    234             else
    235                 bb_printf ("%-10d %-10d", shmid, ipcp->uid);
    236             bb_printf ("%-10o %-10lu %-10ld %-6s %-6s\n",
    237                 ipcp->mode & 0777,
    238                 /*
    239                  * earlier: int, Austin has size_t
    240                  */
    241                 (unsigned long) shmseg.shm_segsz,
    242                 /*
    243                  * glibc-2.1.3 and earlier has unsigned short;
    244                  * Austin has shmatt_t
    245                  */
    246                 (long) shmseg.shm_nattch,
    247                 ipcp->mode & SHM_DEST ? "dest" : " ",
    248                 ipcp->mode & SHM_LOCKED ? "locked" : " ");
    249             break;
    250         }
    251     }
    252     return;
    253 }
    254 
    255 
    256 static void do_sem (char format)
     226            printf("0x%08x ", ipcp->KEY);
     227            if (pw)
     228                printf("%-10d %-10.10s", shmid, pw->pw_name);
     229            else
     230                printf("%-10d %-10d", shmid, ipcp->uid);
     231            printf(" %-10o %-10lu %-10ld %-6s %-6s\n", ipcp->mode & 0777,
     232                      /*
     233                       * earlier: int, Austin has size_t
     234                       */
     235                      (unsigned long) shmseg.shm_segsz,
     236                      /*
     237                       * glibc-2.1.3 and earlier has unsigned short;
     238                       * Austin has shmatt_t
     239                       */
     240                      (long) shmseg.shm_nattch,
     241                      ipcp->mode & SHM_DEST ? "dest" : " ",
     242                      ipcp->mode & SHM_LOCKED ? "locked" : " ");
     243            break;
     244        }
     245    }
     246}
     247
     248
     249static void do_sem(void)
    257250{
    258251    int maxid, semid, id;
     
    263256    union semun arg;
    264257
    265     arg.array = (ushort *)  (void *) &seminfo;
    266     maxid = semctl (0, 0, SEM_INFO, arg);
     258    arg.array = (ushort *) (void *) &seminfo;
     259    maxid = semctl(0, 0, SEM_INFO, arg);
    267260    if (maxid < 0) {
    268         bb_printf ("kernel not configured for semaphores\n");
     261        printf("kernel not configured for %s\n", "semaphores");
    269262        return;
    270263    }
     
    272265    switch (format) {
    273266    case LIMITS:
    274         bb_printf ("------ Semaphore Limits --------\n");
    275         arg.array = (ushort *) (void *) &seminfo; /* damn union */
    276         if ((semctl (0, 0, IPC_INFO, arg)) < 0 )
     267        printf("------ Semaphore %s --------\n", "Limits");
     268        arg.array = (ushort *) (void *) &seminfo;   /* damn union */
     269        if ((semctl(0, 0, IPC_INFO, arg)) < 0)
    277270            return;
    278         bb_printf ("max number of arrays = %d\n"
    279             "max semaphores per array = %d\n"
    280             "max semaphores system wide = %d\n"
    281             "max ops per semop call = %d\n"
    282             "semaphore max value = %d\n",
    283             seminfo.semmni,
    284             seminfo.semmsl,
    285             seminfo.semmns,
    286             seminfo.semopm,
    287             seminfo.semvmx);
     271        printf("max number of arrays = %d\n"
     272                  "max semaphores per array = %d\n"
     273                  "max semaphores system wide = %d\n"
     274                  "max ops per semop call = %d\n"
     275                  "semaphore max value = %d\n",
     276                  seminfo.semmni,
     277                  seminfo.semmsl,
     278                  seminfo.semmns, seminfo.semopm, seminfo.semvmx);
    288279        return;
    289280
    290281    case STATUS:
    291         bb_printf ("------ Semaphore Status --------\n"
    292             "used arrays = %d\n"
    293             "allocated semaphores = %d\n",
    294             seminfo.semusz,
    295             seminfo.semaem);
     282        printf("------ Semaphore %s --------\n", "Status");
     283        printf(   "used arrays = %d\n"
     284                  "allocated semaphores = %d\n",
     285                  seminfo.semusz, seminfo.semaem);
    296286        return;
    297287
    298288    case CREATOR:
    299         bb_printf ("------ Semaphore Arrays Creators/Owners --------\n"
    300             "%-10s %-10s %-10s %-10s %-10s %-10s\n",
    301             "semid","perms","cuid","cgid","uid","gid");
     289        printf("------ Semaphore %s --------\n", "Arrays Creators/Owners");
     290        printf(   "%-10s %-10s %-10s %-10s %-10s %-10s\n",
     291                  "semid", "perms", "cuid", "cgid", "uid", "gid");
    302292        break;
    303293
    304294    case TIME:
    305         bb_printf ("------ Shared Memory Operation/Change Times --------\n"
    306             "%-8s %-10s %-26.24s %-26.24s\n",
    307             "shmid","owner","last-op","last-changed");
     295        printf("------ Shared Memory %s --------\n", "Operation/Change Times");
     296        printf(   "%-8s %-10s %-26.24s %-26.24s\n",
     297                  "shmid", "owner", "last-op", "last-changed");
    308298        break;
    309299
     
    312302
    313303    default:
    314         bb_printf ("------ Semaphore Arrays --------\n"
    315             "%-10s %-10s %-10s %-10s %-10s\n",
    316             "key","semid","owner","perms","nsems");
     304        printf("------ Semaphore %s --------\n", "Arrays");
     305        printf(   "%-10s %-10s %-10s %-10s %-10s\n",
     306                  "key", "semid", "owner", "perms", "nsems");
    317307        break;
    318308    }
     
    320310    for (id = 0; id <= maxid; id++) {
    321311        arg.buf = (struct semid_ds *) &semary;
    322         semid = semctl (id, 0, SEM_STAT, arg);
     312        semid = semctl(id, 0, SEM_STAT, arg);
    323313        if (semid < 0)
    324314            continue;
    325         if (format == CREATOR)  {
    326             print_perms (semid, ipcp);
     315        if (format == CREATOR) {
     316            print_perms(semid, ipcp);
    327317            continue;
    328318        }
     
    331321        case TIME:
    332322            if (pw)
    333                 bb_printf ("%-8d %-10.10s", semid, pw->pw_name);
    334             else
    335                 bb_printf ("%-8d %-10d", semid, ipcp->uid);
    336             bb_printf ("  %-26.24s", semary.sem_otime
    337                 ? ctime(&semary.sem_otime) : "Not set");
    338             bb_printf (" %-26.24s\n", semary.sem_ctime
    339                 ? ctime(&semary.sem_ctime) : "Not set");
     323                printf("%-8d %-10.10s", semid, pw->pw_name);
     324            else
     325                printf("%-8d %-10d", semid, ipcp->uid);
     326            /* ctime uses static buffer: use separate calls */
     327            printf("  %-26.24s", semary.sem_otime
     328                      ? ctime(&semary.sem_otime) : "Not set");
     329            printf(" %-26.24s\n", semary.sem_ctime
     330                      ? ctime(&semary.sem_ctime) : "Not set");
    340331            break;
    341332        case PID:
     
    343334
    344335        default:
    345                 bb_printf("0x%08x ", ipcp->KEY);
    346             if (pw)
    347                 bb_printf ("%-10d %-10.9s", semid, pw->pw_name);
    348             else
    349                 bb_printf ("%-10d %-9d", semid, ipcp->uid);
    350                     bb_printf ("%-10o %-10ld\n",
    351                 ipcp->mode & 0777,
    352                 /*
    353                  * glibc-2.1.3 and earlier has unsigned short;
    354                  * glibc-2.1.91 has variation between
    355                  * unsigned short and unsigned long
    356                  * Austin prescribes unsigned short.
    357                  */
    358                 (long) semary.sem_nsems);
    359             break;
    360         }
    361     }
    362 }
    363 
    364 
    365 static void do_msg (char format)
     336            printf("0x%08x ", ipcp->KEY);
     337            if (pw)
     338                printf("%-10d %-10.9s", semid, pw->pw_name);
     339            else
     340                printf("%-10d %-9d", semid, ipcp->uid);
     341            printf(" %-10o %-10ld\n", ipcp->mode & 0777,
     342                      /*
     343                       * glibc-2.1.3 and earlier has unsigned short;
     344                       * glibc-2.1.91 has variation between
     345                       * unsigned short and unsigned long
     346                       * Austin prescribes unsigned short.
     347                       */
     348                      (long) semary.sem_nsems);
     349            break;
     350        }
     351    }
     352}
     353
     354
     355static void do_msg(void)
    366356{
    367357    int maxid, msqid, id;
     
    371361    struct passwd *pw;
    372362
    373     maxid = msgctl (0, MSG_INFO, (struct msqid_ds *) (void *) &msginfo);
     363    maxid = msgctl(0, MSG_INFO, (struct msqid_ds *) (void *) &msginfo);
    374364    if (maxid < 0) {
    375         bb_printf ("kernel not configured for message queues\n");
     365        printf("kernel not configured for %s\n", "message queues");
    376366        return;
    377367    }
     
    379369    switch (format) {
    380370    case LIMITS:
    381         if ((msgctl (0, IPC_INFO, (struct msqid_ds *) (void *) &msginfo)) < 0 )
     371        if ((msgctl(0, IPC_INFO, (struct msqid_ds *) (void *) &msginfo)) < 0)
    382372            return;
    383         bb_printf ("------ Messages: Limits --------\n"
    384             "max queues system wide = %d\n"
    385             "max size of message (bytes) = %d\n"
    386             "default max size of queue (bytes) = %d\n",
    387             msginfo.msgmni,
    388             msginfo.msgmax,
    389             msginfo.msgmnb);
     373        printf("------ Message%s --------\n", "s: Limits");
     374        printf(   "max queues system wide = %d\n"
     375                  "max size of message (bytes) = %d\n"
     376                  "default max size of queue (bytes) = %d\n",
     377                  msginfo.msgmni, msginfo.msgmax, msginfo.msgmnb);
    390378        return;
    391379
    392380    case STATUS:
    393         bb_printf ("------ Messages: Status --------\n"
    394             "allocated queues = %d\n"
    395             "used headers = %d\n"
    396             "used space = %d bytes\n",
    397             msginfo.msgpool,
    398             msginfo.msgmap,
    399             msginfo.msgtql);
     381        printf("------ Message%s --------\n", "s: Status");
     382        printf(   "allocated queues = %d\n"
     383                  "used headers = %d\n"
     384                  "used space = %d bytes\n",
     385                  msginfo.msgpool, msginfo.msgmap, msginfo.msgtql);
    400386        return;
    401387
    402388    case CREATOR:
    403         bb_printf ("------ Message Queues: Creators/Owners --------\n"
    404             "%-10s %-10s %-10s %-10s %-10s %-10s\n",
    405             "msqid","perms","cuid","cgid","uid","gid");
     389        printf("------ Message%s --------\n", " Queues: Creators/Owners");
     390        printf(   "%-10s %-10s %-10s %-10s %-10s %-10s\n",
     391                  "msqid", "perms", "cuid", "cgid", "uid", "gid");
    406392        break;
    407393
    408394    case TIME:
    409         bb_printf ("------ Message Queues Send/Recv/Change Times --------\n"
    410             "%-8s %-10s %-20s %-20s %-20s\n",
    411             "msqid","owner","send","recv","change");
     395        printf("------ Message%s --------\n", " Queues Send/Recv/Change Times");
     396        printf(   "%-8s %-10s %-20s %-20s %-20s\n",
     397                  "msqid", "owner", "send", "recv", "change");
    412398        break;
    413399
    414400    case PID:
    415         bb_printf ("------ Message Queues PIDs --------\n"
    416             "%-10s %-10s %-10s %-10s\n",
    417             "msqid","owner","lspid","lrpid");
     401        printf("------ Message%s --------\n", " Queues PIDs");
     402        printf(   "%-10s %-10s %-10s %-10s\n",
     403                  "msqid", "owner", "lspid", "lrpid");
    418404        break;
    419405
    420406    default:
    421         bb_printf ("------ Message Queues --------\n"
    422             "%-10s %-10s %-10s %-10s %-12s %-12s\n",
    423             "key","msqid","owner","perms","used-bytes","messages");
     407        printf("------ Message%s --------\n", " Queues");
     408        printf(   "%-10s %-10s %-10s %-10s %-12s %-12s\n",
     409                  "key", "msqid", "owner", "perms", "used-bytes", "messages");
    424410        break;
    425411    }
    426412
    427413    for (id = 0; id <= maxid; id++) {
    428         msqid = msgctl (id, MSG_STAT, &msgque);
     414        msqid = msgctl(id, MSG_STAT, &msgque);
    429415        if (msqid < 0)
    430416            continue;
    431         if (format == CREATOR)  {
    432             print_perms (msqid, ipcp);
     417        if (format == CREATOR) {
     418            print_perms(msqid, ipcp);
    433419            continue;
    434420        }
     
    437423        case TIME:
    438424            if (pw)
    439                 bb_printf ("%-8d %-10.10s", msqid, pw->pw_name);
    440             else
    441                 bb_printf ("%-8d %-10d", msqid, ipcp->uid);
    442             bb_printf (" %-20.16s", msgque.msg_stime
    443                 ? ctime(&msgque.msg_stime) + 4 : "Not set");
    444             bb_printf (" %-20.16s", msgque.msg_rtime
    445                 ? ctime(&msgque.msg_rtime) + 4 : "Not set");
    446             bb_printf (" %-20.16s\n", msgque.msg_ctime
    447                 ? ctime(&msgque.msg_ctime) + 4 : "Not set");
     425                printf("%-8d %-10.10s", msqid, pw->pw_name);
     426            else
     427                printf("%-8d %-10d", msqid, ipcp->uid);
     428            printf(" %-20.16s", msgque.msg_stime
     429                      ? ctime(&msgque.msg_stime) + 4 : "Not set");
     430            printf(" %-20.16s", msgque.msg_rtime
     431                      ? ctime(&msgque.msg_rtime) + 4 : "Not set");
     432            printf(" %-20.16s\n", msgque.msg_ctime
     433                      ? ctime(&msgque.msg_ctime) + 4 : "Not set");
    448434            break;
    449435        case PID:
    450436            if (pw)
    451                 bb_printf ("%-8d %-10.10s", msqid, pw->pw_name);
    452             else
    453                 bb_printf ("%-8d %-10d", msqid, ipcp->uid);
    454             bb_printf ("  %5d     %5d\n",
    455                 msgque.msg_lspid, msgque.msg_lrpid);
     437                printf("%-8d %-10.10s", msqid, pw->pw_name);
     438            else
     439                printf("%-8d %-10d", msqid, ipcp->uid);
     440            printf("  %5d     %5d\n", msgque.msg_lspid, msgque.msg_lrpid);
    456441            break;
    457442
    458443        default:
    459                 bb_printf( "0x%08x ",ipcp->KEY );
    460             if (pw)
    461                 bb_printf ("%-10d %-10.10s", msqid, pw->pw_name);
    462             else
    463                 bb_printf ("%-10d %-10d", msqid, ipcp->uid);
    464                     bb_printf (" %-10o %-12ld %-12ld\n",
    465                 ipcp->mode & 0777,
    466                 /*
    467                  * glibc-2.1.3 and earlier has unsigned short;
    468                  * glibc-2.1.91 has variation between
    469                  * unsigned short, unsigned long
    470                  * Austin has msgqnum_t
    471                  */
    472                 (long) msgque.msg_cbytes,
    473                 (long) msgque.msg_qnum);
    474             break;
    475         }
    476     }
    477     return;
    478 }
    479 
    480 
    481 static void print_shm (int shmid)
     444            printf("0x%08x ", ipcp->KEY);
     445            if (pw)
     446                printf("%-10d %-10.10s", msqid, pw->pw_name);
     447            else
     448                printf("%-10d %-10d", msqid, ipcp->uid);
     449            printf(" %-10o %-12ld %-12ld\n", ipcp->mode & 0777,
     450                      /*
     451                       * glibc-2.1.3 and earlier has unsigned short;
     452                       * glibc-2.1.91 has variation between
     453                       * unsigned short, unsigned long
     454                       * Austin has msgqnum_t
     455                       */
     456                      (long) msgque.msg_cbytes, (long) msgque.msg_qnum);
     457            break;
     458        }
     459    }
     460}
     461
     462
     463static void print_shm(int shmid)
    482464{
    483465    struct shmid_ds shmds;
    484466    struct ipc_perm *ipcp = &shmds.shm_perm;
    485467
    486     if (shmctl (shmid, IPC_STAT, &shmds) == -1) {
    487         perror ("shmctl ");
    488         return;
    489     }
    490 
    491     bb_printf ("\nShared memory Segment shmid=%d\n"
    492         "uid=%d\tgid=%d\tcuid=%d\tcgid=%d\n"
    493         "mode=%#o\taccess_perms=%#o\n"
    494         "bytes=%ld\tlpid=%d\tcpid=%d\tnattch=%ld\n"
    495         "att_time=%-26.24s\n"
    496         "det_time=%-26.24s\n"
    497         "change_time=%-26.24s\n"
    498         "\n",
    499         shmid,
    500         ipcp->uid, ipcp->gid, ipcp->cuid, ipcp->cgid,
    501         ipcp->mode, ipcp->mode & 0777,
    502         (long) shmds.shm_segsz, shmds.shm_lpid, shmds.shm_cpid,
    503         (long) shmds.shm_nattch,
    504         shmds.shm_atime ? ctime (&shmds.shm_atime) : "Not set",
    505         shmds.shm_dtime ? ctime (&shmds.shm_dtime) : "Not set",
    506         ctime (&shmds.shm_ctime));
    507     return;
    508 }
    509 
    510 
    511 static void print_msg (int msqid)
     468    if (shmctl(shmid, IPC_STAT, &shmds) == -1) {
     469        bb_perror_msg("shmctl");
     470        return;
     471    }
     472
     473    printf("\nShared memory Segment shmid=%d\n"
     474              "uid=%d\tgid=%d\tcuid=%d\tcgid=%d\n"
     475              "mode=%#o\taccess_perms=%#o\n"
     476              "bytes=%ld\tlpid=%d\tcpid=%d\tnattch=%ld\n",
     477              shmid,
     478              ipcp->uid, ipcp->gid, ipcp->cuid, ipcp->cgid,
     479              ipcp->mode, ipcp->mode & 0777,
     480              (long) shmds.shm_segsz, shmds.shm_lpid, shmds.shm_cpid,
     481              (long) shmds.shm_nattch);
     482    printf("att_time=%-26.24s\n",
     483              shmds.shm_atime ? ctime(&shmds.shm_atime) : "Not set");
     484    printf("det_time=%-26.24s\n",
     485              shmds.shm_dtime ? ctime(&shmds.shm_dtime) : "Not set");
     486    printf("change_time=%-26.24s\n\n", ctime(&shmds.shm_ctime));
     487}
     488
     489
     490static void print_msg(int msqid)
    512491{
    513492    struct msqid_ds buf;
    514493    struct ipc_perm *ipcp = &buf.msg_perm;
    515494
    516     if (msgctl (msqid, IPC_STAT, &buf) == -1) {
    517         perror ("msgctl ");
    518         return;
    519     }
    520 
    521     bb_printf ("\nMessage Queue msqid=%d\n"
    522         "uid=%d\tgid=%d\tcuid=%d\tcgid=%d\tmode=%#o\n"
    523         "cbytes=%ld\tqbytes=%ld\tqnum=%ld\tlspid=%d\tlrpid=%d\n"
    524         "send_time=%-26.24s\n"
    525         "rcv_time=%-26.24s\n"
    526         "change_time=%-26.24s\n"
    527         "\n",
    528         msqid,
    529         ipcp->uid, ipcp->gid, ipcp->cuid, ipcp->cgid, ipcp->mode,
    530         /*
    531          * glibc-2.1.3 and earlier has unsigned short;
    532          * glibc-2.1.91 has variation between
    533          * unsigned short, unsigned long
    534          * Austin has msgqnum_t (for msg_qbytes)
    535          */
    536         (long) buf.msg_cbytes, (long) buf.msg_qbytes,
    537         (long) buf.msg_qnum, buf.msg_lspid, buf.msg_lrpid,
    538         buf.msg_stime ? ctime (&buf.msg_stime) : "Not set",
    539         buf.msg_rtime ? ctime (&buf.msg_rtime) : "Not set",
    540         buf.msg_ctime ? ctime (&buf.msg_ctime) : "Not set");
    541     return;
    542 }
    543 
    544 static void print_sem (int semid)
     495    if (msgctl(msqid, IPC_STAT, &buf) == -1) {
     496        bb_perror_msg("msgctl");
     497        return;
     498    }
     499
     500    printf("\nMessage Queue msqid=%d\n"
     501              "uid=%d\tgid=%d\tcuid=%d\tcgid=%d\tmode=%#o\n"
     502              "cbytes=%ld\tqbytes=%ld\tqnum=%ld\tlspid=%d\tlrpid=%d\n",
     503              msqid, ipcp->uid, ipcp->gid, ipcp->cuid, ipcp->cgid, ipcp->mode,
     504              /*
     505               * glibc-2.1.3 and earlier has unsigned short;
     506               * glibc-2.1.91 has variation between
     507               * unsigned short, unsigned long
     508               * Austin has msgqnum_t (for msg_qbytes)
     509               */
     510              (long) buf.msg_cbytes, (long) buf.msg_qbytes,
     511              (long) buf.msg_qnum, buf.msg_lspid, buf.msg_lrpid);
     512
     513    printf("send_time=%-26.24s\n",
     514              buf.msg_stime ? ctime(&buf.msg_stime) : "Not set");
     515    printf("rcv_time=%-26.24s\n",
     516              buf.msg_rtime ? ctime(&buf.msg_rtime) : "Not set");
     517    printf("change_time=%-26.24s\n\n",
     518              buf.msg_ctime ? ctime(&buf.msg_ctime) : "Not set");
     519}
     520
     521static void print_sem(int semid)
    545522{
    546523    struct semid_ds semds;
     
    550527
    551528    arg.buf = &semds;
    552     if (semctl (semid, 0, IPC_STAT, arg) < 0) {
    553         perror ("semctl ");
    554         return;
    555     }
    556 
    557     bb_printf ("\nSemaphore Array semid=%d\n"
    558         "uid=%d\t gid=%d\t cuid=%d\t cgid=%d\n"
    559         "mode=%#o, access_perms=%#o\n"
    560         "nsems = %ld\n"
    561         "otime = %-26.24s\n"
    562         "ctime = %-26.24s\n"
    563         "%-10s %-10s %-10s %-10s %-10s\n",
    564         semid,
    565         ipcp->uid, ipcp->gid, ipcp->cuid, ipcp->cgid,
    566         ipcp->mode, ipcp->mode & 0777,
    567         (long) semds.sem_nsems,
    568         semds.sem_otime ? ctime (&semds.sem_otime) : "Not set",
    569         ctime (&semds.sem_ctime),
    570         "semnum","value","ncount","zcount","pid");
     529    if (semctl(semid, 0, IPC_STAT, arg)) {
     530        bb_perror_msg("semctl");
     531        return;
     532    }
     533
     534    printf("\nSemaphore Array semid=%d\n"
     535              "uid=%d\t gid=%d\t cuid=%d\t cgid=%d\n"
     536              "mode=%#o, access_perms=%#o\n"
     537              "nsems = %ld\n"
     538              "otime = %-26.24s\n",
     539              semid,
     540              ipcp->uid, ipcp->gid, ipcp->cuid, ipcp->cgid,
     541              ipcp->mode, ipcp->mode & 0777,
     542              (long) semds.sem_nsems,
     543              semds.sem_otime ? ctime(&semds.sem_otime) : "Not set");
     544    printf("ctime = %-26.24s\n"
     545              "%-10s %-10s %-10s %-10s %-10s\n",
     546              ctime(&semds.sem_ctime),
     547              "semnum", "value", "ncount", "zcount", "pid");
    571548
    572549    arg.val = 0;
    573     for (i=0; i < semds.sem_nsems; i++) {
     550    for (i = 0; i < semds.sem_nsems; i++) {
    574551        int val, ncnt, zcnt, pid;
    575         val = semctl (semid, i, GETVAL, arg);
    576         ncnt = semctl (semid, i, GETNCNT, arg);
    577         zcnt = semctl (semid, i, GETZCNT, arg);
    578         pid = semctl (semid, i, GETPID, arg);
     552
     553        val = semctl(semid, i, GETVAL, arg);
     554        ncnt = semctl(semid, i, GETNCNT, arg);
     555        zcnt = semctl(semid, i, GETZCNT, arg);
     556        pid = semctl(semid, i, GETPID, arg);
    579557        if (val < 0 || ncnt < 0 || zcnt < 0 || pid < 0) {
    580             perror ("semctl ");
    581             bb_fflush_stdout_and_exit (1);
    582         }
    583         bb_printf ("%-10d %-10d %-10d %-10d %-10d\n",
    584             i, val, ncnt, zcnt, pid);
    585     }
    586     bb_printf ("\n");
    587     return;
    588 }
    589 
    590 int ipcs_main (int argc, char **argv) {
    591     int opt, msg = 0, sem = 0, shm = 0, id=0, print=0;
    592     char format = 0;
    593     char options[] = "atclupsmqi:ih?";
    594 
    595     while ((opt = getopt (argc, argv, options)) != -1) {
    596         switch (opt) {
    597         case 'i':
    598             id = atoi (optarg);
    599             print = 1;
    600             break;
    601         case 'a':
    602             msg = shm = sem = 1;
    603             break;
    604         case 'q':
    605             msg = 1;
    606             break;
    607         case 's':
    608             sem = 1;
    609             break;
    610         case 'm':
    611             shm = 1;
    612             break;
    613         case 't':
    614             format = TIME;
    615             break;
    616         case 'c':
    617             format = CREATOR;
    618             break;
    619         case 'p':
    620             format = PID;
    621             break;
    622         case 'l':
    623             format = LIMITS;
    624             break;
    625         case 'u':
    626             format = STATUS;
    627             break;
    628         case 'h':
    629         case '?':
    630             bb_show_usage();
    631             bb_fflush_stdout_and_exit (0);
    632         }
    633     }
    634 
    635     if  (print) {
    636         if (shm) {
    637             print_shm (id);
    638             bb_fflush_stdout_and_exit (0);
    639         }
    640         if (sem) {
    641             print_sem (id);
    642             bb_fflush_stdout_and_exit (0);
    643         }
    644         if (msg) {
    645             print_msg (id);
    646             bb_fflush_stdout_and_exit (0);
     558            bb_perror_msg_and_die("semctl");
     559        }
     560        printf("%-10d %-10d %-10d %-10d %-10d\n", i, val, ncnt, zcnt, pid);
     561    }
     562    puts("");
     563}
     564
     565int ipcs_main(int argc, char **argv);
     566int ipcs_main(int argc, char **argv)
     567{
     568    int id = 0;
     569    unsigned flags = 0;
     570    unsigned opt;
     571    char *opt_i;
     572#define flag_print  (1<<0)
     573#define flag_msg    (1<<1)
     574#define flag_sem    (1<<2)
     575#define flag_shm    (1<<3)
     576
     577    opt = getopt32(argv, "i:aqsmtcplu", &opt_i);
     578    if (opt & 0x1) { // -i
     579        id = xatoi(opt_i);
     580        flags |= flag_print;
     581    }
     582    if (opt & 0x2) flags |= flag_msg | flag_sem | flag_shm; // -a
     583    if (opt & 0x4) flags |= flag_msg; // -q
     584    if (opt & 0x8) flags |= flag_sem; // -s
     585    if (opt & 0x10) flags |= flag_shm; // -m
     586    if (opt & 0x20) format = TIME; // -t
     587    if (opt & 0x40) format = CREATOR; // -c
     588    if (opt & 0x80) format = PID; // -p
     589    if (opt & 0x100) format = LIMITS; // -l
     590    if (opt & 0x200) format = STATUS; // -u
     591
     592    if (flags & flag_print) {
     593        if (flags & flag_shm) {
     594            print_shm(id);
     595            fflush_stdout_and_exit(0);
     596        }
     597        if (flags & flag_sem) {
     598            print_sem(id);
     599            fflush_stdout_and_exit(0);
     600        }
     601        if (flags & flag_msg) {
     602            print_msg(id);
     603            fflush_stdout_and_exit(0);
    647604        }
    648605        bb_show_usage();
    649         bb_fflush_stdout_and_exit (0);
    650     }
    651 
    652     if ( !shm && !msg && !sem)
    653         msg = sem = shm = 1;
    654     bb_printf ("\n");
    655 
    656     if (shm) {
    657         do_shm (format);
    658         bb_printf ("\n");
    659     }
    660     if (sem) {
    661         do_sem (format);
    662         bb_printf ("\n");
    663     }
    664     if (msg) {
    665         do_msg (format);
    666         bb_printf ("\n");
    667     }
    668     return 0;
    669 }
    670 
     606    }
     607
     608    if (!(flags & (flag_shm | flag_msg | flag_sem)))
     609        flags |= flag_msg | flag_shm | flag_sem;
     610    puts("");
     611
     612    if (flags & flag_shm) {
     613        do_shm();
     614        puts("");
     615    }
     616    if (flags & flag_sem) {
     617        do_sem();
     618        puts("");
     619    }
     620    if (flags & flag_msg) {
     621        do_msg();
     622        puts("");
     623    }
     624    fflush_stdout_and_exit(0);
     625}
  • branches/2.2.5/mindi-busybox/util-linux/losetup.c

    r821 r1765  
     1/* vi: set sw=4 ts=4: */
    12/*
    23 * Mini losetup implementation for busybox
     
    89
    910#include <getopt.h>
    10 #include <stdlib.h>
    1111
    12 #include "busybox.h"
     12#include "libbb.h"
    1313
    14 int losetup_main (int argc, char **argv)
     14int losetup_main(int argc, char **argv);
     15int losetup_main(int argc, char **argv)
    1516{
    16   int offset = 0;
     17    unsigned opt;
     18    char *opt_o;
     19    unsigned long long offset = 0;
    1720
    18   /* This will need a "while(getopt()!=-1)" loop when we can have more than
    19      one option, but for now we can't. */
    20   switch(getopt(argc,argv, "do:")) {
    21     case 'd':
    22       /* detach takes exactly one argument */
    23       if(optind+1!=argc) bb_show_usage();
    24       if(!del_loop(argv[optind])) return EXIT_SUCCESS;
    25 die_failed:
    26       bb_perror_msg_and_die("%s",argv[optind]);
     21    opt = getopt32(argv, "do:", &opt_o);
     22    argc -= optind;
     23    argv += optind;
    2724
    28     case 'o':
    29       offset = bb_xparse_number (optarg, NULL);
    30       /* Fall through to do the losetup */
    31     case -1:
    32       /* losetup takes two argument:, loop_device and file */
    33       if(optind+2==argc) {
    34     if(set_loop(&argv[optind], argv[optind + 1], offset)>=0)
    35       return EXIT_SUCCESS;
    36     else goto die_failed;
    37       }
    38       if(optind+1==argc) {
    39     char *s=query_loop(argv[optind]);
    40     if (!s) goto die_failed;
    41     printf("%s: %s\n",argv[optind],s);
    42     if(ENABLE_FEATURE_CLEAN_UP) free(s);
     25    if (opt == 0x3) // -d + -o (illegal)
     26        bb_show_usage();
     27
     28    if (opt == 0x1) { // -d
     29        /* detach takes exactly one argument */
     30        if (argc != 1)
     31            bb_show_usage();
     32        if (!del_loop(argv[0]))
     33            return EXIT_SUCCESS;
     34        bb_perror_nomsg_and_die();
     35    }
     36
     37    if (opt == 0x2) // -o
     38        offset = xatoull(opt_o);
     39
     40    /* -o or no option */
     41
     42    if (argc == 2) {
     43        if (set_loop(&argv[0], argv[1], offset) < 0)
     44            bb_perror_nomsg_and_die();
     45    } else if (argc == 1) {
     46        char *s = query_loop(argv[0]);
     47        if (!s)
     48            bb_perror_nomsg_and_die();
     49        printf("%s: %s\n", argv[0], s);
     50        if (ENABLE_FEATURE_CLEAN_UP)
     51            free(s);
     52    } else {
     53        char dev[sizeof(LOOP_NAME"0")] = LOOP_NAME"0";
     54        char c;
     55        for (c = '0'; c <= '9'; ++c) {
     56            char *s;
     57            dev[sizeof(LOOP_NAME"0")-2] = c;
     58            s = query_loop(dev);
     59            if (s) {
     60                printf("%s: %s\n", dev, s);
     61                if (ENABLE_FEATURE_CLEAN_UP)
     62                    free(s);
     63            }
     64        }
     65    }
    4366    return EXIT_SUCCESS;
    44       }
    45       break;
    46   }
    47   bb_show_usage();
    48   return EXIT_FAILURE;
    4967}
  • branches/2.2.5/mindi-busybox/util-linux/mdev.c

    r902 r1765  
    1 /* vi:set ts=4:
     1/* vi: set sw=4 ts=4: */
     2/*
    23 *
    34 * mdev - Mini udev for busybox
     
    67 * Copyright 2005 Frank Sorenson <frank@tuxrocks.com>
    78 *
    8  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     9 * Licensed under GPL version 2, see file LICENSE in this tarball for details.
    910 */
    1011
    11 #include "busybox.h"
    12 #include <ctype.h>
    13 #include <errno.h>
    14 #include <sys/mman.h>
    15 #include <sys/sysmacros.h>
     12#include "libbb.h"
    1613#include "xregex.h"
    1714
    18 #define DEV_PATH    "/dev"
    19 
    20 struct mdev_globals
    21 {
     15struct globals {
    2216    int root_major, root_minor;
    23 } mdev_globals;
    24 
    25 #define bbg mdev_globals
     17};
     18#define G (*(struct globals*)&bb_common_bufsiz1)
     19#define root_major (G.root_major)
     20#define root_minor (G.root_minor)
     21
     22#define MAX_SYSFS_DEPTH 3 /* prevent infinite loops in /sys symlinks */
    2623
    2724/* mknod in /dev based on a path like "/sys/block/hda/hda1" */
    2825static void make_device(char *path, int delete)
    2926{
    30     char *device_name;
    31     int major, minor, type, len, fd;
     27    const char *device_name;
     28    int major, minor, type, len;
    3229    int mode = 0660;
    3330    uid_t uid = 0;
     
    4340    if (!delete) {
    4441        strcat(path, "/dev");
    45         fd = open(path, O_RDONLY);
    46         len = read(fd, temp + 1, 64);
     42        len = open_read_close(path, temp + 1, 64);
    4743        *temp++ = 0;
    48         close(fd);
    4944        if (len < 1) return;
    5045    }
     
    5247    /* Determine device name, type, major and minor */
    5348
    54     device_name = strrchr(path, '/') + 1;
     49    device_name = bb_basename(path);
    5550    type = path[5]=='c' ? S_IFCHR : S_IFBLK;
    5651
     
    5954    if (ENABLE_FEATURE_MDEV_CONF) {
    6055        char *conf, *pos, *end;
     56        int line, fd;
    6157
    6258        /* mmap the config file */
    63         if (-1 != (fd=open("/etc/mdev.conf",O_RDONLY))) {
    64             len = lseek(fd, 0, SEEK_END);
    65             conf = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
    66             if (conf) {
    67                 int line = 0;
    68 
    69                 /* Loop through lines in mmaped file*/
    70                 for (pos=conf; pos-conf<len;) {
    71                     int field;
    72                     char *end2;
    73 
    74                     line++;
    75                     /* find end of this line */
    76                     for(end=pos; end-conf<len && *end!='\n'; end++)
     59        fd = open("/etc/mdev.conf", O_RDONLY);
     60        if (fd < 0)
     61            goto end_parse;
     62        len = xlseek(fd, 0, SEEK_END);
     63        conf = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
     64        close(fd);
     65        if (!conf)
     66            goto end_parse;
     67
     68        line = 0;
     69        /* Loop through lines in mmaped file*/
     70        for (pos=conf; pos-conf<len;) {
     71            int field;
     72            char *end2;
     73
     74            line++;
     75            /* find end of this line */
     76            for (end=pos; end-conf<len && *end!='\n'; end++)
     77                ;
     78
     79            /* Three fields: regex, uid:gid, mode */
     80            for (field=0; field < (3 + ENABLE_FEATURE_MDEV_EXEC);
     81                    field++)
     82            {
     83                /* Skip whitespace */
     84                while (pos<end && isspace(*pos)) pos++;
     85                if (pos==end || *pos=='#') break;
     86                for (end2=pos;
     87                    end2<end && !isspace(*end2) && *end2!='#'; end2++)
     88                    ;
     89
     90                if (field == 0) {
     91                    /* Regex to match this device */
     92
     93                    char *regex = xstrndup(pos, end2-pos);
     94                    regex_t match;
     95                    regmatch_t off;
     96                    int result;
     97
     98                    /* Is this it? */
     99                    xregcomp(&match,regex, REG_EXTENDED);
     100                    result = regexec(&match, device_name, 1, &off, 0);
     101                    regfree(&match);
     102                    free(regex);
     103
     104                    /* If not this device, skip rest of line */
     105                    if (result || off.rm_so
     106                            || off.rm_eo != strlen(device_name))
     107                        break;
     108                }
     109                if (field == 1) {
     110                    /* uid:gid */
     111
     112                    char *s, *s2;
     113
     114                    /* Find : */
     115                    for (s=pos; s<end2 && *s!=':'; s++)
    77116                        ;
    78 
    79                     /* Three fields: regex, uid:gid, mode */
    80                     for (field=0; field < (3 + ENABLE_FEATURE_MDEV_EXEC);
    81                             field++)
    82                     {
    83                         /* Skip whitespace */
    84                         while (pos<end && isspace(*pos)) pos++;
    85                         if (pos==end || *pos=='#') break;
    86                         for (end2=pos;
    87                             end2<end && !isspace(*end2) && *end2!='#'; end2++)
    88                             ;
    89 
    90                         if (!field) {
    91                             /* Regex to match this device */
    92 
    93                             char *regex = strndupa(pos, end2-pos);
    94                             regex_t match;
    95                             regmatch_t off;
    96                             int result;
    97 
    98                             /* Is this it? */
    99                             xregcomp(&match,regex, REG_EXTENDED);
    100                             result = regexec(&match, device_name, 1, &off, 0);
    101                             regfree(&match);
    102 
    103                             /* If not this device, skip rest of line */
    104                             if (result || off.rm_so
    105                                     || off.rm_eo != strlen(device_name))
    106                                 break;
    107 
    108                         } else if (field == 1) {
    109                             /* uid:gid */
    110 
    111                             char *s, *s2;
    112 
    113                             /* Find : */
    114                             for(s=pos; s<end2 && *s!=':'; s++)
    115                                 ;
    116                             if (s == end2) break;
    117 
    118                             /* Parse UID */
    119                             uid = strtoul(pos,&s2,10);
    120                             if (s != s2) {
    121                                 struct passwd *pass;
    122                                 pass = getpwnam(strndupa(pos, s-pos));
    123                                 if (!pass) break;
    124                                 uid = pass->pw_uid;
    125                             }
    126                             s++;
    127                             /* parse GID */
    128                             gid = strtoul(s, &s2, 10);
    129                             if (end2 != s2) {
    130                                 struct group *grp;
    131                                 grp = getgrnam(strndupa(s, end2-s));
    132                                 if (!grp) break;
    133                                 gid = grp->gr_gid;
    134                             }
    135                         } else if (field == 2) {
    136                             /* mode */
    137 
    138                             mode = strtoul(pos, &pos, 8);
    139                             if (pos != end2) break;
    140                         } else if (ENABLE_FEATURE_MDEV_EXEC && field == 3) {
    141                             // Command to run
    142                             char *s = "@$*", *s2;
    143                             if (!(s2 = strchr(s, *pos++))) {
    144                                 // Force error
    145                                 field = 1;
    146                                 break;
    147                             }
    148                             if ((s2-s+1) & (1<<delete))
    149                                 command = bb_xstrndup(pos, end-pos);
    150                         }
    151 
    152                         pos = end2;
     117                    if (s == end2) break;
     118
     119                    /* Parse UID */
     120                    uid = strtoul(pos, &s2, 10);
     121                    if (s != s2) {
     122                        struct passwd *pass;
     123                        char *_unam = xstrndup(pos, s-pos);
     124                        pass = getpwnam(_unam);
     125                        free(_unam);
     126                        if (!pass) break;
     127                        uid = pass->pw_uid;
    153128                    }
    154 
    155                     /* Did everything parse happily? */
    156 
    157                     if (field > 2) break;
    158                     if (field) bb_error_msg_and_die("Bad line %d",line);
    159 
    160                     /* Next line */
    161                     pos = ++end;
     129                    s++;
     130                    /* parse GID */
     131                    gid = strtoul(s, &s2, 10);
     132                    if (end2 != s2) {
     133                        struct group *grp;
     134                        char *_grnam = xstrndup(s, end2-s);
     135                        grp = getgrnam(_grnam);
     136                        free(_grnam);
     137                        if (!grp) break;
     138                        gid = grp->gr_gid;
     139                    }
    162140                }
    163                 munmap(conf, len);
     141                if (field == 2) {
     142                    /* mode */
     143
     144                    mode = strtoul(pos, &pos, 8);
     145                    if (pos != end2) break;
     146                }
     147                if (ENABLE_FEATURE_MDEV_EXEC && field == 3) {
     148                    // Command to run
     149                    const char *s = "@$*";
     150                    const char *s2;
     151                    s2 = strchr(s, *pos++);
     152                    if (!s2) {
     153                        // Force error
     154                        field = 1;
     155                        break;
     156                    }
     157                    if ((s2-s+1) & (1<<delete))
     158                        command = xstrndup(pos, end-pos);
     159                }
     160
     161                pos = end2;
    164162            }
    165             close(fd);
     163
     164            /* Did everything parse happily? */
     165
     166            if (field > 2) break;
     167            if (field) bb_error_msg_and_die("bad line %d",line);
     168
     169            /* Next line */
     170            pos = ++end;
    166171        }
     172        munmap(conf, len);
     173 end_parse: /* nothing */ ;
    167174    }
    168175
     
    171178        if (sscanf(temp, "%d:%d", &major, &minor) != 2) return;
    172179        if (mknod(device_name, mode | type, makedev(major, minor)) && errno != EEXIST)
    173             bb_perror_msg_and_die("mknod %s failed", device_name);
    174 
    175         if (major == bbg.root_major && minor == bbg.root_minor)
     180            bb_perror_msg_and_die("mknod %s", device_name);
     181
     182        if (major == root_major && minor == root_minor)
    176183            symlink(device_name, "root");
    177    
     184
    178185        if (ENABLE_FEATURE_MDEV_CONF) chown(device_name, uid, gid);
    179186    }
    180187    if (command) {
    181         int rc;
    182         char *s;
    183        
    184         s=bb_xasprintf("MDEV=%s",device_name);
     188        /* setenv will leak memory, so use putenv */
     189        char *s = xasprintf("MDEV=%s", device_name);
    185190        putenv(s);
    186         rc = system(command);
    187         s[4]=0;
    188         putenv(s);
     191        if (system(command) == -1)
     192            bb_perror_msg_and_die("cannot run %s", command);
     193        s[4] = '\0';
     194        unsetenv(s);
    189195        free(s);
    190196        free(command);
    191         if (rc == -1) bb_perror_msg_and_die("Couldn't run %s", command);
    192197    }
    193198    if (delete) unlink(device_name);
    194199}
    195200
    196 /* Recursive search of /sys/block or /sys/class.  path must be a writeable
    197  * buffer of size PATH_MAX containing the directory string to start at. */
    198 
    199 static void find_dev(char *path)
    200 {
    201     DIR *dir;
    202     size_t len = strlen(path);
    203     struct dirent *entry;
    204 
    205     if ((dir = opendir(path)) == NULL)
    206         return;
    207 
    208     while ((entry = readdir(dir)) != NULL) {
    209         struct stat st;
    210 
    211         /* Skip "." and ".." (also skips hidden files, which is ok) */
    212 
    213         if (entry->d_name[0] == '.')
    214             continue;
    215 
    216         // uClibc doesn't fill out entry->d_type reliably. so we use lstat().
    217 
    218         snprintf(path+len, PATH_MAX-len, "/%s", entry->d_name);
    219         if (!lstat(path, &st) && S_ISDIR(st.st_mode)) find_dev(path);
    220         path[len] = 0;
    221 
    222         /* If there's a dev entry, mknod it */
    223 
    224         if (!strcmp(entry->d_name, "dev")) make_device(path, 0);
    225     }
    226 
    227     closedir(dir);
    228 }
    229 
    230 int mdev_main(int argc, char *argv[])
     201/* File callback for /sys/ traversal */
     202static int fileAction(const char *fileName, struct stat *statbuf,
     203                      void *userData, int depth)
     204{
     205    size_t len = strlen(fileName) - 4;
     206    char *scratch = userData;
     207
     208    if (strcmp(fileName + len, "/dev"))
     209        return FALSE;
     210
     211    strcpy(scratch, fileName);
     212    scratch[len] = 0;
     213    make_device(scratch, 0);
     214
     215    return TRUE;
     216}
     217
     218/* Directory callback for /sys/ traversal */
     219static int dirAction(const char *fileName, struct stat *statbuf,
     220                      void *userData, int depth)
     221{
     222    return (depth >= MAX_SYSFS_DEPTH ? SKIP : TRUE);
     223}
     224
     225/* For the full gory details, see linux/Documentation/firmware_class/README
     226 *
     227 * Firmware loading works like this:
     228 * - kernel sets FIRMWARE env var
     229 * - userspace checks /lib/firmware/$FIRMWARE
     230 * - userspace waits for /sys/$DEVPATH/loading to appear
     231 * - userspace writes "1" to /sys/$DEVPATH/loading
     232 * - userspace copies /lib/firmware/$FIRMWARE into /sys/$DEVPATH/data
     233 * - userspace writes "0" (worked) or "-1" (failed) to /sys/$DEVPATH/loading
     234 * - kernel loads firmware into device
     235 */
     236static void load_firmware(const char *const firmware, const char *const sysfs_path)
     237{
     238    int cnt;
     239    int firmware_fd, loading_fd, data_fd;
     240
     241    /* check for $FIRMWARE from kernel */
     242    /* XXX: dont bother: open(NULL) works same as open("no-such-file")
     243     * if (!firmware)
     244     *  return;
     245     */
     246
     247    /* check for /lib/firmware/$FIRMWARE */
     248    xchdir("/lib/firmware");
     249    firmware_fd = xopen(firmware, O_RDONLY);
     250
     251    /* in case we goto out ... */
     252    data_fd = -1;
     253
     254    /* check for /sys/$DEVPATH/loading ... give 30 seconds to appear */
     255    xchdir(sysfs_path);
     256    for (cnt = 0; cnt < 30; ++cnt) {
     257        loading_fd = open("loading", O_WRONLY);
     258        if (loading_fd == -1)
     259            sleep(1);
     260        else
     261            break;
     262    }
     263    if (loading_fd == -1)
     264        goto out;
     265
     266    /* tell kernel we're loading by `echo 1 > /sys/$DEVPATH/loading` */
     267    if (write(loading_fd, "1", 1) != 1)
     268        goto out;
     269
     270    /* load firmware by `cat /lib/firmware/$FIRMWARE > /sys/$DEVPATH/data */
     271    data_fd = open("data", O_WRONLY);
     272    if (data_fd == -1)
     273        goto out;
     274    cnt = bb_copyfd_eof(firmware_fd, data_fd);
     275
     276    /* tell kernel result by `echo [0|-1] > /sys/$DEVPATH/loading` */
     277    if (cnt > 0)
     278        write(loading_fd, "0", 1);
     279    else
     280        write(loading_fd, "-1", 2);
     281
     282 out:
     283    if (ENABLE_FEATURE_CLEAN_UP) {
     284        close(firmware_fd);
     285        close(loading_fd);
     286        close(data_fd);
     287    }
     288}
     289
     290int mdev_main(int argc, char **argv);
     291int mdev_main(int argc, char **argv)
    231292{
    232293    char *action;
     
    234295    RESERVE_CONFIG_BUFFER(temp,PATH_MAX);
    235296
    236     bb_xchdir(DEV_PATH);
     297    xchdir("/dev");
    237298
    238299    /* Scan */
     
    241302        struct stat st;
    242303
    243         stat("/", &st);  // If this fails, we have bigger problems.
    244         bbg.root_major=major(st.st_dev);
    245         bbg.root_minor=minor(st.st_dev);
    246         strcpy(temp,"/sys/block");
    247         find_dev(temp);
    248         strcpy(temp,"/sys/class");
    249         find_dev(temp);
     304        xstat("/", &st);
     305        root_major = major(st.st_dev);
     306        root_minor = minor(st.st_dev);
     307
     308        recursive_action("/sys/block",
     309            ACTION_RECURSE | ACTION_FOLLOWLINKS,
     310            fileAction, dirAction, temp, 0);
     311
     312        recursive_action("/sys/class",
     313            ACTION_RECURSE | ACTION_FOLLOWLINKS,
     314            fileAction, dirAction, temp, 0);
    250315
    251316    /* Hotplug */
     
    254319        action = getenv("ACTION");
    255320        env_path = getenv("DEVPATH");
    256         if (!action || !env_path)
     321        if (!action || !env_path)
    257322            bb_show_usage();
    258323
    259324        sprintf(temp, "/sys%s", env_path);
    260         if (!strcmp(action, "add")) make_device(temp,0);
    261         else if (!strcmp(action, "remove")) make_device(temp,1);
     325        if (!strcmp(action, "remove"))
     326            make_device(temp, 1);
     327        else if (!strcmp(action, "add")) {
     328            make_device(temp, 0);
     329
     330            if (ENABLE_FEATURE_MDEV_LOAD_FIRMWARE)
     331                load_firmware(getenv("FIRMWARE"), temp);
     332        }
    262333    }
    263334
  • branches/2.2.5/mindi-busybox/util-linux/mkfs_minix.c

    r821 r1765  
    3434 *      (Dr. Wettstein, greg%wind.uucp@plains.nodak.edu)
    3535 *
    36  * 30.10.94 - added support for v2 filesystem
    37  *        (Andreas Schwab, schwab@issan.informatik.uni-dortmund.de)
     36 * 30.10.94  - added support for v2 filesystem
     37 *          (Andreas Schwab, schwab@issan.informatik.uni-dortmund.de)
    3838 *
    3939 * 09.11.94  -  Added test to prevent overwrite of mounted fs adapted
     
    6363 */
    6464
    65 #include <stdio.h>
    66 #include <time.h>
    67 #include <unistd.h>
    68 #include <string.h>
    69 #include <signal.h>
    70 #include <fcntl.h>
    71 #include <ctype.h>
    72 #include <stdlib.h>
    73 #include <stdint.h>
    74 #include <termios.h>
    75 #include <sys/ioctl.h>
    76 #include <sys/param.h>
     65#include "libbb.h"
    7766#include <mntent.h>
    78 #include "busybox.h"
    79 
    80 #define MINIX_ROOT_INO 1
    81 #define MINIX_LINK_MAX  250
    82 #define MINIX2_LINK_MAX 65530
    83 
    84 #define MINIX_I_MAP_SLOTS   8
    85 #define MINIX_Z_MAP_SLOTS   64
    86 #define MINIX_SUPER_MAGIC   0x137F      /* original minix fs */
    87 #define MINIX_SUPER_MAGIC2  0x138F      /* minix fs, 30 char names */
    88 #define MINIX2_SUPER_MAGIC  0x2468      /* minix V2 fs */
    89 #define MINIX2_SUPER_MAGIC2 0x2478      /* minix V2 fs, 30 char names */
    90 #define MINIX_VALID_FS      0x0001      /* Clean fs. */
    91 #define MINIX_ERROR_FS      0x0002      /* fs has errors. */
    92 
    93 #define MINIX_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix_inode)))
    94 #define MINIX2_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix2_inode)))
    95 
    96 #define MINIX_V1        0x0001      /* original minix fs */
    97 #define MINIX_V2        0x0002      /* minix V2 fs */
    98 
    99 #define INODE_VERSION(inode)    inode->i_sb->u.minix_sb.s_version
    100 
    101 /*
    102  * This is the original minix inode layout on disk.
    103  * Note the 8-bit gid and atime and ctime.
    104  */
    105 struct minix_inode {
    106     uint16_t i_mode;
    107     uint16_t i_uid;
    108     uint32_t i_size;
    109     uint32_t i_time;
    110     uint8_t  i_gid;
    111     uint8_t  i_nlinks;
    112     uint16_t i_zone[9];
     67
     68#include "minix.h"
     69
     70#define DEBUG 0
     71
     72/* If debugging, store the very same times/uids/gids for image consistency */
     73#if DEBUG
     74# define CUR_TIME 0
     75# define GETUID 0
     76# define GETGID 0
     77#else
     78# define CUR_TIME time(NULL)
     79# define GETUID getuid()
     80# define GETGID getgid()
     81#endif
     82
     83enum {
     84    MAX_GOOD_BLOCKS         = 512,
     85    TEST_BUFFER_BLOCKS      = 16,
    11386};
    11487
    115 /*
    116  * The new minix inode has all the time entries, as well as
    117  * long block numbers and a third indirect block (7+1+1+1
    118  * instead of 7+1+1). Also, some previously 8-bit values are
    119  * now 16-bit. The inode is now 64 bytes instead of 32.
    120  */
    121 struct minix2_inode {
    122     uint16_t i_mode;
    123     uint16_t i_nlinks;
    124     uint16_t i_uid;
    125     uint16_t i_gid;
    126     uint32_t i_size;
    127     uint32_t i_atime;
    128     uint32_t i_mtime;
    129     uint32_t i_ctime;
    130     uint32_t i_zone[10];
     88#if !ENABLE_FEATURE_MINIX2
     89enum { version2 = 0 };
     90#endif
     91
     92struct globals {
     93    int dev_fd;
     94
     95#if ENABLE_FEATURE_MINIX2
     96    smallint version2;
     97#define version2 G.version2
     98#endif
     99    char *device_name;
     100    uint32_t total_blocks;
     101    int badblocks;
     102    int namelen;
     103    int dirsize;
     104    int magic;
     105    char *inode_buffer;
     106    char *inode_map;
     107    char *zone_map;
     108    int used_good_blocks;
     109    unsigned long req_nr_inodes;
     110    unsigned currently_testing;
     111
     112
     113    char root_block[BLOCK_SIZE];
     114    char super_block_buffer[BLOCK_SIZE];
     115    char boot_block_buffer[512];
     116    unsigned short good_blocks_table[MAX_GOOD_BLOCKS];
     117    /* check_blocks(): buffer[] was the biggest static in entire bbox */
     118    char check_blocks_buffer[BLOCK_SIZE * TEST_BUFFER_BLOCKS];
    131119};
    132120
    133 /*
    134  * minix super-block data on disk
    135  */
    136 struct minix_super_block {
    137     uint16_t s_ninodes;
    138     uint16_t s_nzones;
    139     uint16_t s_imap_blocks;
    140     uint16_t s_zmap_blocks;
    141     uint16_t s_firstdatazone;
    142     uint16_t s_log_zone_size;
    143     uint32_t s_max_size;
    144     uint16_t s_magic;
    145     uint16_t s_state;
    146     uint32_t s_zones;
    147 };
    148 
    149 struct minix_dir_entry {
    150     uint16_t inode;
    151     char name[0];
    152 };
    153 
    154 #define NAME_MAX         255   /* # chars in a file name */
    155 
    156 #define MINIX_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix_inode)))
    157 
    158 #define MINIX_VALID_FS               0x0001          /* Clean fs. */
    159 #define MINIX_ERROR_FS               0x0002          /* fs has errors. */
    160 
    161 #define MINIX_SUPER_MAGIC    0x137F          /* original minix fs */
    162 #define MINIX_SUPER_MAGIC2   0x138F          /* minix fs, 30 char names */
     121#define G (*ptr_to_globals)
     122
     123static ALWAYS_INLINE unsigned div_roundup(unsigned size, unsigned n)
     124{
     125    return (size + n-1) / n;
     126}
     127
     128#define INODE_BUF1              (((struct minix1_inode*)G.inode_buffer) - 1)
     129#define INODE_BUF2              (((struct minix2_inode*)G.inode_buffer) - 1)
     130
     131#define SB                      (*(struct minix_super_block*)G.super_block_buffer)
     132
     133#define SB_INODES               (SB.s_ninodes)
     134#define SB_IMAPS                (SB.s_imap_blocks)
     135#define SB_ZMAPS                (SB.s_zmap_blocks)
     136#define SB_FIRSTZONE            (SB.s_firstdatazone)
     137#define SB_ZONE_SIZE            (SB.s_log_zone_size)
     138#define SB_MAXSIZE              (SB.s_max_size)
     139#define SB_MAGIC                (SB.s_magic)
     140
     141#if !ENABLE_FEATURE_MINIX2
     142# define SB_ZONES               (SB.s_nzones)
     143# define INODE_BLOCKS           div_roundup(SB_INODES, MINIX1_INODES_PER_BLOCK)
     144#else
     145# define SB_ZONES               (version2 ? SB.s_zones : SB.s_nzones)
     146# define INODE_BLOCKS           div_roundup(SB_INODES, \
     147                                version2 ? MINIX2_INODES_PER_BLOCK : MINIX1_INODES_PER_BLOCK)
     148#endif
     149
     150#define INODE_BUFFER_SIZE       (INODE_BLOCKS * BLOCK_SIZE)
     151#define NORM_FIRSTZONE          (2 + SB_IMAPS + SB_ZMAPS + INODE_BLOCKS)
     152
     153/* Before you ask "where they come from?": */
     154/* setbit/clrbit are supplied by sys/param.h */
     155
     156static int minix_bit(const char* a, unsigned i)
     157{
     158      return a[i >> 3] & (1<<(i & 7));
     159}
     160
     161static void minix_setbit(char *a, unsigned i)
     162{
     163    setbit(a, i);
     164}
     165static void minix_clrbit(char *a, unsigned i)
     166{
     167    clrbit(a, i);
     168}
     169
     170/* Note: do not assume 0/1, it is 0/nonzero */
     171#define zone_in_use(x)  minix_bit(G.zone_map,(x)-SB_FIRSTZONE+1)
     172/*#define inode_in_use(x) minix_bit(G.inode_map,(x))*/
     173
     174#define mark_inode(x)   minix_setbit(G.inode_map,(x))
     175#define unmark_inode(x) minix_clrbit(G.inode_map,(x))
     176#define mark_zone(x)    minix_setbit(G.zone_map,(x)-SB_FIRSTZONE+1)
     177#define unmark_zone(x)  minix_clrbit(G.zone_map,(x)-SB_FIRSTZONE+1)
    163178
    164179#ifndef BLKGETSIZE
    165 #define BLKGETSIZE _IO(0x12,96)    /* return device size */
    166 #endif
    167 
    168 
    169 #ifndef __linux__
    170 #define volatile
    171 #endif
    172 
    173 #define MINIX_ROOT_INO 1
    174 #define MINIX_BAD_INO 2
    175 
    176 #define TEST_BUFFER_BLOCKS 16
    177 #define MAX_GOOD_BLOCKS 512
    178 
    179 #define UPPER(size,n) (((size)+((n)-1))/(n))
    180 #define INODE_SIZE (sizeof(struct minix_inode))
    181 #ifdef CONFIG_FEATURE_MINIX2
    182 #define INODE_SIZE2 (sizeof(struct minix2_inode))
    183 #define INODE_BLOCKS UPPER(INODES, (version2 ? MINIX2_INODES_PER_BLOCK \
    184                     : MINIX_INODES_PER_BLOCK))
    185 #else
    186 #define INODE_BLOCKS UPPER(INODES, (MINIX_INODES_PER_BLOCK))
    187 #endif
    188 #define INODE_BUFFER_SIZE (INODE_BLOCKS * BLOCK_SIZE)
    189 
    190 #define BITS_PER_BLOCK (BLOCK_SIZE<<3)
    191 
    192 static char *device_name;
    193 static int DEV = -1;
    194 static uint32_t BLOCKS;
    195 static int check;
    196 static int badblocks;
    197 static int namelen = 30;        /* default (changed to 30, per Linus's
    198 
    199                                    suggestion, Sun Nov 21 08:05:07 1993) */
    200 static int dirsize = 32;
    201 static int magic = MINIX_SUPER_MAGIC2;
    202 static int version2;
    203 
    204 static char root_block[BLOCK_SIZE];
    205 
    206 static char *inode_buffer;
    207 
    208 #define Inode (((struct minix_inode *) inode_buffer)-1)
    209 #ifdef CONFIG_FEATURE_MINIX2
    210 #define Inode2 (((struct minix2_inode *) inode_buffer)-1)
    211 #endif
    212 static char super_block_buffer[BLOCK_SIZE];
    213 static char boot_block_buffer[512];
    214 
    215 #define Super (*(struct minix_super_block *)super_block_buffer)
    216 #define INODES (Super.s_ninodes)
    217 #ifdef CONFIG_FEATURE_MINIX2
    218 #define ZONES (version2 ? Super.s_zones : Super.s_nzones)
    219 #else
    220 #define ZONES (Super.s_nzones)
    221 #endif
    222 #define IMAPS (Super.s_imap_blocks)
    223 #define ZMAPS (Super.s_zmap_blocks)
    224 #define FIRSTZONE (Super.s_firstdatazone)
    225 #define ZONESIZE (Super.s_log_zone_size)
    226 #define MAXSIZE (Super.s_max_size)
    227 #define MAGIC (Super.s_magic)
    228 #define NORM_FIRSTZONE (2+IMAPS+ZMAPS+INODE_BLOCKS)
    229 
    230 static char *inode_map;
    231 static char *zone_map;
    232 
    233 static unsigned short good_blocks_table[MAX_GOOD_BLOCKS];
    234 static int used_good_blocks;
    235 static unsigned long req_nr_inodes;
    236 
    237 static inline int bit(char * a,unsigned int i)
    238 {
    239       return (a[i >> 3] & (1<<(i & 7))) != 0;
    240 }
    241 #define inode_in_use(x) (bit(inode_map,(x)))
    242 #define zone_in_use(x) (bit(zone_map,(x)-FIRSTZONE+1))
    243 
    244 #define mark_inode(x) (setbit(inode_map,(x)))
    245 #define unmark_inode(x) (clrbit(inode_map,(x)))
    246 
    247 #define mark_zone(x) (setbit(zone_map,(x)-FIRSTZONE+1))
    248 #define unmark_zone(x) (clrbit(zone_map,(x)-FIRSTZONE+1))
    249 
    250 /*
    251  * Check to make certain that our new filesystem won't be created on
    252  * an already mounted partition.  Code adapted from mke2fs, Copyright
    253  * (C) 1994 Theodore Ts'o.  Also licensed under GPL.
    254  */
    255 static inline void check_mount(void)
    256 {
    257     FILE *f;
    258     struct mntent *mnt;
    259 
    260     if ((f = setmntent(MOUNTED, "r")) == NULL)
    261         return;
    262     while ((mnt = getmntent(f)) != NULL)
    263         if (strcmp(device_name, mnt->mnt_fsname) == 0)
    264             break;
    265     endmntent(f);
    266     if (!mnt)
    267         return;
    268 
    269     bb_error_msg_and_die("%s is mounted; will not make a filesystem here!", device_name);
    270 }
     180# define BLKGETSIZE     _IO(0x12,96)    /* return device size */
     181#endif
     182
    271183
    272184static long valid_offset(int fd, int offset)
     
    274186    char ch;
    275187
    276     if (lseek(fd, offset, 0) < 0)
     188    if (lseek(fd, offset, SEEK_SET) < 0)
    277189        return 0;
    278190    if (read(fd, &ch, 1) < 1)
     
    281193}
    282194
    283 static inline int count_blocks(int fd)
     195static int count_blocks(int fd)
    284196{
    285197    int high, low;
     
    288200    for (high = 1; valid_offset(fd, high); high *= 2)
    289201        low = high;
     202
    290203    while (low < high - 1) {
    291204        const int mid = (low + high) / 2;
     
    300213}
    301214
    302 static inline int get_size(const char *file)
     215static int get_size(const char *file)
    303216{
    304217    int fd;
    305218    long size;
    306219
    307     fd = bb_xopen3(file, O_RDWR, 0);
     220    fd = xopen(file, O_RDWR);
    308221    if (ioctl(fd, BLKGETSIZE, &size) >= 0) {
    309222        close(fd);
     
    316229}
    317230
    318 static inline void write_tables(void)
     231static void write_tables(void)
    319232{
    320233    /* Mark the super block valid. */
    321     Super.s_state |= MINIX_VALID_FS;
    322     Super.s_state &= ~MINIX_ERROR_FS;
    323 
    324     if (lseek(DEV, 0, SEEK_SET))
    325         bb_error_msg_and_die("seek to boot block failed in write_tables");
    326     if (512 != write(DEV, boot_block_buffer, 512))
    327         bb_error_msg_and_die("unable to clear boot sector");
    328     if (BLOCK_SIZE != lseek(DEV, BLOCK_SIZE, SEEK_SET))
    329         bb_error_msg_and_die("seek failed in write_tables");
    330     if (BLOCK_SIZE != write(DEV, super_block_buffer, BLOCK_SIZE))
    331         bb_error_msg_and_die("unable to write super-block");
    332     if (IMAPS * BLOCK_SIZE != write(DEV, inode_map, IMAPS * BLOCK_SIZE))
    333         bb_error_msg_and_die("unable to write inode map");
    334     if (ZMAPS * BLOCK_SIZE != write(DEV, zone_map, ZMAPS * BLOCK_SIZE))
    335         bb_error_msg_and_die("unable to write zone map");
    336     if (INODE_BUFFER_SIZE != write(DEV, inode_buffer, INODE_BUFFER_SIZE))
    337         bb_error_msg_and_die("unable to write inodes");
    338 
     234    SB.s_state |= MINIX_VALID_FS;
     235    SB.s_state &= ~MINIX_ERROR_FS;
     236
     237    msg_eol = "seek to 0 failed";
     238    xlseek(G.dev_fd, 0, SEEK_SET);
     239
     240    msg_eol = "cannot clear boot sector";
     241    xwrite(G.dev_fd, G.boot_block_buffer, 512);
     242
     243    msg_eol = "seek to BLOCK_SIZE failed";
     244    xlseek(G.dev_fd, BLOCK_SIZE, SEEK_SET);
     245
     246    msg_eol = "cannot write superblock";
     247    xwrite(G.dev_fd, G.super_block_buffer, BLOCK_SIZE);
     248
     249    msg_eol = "cannot write inode map";
     250    xwrite(G.dev_fd, G.inode_map, SB_IMAPS * BLOCK_SIZE);
     251
     252    msg_eol = "cannot write zone map";
     253    xwrite(G.dev_fd, G.zone_map, SB_ZMAPS * BLOCK_SIZE);
     254
     255    msg_eol = "cannot write inodes";
     256    xwrite(G.dev_fd, G.inode_buffer, INODE_BUFFER_SIZE);
     257
     258    msg_eol = "\n";
    339259}
    340260
    341261static void write_block(int blk, char *buffer)
    342262{
    343     if (blk * BLOCK_SIZE != lseek(DEV, blk * BLOCK_SIZE, SEEK_SET))
    344         bb_error_msg_and_die("seek failed in write_block");
    345     if (BLOCK_SIZE != write(DEV, buffer, BLOCK_SIZE))
    346         bb_error_msg_and_die("write failed in write_block");
     263    xlseek(G.dev_fd, blk * BLOCK_SIZE, SEEK_SET);
     264    xwrite(G.dev_fd, buffer, BLOCK_SIZE);
    347265}
    348266
     
    351269    int blk;
    352270
    353     if (used_good_blocks + 1 >= MAX_GOOD_BLOCKS)
     271    if (G.used_good_blocks + 1 >= MAX_GOOD_BLOCKS)
    354272        bb_error_msg_and_die("too many bad blocks");
    355     if (used_good_blocks)
    356         blk = good_blocks_table[used_good_blocks - 1] + 1;
     273    if (G.used_good_blocks)
     274        blk = G.good_blocks_table[G.used_good_blocks - 1] + 1;
    357275    else
    358         blk = FIRSTZONE;
    359     while (blk < ZONES && zone_in_use(blk))
     276        blk = SB_FIRSTZONE;
     277    while (blk < SB_ZONES && zone_in_use(blk))
    360278        blk++;
    361     if (blk >= ZONES)
     279    if (blk >= SB_ZONES)
    362280        bb_error_msg_and_die("not enough good blocks");
    363     good_blocks_table[used_good_blocks] = blk;
    364     used_good_blocks++;
     281    G.good_blocks_table[G.used_good_blocks] = blk;
     282    G.used_good_blocks++;
    365283    return blk;
    366284}
    367285
    368 static inline void mark_good_blocks(void)
     286static void mark_good_blocks(void)
    369287{
    370288    int blk;
    371289
    372     for (blk = 0; blk < used_good_blocks; blk++)
    373         mark_zone(good_blocks_table[blk]);
     290    for (blk = 0; blk < G.used_good_blocks; blk++)
     291        mark_zone(G.good_blocks_table[blk]);
    374292}
    375293
     
    377295{
    378296    if (!zone)
    379         zone = FIRSTZONE - 1;
    380     while (++zone < ZONES)
     297        zone = SB_FIRSTZONE - 1;
     298    while (++zone < SB_ZONES)
    381299        if (zone_in_use(zone))
    382300            return zone;
     
    384302}
    385303
    386 static inline void make_bad_inode(void)
    387 {
    388     struct minix_inode *inode = &Inode[MINIX_BAD_INO];
     304static void make_bad_inode(void)
     305{
     306    struct minix1_inode *inode = &INODE_BUF1[MINIX_BAD_INO];
    389307    int i, j, zone;
    390308    int ind = 0, dind = 0;
     
    394312#define NEXT_BAD (zone = next(zone))
    395313
    396     if (!badblocks)
     314    if (!G.badblocks)
    397315        return;
    398316    mark_inode(MINIX_BAD_INO);
    399317    inode->i_nlinks = 1;
    400     inode->i_time = time(NULL);
     318    /* BTW, setting this makes all images different */
     319    /* it's harder to check for bugs then - diff isn't helpful :(... */
     320    inode->i_time = CUR_TIME;
    401321    inode->i_mode = S_IFREG + 0000;
    402     inode->i_size = badblocks * BLOCK_SIZE;
     322    inode->i_size = G.badblocks * BLOCK_SIZE;
    403323    zone = next(0);
    404324    for (i = 0; i < 7; i++) {
     
    427347    }
    428348    bb_error_msg_and_die("too many bad blocks");
    429   end_bad:
     349 end_bad:
    430350    if (ind)
    431351        write_block(ind, (char *) ind_block);
     
    434354}
    435355
    436 #ifdef CONFIG_FEATURE_MINIX2
    437 static inline void make_bad_inode2(void)
    438 {
    439     struct minix2_inode *inode = &Inode2[MINIX_BAD_INO];
     356#if ENABLE_FEATURE_MINIX2
     357static void make_bad_inode2(void)
     358{
     359    struct minix2_inode *inode = &INODE_BUF2[MINIX_BAD_INO];
    440360    int i, j, zone;
    441361    int ind = 0, dind = 0;
     
    443363    unsigned long dind_block[BLOCK_SIZE >> 2];
    444364
    445     if (!badblocks)
     365    if (!G.badblocks)
    446366        return;
    447367    mark_inode(MINIX_BAD_INO);
    448368    inode->i_nlinks = 1;
    449     inode->i_atime = inode->i_mtime = inode->i_ctime = time(NULL);
     369    inode->i_atime = inode->i_mtime = inode->i_ctime = CUR_TIME;
    450370    inode->i_mode = S_IFREG + 0000;
    451     inode->i_size = badblocks * BLOCK_SIZE;
     371    inode->i_size = G.badblocks * BLOCK_SIZE;
    452372    zone = next(0);
    453373    for (i = 0; i < 7; i++) {
     
    477397    /* Could make triple indirect block here */
    478398    bb_error_msg_and_die("too many bad blocks");
    479   end_bad:
     399 end_bad:
    480400    if (ind)
    481401        write_block(ind, (char *) ind_block);
     
    483403        write_block(dind, (char *) dind_block);
    484404}
    485 #endif
    486 
    487 static inline void make_root_inode(void)
    488 {
    489     struct minix_inode *inode = &Inode[MINIX_ROOT_INO];
     405#else
     406void make_bad_inode2(void);
     407#endif
     408
     409static void make_root_inode(void)
     410{
     411    struct minix1_inode *inode = &INODE_BUF1[MINIX_ROOT_INO];
    490412
    491413    mark_inode(MINIX_ROOT_INO);
    492414    inode->i_zone[0] = get_free_block();
    493415    inode->i_nlinks = 2;
    494     inode->i_time = time(NULL);
    495     if (badblocks)
    496         inode->i_size = 3 * dirsize;
     416    inode->i_time = CUR_TIME;
     417    if (G.badblocks)
     418        inode->i_size = 3 * G.dirsize;
    497419    else {
    498         root_block[2 * dirsize] = '\0';
    499         root_block[2 * dirsize + 1] = '\0';
    500         inode->i_size = 2 * dirsize;
     420        G.root_block[2 * G.dirsize] = '\0';
     421        G.root_block[2 * G.dirsize + 1] = '\0';
     422        inode->i_size = 2 * G.dirsize;
    501423    }
    502424    inode->i_mode = S_IFDIR + 0755;
    503     inode->i_uid = getuid();
     425    inode->i_uid = GETUID;
    504426    if (inode->i_uid)
    505         inode->i_gid = getgid();
    506     write_block(inode->i_zone[0], root_block);
    507 }
    508 
    509 #ifdef CONFIG_FEATURE_MINIX2
    510 static inline void make_root_inode2(void)
    511 {
    512     struct minix2_inode *inode = &Inode2[MINIX_ROOT_INO];
     427        inode->i_gid = GETGID;
     428    write_block(inode->i_zone[0], G.root_block);
     429}
     430
     431#if ENABLE_FEATURE_MINIX2
     432static void make_root_inode2(void)
     433{
     434    struct minix2_inode *inode = &INODE_BUF2[MINIX_ROOT_INO];
    513435
    514436    mark_inode(MINIX_ROOT_INO);
    515437    inode->i_zone[0] = get_free_block();
    516438    inode->i_nlinks = 2;
    517     inode->i_atime = inode->i_mtime = inode->i_ctime = time(NULL);
    518     if (badblocks)
    519         inode->i_size = 3 * dirsize;
     439    inode->i_atime = inode->i_mtime = inode->i_ctime = CUR_TIME;
     440    if (G.badblocks)
     441        inode->i_size = 3 * G.dirsize;
    520442    else {
    521         root_block[2 * dirsize] = '\0';
    522         root_block[2 * dirsize + 1] = '\0';
    523         inode->i_size = 2 * dirsize;
     443        G.root_block[2 * G.dirsize] = '\0';
     444        G.root_block[2 * G.dirsize + 1] = '\0';
     445        inode->i_size = 2 * G.dirsize;
    524446    }
    525447    inode->i_mode = S_IFDIR + 0755;
    526     inode->i_uid = getuid();
     448    inode->i_uid = GETUID;
    527449    if (inode->i_uid)
    528         inode->i_gid = getgid();
    529     write_block(inode->i_zone[0], root_block);
    530 }
    531 #endif
    532 
    533 static inline void setup_tables(void)
    534 {
    535     int i;
     450        inode->i_gid = GETGID;
     451    write_block(inode->i_zone[0], G.root_block);
     452}
     453#else
     454void make_root_inode2(void);
     455#endif
     456
     457/*
     458 * Perform a test of a block; return the number of
     459 * blocks readable.
     460 */
     461static size_t do_check(char *buffer, size_t try, unsigned current_block)
     462{
     463    ssize_t got;
     464
     465    /* Seek to the correct loc. */
     466    msg_eol = "seek failed during testing of blocks";
     467    xlseek(G.dev_fd, current_block * BLOCK_SIZE, SEEK_SET);
     468    msg_eol = "\n";
     469
     470    /* Try the read */
     471    got = read(G.dev_fd, buffer, try * BLOCK_SIZE);
     472    if (got < 0)
     473        got = 0;
     474    try = ((size_t)got) / BLOCK_SIZE;
     475
     476    if (got & (BLOCK_SIZE - 1))
     477        fprintf(stderr, "Short read at block %u\n", (unsigned)(current_block + try));
     478    return try;
     479}
     480
     481static void alarm_intr(int alnum)
     482{
     483    if (G.currently_testing >= SB_ZONES)
     484        return;
     485    signal(SIGALRM, alarm_intr);
     486    alarm(5);
     487    if (!G.currently_testing)
     488        return;
     489    printf("%d ...", G.currently_testing);
     490    fflush(stdout);
     491}
     492
     493static void check_blocks(void)
     494{
     495    size_t try, got;
     496
     497    G.currently_testing = 0;
     498    signal(SIGALRM, alarm_intr);
     499    alarm(5);
     500    while (G.currently_testing < SB_ZONES) {
     501        msg_eol = "seek failed in check_blocks";
     502        xlseek(G.dev_fd, G.currently_testing * BLOCK_SIZE, SEEK_SET);
     503        msg_eol = "\n";
     504        try = TEST_BUFFER_BLOCKS;
     505        if (G.currently_testing + try > SB_ZONES)
     506            try = SB_ZONES - G.currently_testing;
     507        got = do_check(G.check_blocks_buffer, try, G.currently_testing);
     508        G.currently_testing += got;
     509        if (got == try)
     510            continue;
     511        if (G.currently_testing < SB_FIRSTZONE)
     512            bb_error_msg_and_die("bad blocks before data-area: cannot make fs");
     513        mark_zone(G.currently_testing);
     514        G.badblocks++;
     515        G.currently_testing++;
     516    }
     517    alarm(0);
     518    printf("%d bad block(s)\n", G.badblocks);
     519}
     520
     521static void get_list_blocks(char *filename)
     522{
     523    FILE *listfile;
     524    unsigned long blockno;
     525
     526    listfile = xfopen(filename, "r");
     527    while (!feof(listfile)) {
     528        fscanf(listfile, "%ld\n", &blockno);
     529        mark_zone(blockno);
     530        G.badblocks++;
     531    }
     532    printf("%d bad block(s)\n", G.badblocks);
     533}
     534
     535static void setup_tables(void)
     536{
    536537    unsigned long inodes;
    537 
    538     memset(super_block_buffer, 0, BLOCK_SIZE);
    539     memset(boot_block_buffer, 0, 512);
    540     MAGIC = magic;
    541     ZONESIZE = 0;
    542     MAXSIZE = version2 ? 0x7fffffff : (7 + 512 + 512 * 512) * 1024;
    543 #ifdef CONFIG_FEATURE_MINIX2
    544     if (version2) {
    545         Super.s_zones =  BLOCKS;
    546     } else
    547 #endif
    548         Super.s_nzones = BLOCKS;
    549 
    550 /* some magic nrs: 1 inode / 3 blocks */
    551     if (req_nr_inodes == 0)
    552         inodes = BLOCKS / 3;
     538    unsigned norm_firstzone;
     539    unsigned sb_zmaps;
     540    unsigned i;
     541
     542    /* memset(G.super_block_buffer, 0, BLOCK_SIZE); */
     543    /* memset(G.boot_block_buffer, 0, 512); */
     544    SB_MAGIC = G.magic;
     545    SB_ZONE_SIZE = 0;
     546    SB_MAXSIZE = version2 ? 0x7fffffff : (7 + 512 + 512 * 512) * 1024;
     547    if (version2)
     548        SB.s_zones = G.total_blocks;
    553549    else
    554         inodes = req_nr_inodes;
     550        SB.s_nzones = G.total_blocks;
     551
     552    /* some magic nrs: 1 inode / 3 blocks */
     553    if (G.req_nr_inodes == 0)
     554        inodes = G.total_blocks / 3;
     555    else
     556        inodes = G.req_nr_inodes;
    555557    /* Round up inode count to fill block size */
    556 #ifdef CONFIG_FEATURE_MINIX2
    557558    if (version2)
    558         inodes = ((inodes + MINIX2_INODES_PER_BLOCK - 1) &
    559                   ~(MINIX2_INODES_PER_BLOCK - 1));
     559        inodes = (inodes + MINIX2_INODES_PER_BLOCK - 1) &
     560                         ~(MINIX2_INODES_PER_BLOCK - 1);
    560561    else
    561 #endif
    562         inodes = ((inodes + MINIX_INODES_PER_BLOCK - 1) &
    563                   ~(MINIX_INODES_PER_BLOCK - 1));
     562        inodes = (inodes + MINIX1_INODES_PER_BLOCK - 1) &
     563                         ~(MINIX1_INODES_PER_BLOCK - 1);
    564564    if (inodes > 65535)
    565565        inodes = 65535;
    566     INODES = inodes;
    567     IMAPS = UPPER(INODES + 1, BITS_PER_BLOCK);
    568     ZMAPS = 0;
    569     i = 0;
    570     while (ZMAPS !=
    571            UPPER(BLOCKS - (2 + IMAPS + ZMAPS + INODE_BLOCKS) + 1,
    572                  BITS_PER_BLOCK) && i < 1000) {
    573         ZMAPS =
    574             UPPER(BLOCKS - (2 + IMAPS + ZMAPS + INODE_BLOCKS) + 1,
    575                   BITS_PER_BLOCK);
    576         i++;
    577     }
     566    SB_INODES = inodes;
     567    SB_IMAPS = div_roundup(SB_INODES + 1, BITS_PER_BLOCK);
     568
    578569    /* Real bad hack but overwise mkfs.minix can be thrown
    579570     * in infinite loop...
    580571     * try:
    581572     * dd if=/dev/zero of=test.fs count=10 bs=1024
    582      * /sbin/mkfs.minix -i 200 test.fs
    583      * */
    584     if (i >= 999) {
    585         bb_error_msg_and_die("unable to allocate buffers for maps");
    586     }
    587     FIRSTZONE = NORM_FIRSTZONE;
    588     inode_map = xmalloc(IMAPS * BLOCK_SIZE);
    589     zone_map = xmalloc(ZMAPS * BLOCK_SIZE);
    590     memset(inode_map, 0xff, IMAPS * BLOCK_SIZE);
    591     memset(zone_map, 0xff, ZMAPS * BLOCK_SIZE);
    592     for (i = FIRSTZONE; i < ZONES; i++)
     573     * mkfs.minix -i 200 test.fs
     574     */
     575    /* This code is not insane: NORM_FIRSTZONE is not a constant,
     576     * it is calculated from SB_INODES, SB_IMAPS and SB_ZMAPS */
     577    i = 999;
     578    SB_ZMAPS = 0;
     579    do {
     580        norm_firstzone = NORM_FIRSTZONE;
     581        sb_zmaps = div_roundup(G.total_blocks - norm_firstzone + 1, BITS_PER_BLOCK);
     582        if (SB_ZMAPS == sb_zmaps) goto got_it;
     583        SB_ZMAPS = sb_zmaps;
     584        /* new SB_ZMAPS, need to recalc NORM_FIRSTZONE */
     585    } while (--i);
     586    bb_error_msg_and_die("incompatible size/inode count, try different -i N");
     587 got_it:
     588
     589    SB_FIRSTZONE = norm_firstzone;
     590    G.inode_map = xmalloc(SB_IMAPS * BLOCK_SIZE);
     591    G.zone_map = xmalloc(SB_ZMAPS * BLOCK_SIZE);
     592    memset(G.inode_map, 0xff, SB_IMAPS * BLOCK_SIZE);
     593    memset(G.zone_map, 0xff, SB_ZMAPS * BLOCK_SIZE);
     594    for (i = SB_FIRSTZONE; i < SB_ZONES; i++)
    593595        unmark_zone(i);
    594     for (i = MINIX_ROOT_INO; i <= INODES; i++)
     596    for (i = MINIX_ROOT_INO; i <= SB_INODES; i++)
    595597        unmark_inode(i);
    596     inode_buffer = xmalloc(INODE_BUFFER_SIZE);
    597     memset(inode_buffer, 0, INODE_BUFFER_SIZE);
    598     printf("%ld inodes\n", (long)INODES);
    599     printf("%ld blocks\n", (long)ZONES);
    600     printf("Firstdatazone=%ld (%ld)\n", (long)FIRSTZONE, (long)NORM_FIRSTZONE);
    601     printf("Zonesize=%d\n", BLOCK_SIZE << ZONESIZE);
    602     printf("Maxsize=%ld\n\n", (long)MAXSIZE);
    603 }
    604 
    605 /*
    606  * Perform a test of a block; return the number of
    607  * blocks readable/writable.
    608  */
    609 static inline long do_check(char *buffer, int try, unsigned int current_block)
    610 {
    611     long got;
    612 
    613     /* Seek to the correct loc. */
    614     if (lseek(DEV, current_block * BLOCK_SIZE, SEEK_SET) !=
    615         current_block * BLOCK_SIZE) {
    616         bb_error_msg_and_die("seek failed during testing of blocks");
    617     }
    618 
    619 
    620     /* Try the read */
    621     got = read(DEV, buffer, try * BLOCK_SIZE);
    622     if (got < 0)
    623         got = 0;
    624     if (got & (BLOCK_SIZE - 1)) {
    625         printf("Weird values in do_check: probably bugs\n");
    626     }
    627     got /= BLOCK_SIZE;
    628     return got;
    629 }
    630 
    631 static unsigned int currently_testing;
    632 
    633 static void alarm_intr(int alnum)
    634 {
    635     if (currently_testing >= ZONES)
    636         return;
    637     signal(SIGALRM, alarm_intr);
    638     alarm(5);
    639     if (!currently_testing)
    640         return;
    641     printf("%d ...", currently_testing);
    642     fflush(stdout);
    643 }
    644 
    645 static void check_blocks(void)
    646 {
    647     int try, got;
    648     static char buffer[BLOCK_SIZE * TEST_BUFFER_BLOCKS];
    649 
    650     currently_testing = 0;
    651     signal(SIGALRM, alarm_intr);
    652     alarm(5);
    653     while (currently_testing < ZONES) {
    654         if (lseek(DEV, currently_testing * BLOCK_SIZE, SEEK_SET) !=
    655             currently_testing * BLOCK_SIZE)
    656             bb_error_msg_and_die("seek failed in check_blocks");
    657         try = TEST_BUFFER_BLOCKS;
    658         if (currently_testing + try > ZONES)
    659             try = ZONES - currently_testing;
    660         got = do_check(buffer, try, currently_testing);
    661         currently_testing += got;
    662         if (got == try)
    663             continue;
    664         if (currently_testing < FIRSTZONE)
    665             bb_error_msg_and_die("bad blocks before data-area: cannot make fs");
    666         mark_zone(currently_testing);
    667         badblocks++;
    668         currently_testing++;
    669     }
    670     if (badblocks > 1)
    671         printf("%d bad blocks\n", badblocks);
    672     else if (badblocks == 1)
    673         printf("one bad block\n");
    674 }
    675 
    676 static void get_list_blocks(char *filename)
    677 {
    678     FILE *listfile;
    679     unsigned long blockno;
    680 
    681     listfile = bb_xfopen(filename, "r");
    682     while (!feof(listfile)) {
    683         fscanf(listfile, "%ld\n", &blockno);
    684         mark_zone(blockno);
    685         badblocks++;
    686     }
    687     if (badblocks > 1)
    688         printf("%d bad blocks\n", badblocks);
    689     else if (badblocks == 1)
    690         printf("one bad block\n");
    691 }
    692 
     598    G.inode_buffer = xzalloc(INODE_BUFFER_SIZE);
     599    printf("%ld inodes\n", (long)SB_INODES);
     600    printf("%ld blocks\n", (long)SB_ZONES);
     601    printf("Firstdatazone=%ld (%ld)\n", (long)SB_FIRSTZONE, (long)norm_firstzone);
     602    printf("Zonesize=%d\n", BLOCK_SIZE << SB_ZONE_SIZE);
     603    printf("Maxsize=%ld\n", (long)SB_MAXSIZE);
     604}
     605
     606int mkfs_minix_main(int argc, char **argv);
    693607int mkfs_minix_main(int argc, char **argv)
    694608{
    695     int i=1;
     609    struct mntent *mp;
     610    unsigned opt;
    696611    char *tmp;
    697612    struct stat statbuf;
     613    char *str_i, *str_n;
    698614    char *listfile = NULL;
    699     int stopIt=FALSE;
    700 
    701     if (INODE_SIZE * MINIX_INODES_PER_BLOCK != BLOCK_SIZE)
     615
     616    PTR_TO_GLOBALS = xzalloc(sizeof(G));
     617/* default (changed to 30, per Linus's suggestion, Sun Nov 21 08:05:07 1993) */
     618    G.namelen = 30;
     619    G.dirsize = 32;
     620    G.magic = MINIX1_SUPER_MAGIC2;
     621
     622    if (INODE_SIZE1 * MINIX1_INODES_PER_BLOCK != BLOCK_SIZE)
    702623        bb_error_msg_and_die("bad inode size");
    703 #ifdef CONFIG_FEATURE_MINIX2
     624#if ENABLE_FEATURE_MINIX2
    704625    if (INODE_SIZE2 * MINIX2_INODES_PER_BLOCK != BLOCK_SIZE)
    705626        bb_error_msg_and_die("bad inode size");
    706627#endif
    707628
    708     /* Parse options */
    709     argv++;
    710     while (--argc >= 0 && *argv && **argv) {
    711         if (**argv == '-') {
    712             stopIt=FALSE;
    713             while (i > 0 && *++(*argv) && stopIt==FALSE) {
    714                 switch (**argv) {
    715                     case 'c':
    716                         check = 1;
    717                         break;
    718                     case 'i':
    719                         {
    720                             char *cp=NULL;
    721                             if (*(*argv+1) != 0) {
    722                                 cp = ++(*argv);
    723                             } else {
    724                                 if (--argc == 0) {
    725                                     goto goodbye;
    726                                 }
    727                                 cp = *(++argv);
    728                             }
    729                             req_nr_inodes = strtoul(cp, &tmp, 0);
    730                             if (*tmp)
    731                                 bb_show_usage();
    732                             stopIt=TRUE;
    733                             break;
    734                         }
    735                     case 'l':
    736                         if (--argc == 0) {
    737                             goto goodbye;
    738                         }
    739                         listfile = *(++argv);
    740                         break;
    741                     case 'n':
    742                         {
    743                             char *cp=NULL;
    744 
    745                             if (*(*argv+1) != 0) {
    746                                 cp = ++(*argv);
    747                             } else {
    748                                 if (--argc == 0) {
    749                                     goto goodbye;
    750                                 }
    751                                 cp = *(++argv);
    752                             }
    753                             i = strtoul(cp, &tmp, 0);
    754                             if (*tmp)
    755                                 bb_show_usage();
    756                             if (i == 14)
    757                                 magic = MINIX_SUPER_MAGIC;
    758                             else if (i == 30)
    759                                 magic = MINIX_SUPER_MAGIC2;
    760                             else
    761                                 bb_show_usage();
    762                             namelen = i;
    763                             dirsize = i + 2;
    764                             stopIt=TRUE;
    765                             break;
    766                         }
    767                     case 'v':
    768 #ifdef CONFIG_FEATURE_MINIX2
    769                         version2 = 1;
     629    opt = getopt32(argv, "ci:l:n:v", &str_i, &listfile, &str_n);
     630    argv += optind;
     631    //if (opt & 1) -c
     632    if (opt & 2) G.req_nr_inodes = xatoul(str_i); // -i
     633    //if (opt & 4) -l
     634    if (opt & 8) { // -n
     635        G.namelen = xatoi_u(str_n);
     636        if (G.namelen == 14) G.magic = MINIX1_SUPER_MAGIC;
     637        else if (G.namelen == 30) G.magic = MINIX1_SUPER_MAGIC2;
     638        else bb_show_usage();
     639        G.dirsize = G.namelen + 2;
     640    }
     641    if (opt & 0x10) { // -v
     642#if ENABLE_FEATURE_MINIX2
     643        version2 = 1;
    770644#else
    771                         bb_error_msg("%s: not compiled with minix v2 support",
    772                                 device_name);
    773                         exit(-1);
    774 #endif
    775                         break;
    776                     case '-':
    777                     case 'h':
    778                     default:
    779 goodbye:
    780                         bb_show_usage();
    781                 }
    782             }
    783         } else {
    784             if (device_name == NULL)
    785                 device_name = *argv;
    786             else if (BLOCKS == 0)
    787                 BLOCKS = strtol(*argv, &tmp, 0);
    788             else {
    789                 goto goodbye;
    790             }
    791         }
    792         argv++;
    793     }
    794 
    795     if (device_name && !BLOCKS)
    796         BLOCKS = get_size(device_name) / 1024;
    797     if (!device_name || BLOCKS < 10) {
     645        bb_error_msg_and_die("not compiled with minix v2 support");
     646#endif
     647    }
     648
     649    G.device_name = *argv++;
     650    if (!G.device_name)
    798651        bb_show_usage();
    799     }
    800 #ifdef CONFIG_FEATURE_MINIX2
     652    if (*argv)
     653        G.total_blocks = xatou32(*argv);
     654    else
     655        G.total_blocks = get_size(G.device_name) / 1024;
     656
     657    if (G.total_blocks < 10)
     658        bb_error_msg_and_die("must have at least 10 blocks");
     659
    801660    if (version2) {
    802         if (namelen == 14)
    803             magic = MINIX2_SUPER_MAGIC;
    804         else
    805             magic = MINIX2_SUPER_MAGIC2;
    806     } else
    807 #endif
    808     if (BLOCKS > 65535)
    809         BLOCKS = 65535;
    810     check_mount();              /* is it already mounted? */
    811     tmp = root_block;
     661        G.magic = MINIX2_SUPER_MAGIC2;
     662        if (G.namelen == 14)
     663            G.magic = MINIX2_SUPER_MAGIC;
     664    } else if (G.total_blocks > 65535)
     665        G.total_blocks = 65535;
     666
     667    /* Check if it is mounted */
     668    mp = find_mount_point(G.device_name, NULL);
     669    if (mp && strcmp(G.device_name, mp->mnt_fsname) == 0)
     670        bb_error_msg_and_die("%s is mounted on %s; "
     671                "refusing to make a filesystem",
     672                G.device_name, mp->mnt_dir);
     673
     674    G.dev_fd = xopen(G.device_name, O_RDWR);
     675    if (fstat(G.dev_fd, &statbuf) < 0)
     676        bb_error_msg_and_die("cannot stat %s", G.device_name);
     677    if (!S_ISBLK(statbuf.st_mode))
     678        opt &= ~1; // clear -c (check)
     679
     680/* I don't know why someone has special code to prevent mkfs.minix
     681 * on IDE devices. Why IDE but not SCSI, etc?... */
     682#if 0
     683    else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340)
     684        /* what is this? */
     685        bb_error_msg_and_die("will not try "
     686            "to make filesystem on '%s'", G.device_name);
     687#endif
     688
     689    tmp = G.root_block;
    812690    *(short *) tmp = 1;
    813691    strcpy(tmp + 2, ".");
    814     tmp += dirsize;
     692    tmp += G.dirsize;
    815693    *(short *) tmp = 1;
    816694    strcpy(tmp + 2, "..");
    817     tmp += dirsize;
     695    tmp += G.dirsize;
    818696    *(short *) tmp = 2;
    819697    strcpy(tmp + 2, ".badblocks");
    820     DEV = bb_xopen3(device_name, O_RDWR, 0);
    821     if (fstat(DEV, &statbuf) < 0)
    822         bb_error_msg_and_die("unable to stat %s", device_name);
    823     if (!S_ISBLK(statbuf.st_mode))
    824         check = 0;
    825     else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340)
    826         bb_error_msg_and_die("will not try to make filesystem on '%s'", device_name);
     698
    827699    setup_tables();
    828     if (check)
     700
     701    if (opt & 1) // -c ?
    829702        check_blocks();
    830703    else if (listfile)
    831704        get_list_blocks(listfile);
    832 #ifdef CONFIG_FEATURE_MINIX2
     705
    833706    if (version2) {
    834707        make_root_inode2();
    835708        make_bad_inode2();
    836     } else
    837 #endif
    838     {
     709    } else {
    839710        make_root_inode();
    840711        make_bad_inode();
    841712    }
     713
    842714    mark_good_blocks();
    843715    write_tables();
    844716    return 0;
    845 
    846 }
     717}
  • branches/2.2.5/mindi-busybox/util-linux/mkswap.c

    r821 r1765  
    11/* vi: set sw=4 ts=4: */
    2 /*
    3  * mkswap.c - set up a linux swap device
     2/* mkswap.c - format swap device (Linux v1 only)
    43 *
    5  * (C) 1991 Linus Torvalds. This file may be redistributed as per
    6  * the Linux copyright.
     4 * Copyright 2006 Rob Landley <rob@landley.net>
     5 *
     6 * Licensed under GPL version 2, see file LICENSE in this tarball for details.
    77 */
    88
    9 /*
    10  * 20.12.91  -  time began. Got VM working yesterday by doing this by hand.
    11  *
    12  * Usage: mkswap [-c] [-vN] [-f] device [size-in-blocks]
    13  *
    14  *  -c   for readability checking. (Use it unless you are SURE!)
    15  *  -vN  for swap areas version N. (Only N=0,1 known today.)
    16  *      -f   for forcing swap creation even if it would smash partition table.
    17  *
    18  * The device may be a block device or an image of one, but this isn't
    19  * enforced (but it's not much fun on a character device :-).
    20  *
    21  * Patches from jaggy@purplet.demon.co.uk (Mike Jagdis) to make the
    22  * size-in-blocks parameter optional added Wed Feb  8 10:33:43 1995.
    23  *
    24  * Version 1 swap area code (for kernel 2.1.117), aeb, 981010.
    25  *
    26  * Sparc fixes, jj@ultra.linux.cz (Jakub Jelinek), 981201 - mangled by aeb.
    27  * V1_MAX_PAGES fixes, jj, 990325.
    28  *
    29  * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@misiek.eu.org>
    30  * - added Native Language Support
    31  *
    32  *  from util-linux -- adapted for busybox by
    33  *  Erik Andersen <andersen@codepoet.org>. I ripped out Native Language
    34  *  Support, made some stuff smaller, and fitted for life in busybox.
    35  *
    36  */
     9#include "libbb.h"
    3710
    38 #include "busybox.h"
    39 #include <unistd.h>
    40 #include <string.h>
    41 #include <fcntl.h>
    42 #include <sys/ioctl.h>          /* for _IO */
    43 #include <sys/utsname.h>
    44 #include <asm/page.h>           /* for PAGE_SIZE and PAGE_SHIFT */
    45                 /* we also get PAGE_SIZE via getpagesize() */
    46 
    47 static char *device_name = NULL;
    48 static int DEV = -1;
    49 static long PAGES = 0;
    50 static int check = 0;
    51 static int badpages = 0;
    52 #if ENABLE_FEATURE_MKSWAP_V0
    53 static int version = -1;
    54 #else
    55 #define version 1
    56 /* and make sure that we optimize away anything which would deal with checking
    57  * the kernel revision as we have v1 support only anyway.
    58  */
    59 #undef KERNEL_VERSION
    60 #define KERNEL_VERSION(p,q,r) 1
    61 #define get_linux_version_code() 1
    62 #endif
    63 
    64 /*
    65  * The definition of the union swap_header uses the constant PAGE_SIZE.
    66  * Unfortunately, on some architectures this depends on the hardware model,
    67  * and can only be found at run time -- we use getpagesize().
    68  */
    69 
    70 static int pagesize;
    71 static unsigned int *signature_page;
    72 
    73 static struct swap_header_v1 {
    74     char bootbits[1024];        /* Space for disklabel etc. */
    75     unsigned int swap_version;
    76     unsigned int last_page;
    77     unsigned int nr_badpages;
    78     unsigned int padding[125];
    79     unsigned int badpages[1];
    80 } *p;
    81 
    82 static inline void init_signature_page(void)
    83 {
    84     pagesize = getpagesize();
    85 
    86 #ifdef PAGE_SIZE
    87     if (pagesize != PAGE_SIZE)
    88         bb_error_msg("Assuming pages of size %d", pagesize);
    89 #endif
    90     signature_page = (unsigned int *) xmalloc(pagesize);
    91     memset(signature_page, 0, pagesize);
    92     p = (struct swap_header_v1 *) signature_page;
    93 }
    94 
    95 static inline void write_signature(char *sig)
    96 {
    97     char *sp = (char *) signature_page;
    98 
    99     strncpy(sp + pagesize - 10, sig, 10);
    100 }
    101 
    102 #define V0_MAX_PAGES    (8 * (pagesize - 10))
    103 /* Before 2.2.0pre9 */
    104 #define V1_OLD_MAX_PAGES    ((0x7fffffff / pagesize) - 1)
    105 /* Since 2.2.0pre9:
    106    error if nr of pages >= SWP_OFFSET(SWP_ENTRY(0,~0UL))
    107    with variations on
    108     #define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8))
    109     #define SWP_OFFSET(entry) ((entry) >> 8)
    110    on the various architectures. Below the result - yuk.
    111 
    112    Machine  pagesize    SWP_ENTRY   SWP_OFFSET  bound+1 oldbound+2
    113    i386     2^12        o<<8        e>>8        1<<24   1<<19
    114    mips     2^12        o<<15       e>>15       1<<17   1<<19
    115    alpha    2^13        o<<40       e>>40       1<<24   1<<18
    116    m68k     2^12        o<<12       e>>12       1<<20   1<<19
    117    sparc    2^{12,13}   (o&0x3ffff)<<9  (e>>9)&0x3ffff  1<<18   1<<{19,18}
    118    sparc64  2^13        o<<13       e>>13       1<<51   1<<18
    119    ppc      2^12        o<<8        e>>8        1<<24   1<<19
    120    armo     2^{13,14,15}    o<<8        e>>8        1<<24   1<<{18,17,16}
    121    armv     2^12        o<<9        e>>9        1<<23   1<<19
    122 
    123    assuming that longs have 64 bits on alpha and sparc64 and 32 bits elsewhere.
    124 
    125    The bad part is that we need to know this since the kernel will
    126    refuse a swap space if it is too large.
    127 */
    128 /* patch from jj - why does this differ from the above? */
    129 #if defined(__alpha__)
    130 #define V1_MAX_PAGES           ((1 << 24) - 1)
    131 #elif defined(__mips__)
    132 #define V1_MAX_PAGES           ((1 << 17) - 1)
    133 #elif defined(__sparc_v9__)
    134 #define V1_MAX_PAGES           ((3 << 29) - 1)
    135 #elif defined(__sparc__)
    136 #define V1_MAX_PAGES           (pagesize == 8192 ? ((3 << 29) - 1) : ((1 << 18) - 1))
    137 #else
    138 #define V1_MAX_PAGES           V1_OLD_MAX_PAGES
    139 #endif
    140 /* man page now says:
    141 The maximum useful size of a swap area now depends on the architecture.
    142 It is roughly 2GB on i386, PPC, m68k, ARM, 1GB on sparc, 512MB on mips,
    143 128GB on alpha and 3TB on sparc64.
    144 */
    145 
    146 #define MAX_BADPAGES    ((pagesize-1024-128*sizeof(int)-10)/sizeof(int))
    147 
    148 static inline void bit_set(unsigned int *addr, unsigned int nr)
    149 {
    150     unsigned int r, m;
    151 
    152     addr += nr / (8 * sizeof(int));
    153 
    154     r = *addr;
    155     m = 1 << (nr & (8 * sizeof(int) - 1));
    156 
    157     *addr = r | m;
    158 }
    159 
    160 static int bit_test_and_clear(unsigned int *addr, unsigned int nr)
    161 {
    162     unsigned int r, m;
    163 
    164     addr += nr / (8 * sizeof(int));
    165 
    166     r = *addr;
    167     m = 1 << (nr & (8 * sizeof(int) - 1));
    168 
    169     *addr = r & ~m;
    170     return (r & m) != 0;
    171 }
    172 
    173 static void page_ok(int page)
    174 {
    175     if (ENABLE_FEATURE_MKSWAP_V0) {
    176         bit_set(signature_page, page);
    177     }
    178 }
    179 
    180 static void check_blocks(void)
    181 {
    182     unsigned int current_page;
    183     int do_seek = 1;
    184     char *buffer;
    185 
    186     buffer = xmalloc(pagesize);
    187     current_page = 0;
    188     while (current_page < PAGES) {
    189         if (!check && version == 0) {
    190             page_ok(current_page++);
    191             continue;
    192         }
    193         if (do_seek && lseek(DEV, current_page * pagesize, SEEK_SET) !=
    194             current_page * pagesize)
    195             bb_error_msg_and_die("seek failed in check_blocks");
    196         if ((do_seek = (pagesize != read(DEV, buffer, pagesize)))) {
    197             current_page++;
    198             if (version == 0)
    199                 bit_test_and_clear(signature_page, current_page);
    200             else {
    201                 if (badpages == MAX_BADPAGES)
    202                     bb_error_msg_and_die("too many bad pages");
    203                 p->badpages[badpages] = current_page;
    204             }
    205             badpages++;
    206             continue;
    207         }
    208         page_ok(current_page++);
    209     }
    210     if (ENABLE_FEATURE_CLEAN_UP)
    211         free(buffer);
    212     if (badpages > 0)
    213         printf("%d bad page%s\n", badpages, (badpages==1)?"":"s");
    214 }
    215 
    216 static long valid_offset(int fd, int offset)
    217 {
    218     char ch;
    219 
    220     if (lseek(fd, offset, 0) < 0)
    221         return 0;
    222     if (read(fd, &ch, 1) < 1)
    223         return 0;
    224     return 1;
    225 }
    226 
    227 static int find_size(int fd)
    228 {
    229     unsigned int high, low;
    230 
    231     low = 0;
    232     for (high = 1; high > 0 && valid_offset(fd, high); high *= 2)
    233         low = high;
    234     while (low < high - 1) {
    235         const int mid = (low + high) / 2;
    236 
    237         if (valid_offset(fd, mid))
    238             low = mid;
    239         else
    240             high = mid;
    241     }
    242     return (low + 1);
    243 }
    244 
    245 /* return size in pages, to avoid integer overflow */
    246 static inline long get_size(const char *file)
    247 {
    248     int fd;
    249     long size;
    250 
    251     fd = bb_xopen3(file, O_RDONLY, 0);
    252     if (ioctl(fd, BLKGETSIZE, &size) >= 0) {
    253         size /= pagesize / 512;
    254     } else {
    255         size = find_size(fd) / pagesize;
    256     }
    257     close(fd);
    258     return size;
    259 }
    260 
     11int mkswap_main(int argc, char **argv);
    26112int mkswap_main(int argc, char **argv)
    26213{
    263     char *tmp;
    264     struct stat statbuf;
    265     int sz;
    266     int maxpages;
    267     int goodpages;
    268 #ifdef __sparc__
    269     int force = 0;
    270 #endif
     14    int fd, pagesize;
     15    off_t len;
     16    unsigned int hdr[129];
    27117
    272     init_signature_page();      /* get pagesize */
     18    // No options supported.
    27319
    274     bb_opt_complementally = "?"; /* call bb_show_usage internally */
    275     sz = bb_getopt_ulflags(argc, argv, "+cfv:", &tmp);
    276     if (sz & 1)
    277         check = 1;
    278 #ifdef __sparc__
    279     if (sz & 2)
    280         force = 1;
    281 #endif
    282 #if ENABLE_FEATURE_MKSWAP_V0
    283     if (sz & 4) {
    284         version = bb_xgetlarg(tmp, 10, 0, 1);
    285     } else {
    286         if (get_linux_version_code() < KERNEL_VERSION(2, 1, 117))
    287             version = 0;
    288         else
    289             version = 1;
    290     }
    291 #endif
     20    if (argc != 2) bb_show_usage();
    29221
    293     argv += optind;
    294     argc -= optind;
     22    // Figure out how big the device is and announce our intentions.
    29523
    296     goodpages = pagesize / 1024; /* cache division */
    297     while (argc--) {
    298         if (device_name) {
    299             PAGES = bb_xgetlarg(argv[0], 0, 10, sz * goodpages) / goodpages;
    300             argc = 0; /* ignore any surplus args.. */
    301         } else {
    302             device_name = argv[0];
    303             sz = get_size(device_name);
    304             argv++;
    305         }
    306     }
     24    fd = xopen(argv[1], O_RDWR);
     25    len = fdlength(fd);
     26    pagesize = getpagesize();
     27    printf("Setting up swapspace version 1, size = %"OFF_FMT"d bytes\n",
     28            len - pagesize);
    30729
    308     if (!device_name) {
    309         bb_error_msg_and_die("error: Nowhere to set up swap on?");
    310     }
    311     if (!PAGES) {
    312         PAGES = sz;
    313     }
     30    // Make a header.
    31431
    315 #if 0
    316     maxpages = ((version == 0) ? V0_MAX_PAGES : V1_MAX_PAGES);
    317 #else
    318     if (!version)
    319         maxpages = V0_MAX_PAGES;
    320     else if (get_linux_version_code() >= KERNEL_VERSION(2,2,1))
    321         maxpages = V1_MAX_PAGES;
    322     else {
    323         maxpages = V1_OLD_MAX_PAGES;
    324         if (maxpages > V1_MAX_PAGES)
    325             maxpages = V1_MAX_PAGES;
    326     }
    327 #endif
    328     if (PAGES > maxpages) {
    329         PAGES = maxpages;
    330         bb_error_msg("warning: truncating swap area to %ldkB",
    331                 PAGES * goodpages);
    332     }
     32    memset(hdr, 0, sizeof(hdr));
     33    hdr[0] = 1;
     34    hdr[1] = (len / pagesize) - 1;
    33335
    334     DEV = bb_xopen3(device_name, O_RDWR, 0);
    335     if (fstat(DEV, &statbuf) < 0)
    336         bb_perror_msg_and_die("%s", device_name);
    337     if (!S_ISBLK(statbuf.st_mode))
    338         check = 0;
    339     else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340)
    340         bb_error_msg_and_die("Will not try to make swapdevice on '%s'", device_name);
     36    // Write the header.  Sync to disk because some kernel versions check
     37    // signature on disk (not in cache) during swapon.
    34138
    342 #ifdef __sparc__
    343     if (!force && version == 0) {
    344         /* Don't overwrite partition table unless forced */
    345         unsigned char *buffer = (unsigned char *) signature_page;
    346         unsigned short *q, sum;
     39    xlseek(fd, 1024, SEEK_SET);
     40    xwrite(fd, hdr, sizeof(hdr));
     41    xlseek(fd, pagesize-10, SEEK_SET);
     42    xwrite(fd, "SWAPSPACE2", 10);
     43    fsync(fd);
    34744
    348         if (read(DEV, buffer, 512) != 512)
    349             bb_error_msg_and_die("fatal: first page unreadable");
    350         if (buffer[508] == 0xDA && buffer[509] == 0xBE) {
    351             q = (unsigned short *) (buffer + 510);
    352             for (sum = 0; q >= (unsigned short *) buffer;)
    353                 sum ^= *q--;
    354             if (!sum) {
    355                 bb_error_msg("Device '%s' contains a valid Sun disklabel.\n"
    356 "This probably means creating v0 swap would destroy your partition table\n"
    357 "No swap created. If you really want to create swap v0 on that device, use\n"
    358 "the -f option to force it.", device_name);
    359                 return EXIT_FAILURE;
    360             }
    361         }
    362     }
    363 #endif
     45    if (ENABLE_FEATURE_CLEAN_UP) close(fd);
    36446
    365     if (version == 0 || check)
    366         check_blocks();
    367     if (version == 0 && !bit_test_and_clear(signature_page, 0))
    368         bb_error_msg_and_die("fatal: first page unreadable");
    369     if (version == 1) {
    370         p->swap_version = version;
    371         p->last_page = PAGES - 1;
    372         p->nr_badpages = badpages;
    373     }
    374 
    375     goodpages = PAGES - badpages - 1;
    376     if (goodpages <= 0)
    377         bb_error_msg_and_die("Unable to set up swap-space: unreadable");
    378     printf("Setting up swapspace version %d, size = %ld bytes\n",
    379            version, (long) (goodpages * pagesize));
    380     write_signature((version == 0) ? "SWAP-SPACE" : "SWAPSPACE2");
    381 
    382     sz = ((version == 0) ? 0 : 1024); /* offset */
    383     if (lseek(DEV, sz, SEEK_SET) != sz)
    384         bb_error_msg_and_die("unable to rewind swap-device");
    385     goodpages = pagesize - sz; /* cache substraction */
    386     if (write(DEV, (char *) signature_page + sz, goodpages)
    387         != goodpages)
    388         bb_error_msg_and_die("unable to write signature page");
    389 
    390     /*
    391      * A subsequent swapon() will fail if the signature
    392      * is not actually on disk. (This is a kernel bug.)
    393      */
    394     if (fsync(DEV))
    395         bb_error_msg_and_die("fsync failed");
    396     if (ENABLE_FEATURE_CLEAN_UP) {
    397         close(DEV);
    398         free(signature_page);
    399     }
    400     return EXIT_SUCCESS;
     47    return 0;
    40148}
  • branches/2.2.5/mindi-busybox/util-linux/more.c

    r821 r1765  
    1212 * Termios corrects by Vladimir Oleynik <dzo@simtreas.ru>
    1313 *
    14  * This program is free software; you can redistribute it and/or modify
    15  * it under the terms of the GNU General Public License as published by
    16  * the Free Software Foundation; either version 2 of the License, or
    17  * (at your option) any later version.
    18  *
    19  * This program is distributed in the hope that it will be useful,
    20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    22  * General Public License for more details.
    23  *
    24  * You should have received a copy of the GNU General Public License
    25  * along with this program; if not, write to the Free Software
    26  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    27  *
     14 * Licensed under GPLv2 or later, see file License in this tarball for details.
    2815 */
    2916
    30 #include <stdio.h>
    31 #include <fcntl.h>
    32 #include <signal.h>
    33 #include <stdlib.h>
    34 #include <unistd.h>
    35 #include <sys/ioctl.h>
    36 #include "busybox.h"
    37 
    38 
    39 #ifdef CONFIG_FEATURE_USE_TERMIOS
    40 static int cin_fileno;
     17#include "libbb.h"
     18#if ENABLE_FEATURE_USE_TERMIOS
    4119#include <termios.h>
    42 #define setTermSettings(fd,argp) tcsetattr(fd,TCSANOW,argp)
    43 #define getTermSettings(fd,argp) tcgetattr(fd, argp);
    44 
    45 static struct termios initial_settings, new_settings;
    46 
    47 static void set_tty_to_initial_mode(void)
    48 {
    49     setTermSettings(cin_fileno, &initial_settings);
    50 }
     20#endif /* FEATURE_USE_TERMIOS */
     21
     22
     23#if ENABLE_FEATURE_USE_TERMIOS
     24
     25struct globals {
     26    int cin_fileno;
     27    struct termios initial_settings;
     28    struct termios new_settings;
     29};
     30#define G (*(struct globals*)bb_common_bufsiz1)
     31//#define G (*ptr_to_globals)
     32#define INIT_G() ((void)0)
     33//#define INIT_G() PTR_TO_GLOBALS = xzalloc(sizeof(G))
     34#define initial_settings (G.initial_settings)
     35#define new_settings     (G.new_settings    )
     36#define cin_fileno       (G.cin_fileno      )
     37
     38#define setTermSettings(fd, argp) tcsetattr(fd, TCSANOW, argp)
     39#define getTermSettings(fd, argp) tcgetattr(fd, argp)
    5140
    5241static void gotsig(int sig)
    5342{
    5443    putchar('\n');
     44    setTermSettings(cin_fileno, &initial_settings);
    5545    exit(EXIT_FAILURE);
    5646}
    57 #endif /* CONFIG_FEATURE_USE_TERMIOS */
    58 
    59 
     47
     48#else /* !FEATURE_USE_TERMIOS */
     49#define INIT_G() ((void)0)
     50#define setTermSettings(fd, argp) ((void)0)
     51#endif /* FEATURE_USE_TERMIOS */
     52
     53#define CONVERTED_TAB_SIZE 8
     54
     55int more_main(int argc, char **argv);
    6056int more_main(int argc, char **argv)
    6157{
    62     int c, lines, input = 0;
    63     int please_display_more_prompt = 0;
     58    int c = c; /* for gcc */
     59    int lines;
     60    int input = 0;
     61    int spaces = 0;
     62    int please_display_more_prompt;
    6463    struct stat st;
    6564    FILE *file;
    6665    FILE *cin;
    67     int len, page_height;
     66    int len;
    6867    int terminal_width;
    6968    int terminal_height;
    7069
    71     argc--;
     70    INIT_G();
     71
    7272    argv++;
    73 
    74 
    75     /* not use inputing from terminal if usage: more > outfile */
    76     if(isatty(STDOUT_FILENO)) {
    77         cin = fopen(CURRENT_TTY, "r");
    78         if (!cin)
    79             cin = bb_xfopen(CONSOLE_DEV, "r");
    80         please_display_more_prompt = 2;
    81 #ifdef CONFIG_FEATURE_USE_TERMIOS
    82         cin_fileno = fileno(cin);
    83         getTermSettings(cin_fileno, &initial_settings);
    84         new_settings = initial_settings;
    85         new_settings.c_lflag &= ~ICANON;
    86         new_settings.c_lflag &= ~ECHO;
    87         new_settings.c_cc[VMIN] = 1;
    88         new_settings.c_cc[VTIME] = 0;
    89         setTermSettings(cin_fileno, &new_settings);
    90         atexit(set_tty_to_initial_mode);
    91         (void) signal(SIGINT, gotsig);
    92         (void) signal(SIGQUIT, gotsig);
    93         (void) signal(SIGTERM, gotsig);
     73    /* Another popular pager, most, detects when stdout
     74     * is not a tty and turns into cat. This makes sense. */
     75    if (!isatty(STDOUT_FILENO))
     76        return bb_cat(argv);
     77    cin = fopen(CURRENT_TTY, "r");
     78    if (!cin)
     79        return bb_cat(argv);
     80
     81#if ENABLE_FEATURE_USE_TERMIOS
     82    cin_fileno = fileno(cin);
     83    getTermSettings(cin_fileno, &initial_settings);
     84    new_settings = initial_settings;
     85    new_settings.c_lflag &= ~ICANON;
     86    new_settings.c_lflag &= ~ECHO;
     87    new_settings.c_cc[VMIN] = 1;
     88    new_settings.c_cc[VTIME] = 0;
     89    setTermSettings(cin_fileno, &new_settings);
     90    signal(SIGINT, gotsig);
     91    signal(SIGQUIT, gotsig);
     92    signal(SIGTERM, gotsig);
    9493#endif
    95     } else {
    96         cin = stdin;
    97     }
    9894
    9995    do {
    100         if (argc == 0) {
    101             file = stdin;
    102         } else
    103             file = bb_wfopen(*argv, "r");
    104         if(file==0)
    105             goto loop;
    106 
     96        file = stdin;
     97        if (*argv) {
     98            file = fopen_or_warn(*argv, "r");
     99            if (!file)
     100                continue;
     101        }
    107102        st.st_size = 0;
    108103        fstat(fileno(file), &st);
    109104
    110         please_display_more_prompt &= ~1;
    111 
     105        please_display_more_prompt = 0;
     106        /* never returns w, h <= 1 */
    112107        get_terminal_width_height(fileno(cin), &terminal_width, &terminal_height);
    113         if (terminal_height > 4)
    114             terminal_height -= 2;
    115         if (terminal_width > 0)
    116             terminal_width -= 1;
    117 
    118         len=0;
     108        terminal_height -= 1;
     109
     110        len = 0;
    119111        lines = 0;
    120         page_height = terminal_height;
    121         while ((c = getc(file)) != EOF) {
    122 
    123             if ((please_display_more_prompt & 3) == 3) {
     112        while (spaces || (c = getc(file)) != EOF) {
     113            int wrap;
     114            if (spaces)
     115                spaces--;
     116 loop_top:
     117            if (input != 'r' && please_display_more_prompt) {
    124118                len = printf("--More-- ");
    125                 if (file != stdin && st.st_size > 0) {
    126 #if _FILE_OFFSET_BITS == 64
    127                     len += printf("(%d%% of %lld bytes)",
    128                            (int) (100 * ((double) ftell(file) /
    129                            (double) st.st_size)), (long long)st.st_size);
    130 #else
    131                     len += printf("(%d%% of %ld bytes)",
    132                            (int) (100 * ((double) ftell(file) /
    133                            (double) st.st_size)), (long)st.st_size);
    134 #endif
     119                if (st.st_size > 0) {
     120                    len += printf("(%d%% of %"OFF_FMT"d bytes)",
     121                        (int) (ftello(file)*100 / st.st_size),
     122                        st.st_size);
    135123                }
    136 
    137124                fflush(stdout);
    138125
     
    141128                 * to get input from the user.
    142129                 */
    143                 input = getc(cin);
    144 #ifndef CONFIG_FEATURE_USE_TERMIOS
    145                 printf("\033[A"); /* up cursor */
     130                for (;;) {
     131                    input = getc(cin);
     132                    input = tolower(input);
     133#if !ENABLE_FEATURE_USE_TERMIOS
     134                    printf("\033[A"); /* up cursor */
    146135#endif
    147                 /* Erase the "More" message */
    148                 putc('\r', stdout);
    149                 while (--len >= 0)
    150                     putc(' ', stdout);
    151                 putc('\r', stdout);
    152                 len=0;
     136                    /* Erase the last message */
     137                    printf("\r%*s\r", len, "");
     138
     139                    /* Due to various multibyte escape
     140                     * sequences, it's not ok to accept
     141                     * any input as a command to scroll
     142                     * the screen. We only allow known
     143                     * commands, else we show help msg. */
     144                    if (input == ' ' || input == '\n' || input == 'q' || input == 'r')
     145                        break;
     146                    len = printf("(Enter:next line Space:next page Q:quit R:show the rest)");
     147                }
     148                len = 0;
    153149                lines = 0;
    154                 page_height = terminal_height;
    155                 please_display_more_prompt &= ~1;
     150                please_display_more_prompt = 0;
    156151
    157152                if (input == 'q')
    158153                    goto end;
     154
     155                /* The user may have resized the terminal.
     156                 * Re-read the dimensions. */
     157#if ENABLE_FEATURE_USE_TERMIOS
     158                get_terminal_width_height(cin_fileno, &terminal_width, &terminal_height);
     159                terminal_height -= 1;
     160#endif
    159161            }
     162
     163            /* Crudely convert tabs into spaces, which are
     164             * a bajillion times easier to deal with. */
     165            if (c == '\t') {
     166                spaces = CONVERTED_TAB_SIZE - 1;
     167                c = ' ';
     168            }
    160169
    161170            /*
    162171             * There are two input streams to worry about here:
    163172             *
    164              * c     : the character we are reading from the file being "mored"
    165              * input : a character received from the keyboard
     173             * c    : the character we are reading from the file being "mored"
     174             * input: a character received from the keyboard
    166175             *
    167176             * If we hit a newline in the _file_ stream, we want to test and
     
    169178             * allows the user to quit while in the middle of a file.
    170179             */
    171             if (c == '\n') {
    172                 /* increment by just one line if we are at
    173                  * the end of this line */
    174                 if (input == '\n')
    175                     please_display_more_prompt |= 1;
    176                 /* Adjust the terminal height for any overlap, so that
    177                  * no lines get lost off the top. */
    178                 if (len >= terminal_width) {
    179                     int quot, rem;
    180                     quot = len / terminal_width;
    181                     rem  = len - (quot * terminal_width);
    182                     if (quot) {
    183                         if (rem)
    184                             page_height-=quot;
    185                         else
    186                             page_height-=(quot-1);
    187                     }
    188                 }
    189                 if (++lines >= page_height) {
    190                     please_display_more_prompt |= 1;
    191                 }
    192                 len=0;
     180            wrap = (++len > terminal_width);
     181            if (c == '\n' || wrap) {
     182                /* Then outputting this character
     183                 * will move us to a new line. */
     184                if (++lines >= terminal_height || input == '\n')
     185                    please_display_more_prompt = 1;
     186                len = 0;
    193187            }
    194             /*
    195              * If we just read a newline from the file being 'mored' and any
    196              * key other than a return is hit, scroll by one page
    197              */
    198             putc(c, stdout);
    199             len++;
     188            if (c != '\n' && wrap) {
     189                /* Then outputting this will also put a character on
     190                 * the beginning of that new line. Thus we first want to
     191                 * display the prompt (if any), so we skip the putchar()
     192                 * and go back to the top of the loop, without reading
     193                 * a new character. */
     194                goto loop_top;
     195            }
     196            /* My small mind cannot fathom backspaces and UTF-8 */
     197            putchar(c);
    200198        }
    201199        fclose(file);
    202200        fflush(stdout);
    203 loop:
    204         argv++;
    205     } while (--argc > 0);
    206   end:
     201    } while (*argv && *++argv);
     202 end:
     203    setTermSettings(cin_fileno, &initial_settings);
    207204    return 0;
    208205}
  • branches/2.2.5/mindi-busybox/util-linux/mount.c

    r902 r1765  
    1010 */
    1111
    12 /* todo:
    13  * bb_getopt_ulflags();
    14  */
    15 
    1612/* Design notes: There is no spec for mount.  Remind me to write one.
    1713
     
    2319*/
    2420
    25 #include "busybox.h"
    26 #include <unistd.h>
    27 #include <errno.h>
    28 #include <string.h>
     21#include "libbb.h"
    2922#include <mntent.h>
    30 #include <ctype.h>
    31 #include <fcntl.h>      // for CONFIG_FEATURE_MOUNT_LOOP
    32 #include <sys/ioctl.h>  // for CONFIG_FEATURE_MOUNT_LOOP
    33 
    34 // These two aren't always defined in old headers
    35 #ifndef MS_BIND
    36 #define MS_BIND     4096
     23
     24/* Needed for nfs support only... */
     25#include <syslog.h>
     26#include <sys/utsname.h>
     27#undef TRUE
     28#undef FALSE
     29#include <rpc/rpc.h>
     30#include <rpc/pmap_prot.h>
     31#include <rpc/pmap_clnt.h>
     32
     33
     34#if defined(__dietlibc__)
     35/* 16.12.2006, Sampo Kellomaki (sampo@iki.fi)
     36 * dietlibc-0.30 does not have implementation of getmntent_r() */
     37/* OTOH: why we use getmntent_r instead of getmntent? TODO... */
     38struct mntent *getmntent_r(FILE* stream, struct mntent* result, char* buffer, int bufsize)
     39{
     40    /* *** XXX FIXME WARNING: This hack is NOT thread safe. --Sampo */
     41    struct mntent* ment = getmntent(stream);
     42    memcpy(result, ment, sizeof(struct mntent));
     43    return result;
     44}
    3745#endif
    38 #ifndef MS_MOVE
    39 #define MS_MOVE     8192
    40 #endif
    41 #ifndef MS_SILENT
    42 #define MS_SILENT   32768
    43 #endif
     46
    4447
    4548// Not real flags, but we want to be able to check for this.
    46 #define MOUNT_NOAUTO    (1<<29)
    47 #define MOUNT_SWAP      (1<<30)
     49enum {
     50    MOUNT_USERS  = (1<<28)*ENABLE_DESKTOP,
     51    MOUNT_NOAUTO = (1<<29),
     52    MOUNT_SWAP   = (1<<30),
     53};
     54// TODO: more "user" flag compatibility.
     55// "user" option (from mount manpage):
     56// Only the user that mounted a filesystem can unmount it again.
     57// If any user should be able to unmount, then use users instead of user
     58// in the fstab line.  The owner option is similar to the user option,
     59// with the restriction that the user must be the owner of the special file.
     60// This may be useful e.g. for /dev/fd if a login script makes
     61// the console user owner of this device.
     62
    4863/* Standard mount options (from -o options or --options), with corresponding
    4964 * flags */
     
    5267    const char *name;
    5368    long flags;
    54 } static const mount_options[] = {
    55     // NOP flags.
    56 
    57     {"loop", 0},
    58     {"defaults", 0},
    59     {"quiet", 0},
    60 
    61     // vfs flags
    62 
    63     {"ro", MS_RDONLY},
    64     {"rw", ~MS_RDONLY},
    65     {"nosuid", MS_NOSUID},
    66     {"suid", ~MS_NOSUID},
    67     {"dev", ~MS_NODEV},
    68     {"nodev", MS_NODEV},
    69     {"exec", ~MS_NOEXEC},
    70     {"noexec", MS_NOEXEC},
    71     {"sync", MS_SYNCHRONOUS},
    72     {"async", ~MS_SYNCHRONOUS},
    73     {"atime", ~MS_NOATIME},
    74     {"noatime", MS_NOATIME},
    75     {"diratime", ~MS_NODIRATIME},
    76     {"nodiratime", MS_NODIRATIME},
    77     {"loud", ~MS_SILENT},
    78 
    79     // action flags
    80 
    81     {"remount", MS_REMOUNT},
    82     {"bind", MS_BIND},
    83     {"move", MS_MOVE},
    84     {"noauto",MOUNT_NOAUTO},
    85     {"swap",MOUNT_SWAP}
     69} static mount_options[] = {
     70    // MS_FLAGS set a bit.  ~MS_FLAGS disable that bit.  0 flags are NOPs.
     71
     72    USE_FEATURE_MOUNT_LOOP(
     73        {"loop", 0},
     74    )
     75
     76    USE_FEATURE_MOUNT_FSTAB(
     77        {"defaults", 0},
     78        /* {"quiet", 0}, - do not filter out, vfat wants to see it */
     79        {"noauto", MOUNT_NOAUTO},
     80        {"sw", MOUNT_SWAP},
     81        {"swap", MOUNT_SWAP},
     82        USE_DESKTOP({"user",  MOUNT_USERS},)
     83        USE_DESKTOP({"users", MOUNT_USERS},)
     84    )
     85
     86    USE_FEATURE_MOUNT_FLAGS(
     87        // vfs flags
     88        {"nosuid", MS_NOSUID},
     89        {"suid", ~MS_NOSUID},
     90        {"dev", ~MS_NODEV},
     91        {"nodev", MS_NODEV},
     92        {"exec", ~MS_NOEXEC},
     93        {"noexec", MS_NOEXEC},
     94        {"sync", MS_SYNCHRONOUS},
     95        {"async", ~MS_SYNCHRONOUS},
     96        {"atime", ~MS_NOATIME},
     97        {"noatime", MS_NOATIME},
     98        {"diratime", ~MS_NODIRATIME},
     99        {"nodiratime", MS_NODIRATIME},
     100        {"loud", ~MS_SILENT},
     101
     102        // action flags
     103
     104        {"bind", MS_BIND},
     105        {"move", MS_MOVE},
     106        {"shared", MS_SHARED},
     107        {"slave", MS_SLAVE},
     108        {"private", MS_PRIVATE},
     109        {"unbindable", MS_UNBINDABLE},
     110        {"rshared", MS_SHARED|MS_RECURSIVE},
     111        {"rslave", MS_SLAVE|MS_RECURSIVE},
     112        {"rprivate", MS_SLAVE|MS_RECURSIVE},
     113        {"runbindable", MS_UNBINDABLE|MS_RECURSIVE},
     114    )
     115
     116    // Always understood.
     117
     118    {"ro", MS_RDONLY},        // vfs flag
     119    {"rw", ~MS_RDONLY},       // vfs flag
     120    {"remount", MS_REMOUNT},  // action flag
    86121};
    87122
     123
    88124/* Append mount options to string */
    89 static void append_mount_options(char **oldopts, char *newopts)
    90 {
    91     if(*oldopts && **oldopts) {
    92         char *temp=bb_xasprintf("%s,%s",*oldopts,newopts);
    93         free(*oldopts);
    94         *oldopts=temp;
     125static void append_mount_options(char **oldopts, const char *newopts)
     126{
     127    if (*oldopts && **oldopts) {
     128        /* do not insert options which are already there */
     129        while (newopts[0]) {
     130            char *p;
     131            int len = strlen(newopts);
     132            p = strchr(newopts, ',');
     133            if (p) len = p - newopts;
     134            p = *oldopts;
     135            while (1) {
     136                if (!strncmp(p, newopts, len)
     137                 && (p[len]==',' || p[len]==0))
     138                    goto skip;
     139                p = strchr(p,',');
     140                if (!p) break;
     141                p++;
     142            }
     143            p = xasprintf("%s,%.*s", *oldopts, len, newopts);
     144            free(*oldopts);
     145            *oldopts = p;
     146skip:
     147            newopts += len;
     148            while (newopts[0] == ',') newopts++;
     149        }
    95150    } else {
    96151        if (ENABLE_FEATURE_CLEAN_UP) free(*oldopts);
    97         *oldopts = bb_xstrdup(newopts);
     152        *oldopts = xstrdup(newopts);
    98153    }
    99154}
    100155
    101156/* Use the mount_options list to parse options into flags.
    102  * Return list of unrecognized options in *strflags if strflags!=NULL */
     157 * Also return list of unrecognized options if unrecognized!=NULL */
    103158static int parse_mount_options(char *options, char **unrecognized)
    104159{
     
    113168
    114169        // Find this option in mount_options
    115         for (i = 0; i < (sizeof(mount_options) / sizeof(*mount_options)); i++) {
     170        for (i = 0; i < ARRAY_SIZE(mount_options); i++) {
    116171            if (!strcasecmp(mount_options[i].name, options)) {
    117172                long fl = mount_options[i].flags;
    118                 if(fl < 0) flags &= fl;
     173                if (fl < 0) flags &= fl;
    119174                else flags |= fl;
    120175                break;
     
    122177        }
    123178        // If unrecognized not NULL, append unrecognized mount options */
    124         if (unrecognized
    125                 && i == (sizeof(mount_options) / sizeof(*mount_options)))
    126         {
     179        if (unrecognized && i == ARRAY_SIZE(mount_options)) {
    127180            // Add it to strflags, to pass on to kernel
    128181            i = *unrecognized ? strlen(*unrecognized) : 0;
     
    135188
    136189        // Advance to next option, or finish
    137         if(comma) {
     190        if (comma) {
    138191            *comma = ',';
    139192            options = ++comma;
     
    148201static llist_t *get_block_backed_filesystems(void)
    149202{
    150     char *fs, *buf,
    151          *filesystems[] = {"/etc/filesystems", "/proc/filesystems", 0};
     203    static const char filesystems[2][sizeof("/proc/filesystems")] = {
     204        "/etc/filesystems",
     205        "/proc/filesystems",
     206    };
     207    char *fs, *buf;
    152208    llist_t *list = 0;
    153209    int i;
    154210    FILE *f;
    155211
    156     for(i = 0; filesystems[i]; i++) {
    157         if(!(f = fopen(filesystems[i], "r"))) continue;
    158 
    159         for(fs = buf = 0; (fs = buf = bb_get_chomped_line_from_file(f));
    160             free(buf))
    161         {
    162             if(!strncmp(buf,"nodev",5) && isspace(buf[5])) continue;
    163 
    164             while(isspace(*fs)) fs++;
    165             if(*fs=='#' || *fs=='*') continue;
    166             if(!*fs) continue;
    167 
    168             llist_add_to_end(&list,bb_xstrdup(fs));
     212    for (i = 0; i < 2; i++) {
     213        f = fopen(filesystems[i], "r");
     214        if (!f) continue;
     215
     216        while ((buf = xmalloc_getline(f)) != 0) {
     217            if (!strncmp(buf, "nodev", 5) && isspace(buf[5]))
     218                continue;
     219            fs = skip_whitespace(buf);
     220            if (*fs=='#' || *fs=='*' || !*fs) continue;
     221
     222            llist_add_to_end(&list, xstrdup(fs));
     223            free(buf);
    169224        }
    170225        if (ENABLE_FEATURE_CLEAN_UP) fclose(f);
     
    186241
    187242#if ENABLE_FEATURE_MTAB_SUPPORT
    188 static int useMtab;
     243static int useMtab = 1;
    189244static int fakeIt;
    190245#else
     
    194249
    195250// Perform actual mount of specific filesystem at specific location.
    196 
     251// NB: mp->xxx fields may be trashed on exit
    197252static int mount_it_now(struct mntent *mp, int vfsflags, char *filteropts)
    198253{
    199     int rc;
    200 
    201     if (fakeIt) { return 0; }
     254    int rc = 0;
     255
     256    if (fakeIt) goto mtab;
    202257
    203258    // Mount, with fallback to read-only if necessary.
    204259
    205     for(;;) {
     260    for (;;) {
    206261        rc = mount(mp->mnt_fsname, mp->mnt_dir, mp->mnt_type,
    207262                vfsflags, filteropts);
    208         if(!rc || (vfsflags&MS_RDONLY) || (errno!=EACCES && errno!=EROFS))
     263        if (!rc || (vfsflags&MS_RDONLY) || (errno!=EACCES && errno!=EROFS))
    209264            break;
    210265        bb_error_msg("%s is write-protected, mounting read-only",
     
    220275    /* If the mount was successful, and we're maintaining an old-style
    221276     * mtab file by hand, add the new entry to it now. */
    222 
    223     if(ENABLE_FEATURE_MTAB_SUPPORT && useMtab && !rc) {
     277 mtab:
     278    if (ENABLE_FEATURE_MTAB_SUPPORT && useMtab && !rc && !(vfsflags & MS_REMOUNT)) {
     279        char *fsname;
    224280        FILE *mountTable = setmntent(bb_path_mtab_file, "a+");
    225281        int i;
    226282
    227         if(!mountTable)
    228             bb_error_msg("No %s\n",bb_path_mtab_file);
     283        if (!mountTable) {
     284            bb_error_msg("no %s",bb_path_mtab_file);
     285            goto ret;
     286        }
    229287
    230288        // Add vfs string flags
    231289
    232         for(i=0; mount_options[i].flags != MS_REMOUNT; i++)
    233             if (mount_options[i].flags > 0)
    234                 append_mount_options(&(mp->mnt_opts),
    235 // Shut up about the darn const.  It's not important.  I don't care.
    236                         (char *)mount_options[i].name);
     290        for (i=0; mount_options[i].flags != MS_REMOUNT; i++)
     291            if (mount_options[i].flags > 0 && (mount_options[i].flags & vfsflags))
     292                append_mount_options(&(mp->mnt_opts), mount_options[i].name);
    237293
    238294        // Remove trailing / (if any) from directory we mounted on
    239295
    240         i = strlen(mp->mnt_dir);
    241         if(i>1 && mp->mnt_dir[i-1] == '/') mp->mnt_dir[i-1] = 0;
     296        i = strlen(mp->mnt_dir) - 1;
     297        if (i > 0 && mp->mnt_dir[i] == '/') mp->mnt_dir[i] = 0;
     298
     299        // Convert to canonical pathnames as needed
     300
     301        mp->mnt_dir = bb_simplify_path(mp->mnt_dir);
     302        fsname = 0;
     303        if (!mp->mnt_type || !*mp->mnt_type) { /* bind mount */
     304            mp->mnt_fsname = fsname = bb_simplify_path(mp->mnt_fsname);
     305            mp->mnt_type = (char*)"bind";
     306        }
     307        mp->mnt_freq = mp->mnt_passno = 0;
    242308
    243309        // Write and close.
    244310
    245         if(!mp->mnt_type || !*mp->mnt_type) mp->mnt_type="--bind";
    246311        addmntent(mountTable, mp);
    247312        endmntent(mountTable);
    248         if (ENABLE_FEATURE_CLEAN_UP)
    249             if(strcmp(mp->mnt_type,"--bind")) mp->mnt_type = 0;
    250     }
    251 
     313        if (ENABLE_FEATURE_CLEAN_UP) {
     314            free(mp->mnt_dir);
     315            free(fsname);
     316        }
     317    }
     318 ret:
    252319    return rc;
    253320}
    254321
    255 
    256 // Mount one directory.  Handles NFS, loopback, autobind, and filesystem type
    257 // detection.  Returns 0 for success, nonzero for failure.
    258 
     322#if ENABLE_FEATURE_MOUNT_NFS
     323
     324/*
     325 * Linux NFS mount
     326 * Copyright (C) 1993 Rick Sladkey <jrs@world.std.com>
     327 *
     328 * Licensed under GPLv2, see file LICENSE in this tarball for details.
     329 *
     330 * Wed Feb  8 12:51:48 1995, biro@yggdrasil.com (Ross Biro): allow all port
     331 * numbers to be specified on the command line.
     332 *
     333 * Fri, 8 Mar 1996 18:01:39, Swen Thuemmler <swen@uni-paderborn.de>:
     334 * Omit the call to connect() for Linux version 1.3.11 or later.
     335 *
     336 * Wed Oct  1 23:55:28 1997: Dick Streefland <dick_streefland@tasking.com>
     337 * Implemented the "bg", "fg" and "retry" mount options for NFS.
     338 *
     339 * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@misiek.eu.org>
     340 * - added Native Language Support
     341 *
     342 * Modified by Olaf Kirch and Trond Myklebust for new NFS code,
     343 * plus NFSv3 stuff.
     344 */
     345
     346/* This is just a warning of a common mistake.  Possibly this should be a
     347 * uclibc faq entry rather than in busybox... */
     348#if defined(__UCLIBC__) && ! defined(__UCLIBC_HAS_RPC__)
     349#error "You need to build uClibc with UCLIBC_HAS_RPC for NFS support."
     350#endif
     351
     352#define MOUNTPORT 635
     353#define MNTPATHLEN 1024
     354#define MNTNAMLEN 255
     355#define FHSIZE 32
     356#define FHSIZE3 64
     357
     358typedef char fhandle[FHSIZE];
     359
     360typedef struct {
     361    unsigned int fhandle3_len;
     362    char *fhandle3_val;
     363} fhandle3;
     364
     365enum mountstat3 {
     366    MNT_OK = 0,
     367    MNT3ERR_PERM = 1,
     368    MNT3ERR_NOENT = 2,
     369    MNT3ERR_IO = 5,
     370    MNT3ERR_ACCES = 13,
     371    MNT3ERR_NOTDIR = 20,
     372    MNT3ERR_INVAL = 22,
     373    MNT3ERR_NAMETOOLONG = 63,
     374    MNT3ERR_NOTSUPP = 10004,
     375    MNT3ERR_SERVERFAULT = 10006,
     376};
     377typedef enum mountstat3 mountstat3;
     378
     379struct fhstatus {
     380    unsigned int fhs_status;
     381    union {
     382        fhandle fhs_fhandle;
     383    } fhstatus_u;
     384};
     385typedef struct fhstatus fhstatus;
     386
     387struct mountres3_ok {
     388    fhandle3 fhandle;
     389    struct {
     390        unsigned int auth_flavours_len;
     391        char *auth_flavours_val;
     392    } auth_flavours;
     393};
     394typedef struct mountres3_ok mountres3_ok;
     395
     396struct mountres3 {
     397    mountstat3 fhs_status;
     398    union {
     399        mountres3_ok mountinfo;
     400    } mountres3_u;
     401};
     402typedef struct mountres3 mountres3;
     403
     404typedef char *dirpath;
     405
     406typedef char *name;
     407
     408typedef struct mountbody *mountlist;
     409
     410struct mountbody {
     411    name ml_hostname;
     412    dirpath ml_directory;
     413    mountlist ml_next;
     414};
     415typedef struct mountbody mountbody;
     416
     417typedef struct groupnode *groups;
     418
     419struct groupnode {
     420    name gr_name;
     421    groups gr_next;
     422};
     423typedef struct groupnode groupnode;
     424
     425typedef struct exportnode *exports;
     426
     427struct exportnode {
     428    dirpath ex_dir;
     429    groups ex_groups;
     430    exports ex_next;
     431};
     432typedef struct exportnode exportnode;
     433
     434struct ppathcnf {
     435    int pc_link_max;
     436    short pc_max_canon;
     437    short pc_max_input;
     438    short pc_name_max;
     439    short pc_path_max;
     440    short pc_pipe_buf;
     441    uint8_t pc_vdisable;
     442    char pc_xxx;
     443    short pc_mask[2];
     444};
     445typedef struct ppathcnf ppathcnf;
     446
     447#define MOUNTPROG 100005
     448#define MOUNTVERS 1
     449
     450#define MOUNTPROC_NULL 0
     451#define MOUNTPROC_MNT 1
     452#define MOUNTPROC_DUMP 2
     453#define MOUNTPROC_UMNT 3
     454#define MOUNTPROC_UMNTALL 4
     455#define MOUNTPROC_EXPORT 5
     456#define MOUNTPROC_EXPORTALL 6
     457
     458#define MOUNTVERS_POSIX 2
     459
     460#define MOUNTPROC_PATHCONF 7
     461
     462#define MOUNT_V3 3
     463
     464#define MOUNTPROC3_NULL 0
     465#define MOUNTPROC3_MNT 1
     466#define MOUNTPROC3_DUMP 2
     467#define MOUNTPROC3_UMNT 3
     468#define MOUNTPROC3_UMNTALL 4
     469#define MOUNTPROC3_EXPORT 5
     470
     471enum {
     472#ifndef NFS_FHSIZE
     473    NFS_FHSIZE = 32,
     474#endif
     475#ifndef NFS_PORT
     476    NFS_PORT = 2049
     477#endif
     478};
     479
     480/*
     481 * We want to be able to compile mount on old kernels in such a way
     482 * that the binary will work well on more recent kernels.
     483 * Thus, if necessary we teach nfsmount.c the structure of new fields
     484 * that will come later.
     485 *
     486 * Moreover, the new kernel includes conflict with glibc includes
     487 * so it is easiest to ignore the kernel altogether (at compile time).
     488 */
     489
     490struct nfs2_fh {
     491    char                    data[32];
     492};
     493struct nfs3_fh {
     494    unsigned short          size;
     495    unsigned char           data[64];
     496};
     497
     498struct nfs_mount_data {
     499    int     version;        /* 1 */
     500    int     fd;         /* 1 */
     501    struct nfs2_fh  old_root;       /* 1 */
     502    int     flags;          /* 1 */
     503    int     rsize;          /* 1 */
     504    int     wsize;          /* 1 */
     505    int     timeo;          /* 1 */
     506    int     retrans;        /* 1 */
     507    int     acregmin;       /* 1 */
     508    int     acregmax;       /* 1 */
     509    int     acdirmin;       /* 1 */
     510    int     acdirmax;       /* 1 */
     511    struct sockaddr_in addr;        /* 1 */
     512    char        hostname[256];      /* 1 */
     513    int     namlen;         /* 2 */
     514    unsigned int    bsize;          /* 3 */
     515    struct nfs3_fh  root;           /* 4 */
     516};
     517
     518/* bits in the flags field */
     519enum {
     520    NFS_MOUNT_SOFT = 0x0001,    /* 1 */
     521    NFS_MOUNT_INTR = 0x0002,    /* 1 */
     522    NFS_MOUNT_SECURE = 0x0004,  /* 1 */
     523    NFS_MOUNT_POSIX = 0x0008,   /* 1 */
     524    NFS_MOUNT_NOCTO = 0x0010,   /* 1 */
     525    NFS_MOUNT_NOAC = 0x0020,    /* 1 */
     526    NFS_MOUNT_TCP = 0x0040,     /* 2 */
     527    NFS_MOUNT_VER3 = 0x0080,    /* 3 */
     528    NFS_MOUNT_KERBEROS = 0x0100,    /* 3 */
     529    NFS_MOUNT_NONLM = 0x0200    /* 3 */
     530};
     531
     532
     533/*
     534 * We need to translate between nfs status return values and
     535 * the local errno values which may not be the same.
     536 *
     537 * Andreas Schwab <schwab@LS5.informatik.uni-dortmund.de>: change errno:
     538 * "after #include <errno.h> the symbol errno is reserved for any use,
     539 *  it cannot even be used as a struct tag or field name".
     540 */
     541
     542#ifndef EDQUOT
     543#define EDQUOT  ENOSPC
     544#endif
     545
     546// Convert each NFSERR_BLAH into EBLAH
     547
     548static const struct {
     549    int stat;
     550    int errnum;
     551} nfs_errtbl[] = {
     552    {0,0}, {1,EPERM}, {2,ENOENT}, {5,EIO}, {6,ENXIO}, {13,EACCES}, {17,EEXIST},
     553    {19,ENODEV}, {20,ENOTDIR}, {21,EISDIR}, {22,EINVAL}, {27,EFBIG},
     554    {28,ENOSPC}, {30,EROFS}, {63,ENAMETOOLONG}, {66,ENOTEMPTY}, {69,EDQUOT},
     555    {70,ESTALE}, {71,EREMOTE}, {-1,EIO}
     556};
     557
     558static char *nfs_strerror(int status)
     559{
     560    int i;
     561    static char buf[sizeof("unknown nfs status return value: ") + sizeof(int)*3];
     562
     563    for (i = 0; nfs_errtbl[i].stat != -1; i++) {
     564        if (nfs_errtbl[i].stat == status)
     565            return strerror(nfs_errtbl[i].errnum);
     566    }
     567    sprintf(buf, "unknown nfs status return value: %d", status);
     568    return buf;
     569}
     570
     571static bool_t xdr_fhandle(XDR *xdrs, fhandle objp)
     572{
     573    if (!xdr_opaque(xdrs, objp, FHSIZE))
     574         return FALSE;
     575    return TRUE;
     576}
     577
     578static bool_t xdr_fhstatus(XDR *xdrs, fhstatus *objp)
     579{
     580    if (!xdr_u_int(xdrs, &objp->fhs_status))
     581         return FALSE;
     582    switch (objp->fhs_status) {
     583    case 0:
     584        if (!xdr_fhandle(xdrs, objp->fhstatus_u.fhs_fhandle))
     585             return FALSE;
     586        break;
     587    default:
     588        break;
     589    }
     590    return TRUE;
     591}
     592
     593static bool_t xdr_dirpath(XDR *xdrs, dirpath *objp)
     594{
     595    if (!xdr_string(xdrs, objp, MNTPATHLEN))
     596         return FALSE;
     597    return TRUE;
     598}
     599
     600static bool_t xdr_fhandle3(XDR *xdrs, fhandle3 *objp)
     601{
     602    if (!xdr_bytes(xdrs, (char **)&objp->fhandle3_val, (unsigned int *) &objp->fhandle3_len, FHSIZE3))
     603         return FALSE;
     604    return TRUE;
     605}
     606
     607static bool_t xdr_mountres3_ok(XDR *xdrs, mountres3_ok *objp)
     608{
     609    if (!xdr_fhandle3(xdrs, &objp->fhandle))
     610        return FALSE;
     611    if (!xdr_array(xdrs, &(objp->auth_flavours.auth_flavours_val), &(objp->auth_flavours.auth_flavours_len), ~0,
     612                sizeof (int), (xdrproc_t) xdr_int))
     613        return FALSE;
     614    return TRUE;
     615}
     616
     617static bool_t xdr_mountstat3(XDR *xdrs, mountstat3 *objp)
     618{
     619    if (!xdr_enum(xdrs, (enum_t *) objp))
     620         return FALSE;
     621    return TRUE;
     622}
     623
     624static bool_t xdr_mountres3(XDR *xdrs, mountres3 *objp)
     625{
     626    if (!xdr_mountstat3(xdrs, &objp->fhs_status))
     627        return FALSE;
     628    switch (objp->fhs_status) {
     629    case MNT_OK:
     630        if (!xdr_mountres3_ok(xdrs, &objp->mountres3_u.mountinfo))
     631             return FALSE;
     632        break;
     633    default:
     634        break;
     635    }
     636    return TRUE;
     637}
     638
     639#define MAX_NFSPROT ((nfs_mount_version >= 4) ? 3 : 2)
     640
     641/*
     642 * nfs_mount_version according to the sources seen at compile time.
     643 */
     644static int nfs_mount_version;
     645static int kernel_version;
     646
     647/*
     648 * Unfortunately, the kernel prints annoying console messages
     649 * in case of an unexpected nfs mount version (instead of
     650 * just returning some error).  Therefore we'll have to try
     651 * and figure out what version the kernel expects.
     652 *
     653 * Variables:
     654 *  KERNEL_NFS_MOUNT_VERSION: kernel sources at compile time
     655 *  NFS_MOUNT_VERSION: these nfsmount sources at compile time
     656 *  nfs_mount_version: version this source and running kernel can handle
     657 */
     658static void
     659find_kernel_nfs_mount_version(void)
     660{
     661    if (kernel_version)
     662        return;
     663
     664    nfs_mount_version = 4; /* default */
     665
     666    kernel_version = get_linux_version_code();
     667    if (kernel_version) {
     668        if (kernel_version < KERNEL_VERSION(2,1,32))
     669            nfs_mount_version = 1;
     670        else if (kernel_version < KERNEL_VERSION(2,2,18) ||
     671                (kernel_version >= KERNEL_VERSION(2,3,0) &&
     672                 kernel_version < KERNEL_VERSION(2,3,99)))
     673            nfs_mount_version = 3;
     674        /* else v4 since 2.3.99pre4 */
     675    }
     676}
     677
     678static struct pmap *
     679get_mountport(struct sockaddr_in *server_addr,
     680    long unsigned prog,
     681    long unsigned version,
     682    long unsigned proto,
     683    long unsigned port)
     684{
     685    struct pmaplist *pmap;
     686    static struct pmap p = {0, 0, 0, 0};
     687
     688    server_addr->sin_port = PMAPPORT;
     689/* glibc 2.4 (still) has pmap_getmaps(struct sockaddr_in *).
     690 * I understand it like "IPv6 for this is not 100% ready" */
     691    pmap = pmap_getmaps(server_addr);
     692
     693    if (version > MAX_NFSPROT)
     694        version = MAX_NFSPROT;
     695    if (!prog)
     696        prog = MOUNTPROG;
     697    p.pm_prog = prog;
     698    p.pm_vers = version;
     699    p.pm_prot = proto;
     700    p.pm_port = port;
     701
     702    while (pmap) {
     703        if (pmap->pml_map.pm_prog != prog)
     704            goto next;
     705        if (!version && p.pm_vers > pmap->pml_map.pm_vers)
     706            goto next;
     707        if (version > 2 && pmap->pml_map.pm_vers != version)
     708            goto next;
     709        if (version && version <= 2 && pmap->pml_map.pm_vers > 2)
     710            goto next;
     711        if (pmap->pml_map.pm_vers > MAX_NFSPROT ||
     712            (proto && p.pm_prot && pmap->pml_map.pm_prot != proto) ||
     713            (port && pmap->pml_map.pm_port != port))
     714            goto next;
     715        memcpy(&p, &pmap->pml_map, sizeof(p));
     716next:
     717        pmap = pmap->pml_next;
     718    }
     719    if (!p.pm_vers)
     720        p.pm_vers = MOUNTVERS;
     721    if (!p.pm_port)
     722        p.pm_port = MOUNTPORT;
     723    if (!p.pm_prot)
     724        p.pm_prot = IPPROTO_TCP;
     725    return &p;
     726}
     727
     728static int daemonize(void)
     729{
     730    int fd;
     731    int pid = fork();
     732    if (pid < 0) /* error */
     733        return -errno;
     734    if (pid > 0) /* parent */
     735        return 0;
     736    /* child */
     737    fd = xopen(bb_dev_null, O_RDWR);
     738    dup2(fd, 0);
     739    dup2(fd, 1);
     740    dup2(fd, 2);
     741    while (fd > 2) close(fd--);
     742    setsid();
     743    openlog(applet_name, LOG_PID, LOG_DAEMON);
     744    logmode = LOGMODE_SYSLOG;
     745    return 1;
     746}
     747
     748// TODO
     749static inline int we_saw_this_host_before(const char *hostname)
     750{
     751    return 0;
     752}
     753
     754/* RPC strerror analogs are terminally idiotic:
     755 * *mandatory* prefix and \n at end.
     756 * This hopefully helps. Usage:
     757 * error_msg_rpc(clnt_*error*(" ")) */
     758static void error_msg_rpc(const char *msg)
     759{
     760    int len;
     761    while (msg[0] == ' ' || msg[0] == ':') msg++;
     762    len = strlen(msg);
     763    while (len && msg[len-1] == '\n') len--;
     764    bb_error_msg("%.*s", len, msg);
     765}
     766
     767// NB: mp->xxx fields may be trashed on exit
     768static int nfsmount(struct mntent *mp, int vfsflags, char *filteropts)
     769{
     770    CLIENT *mclient;
     771    char *hostname;
     772    char *pathname;
     773    char *mounthost;
     774    struct nfs_mount_data data;
     775    char *opt;
     776    struct hostent *hp;
     777    struct sockaddr_in server_addr;
     778    struct sockaddr_in mount_server_addr;
     779    int msock, fsock;
     780    union {
     781        struct fhstatus nfsv2;
     782        struct mountres3 nfsv3;
     783    } status;
     784    int daemonized;
     785    char *s;
     786    int port;
     787    int mountport;
     788    int proto;
     789    int bg;
     790    int soft;
     791    int intr;
     792    int posix;
     793    int nocto;
     794    int noac;
     795    int nolock;
     796    int retry;
     797    int tcp;
     798    int mountprog;
     799    int mountvers;
     800    int nfsprog;
     801    int nfsvers;
     802    int retval;
     803
     804    find_kernel_nfs_mount_version();
     805
     806    daemonized = 0;
     807    mounthost = NULL;
     808    retval = ETIMEDOUT;
     809    msock = fsock = -1;
     810    mclient = NULL;
     811
     812    /* NB: hostname, mounthost, filteropts must be free()d prior to return */
     813
     814    filteropts = xstrdup(filteropts); /* going to trash it later... */
     815
     816    hostname = xstrdup(mp->mnt_fsname);
     817    /* mount_main() guarantees that ':' is there */
     818    s = strchr(hostname, ':');
     819    pathname = s + 1;
     820    *s = '\0';
     821    /* Ignore all but first hostname in replicated mounts
     822       until they can be fully supported. (mack@sgi.com) */
     823    s = strchr(hostname, ',');
     824    if (s) {
     825        *s = '\0';
     826        bb_error_msg("warning: multiple hostnames not supported");
     827    }
     828
     829    server_addr.sin_family = AF_INET;
     830    if (!inet_aton(hostname, &server_addr.sin_addr)) {
     831        hp = gethostbyname(hostname);
     832        if (hp == NULL) {
     833            bb_herror_msg("%s", hostname);
     834            goto fail;
     835        }
     836        if (hp->h_length > sizeof(struct in_addr)) {
     837            bb_error_msg("got bad hp->h_length");
     838            hp->h_length = sizeof(struct in_addr);
     839        }
     840        memcpy(&server_addr.sin_addr,
     841                hp->h_addr, hp->h_length);
     842    }
     843
     844    memcpy(&mount_server_addr, &server_addr, sizeof(mount_server_addr));
     845
     846    /* add IP address to mtab options for use when unmounting */
     847
     848    if (!mp->mnt_opts) { /* TODO: actually mp->mnt_opts is never NULL */
     849        mp->mnt_opts = xasprintf("addr=%s", inet_ntoa(server_addr.sin_addr));
     850    } else {
     851        char *tmp = xasprintf("%s%saddr=%s", mp->mnt_opts,
     852                    mp->mnt_opts[0] ? "," : "",
     853                    inet_ntoa(server_addr.sin_addr));
     854        free(mp->mnt_opts);
     855        mp->mnt_opts = tmp;
     856    }
     857
     858    /* Set default options.
     859     * rsize/wsize (and bsize, for ver >= 3) are left 0 in order to
     860     * let the kernel decide.
     861     * timeo is filled in after we know whether it'll be TCP or UDP. */
     862    memset(&data, 0, sizeof(data));
     863    data.retrans    = 3;
     864    data.acregmin   = 3;
     865    data.acregmax   = 60;
     866    data.acdirmin   = 30;
     867    data.acdirmax   = 60;
     868    data.namlen = NAME_MAX;
     869
     870    bg = 0;
     871    soft = 0;
     872    intr = 0;
     873    posix = 0;
     874    nocto = 0;
     875    nolock = 0;
     876    noac = 0;
     877    retry = 10000;      /* 10000 minutes ~ 1 week */
     878    tcp = 0;
     879
     880    mountprog = MOUNTPROG;
     881    mountvers = 0;
     882    port = 0;
     883    mountport = 0;
     884    nfsprog = 100003;
     885    nfsvers = 0;
     886
     887    /* parse options */
     888    if (filteropts) for (opt = strtok(filteropts, ","); opt; opt = strtok(NULL, ",")) {
     889        char *opteq = strchr(opt, '=');
     890        if (opteq) {
     891            static const char options[] ALIGN1 =
     892                /* 0 */ "rsize\0"
     893                /* 1 */ "wsize\0"
     894                /* 2 */ "timeo\0"
     895                /* 3 */ "retrans\0"
     896                /* 4 */ "acregmin\0"
     897                /* 5 */ "acregmax\0"
     898                /* 6 */ "acdirmin\0"
     899                /* 7 */ "acdirmax\0"
     900                /* 8 */ "actimeo\0"
     901                /* 9 */ "retry\0"
     902                /* 10 */ "port\0"
     903                /* 11 */ "mountport\0"
     904                /* 12 */ "mounthost\0"
     905                /* 13 */ "mountprog\0"
     906                /* 14 */ "mountvers\0"
     907                /* 15 */ "nfsprog\0"
     908                /* 16 */ "nfsvers\0"
     909                /* 17 */ "vers\0"
     910                /* 18 */ "proto\0"
     911                /* 19 */ "namlen\0"
     912                /* 20 */ "addr\0";
     913            int val = xatoi_u(opteq + 1);
     914            *opteq = '\0';
     915            switch (index_in_strings(options, opt)) {
     916            case 0: // "rsize"
     917                data.rsize = val;
     918                break;
     919            case 1: // "wsize"
     920                data.wsize = val;
     921                break;
     922            case 2: // "timeo"
     923                data.timeo = val;
     924                break;
     925            case 3: // "retrans"
     926                data.retrans = val;
     927                break;
     928            case 4: // "acregmin"
     929                data.acregmin = val;
     930                break;
     931            case 5: // "acregmax"
     932                data.acregmax = val;
     933                break;
     934            case 6: // "acdirmin"
     935                data.acdirmin = val;
     936                break;
     937            case 7: // "acdirmax"
     938                data.acdirmax = val;
     939                break;
     940            case 8: // "actimeo"
     941                data.acregmin = val;
     942                data.acregmax = val;
     943                data.acdirmin = val;
     944                data.acdirmax = val;
     945                break;
     946            case 9: // "retry"
     947                retry = val;
     948                break;
     949            case 10: // "port"
     950                port = val;
     951                break;
     952            case 11: // "mountport"
     953                mountport = val;
     954                break;
     955            case 12: // "mounthost"
     956                mounthost = xstrndup(opteq+1,
     957                        strcspn(opteq+1," \t\n\r,"));
     958                break;
     959            case 13: // "mountprog"
     960                mountprog = val;
     961                break;
     962            case 14: // "mountvers"
     963                mountvers = val;
     964                break;
     965            case 15: // "nfsprog"
     966                nfsprog = val;
     967                break;
     968            case 16: // "nfsvers"
     969            case 17: // "vers"
     970                nfsvers = val;
     971                break;
     972            case 18: // "proto"
     973                if (!strncmp(opteq+1, "tcp", 3))
     974                    tcp = 1;
     975                else if (!strncmp(opteq+1, "udp", 3))
     976                    tcp = 0;
     977                else
     978                    bb_error_msg("warning: unrecognized proto= option");
     979                break;
     980            case 19: // "namlen"
     981                if (nfs_mount_version >= 2)
     982                    data.namlen = val;
     983                else
     984                    bb_error_msg("warning: option namlen is not supported\n");
     985                break;
     986            case 20: // "addr" - ignore
     987                break;
     988            default:
     989                bb_error_msg("unknown nfs mount parameter: %s=%d", opt, val);
     990                goto fail;
     991            }
     992        }
     993        else {
     994            static const char options[] ALIGN1 =
     995                "bg\0"
     996                "fg\0"
     997                "soft\0"
     998                "hard\0"
     999                "intr\0"
     1000                "posix\0"
     1001                "cto\0"
     1002                "ac\0"
     1003                "tcp\0"
     1004                "udp\0"
     1005                "lock\0";
     1006            int val = 1;
     1007            if (!strncmp(opt, "no", 2)) {
     1008                val = 0;
     1009                opt += 2;
     1010            }
     1011            switch (index_in_strings(options, opt)) {
     1012            case 0: // "bg"
     1013                bg = val;
     1014                break;
     1015            case 1: // "fg"
     1016                bg = !val;
     1017                break;
     1018            case 2: // "soft"
     1019                soft = val;
     1020                break;
     1021            case 3: // "hard"
     1022                soft = !val;
     1023                break;
     1024            case 4: // "intr"
     1025                intr = val;
     1026                break;
     1027            case 5: // "posix"
     1028                posix = val;
     1029                break;
     1030            case 6: // "cto"
     1031                nocto = !val;
     1032                break;
     1033            case 7: // "ac"
     1034                noac = !val;
     1035                break;
     1036            case 8: // "tcp"
     1037                tcp = val;
     1038                break;
     1039            case 9: // "udp"
     1040                tcp = !val;
     1041                break;
     1042            case 10: // "lock"
     1043                if (nfs_mount_version >= 3)
     1044                    nolock = !val;
     1045                else
     1046                    bb_error_msg("warning: option nolock is not supported");
     1047                break;
     1048            default:
     1049                bb_error_msg("unknown nfs mount option: %s%s", val ? "" : "no", opt);
     1050                goto fail;
     1051            }
     1052        }
     1053    }
     1054    proto = (tcp) ? IPPROTO_TCP : IPPROTO_UDP;
     1055
     1056    data.flags = (soft ? NFS_MOUNT_SOFT : 0)
     1057        | (intr ? NFS_MOUNT_INTR : 0)
     1058        | (posix ? NFS_MOUNT_POSIX : 0)
     1059        | (nocto ? NFS_MOUNT_NOCTO : 0)
     1060        | (noac ? NFS_MOUNT_NOAC : 0);
     1061    if (nfs_mount_version >= 2)
     1062        data.flags |= (tcp ? NFS_MOUNT_TCP : 0);
     1063    if (nfs_mount_version >= 3)
     1064        data.flags |= (nolock ? NFS_MOUNT_NONLM : 0);
     1065    if (nfsvers > MAX_NFSPROT || mountvers > MAX_NFSPROT) {
     1066        bb_error_msg("NFSv%d not supported", nfsvers);
     1067        goto fail;
     1068    }
     1069    if (nfsvers && !mountvers)
     1070        mountvers = (nfsvers < 3) ? 1 : nfsvers;
     1071    if (nfsvers && nfsvers < mountvers) {
     1072        mountvers = nfsvers;
     1073    }
     1074
     1075    /* Adjust options if none specified */
     1076    if (!data.timeo)
     1077        data.timeo = tcp ? 70 : 7;
     1078
     1079    data.version = nfs_mount_version;
     1080
     1081    if (vfsflags & MS_REMOUNT)
     1082        goto do_mount;
     1083
     1084    /*
     1085     * If the previous mount operation on the same host was
     1086     * backgrounded, and the "bg" for this mount is also set,
     1087     * give up immediately, to avoid the initial timeout.
     1088     */
     1089    if (bg && we_saw_this_host_before(hostname)) {
     1090        daemonized = daemonize(); /* parent or error */
     1091        if (daemonized <= 0) { /* parent or error */
     1092            retval = -daemonized;
     1093            goto ret;
     1094        }
     1095    }
     1096
     1097    /* create mount daemon client */
     1098    /* See if the nfs host = mount host. */
     1099    if (mounthost) {
     1100        if (mounthost[0] >= '0' && mounthost[0] <= '9') {
     1101            mount_server_addr.sin_family = AF_INET;
     1102            mount_server_addr.sin_addr.s_addr = inet_addr(hostname);
     1103        } else {
     1104            hp = gethostbyname(mounthost);
     1105            if (hp == NULL) {
     1106                bb_herror_msg("%s", mounthost);
     1107                goto fail;
     1108            } else {
     1109                if (hp->h_length > sizeof(struct in_addr)) {
     1110                    bb_error_msg("got bad hp->h_length?");
     1111                    hp->h_length = sizeof(struct in_addr);
     1112                }
     1113                mount_server_addr.sin_family = AF_INET;
     1114                memcpy(&mount_server_addr.sin_addr,
     1115                        hp->h_addr, hp->h_length);
     1116            }
     1117        }
     1118    }
     1119
     1120    /*
     1121     * The following loop implements the mount retries. When the mount
     1122     * times out, and the "bg" option is set, we background ourself
     1123     * and continue trying.
     1124     *
     1125     * The case where the mount point is not present and the "bg"
     1126     * option is set, is treated as a timeout. This is done to
     1127     * support nested mounts.
     1128     *
     1129     * The "retry" count specified by the user is the number of
     1130     * minutes to retry before giving up.
     1131     */
     1132    {
     1133        struct timeval total_timeout;
     1134        struct timeval retry_timeout;
     1135        struct pmap* pm_mnt;
     1136        time_t t;
     1137        time_t prevt;
     1138        time_t timeout;
     1139
     1140        retry_timeout.tv_sec = 3;
     1141        retry_timeout.tv_usec = 0;
     1142        total_timeout.tv_sec = 20;
     1143        total_timeout.tv_usec = 0;
     1144        timeout = time(NULL) + 60 * retry;
     1145        prevt = 0;
     1146        t = 30;
     1147retry:
     1148        /* be careful not to use too many CPU cycles */
     1149        if (t - prevt < 30)
     1150            sleep(30);
     1151
     1152        pm_mnt = get_mountport(&mount_server_addr,
     1153                mountprog,
     1154                mountvers,
     1155                proto,
     1156                mountport);
     1157        nfsvers = (pm_mnt->pm_vers < 2) ? 2 : pm_mnt->pm_vers;
     1158
     1159        /* contact the mount daemon via TCP */
     1160        mount_server_addr.sin_port = htons(pm_mnt->pm_port);
     1161        msock = RPC_ANYSOCK;
     1162
     1163        switch (pm_mnt->pm_prot) {
     1164        case IPPROTO_UDP:
     1165            mclient = clntudp_create(&mount_server_addr,
     1166                         pm_mnt->pm_prog,
     1167                         pm_mnt->pm_vers,
     1168                         retry_timeout,
     1169                         &msock);
     1170            if (mclient)
     1171                break;
     1172            mount_server_addr.sin_port = htons(pm_mnt->pm_port);
     1173            msock = RPC_ANYSOCK;
     1174        case IPPROTO_TCP:
     1175            mclient = clnttcp_create(&mount_server_addr,
     1176                         pm_mnt->pm_prog,
     1177                         pm_mnt->pm_vers,
     1178                         &msock, 0, 0);
     1179            break;
     1180        default:
     1181            mclient = 0;
     1182        }
     1183        if (!mclient) {
     1184            if (!daemonized && prevt == 0)
     1185                error_msg_rpc(clnt_spcreateerror(" "));
     1186        } else {
     1187            enum clnt_stat clnt_stat;
     1188            /* try to mount hostname:pathname */
     1189            mclient->cl_auth = authunix_create_default();
     1190
     1191            /* make pointers in xdr_mountres3 NULL so
     1192             * that xdr_array allocates memory for us
     1193             */
     1194            memset(&status, 0, sizeof(status));
     1195
     1196            if (pm_mnt->pm_vers == 3)
     1197                clnt_stat = clnt_call(mclient, MOUNTPROC3_MNT,
     1198                          (xdrproc_t) xdr_dirpath,
     1199                          (caddr_t) &pathname,
     1200                          (xdrproc_t) xdr_mountres3,
     1201                          (caddr_t) &status,
     1202                          total_timeout);
     1203            else
     1204                clnt_stat = clnt_call(mclient, MOUNTPROC_MNT,
     1205                          (xdrproc_t) xdr_dirpath,
     1206                          (caddr_t) &pathname,
     1207                          (xdrproc_t) xdr_fhstatus,
     1208                          (caddr_t) &status,
     1209                          total_timeout);
     1210
     1211            if (clnt_stat == RPC_SUCCESS)
     1212                goto prepare_kernel_data; /* we're done */
     1213            if (errno != ECONNREFUSED) {
     1214                error_msg_rpc(clnt_sperror(mclient, " "));
     1215                goto fail;  /* don't retry */
     1216            }
     1217            /* Connection refused */
     1218            if (!daemonized && prevt == 0) /* print just once */
     1219                error_msg_rpc(clnt_sperror(mclient, " "));
     1220            auth_destroy(mclient->cl_auth);
     1221            clnt_destroy(mclient);
     1222            mclient = 0;
     1223            close(msock);
     1224        }
     1225
     1226        /* Timeout. We are going to retry... maybe */
     1227
     1228        if (!bg)
     1229            goto fail;
     1230        if (!daemonized) {
     1231            daemonized = daemonize();
     1232            if (daemonized <= 0) { /* parent or error */
     1233                retval = -daemonized;
     1234                goto ret;
     1235            }
     1236        }
     1237        prevt = t;
     1238        t = time(NULL);
     1239        if (t >= timeout)
     1240            /* TODO error message */
     1241            goto fail;
     1242
     1243        goto retry;
     1244    }
     1245
     1246prepare_kernel_data:
     1247
     1248    if (nfsvers == 2) {
     1249        if (status.nfsv2.fhs_status != 0) {
     1250            bb_error_msg("%s:%s failed, reason given by server: %s",
     1251                hostname, pathname,
     1252                nfs_strerror(status.nfsv2.fhs_status));
     1253            goto fail;
     1254        }
     1255        memcpy(data.root.data,
     1256                (char *) status.nfsv2.fhstatus_u.fhs_fhandle,
     1257                NFS_FHSIZE);
     1258        data.root.size = NFS_FHSIZE;
     1259        memcpy(data.old_root.data,
     1260                (char *) status.nfsv2.fhstatus_u.fhs_fhandle,
     1261                NFS_FHSIZE);
     1262    } else {
     1263        fhandle3 *my_fhandle;
     1264        if (status.nfsv3.fhs_status != 0) {
     1265            bb_error_msg("%s:%s failed, reason given by server: %s",
     1266                hostname, pathname,
     1267                nfs_strerror(status.nfsv3.fhs_status));
     1268            goto fail;
     1269        }
     1270        my_fhandle = &status.nfsv3.mountres3_u.mountinfo.fhandle;
     1271        memset(data.old_root.data, 0, NFS_FHSIZE);
     1272        memset(&data.root, 0, sizeof(data.root));
     1273        data.root.size = my_fhandle->fhandle3_len;
     1274        memcpy(data.root.data,
     1275                (char *) my_fhandle->fhandle3_val,
     1276                my_fhandle->fhandle3_len);
     1277
     1278        data.flags |= NFS_MOUNT_VER3;
     1279    }
     1280
     1281    /* create nfs socket for kernel */
     1282
     1283    if (tcp) {
     1284        if (nfs_mount_version < 3) {
     1285            bb_error_msg("NFS over TCP is not supported");
     1286            goto fail;
     1287        }
     1288        fsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
     1289    } else
     1290        fsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
     1291    if (fsock < 0) {
     1292        bb_perror_msg("nfs socket");
     1293        goto fail;
     1294    }
     1295    if (bindresvport(fsock, 0) < 0) {
     1296        bb_perror_msg("nfs bindresvport");
     1297        goto fail;
     1298    }
     1299    if (port == 0) {
     1300        server_addr.sin_port = PMAPPORT;
     1301        port = pmap_getport(&server_addr, nfsprog, nfsvers,
     1302                    tcp ? IPPROTO_TCP : IPPROTO_UDP);
     1303        if (port == 0)
     1304            port = NFS_PORT;
     1305    }
     1306    server_addr.sin_port = htons(port);
     1307
     1308    /* prepare data structure for kernel */
     1309
     1310    data.fd = fsock;
     1311    memcpy((char *) &data.addr, (char *) &server_addr, sizeof(data.addr));
     1312    strncpy(data.hostname, hostname, sizeof(data.hostname));
     1313
     1314    /* clean up */
     1315
     1316    auth_destroy(mclient->cl_auth);
     1317    clnt_destroy(mclient);
     1318    close(msock);
     1319
     1320    if (bg) {
     1321        /* We must wait until mount directory is available */
     1322        struct stat statbuf;
     1323        int delay = 1;
     1324        while (stat(mp->mnt_dir, &statbuf) == -1) {
     1325            if (!daemonized) {
     1326                daemonized = daemonize();
     1327                if (daemonized <= 0) { /* parent or error */
     1328                    retval = -daemonized;
     1329                    goto ret;
     1330                }
     1331            }
     1332            sleep(delay);   /* 1, 2, 4, 8, 16, 30, ... */
     1333            delay *= 2;
     1334            if (delay > 30)
     1335                delay = 30;
     1336        }
     1337    }
     1338
     1339do_mount: /* perform actual mount */
     1340
     1341    mp->mnt_type = (char*)"nfs";
     1342    retval = mount_it_now(mp, vfsflags, (char*)&data);
     1343    goto ret;
     1344
     1345fail:   /* abort */
     1346
     1347    if (msock != -1) {
     1348        if (mclient) {
     1349            auth_destroy(mclient->cl_auth);
     1350            clnt_destroy(mclient);
     1351        }
     1352        close(msock);
     1353    }
     1354    if (fsock != -1)
     1355        close(fsock);
     1356
     1357ret:
     1358    free(hostname);
     1359    free(mounthost);
     1360    free(filteropts);
     1361    return retval;
     1362}
     1363
     1364#else /* !ENABLE_FEATURE_MOUNT_NFS */
     1365
     1366/* Never called. Call should be optimized out. */
     1367int nfsmount(struct mntent *mp, int vfsflags, char *filteropts);
     1368
     1369#endif /* !ENABLE_FEATURE_MOUNT_NFS */
     1370
     1371// Mount one directory.  Handles CIFS, NFS, loopback, autobind, and filesystem
     1372// type detection.  Returns 0 for success, nonzero for failure.
     1373// NB: mp->xxx fields may be trashed on exit
    2591374static int singlemount(struct mntent *mp, int ignore_busy)
    2601375{
     
    2681383    // Treat fstype "auto" as unspecified.
    2691384
    270     if (mp->mnt_type && !strcmp(mp->mnt_type,"auto")) mp->mnt_type = 0;
     1385    if (mp->mnt_type && strcmp(mp->mnt_type,"auto") == 0)
     1386        mp->mnt_type = 0;
     1387
     1388    // Might this be an CIFS filesystem?
     1389
     1390    if (ENABLE_FEATURE_MOUNT_CIFS
     1391     && (!mp->mnt_type || strcmp(mp->mnt_type,"cifs") == 0)
     1392     && (mp->mnt_fsname[0]=='/' || mp->mnt_fsname[0]=='\\')
     1393     && mp->mnt_fsname[0]==mp->mnt_fsname[1]
     1394    ) {
     1395        len_and_sockaddr *lsa;
     1396        char *ip, *dotted;
     1397        char *s;
     1398
     1399        rc = 1;
     1400        // Replace '/' with '\' and verify that unc points to "//server/share".
     1401
     1402        for (s = mp->mnt_fsname; *s; ++s)
     1403            if (*s == '/') *s = '\\';
     1404
     1405        // get server IP
     1406
     1407        s = strrchr(mp->mnt_fsname, '\\');
     1408        if (s <= mp->mnt_fsname+1) goto report_error;
     1409        *s = '\0';
     1410        lsa = host2sockaddr(mp->mnt_fsname+2, 0);
     1411        *s = '\\';
     1412        if (!lsa) goto report_error;
     1413
     1414        // insert ip=... option into string flags.
     1415
     1416        dotted = xmalloc_sockaddr2dotted_noport(&lsa->sa);
     1417        ip = xasprintf("ip=%s", dotted);
     1418        parse_mount_options(ip, &filteropts);
     1419
     1420        // compose new unc '\\server-ip\share'
     1421        // (s => slash after hostname)
     1422
     1423        mp->mnt_fsname = xasprintf("\\\\%s%s", dotted, s);
     1424
     1425        // lock is required
     1426        vfsflags |= MS_MANDLOCK;
     1427
     1428        mp->mnt_type = (char*)"cifs";
     1429        rc = mount_it_now(mp, vfsflags, filteropts);
     1430        if (ENABLE_FEATURE_CLEAN_UP) {
     1431            free(mp->mnt_fsname);
     1432            free(ip);
     1433            free(dotted);
     1434            free(lsa);
     1435        }
     1436        goto report_error;
     1437    }
    2711438
    2721439    // Might this be an NFS filesystem?
    2731440
    274     if (ENABLE_FEATURE_MOUNT_NFS &&
    275         (!mp->mnt_type || !strcmp(mp->mnt_type,"nfs")) &&
    276         strchr(mp->mnt_fsname, ':') != NULL)
    277     {
    278         if (nfsmount(mp->mnt_fsname, mp->mnt_dir, &vfsflags, &filteropts, 1)) {
    279             bb_perror_msg("nfsmount failed");
    280             goto report_error;
    281         } else {
    282             // Strangely enough, nfsmount() doesn't actually mount() anything.
    283             mp->mnt_type = "nfs";
    284             rc = mount_it_now(mp, vfsflags, filteropts);
    285             if (ENABLE_FEATURE_CLEAN_UP) free(filteropts);
    286            
    287             goto report_error;
    288         }
     1441    if (ENABLE_FEATURE_MOUNT_NFS
     1442     && (!mp->mnt_type || !strcmp(mp->mnt_type, "nfs"))
     1443     && strchr(mp->mnt_fsname, ':') != NULL
     1444    ) {
     1445        rc = nfsmount(mp, vfsflags, filteropts);
     1446        goto report_error;
    2891447    }
    2901448
    2911449    // Look at the file.  (Not found isn't a failure for remount, or for
    2921450    // a synthetic filesystem like proc or sysfs.)
    293 
    294     if (stat(mp->mnt_fsname, &st));
    295     else if (!(vfsflags & (MS_REMOUNT | MS_BIND | MS_MOVE))) {
     1451    // (We use stat, not lstat, in order to allow
     1452    // mount symlink_to_file_or_blkdev dir)
     1453
     1454    if (!stat(mp->mnt_fsname, &st)
     1455     && !(vfsflags & (MS_REMOUNT | MS_BIND | MS_MOVE))
     1456    ) {
    2961457        // Do we need to allocate a loopback device for it?
    2971458
    2981459        if (ENABLE_FEATURE_MOUNT_LOOP && S_ISREG(st.st_mode)) {
    2991460            loopFile = bb_simplify_path(mp->mnt_fsname);
    300             mp->mnt_fsname = 0;
    301             switch(set_loop(&(mp->mnt_fsname), loopFile, 0)) {
    302                 case 0:
    303                 case 1:
    304                     break;
    305                 default:
    306                     bb_error_msg( errno == EPERM || errno == EACCES
    307                         ? bb_msg_perm_denied_are_you_root
    308                         : "Couldn't setup loop device");
    309                     return errno;
     1461            mp->mnt_fsname = NULL; /* will receive malloced loop dev name */
     1462            if (set_loop(&(mp->mnt_fsname), loopFile, 0) < 0) {
     1463                if (errno == EPERM || errno == EACCES)
     1464                    bb_error_msg(bb_msg_perm_denied_are_you_root);
     1465                else
     1466                    bb_perror_msg("cannot setup loop device");
     1467                return errno;
    3101468            }
    3111469
    3121470        // Autodetect bind mounts
    3131471
    314         } else if (S_ISDIR(st.st_mode) && !mp->mnt_type) vfsflags |= MS_BIND;
     1472        } else if (S_ISDIR(st.st_mode) && !mp->mnt_type)
     1473            vfsflags |= MS_BIND;
    3151474    }
    3161475
     
    3201479    if (mp->mnt_type || (vfsflags & (MS_REMOUNT | MS_BIND | MS_MOVE)))
    3211480        rc = mount_it_now(mp, vfsflags, filteropts);
    322 
    323     // Loop through filesystem types until mount succeeds or we run out
    324 
    3251481    else {
     1482        // Loop through filesystem types until mount succeeds
     1483        // or we run out
    3261484
    3271485        /* Initialize list of block backed filesystems.  This has to be
     
    3371495        for (fl = fslist; fl; fl = fl->link) {
    3381496            mp->mnt_type = fl->data;
    339 
    340             if (!(rc = mount_it_now(mp,vfsflags, filteropts))) break;
    341 
    342             mp->mnt_type = 0;
    343         }
    344     }
    345 
    346     if (ENABLE_FEATURE_CLEAN_UP) free(filteropts);
     1497            rc = mount_it_now(mp, vfsflags, filteropts);
     1498            if (!rc) break;
     1499        }
     1500    }
    3471501
    3481502    // If mount failed, clean up loop file (if any).
     
    3551509        }
    3561510    }
    357 report_error:
    358     if (rc && errno == EBUSY && ignore_busy) rc = 0;
     1511
     1512 report_error:
     1513    if (ENABLE_FEATURE_CLEAN_UP)
     1514        free(filteropts);
     1515
     1516    if (rc && errno == EBUSY && ignore_busy)
     1517        rc = 0;
    3591518    if (rc < 0)
    360         bb_perror_msg("Mounting %s on %s failed", mp->mnt_fsname, mp->mnt_dir);
     1519        bb_perror_msg("mounting %s on %s failed", mp->mnt_fsname, mp->mnt_dir);
    3611520
    3621521    return rc;
     
    3661525// each directory to be mounted.
    3671526
     1527static const char must_be_root[] ALIGN1 = "you must be root";
     1528
     1529int mount_main(int argc, char **argv);
    3681530int mount_main(int argc, char **argv)
    3691531{
    370     char *cmdopts = bb_xstrdup(""), *fstabname, *fstype=0, *storage_path=0;
     1532    enum { OPT_ALL = 0x10 };
     1533
     1534    char *cmdopts = xstrdup(""), *fstype=0, *storage_path=0;
     1535    char *opt_o;
     1536    const char *fstabname;
    3711537    FILE *fstab;
    372     int i, opt, all = FALSE, rc = 0;
     1538    int i, j, rc = 0;
     1539    unsigned opt;
    3731540    struct mntent mtpair[2], *mtcur = mtpair;
     1541    SKIP_DESKTOP(const int nonroot = 0;)
     1542    USE_DESKTOP( int nonroot = (getuid() != 0);)
    3741543
    3751544    /* parse long options, like --bind and --move.  Note that -o option
    3761545     * and --option are synonymous.  Yes, this means --remount,rw works. */
    3771546
    378     for (i = opt = 0; i < argc; i++) {
     1547    for (i = j = 0; i < argc; i++) {
    3791548        if (argv[i][0] == '-' && argv[i][1] == '-') {
    380             append_mount_options(&cmdopts,argv[i]+2);
    381         } else argv[opt++] = argv[i];
    382     }
    383     argc = opt;
     1549            append_mount_options(&cmdopts, argv[i]+2);
     1550        } else argv[j++] = argv[i];
     1551    }
     1552    argv[j] = 0;
     1553    argc = j;
    3841554
    3851555    // Parse remaining options
    3861556
    387     while ((opt = getopt(argc, argv, "o:t:rwavnf")) > 0) {
    388         switch (opt) {
    389             case 'o':
    390                 append_mount_options(&cmdopts, optarg);
    391                 break;
    392             case 't':
    393                 fstype = optarg;
    394                 break;
    395             case 'r':
    396                 append_mount_options(&cmdopts, "ro");
    397                 break;
    398             case 'w':
    399                 append_mount_options(&cmdopts, "rw");
    400                 break;
    401             case 'a':
    402                 all = TRUE;
    403                 break;
    404             case 'n':
    405                 USE_FEATURE_MTAB_SUPPORT(useMtab = FALSE;)
    406                 break;
    407             case 'f':
    408                 USE_FEATURE_MTAB_SUPPORT(fakeIt = FALSE;)
    409                 break;
    410             case 'v':
    411                 break;      // ignore -v
    412             default:
    413                 bb_show_usage();
    414         }
    415     }
     1557    opt = getopt32(argv, "o:t:rwanfvs", &opt_o, &fstype);
     1558    if (opt & 0x1) append_mount_options(&cmdopts, opt_o); // -o
     1559    //if (opt & 0x2) // -t
     1560    if (opt & 0x4) append_mount_options(&cmdopts, "ro"); // -r
     1561    if (opt & 0x8) append_mount_options(&cmdopts, "rw"); // -w
     1562    //if (opt & 0x10) // -a
     1563    if (opt & 0x20) USE_FEATURE_MTAB_SUPPORT(useMtab = 0); // -n
     1564    if (opt & 0x40) USE_FEATURE_MTAB_SUPPORT(fakeIt = 1); // -f
     1565    //if (opt & 0x80) // -v: verbose (ignore)
     1566    //if (opt & 0x100) // -s: sloppy (ignore)
     1567    argv += optind;
     1568    argc -= optind;
    4161569
    4171570    // Three or more non-option arguments?  Die with a usage message.
    4181571
    419     if (optind-argc>2) bb_show_usage();
     1572    if (argc > 2) bb_show_usage();
    4201573
    4211574    // If we have no arguments, show currently mounted filesystems
    4221575
    423     if (optind == argc) {
    424         if (!all) {
     1576    if (!argc) {
     1577        if (!(opt & OPT_ALL)) {
    4251578            FILE *mountTable = setmntent(bb_path_mtab_file, "r");
    4261579
    427             if(!mountTable) bb_error_msg_and_die("No %s",bb_path_mtab_file);
    428 
    429             while (getmntent_r(mountTable,mtpair,bb_common_bufsiz1,
     1580            if (!mountTable) bb_error_msg_and_die("no %s", bb_path_mtab_file);
     1581
     1582            while (getmntent_r(mountTable, mtpair, bb_common_bufsiz1,
    4301583                                sizeof(bb_common_bufsiz1)))
    4311584            {
    432                 // Don't show rootfs.
    433                 if (!strcmp(mtpair->mnt_fsname, "rootfs")) continue;
     1585                // Don't show rootfs. FIXME: why??
     1586                // util-linux 2.12a happily shows rootfs...
     1587                //if (!strcmp(mtpair->mnt_fsname, "rootfs")) continue;
    4341588
    4351589                if (!fstype || !strcmp(mtpair->mnt_type, fstype))
     
    4411595            return EXIT_SUCCESS;
    4421596        }
    443     }
     1597    } else storage_path = bb_simplify_path(argv[0]);
    4441598
    4451599    // When we have two arguments, the second is the directory and we can
     
    4471601    // argument when we get it.
    4481602
    449     if (optind+2 == argc) {
    450         mtpair->mnt_fsname = argv[optind];
    451         mtpair->mnt_dir = argv[optind+1];
     1603    if (argc == 2) {
     1604        if (nonroot)
     1605            bb_error_msg_and_die(must_be_root);
     1606        mtpair->mnt_fsname = argv[0];
     1607        mtpair->mnt_dir = argv[1];
    4521608        mtpair->mnt_type = fstype;
    4531609        mtpair->mnt_opts = cmdopts;
     
    4561612    }
    4571613
    458     // If we have at least one argument, it's the storage location
    459 
    460     if (optind < argc) storage_path = bb_simplify_path(argv[optind]);
     1614    i = parse_mount_options(cmdopts, 0);
     1615    if (nonroot && (i & ~MS_SILENT)) // Non-root users cannot specify flags
     1616        bb_error_msg_and_die(must_be_root);
     1617
     1618    // If we have a shared subtree flag, don't worry about fstab or mtab.
     1619
     1620    if (ENABLE_FEATURE_MOUNT_FLAGS
     1621     && (i & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))
     1622    ) {
     1623        rc = mount("", argv[0], "", i, "");
     1624        if (rc) bb_perror_msg_and_die("%s", argv[0]);
     1625        goto clean_up;
     1626    }
    4611627
    4621628    // Open either fstab or mtab
    4631629
    464     if (parse_mount_options(cmdopts,0) & MS_REMOUNT)
    465         fstabname = (char *)bb_path_mtab_file;  // Again with the evil const.
    466     else fstabname="/etc/fstab";
    467 
    468     if (!(fstab=setmntent(fstabname,"r")))
    469         bb_perror_msg_and_die("Cannot read %s",fstabname);
     1630    fstabname = "/etc/fstab";
     1631    if (i & MS_REMOUNT) {
     1632        fstabname = bb_path_mtab_file;
     1633    }
     1634    fstab = setmntent(fstabname, "r");
     1635    if (!fstab)
     1636        bb_perror_msg_and_die("cannot read %s", fstabname);
    4701637
    4711638    // Loop through entries until we find what we're looking for.
    4721639
    473     memset(mtpair,0,sizeof(mtpair));
     1640    memset(mtpair, 0, sizeof(mtpair));
    4741641    for (;;) {
    475         struct mntent *mtnext = mtpair + (mtcur==mtpair ? 1 : 0);
     1642        struct mntent *mtnext = (mtcur==mtpair ? mtpair+1 : mtpair);
    4761643
    4771644        // Get next fstab entry
     
    4831650            // Were we looking for something specific?
    4841651
    485             if (optind != argc) {
     1652            if (argc) {
    4861653
    4871654                // If we didn't find anything, complain.
    4881655
    4891656                if (!mtnext->mnt_fsname)
    490                     bb_error_msg_and_die("Can't find %s in %s",
    491                         argv[optind], fstabname);
     1657                    bb_error_msg_and_die("can't find %s in %s",
     1658                        argv[0], fstabname);
     1659
     1660                mtcur = mtnext;
     1661                if (nonroot) {
     1662                    // fstab must have "users" or "user"
     1663                    if (!(parse_mount_options(mtcur->mnt_opts, 0) & MOUNT_USERS))
     1664                        bb_error_msg_and_die(must_be_root);
     1665                }
    4921666
    4931667                // Mount the last thing we found.
    4941668
    495                 mtcur = mtnext;
    496                 mtcur->mnt_opts=bb_xstrdup(mtcur->mnt_opts);
    497                 append_mount_options(&(mtcur->mnt_opts),cmdopts);
     1669                mtcur->mnt_opts = xstrdup(mtcur->mnt_opts);
     1670                append_mount_options(&(mtcur->mnt_opts), cmdopts);
    4981671                rc = singlemount(mtcur, 0);
    4991672                free(mtcur->mnt_opts);
     
    5061679         * "proc") or a full path from root */
    5071680
    508         if (optind != argc) {
     1681        if (argc) {
    5091682
    5101683            // Is this what we're looking for?
    5111684
    512             if(strcmp(argv[optind],mtcur->mnt_fsname) &&
    513                strcmp(storage_path,mtcur->mnt_fsname) &&
    514                strcmp(argv[optind],mtcur->mnt_dir) &&
    515                strcmp(storage_path,mtcur->mnt_dir)) continue;
     1685            if (strcmp(argv[0], mtcur->mnt_fsname) &&
     1686               strcmp(storage_path, mtcur->mnt_fsname) &&
     1687               strcmp(argv[0], mtcur->mnt_dir) &&
     1688               strcmp(storage_path, mtcur->mnt_dir)) continue;
    5161689
    5171690            // Remember this entry.  Something later may have overmounted
     
    5231696
    5241697        } else {
    525 
    5261698            // Do we need to match a filesystem type?
    527             if (fstype && strcmp(mtcur->mnt_type,fstype)) continue;
     1699            if (fstype && match_fstype(mtcur, fstype)) continue;
    5281700
    5291701            // Skip noauto and swap anyway.
    5301702
    531             if (parse_mount_options(mtcur->mnt_opts,0)
     1703            if (parse_mount_options(mtcur->mnt_opts, 0)
    5321704                & (MOUNT_NOAUTO | MOUNT_SWAP)) continue;
    5331705
     1706            // No, mount -a won't mount anything,
     1707            // even user mounts, for mere humans.
     1708
     1709            if (nonroot)
     1710                bb_error_msg_and_die(must_be_root);
     1711
    5341712            // Mount this thing.
    5351713
     1714            // NFS mounts want this to be xrealloc-able
     1715            mtcur->mnt_opts = xstrdup(mtcur->mnt_opts);
    5361716            if (singlemount(mtcur, 1)) {
    5371717                /* Count number of failed mounts */
    5381718                rc++;
    5391719            }
     1720            free(mtcur->mnt_opts);
    5401721        }
    5411722    }
  • branches/2.2.5/mindi-busybox/util-linux/pivot_root.c

    r821 r1765  
    77 *     regardless of the kernel being used.
    88 *
    9  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     9 * Licensed under GPL version 2, see file LICENSE in this tarball for details.
    1010 */
    11 #include <stdlib.h>
    12 #include <stdio.h>
    13 #include <errno.h>
    14 #include "busybox.h"
     11#include "libbb.h"
    1512
    1613extern int pivot_root(const char * new_root,const char * put_old);
    1714
     15int pivot_root_main(int argc, char **argv);
    1816int pivot_root_main(int argc, char **argv)
    1917{
    20     if (argc != 3)
    21     bb_show_usage();
     18    if (argc != 3)
     19        bb_show_usage();
    2220
    23     if (pivot_root(argv[1],argv[2]) < 0)
    24         bb_perror_msg_and_die("pivot_root");
     21    if (pivot_root(argv[1], argv[2]) < 0) {
     22        /* prints "pivot_root: <strerror text>" */
     23        bb_perror_nomsg_and_die();
     24    }
    2525
    26     return EXIT_SUCCESS;
    27 
     26    return EXIT_SUCCESS;
    2827}
  • branches/2.2.5/mindi-busybox/util-linux/rdate.c

    r821 r1765  
    99*/
    1010
    11 #include <sys/types.h>
    12 #include <sys/socket.h>
    13 #include <netinet/in.h>
    14 #include <netdb.h>
    15 #include <stdio.h>
    16 #include <string.h>
    17 #include <time.h>
    18 #include <stdlib.h>
    19 #include <unistd.h>
    20 #include <signal.h>
     11#include "libbb.h"
    2112
    22 #include "busybox.h"
    23 
    24 
    25 static const int RFC_868_BIAS = 2208988800UL;
     13enum { RFC_868_BIAS = 2208988800UL };
    2614
    2715static void socket_timeout(int sig)
     
    3220static time_t askremotedate(const char *host)
    3321{
    34     unsigned long nett;
    35     struct sockaddr_in s_in;
     22    uint32_t nett;
    3623    int fd;
    37 
    38     bb_lookup_host(&s_in, host);
    39     s_in.sin_port = bb_lookup_port("time", "tcp", 37);
    4024
    4125    /* Add a timeout for dead or inaccessible servers */
     
    4327    signal(SIGALRM, socket_timeout);
    4428
    45     fd = xconnect(&s_in);
     29    fd = create_and_connect_stream_or_die(host, bb_lookup_port("time", "tcp", 37));
    4630
    4731    if (safe_read(fd, (void *)&nett, 4) != 4)    /* read time from server */
     
    5135    /* convert from network byte order to local byte order.
    5236     * RFC 868 time is the number of seconds
    53      *  since 00:00 (midnight) 1 January 1900 GMT
    54      *  the RFC 868 time 2,208,988,800 corresponds to 00:00  1 Jan 1970 GMT
    55      * Subtract the RFC 868 time  to get Linux epoch
     37     * since 00:00 (midnight) 1 January 1900 GMT
     38     * the RFC 868 time 2,208,988,800 corresponds to 00:00  1 Jan 1970 GMT
     39     * Subtract the RFC 868 time to get Linux epoch
    5640     */
    5741
    58     return(ntohl(nett) - RFC_868_BIAS);
     42    return ntohl(nett) - RFC_868_BIAS;
    5943}
    6044
     45int rdate_main(int argc, char **argv);
    6146int rdate_main(int argc, char **argv)
    6247{
     
    6449    unsigned long flags;
    6550
    66     bb_opt_complementally = "-1";
    67     flags = bb_getopt_ulflags(argc, argv, "sp");
     51    opt_complementary = "-1";
     52    flags = getopt32(argv, "sp");
    6853
    6954    remote_time = askremotedate(argv[optind]);
     
    7459        time(&current_time);
    7560        if (current_time == remote_time)
    76             bb_error_msg("Current time matches remote time.");
     61            bb_error_msg("current time matches remote time");
    7762        else
    7863            if (stime(&remote_time) < 0)
    79                 bb_perror_msg_and_die("Could not set time of day");
     64                bb_perror_msg_and_die("cannot set time of day");
    8065    }
    8166
  • branches/2.2.5/mindi-busybox/util-linux/readprofile.c

    r902 r1765  
     1/* vi: set sw=4 ts=4: */
    12/*
    23 *  readprofile.c - used to read /proc/profile
     
    45 *  Copyright (C) 1994,1996 Alessandro Rubini (rubini@ipvvis.unipv.it)
    56 *
    6  *   This program is free software; you can redistribute it and/or modify
    7  *   it under the terms of the GNU General Public License as published by
    8  *   the Free Software Foundation; either version 2 of the License, or
    9  *   (at your option) any later version.
    10  *
    11  *   This program is distributed in the hope that it will be useful,
    12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
    13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    14  *   GNU General Public License for more details.
    15  *
    16  *   You should have received a copy of the GNU General Public License
    17  *   along with this program; if not, write to the Free Software
    18  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
     7 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
    198 */
    209
     
    4433 */
    4534
    46 #include <errno.h>
    47 #include <stdio.h>
    48 #include <fcntl.h>
    49 #include <stdlib.h>
    50 #include <unistd.h>
    51 #include <string.h>
    52 #include <sys/types.h>
    53 #include <sys/stat.h>
     35#include "libbb.h"
    5436#include <sys/utsname.h>
    5537
    56 #include "busybox.h"
    57 
    5838#define S_LEN 128
    5939
    6040/* These are the defaults */
    61 static const char defaultmap[]="/boot/System.map";
    62 static const char defaultpro[]="/proc/profile";
    63 
     41static const char defaultmap[] ALIGN1 = "/boot/System.map";
     42static const char defaultpro[] ALIGN1 = "/proc/profile";
     43
     44int readprofile_main(int argc, char **argv);
    6445int readprofile_main(int argc, char **argv)
    6546{
    6647    FILE *map;
    67     int proFd;
    68     const char *mapFile, *proFile, *mult=0;
    69     unsigned long len=0, indx=1;
    70     uint64_t add0=0;
     48    const char *mapFile, *proFile, *mult = 0;
     49    unsigned long indx = 1;
     50    size_t len;
     51    uint64_t add0 = 0;
    7152    unsigned int step;
    7253    unsigned int *buf, total, fn_len;
    73     unsigned long long fn_add, next_add;          /* current and next address */
     54    unsigned long long fn_add, next_add;     /* current and next address */
    7455    char fn_name[S_LEN], next_name[S_LEN];   /* current and next name */
     56    char mapline[S_LEN];
    7557    char mode[8];
    76     int c;
    77     int optAll=0, optInfo=0, optReset=0, optVerbose=0, optNative=0;
    78     int optBins=0, optSub=0;
    79     char mapline[S_LEN];
    80     int maplineno=1;
     58    int optAll = 0, optInfo = 0, optReset = 0;
     59    int optVerbose = 0, optNative = 0;
     60    int optBins = 0, optSub = 0;
     61    int maplineno = 1;
    8162    int header_printed;
    8263
     
    8667    mapFile = defaultmap;
    8768
    88     while ((c = getopt(argc, argv, "M:m:np:itvarVbs")) != -1) {
    89         switch(c) {
    90         case 'm':
    91             mapFile = optarg;
    92             break;
    93         case 'n':
    94             optNative++;
    95             break;
    96         case 'p':
    97             proFile = optarg;
    98             break;
    99         case 'a':
    100             optAll++;
    101             break;
    102         case 'b':
    103             optBins++;
    104             break;
    105         case 's':
    106             optSub++;
    107             break;
    108         case 'i':
    109             optInfo++;
    110             break;
    111         case 'M':
    112             mult = optarg;
    113             break;
    114         case 'r':
    115             optReset++;
    116             break;
    117         case 'v':
    118             optVerbose++;
    119             break;
    120         default:
    121             bb_show_usage();
    122         }
    123     }
     69    opt_complementary = "nn:aa:bb:ss:ii:rr:vv";
     70    getopt32(argv, "M:m:p:nabsirv",
     71            &mult, &mapFile, &proFile,
     72            &optNative, &optAll, &optBins, &optSub,
     73            &optInfo, &optReset, &optVerbose);
    12474
    12575    if (optReset || mult) {
     
    13181         */
    13282        if (mult) {
    133             multiplier = strtoul(mult, 0, 10);
     83            multiplier = xatoi_u(mult);
    13484            to_write = sizeof(int);
    13585        } else {
     
    13888        }
    13989
    140         fd = bb_xopen(defaultpro,O_WRONLY);
    141 
    142         if (write(fd, &multiplier, to_write) != to_write)
     90        fd = xopen(defaultpro, O_WRONLY);
     91
     92        if (full_write(fd, &multiplier, to_write) != to_write)
    14393            bb_perror_msg_and_die("error writing %s", defaultpro);
    14494
     
    150100     * Use an fd for the profiling buffer, to skip stdio overhead
    151101     */
    152 
    153     proFd = bb_xopen(proFile,O_RDONLY);
    154 
    155     if (((int)(len=lseek(proFd,0,SEEK_END)) < 0)
    156         || (lseek(proFd,0,SEEK_SET) < 0))
    157         bb_perror_msg_and_die(proFile);
    158 
    159     buf = xmalloc(len);
    160 
    161     if (read(proFd,buf,len) != len)
    162         bb_perror_msg_and_die(proFile);
    163 
    164     close(proFd);
    165 
     102    len = MAXINT(ssize_t);
     103    buf = xmalloc_open_read_close(proFile, &len);
    166104    if (!optNative) {
    167105        int entries = len/sizeof(*buf);
    168         int big = 0,small = 0,i;
     106        int big = 0, small = 0, i;
    169107        unsigned *p;
    170108
     
    176114        }
    177115        if (big > small) {
    178             bb_error_msg("Assuming reversed byte order. "
    179                 "Use -n to force native byte order.");
     116            bb_error_msg("assuming reversed byte order, "
     117                "use -n to force native byte order");
    180118            for (p = buf; p < buf+entries; p++)
    181119                for (i = 0; i < sizeof(*buf)/2; i++) {
     
    198136    total = 0;
    199137
    200     map = bb_xfopen(mapFile, "r");
    201 
    202     while (fgets(mapline,S_LEN,map)) {
    203         if (sscanf(mapline,"%llx %s %s",&fn_add,mode,fn_name) != 3)
     138    map = xfopen(mapFile, "r");
     139
     140    while (fgets(mapline, S_LEN, map)) {
     141        if (sscanf(mapline, "%llx %s %s", &fn_add, mode, fn_name) != 3)
    204142            bb_error_msg_and_die("%s(%i): wrong map line",
    205143                         mapFile, maplineno);
    206144
    207         if (!strcmp(fn_name,"_stext")) /* only elf works like this */ {
     145        if (!strcmp(fn_name, "_stext")) /* only elf works like this */ {
    208146            add0 = fn_add;
    209147            break;
     
    218156     * Main loop.
    219157     */
    220     while (fgets(mapline,S_LEN,map)) {
     158    while (fgets(mapline, S_LEN, map)) {
    221159        unsigned int this = 0;
    222160
    223         if (sscanf(mapline,"%llx %s %s",&next_add,mode,next_name) != 3)
     161        if (sscanf(mapline, "%llx %s %s", &next_add, mode, next_name) != 3)
    224162            bb_error_msg_and_die("%s(%i): wrong map line",
    225                          mapFile, maplineno);
     163                    mapFile, maplineno);
    226164
    227165        header_printed = 0;
     
    241179            if (optBins && (buf[indx] || optAll)) {
    242180                if (!header_printed) {
    243                     printf ("%s:\n", fn_name);
     181                    printf("%s:\n", fn_name);
    244182                    header_printed = 1;
    245183                }
    246                 printf ("\t%"PRIx64"\t%u\n", (indx - 1)*step + add0, buf[indx]);
     184                printf("\t%"PRIx64"\t%u\n", (indx - 1)*step + add0, buf[indx]);
    247185            }
    248186            this += buf[indx++];
     
    252190        if (optBins) {
    253191            if (optVerbose || this > 0)
    254                 printf ("  total\t\t\t\t%u\n", this);
     192                printf("  total\t\t\t\t%u\n", this);
    255193        } else if ((this || optAll) &&
    256194               (fn_len = next_add-fn_add) != 0) {
    257195            if (optVerbose)
    258196                printf("%016llx %-40s %6i %8.4f\n", fn_add,
    259                        fn_name,this,this/(double)fn_len);
     197                       fn_name, this, this/(double)fn_len);
    260198            else
    261199                printf("%6i %-40s %8.4f\n",
    262                        this,fn_name,this/(double)fn_len);
     200                       this, fn_name, this/(double)fn_len);
    263201            if (optSub) {
    264202                unsigned long long scan;
     
    277215
    278216        fn_add = next_add;
    279         strcpy(fn_name,next_name);
     217        strcpy(fn_name, next_name);
    280218
    281219        maplineno++;
     
    288226    if (optVerbose)
    289227        printf("%016x %-40s %6i %8.4f\n",
    290                0,"total",total,total/(double)(fn_add-add0));
     228               0, "total", total, total/(double)(fn_add-add0));
    291229    else
    292230        printf("%6i %-40s %8.4f\n",
    293                total,"total",total/(double)(fn_add-add0));
     231               total, "total", total/(double)(fn_add-add0));
    294232
    295233    fclose(map);
  • branches/2.2.5/mindi-busybox/util-linux/setarch.c

    r821 r1765  
    88*/
    99
    10 #include <stdlib.h>
    11 #include <unistd.h>
    12 #include <string.h>
    13 #include <errno.h>
    14 #include <stdio.h>
    1510#include <sys/personality.h>
    1611
    17 #include "busybox.h"
     12#include "libbb.h"
    1813
     14int setarch_main(int ATTRIBUTE_UNUSED argc, char **argv);
    1915int setarch_main(int ATTRIBUTE_UNUSED argc, char **argv)
    2016{
     
    4642
    4743        /* Try to execute the program */
    48         execvp(argv[0], argv);
     44        BB_EXECVP(argv[0], argv);
    4945    }
    5046
  • branches/2.2.5/mindi-busybox/util-linux/swaponoff.c

    r821 r1765  
    55 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
    66 *
    7  * Licensed under the GPL v2, see the file LICENSE in this tarball.
     7 * Licensed under the GPL version 2, see the file LICENSE in this tarball.
    88 */
    99
    10 #include "busybox.h"
     10#include "libbb.h"
    1111#include <mntent.h>
    12 #include <dirent.h>
    13 #include <errno.h>
    14 #include <string.h>
    1512#include <sys/swap.h>
    1613
    17 
    18 static int swap_enable_disable(const char *device)
     14static int swap_enable_disable(char *device)
    1915{
    2016    int status;
     
    2319    xstat(device, &st);
    2420
     21#if ENABLE_DESKTOP
    2522    /* test for holes */
    2623    if (S_ISREG(st.st_mode))
    2724        if (st.st_blocks * 512 < st.st_size)
    28             bb_error_msg_and_die("swap file has holes");
     25            bb_error_msg("warning: swap file has holes");
     26#endif
    2927
    30     if (bb_applet_name[5] == 'n')
     28    if (applet_name[5] == 'n')
    3129        status = swapon(device, 0);
    3230    else
     
    6159}
    6260
    63 #define DO_ALL    0x01
    64 
     61int swap_on_off_main(int argc, char **argv);
    6562int swap_on_off_main(int argc, char **argv)
    6663{
     
    7067        bb_show_usage();
    7168
    72     ret = bb_getopt_ulflags(argc, argv, "a");
    73     if (ret & DO_ALL)
     69    ret = getopt32(argv, "a");
     70    if (ret)
    7471        return do_em_all();
    7572
    76     ret = 0;
     73    /* ret = 0; redundant */
    7774    while (*++argv)
    7875        ret += swap_enable_disable(*argv);
  • branches/2.2.5/mindi-busybox/util-linux/switch_root.c

    r821 r1765  
    1 /* vi:set ts=4:*/
     1/* vi: set sw=4 ts=4: */
    22/* Copyright 2005 Rob Landley <rob@landley.net>
    33 *
    44 * Switch from rootfs to another filesystem as the root of the mount tree.
    55 *
    6  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     6 * Licensed under GPL version 2, see file LICENSE in this tarball for details.
    77 */
    88
    9 #include "busybox.h"
    10 #include <fcntl.h>
    11 #include <string.h>
     9#include "libbb.h"
    1210#include <sys/vfs.h>
    13 #include <unistd.h>
    1411
    1512
     
    2825#endif
    2926
    30 dev_t rootdev;
     27static dev_t rootdev;
    3128
    3229// Recursively delete contents of rootfs.
    3330
    34 static void delete_contents(char *directory)
     31static void delete_contents(const char *directory)
    3532{
    3633    DIR *dir;
     
    3936
    4037    // Don't descend into other filesystems
    41     if (lstat(directory,&st) || st.st_dev != rootdev) return;
     38    if (lstat(directory, &st) || st.st_dev != rootdev) return;
    4239
    4340    // Recursively delete the contents of directories.
    4441    if (S_ISDIR(st.st_mode)) {
    45         if((dir = opendir(directory))) {
     42        dir = opendir(directory);
     43        if (dir) {
    4644            while ((d = readdir(dir))) {
    47                 char *newdir=d->d_name;
     45                char *newdir = d->d_name;
    4846
    4947                // Skip . and ..
    50                 if(*newdir=='.' && (!newdir[1] || (newdir[1]=='.' && !newdir[2])))
     48                if (*newdir=='.' && (!newdir[1] || (newdir[1]=='.' && !newdir[2])))
    5149                    continue;
    5250
     
    6765}
    6866
    69 int switch_root_main(int argc, char *argv[])
     67int switch_root_main(int argc, char **argv);
     68int switch_root_main(int argc, char **argv)
    7069{
    71     char *newroot, *console=NULL;
     70    char *newroot, *console = NULL;
    7271    struct stat st1, st2;
    7372    struct statfs stfs;
     
    7574    // Parse args (-c console)
    7675
    77     bb_opt_complementally="-2";
    78     bb_getopt_ulflags(argc,argv,"c:",&console);
     76    opt_complementary = "-2";
     77    getopt32(argv, "c:", &console);
     78    argv += optind;
    7979
    8080    // Change to new root directory and verify it's a different fs.
    8181
    82     newroot=argv[optind++];
     82    newroot = *argv++;
    8383
    84     if (chdir(newroot) || lstat(".", &st1) || lstat("/", &st2) ||
    85         st1.st_dev == st2.st_dev)
    86     {
    87         bb_error_msg_and_die("bad newroot %s",newroot);
     84    xchdir(newroot);
     85    if (lstat(".", &st1) || lstat("/", &st2) || st1.st_dev == st2.st_dev) {
     86        bb_error_msg_and_die("bad newroot %s", newroot);
    8887    }
    89     rootdev=st2.st_dev;
     88    rootdev = st2.st_dev;
    9089
    9190    // Additional sanity checks: we're about to rm -rf /,  so be REALLY SURE
    9291    // we mean it.  (I could make this a CONFIG option, but I would get email
    93     // from all the people who WILL eat their filesystemss.)
     92    // from all the people who WILL eat their filesystems.)
    9493
    9594    if (lstat("/init", &st1) || !S_ISREG(st1.st_mode) || statfs("/", &stfs) ||
     
    107106    // recalculate "." and ".." links.
    108107
    109     if (mount(".", "/", NULL, MS_MOVE, NULL) || chroot(".") || chdir("/"))
    110         bb_error_msg_and_die("moving root");
     108    if (mount(".", "/", NULL, MS_MOVE, NULL) || chroot("."))
     109        bb_error_msg_and_die("error moving root");
     110    xchdir("/");
    111111
    112112    // If a new console specified, redirect stdin/stdout/stderr to that.
     
    114114    if (console) {
    115115        close(0);
    116         if(open(console, O_RDWR) < 0)
    117             bb_error_msg_and_die("Bad console '%s'",console);
     116        xopen(console, O_RDWR);
    118117        dup2(0, 1);
    119118        dup2(0, 2);
     
    121120
    122121    // Exec real init.  (This is why we must be pid 1.)
    123     execv(argv[optind],argv+optind);
    124     bb_error_msg_and_die("Bad init '%s'",argv[optind]);
     122    execv(argv[0], argv);
     123    bb_perror_msg_and_die("bad init %s", argv[0]);
    125124}
  • branches/2.2.5/mindi-busybox/util-linux/umount.c

    r902 r1765  
    66 * Copyright (C) 2005 by Rob Landley <rob@landley.net>
    77 *
    8  * This program is licensed under the GNU General Public license (GPL)
    9  * version 2 or later, see http://www.fsf.org/licensing/licenses/gpl.html
    10  * or the file "LICENSE" in the busybox source tarball for the full text.
    11  *
     8 * Licensed under GPL version 2, see file LICENSE in this tarball for details.
    129 */
    1310
    14 #include "busybox.h"
    1511#include <mntent.h>
    16 #include <errno.h>
    1712#include <getopt.h>
     13#include "libbb.h"
    1814
    19 #define OPTION_STRING       "flDnravd"
     15#define OPTION_STRING       "flDnravdt:"
    2016#define OPT_FORCE           1
    2117#define OPT_LAZY            2
     
    2521#define OPT_ALL             (ENABLE_FEATURE_UMOUNT_ALL ? 32 : 0)
    2622
     23int umount_main(int argc, char **argv);
    2724int umount_main(int argc, char **argv)
    2825{
     
    3128    struct mntent me;
    3229    FILE *fp;
     30    char *fstype = 0;
    3331    int status = EXIT_SUCCESS;
    34     unsigned long opt;
     32    unsigned opt;
    3533    struct mtab_list {
    3634        char *dir;
     
    4139    /* Parse any options */
    4240
    43     opt = bb_getopt_ulflags(argc, argv, OPTION_STRING);
     41    opt = getopt32(argv, OPTION_STRING, &fstype);
    4442
    4543    argc -= optind;
     
    5957     * the argument list should be empty (which will match all). */
    6058
    61     if (!(fp = setmntent(bb_path_mtab_file, "r"))) {
     59    fp = setmntent(bb_path_mtab_file, "r");
     60    if (!fp) {
    6261        if (opt & OPT_ALL)
    63             bb_error_msg_and_die("Cannot open %s", bb_path_mtab_file);
    64     } else while (getmntent_r(fp,&me,path,sizeof(path))) {
    65         m = xmalloc(sizeof(struct mtab_list));
    66         m->next = mtl;
    67         m->device = bb_xstrdup(me.mnt_fsname);
    68         m->dir = bb_xstrdup(me.mnt_dir);
    69         mtl = m;
     62            bb_error_msg_and_die("cannot open %s", bb_path_mtab_file);
     63    } else {
     64        while (getmntent_r(fp, &me, path, sizeof(path))) {
     65            /* Match fstype if passed */
     66            if (fstype && match_fstype(&me, fstype))
     67                continue;
     68            m = xmalloc(sizeof(struct mtab_list));
     69            m->next = mtl;
     70            m->device = xstrdup(me.mnt_fsname);
     71            m->dir = xstrdup(me.mnt_dir);
     72            mtl = m;
     73        }
     74        endmntent(fp);
    7075    }
    71     endmntent(fp);
    7276
    73     /* If we're not mounting all, we need at least one argument. */
    74     if (!(opt & OPT_ALL)) {
     77    /* If we're not umounting all, we need at least one argument. */
     78    if (!(opt & OPT_ALL) && !fstype) {
    7579        m = 0;
    7680        if (!argc) bb_show_usage();
    7781    }
    78    
     82
    7983    // Loop through everything we're supposed to umount, and do so.
    8084    for (;;) {
     
    107111            curstat = umount2(zapit, doForce);
    108112            if (curstat)
    109                 bb_error_msg_and_die("forced umount of %s failed!", zapit);
     113                bb_error_msg("forced umount of %s failed!", zapit);
    110114        }
    111115
     
    113117        if (curstat && (opt & OPT_REMOUNT) && errno == EBUSY && m) {
    114118            curstat = mount(m->device, zapit, NULL, MS_REMOUNT|MS_RDONLY, NULL);
    115             bb_error_msg(curstat ? "Cannot remount %s read-only" :
     119            bb_error_msg(curstat ? "cannot remount %s read-only" :
    116120                         "%s busy - remounted read-only", m->device);
    117121        }
     
    119123        if (curstat) {
    120124            status = EXIT_FAILURE;
    121             bb_perror_msg("Couldn't umount %s", zapit);
     125            bb_perror_msg("cannot umount %s", zapit);
    122126        } else {
    123127            /* De-allocate the loop device.  This ioctl should be ignored on
     
    133137        // of /dev/blah, not just the most recent.
    134138        while (m && (m = m->next))
    135             if ((opt & OPT_ALL) || !strcmp(path,m->device))
     139            if ((opt & OPT_ALL) || !strcmp(path, m->device))
    136140                break;
    137141    }
     
    145149            free(mtl->dir);
    146150            free(mtl);
    147             mtl=m;
     151            mtl = m;
    148152        }
    149153    }
Note: See TracChangeset for help on using the changeset viewer.