Changeset 2725 in MondoRescue for branches/2.2.9/mindi-busybox/util-linux


Ignore:
Timestamp:
Feb 25, 2011, 9:26:54 PM (13 years ago)
Author:
Bruno Cornec
Message:
  • Update mindi-busybox to 1.18.3 to avoid problems with the tar command which is now failing on recent versions with busybox 1.7.3
Location:
branches/2.2.9/mindi-busybox/util-linux
Files:
56 added
31 edited

Legend:

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

    r1765 r2725  
     1# DO NOT EDIT. This file is generated from Config.src
    12#
    23# For a description of the syntax of this configuration file,
     
    67menu "Linux System Utilities"
    78
     9config BLOCKDEV
     10    bool "blockdev"
     11    default y
     12    help
     13      Performs some ioctls with block devices.
     14config REV
     15    bool "rev"
     16    default y
     17    help
     18      Reverse lines of a file or files.
     19
     20config ACPID
     21    bool "acpid"
     22    default y
     23    depends on PLATFORM_LINUX
     24    help
     25      acpid listens to ACPI events coming either in textual form from
     26      /proc/acpi/event (though it is marked deprecated it is still widely
     27      used and _is_ a standard) or in binary form from specified evdevs
     28      (just use /dev/input/event*).
     29
     30      It parses the event to retrieve ACTION and a possible PARAMETER.
     31      It then spawns /etc/acpi/<ACTION>[/<PARAMETER>] either via run-parts
     32      (if the resulting path is a directory) or directly as an executable.
     33
     34      N.B. acpid relies on run-parts so have the latter installed.
     35
     36config FEATURE_ACPID_COMPAT
     37    bool "Accept and ignore redundant options"
     38    default y
     39    depends on ACPID
     40    help
     41      Accept and ignore compatibility options -g -m -s -S -v.
     42
     43config BLKID
     44    bool "blkid"
     45    default y
     46    depends on PLATFORM_LINUX
     47    select VOLUMEID
     48    help
     49      Lists labels and UUIDs of all filesystems.
     50      WARNING:
     51      With all submodules selected, it will add ~8k to busybox.
     52
    853config DMESG
    954    bool "dmesg"
    10     default n
    11     help
    12       dmesg is used to examine or control the kernel ring buffer.  When the
     55    default y
     56    depends on PLATFORM_LINUX
     57    help
     58      dmesg is used to examine or control the kernel ring buffer. When the
    1359      Linux kernel prints messages to the system log, they are stored in
    14       the kernel ring buffer.  You can use dmesg to print the kernel's ring
     60      the kernel ring buffer. You can use dmesg to print the kernel's ring
    1561      buffer, clear the kernel ring buffer, change the size of the kernel
    1662      ring buffer, and change the priority level at which kernel messages
    17       are also logged to the system console.  Enable this option if you
     63      are also logged to the system console. Enable this option if you
    1864      wish to enable the 'dmesg' utility.
    1965
    2066config FEATURE_DMESG_PRETTY
    21     bool "pretty dmesg output"
     67    bool "Pretty dmesg output"
    2268    default y
    2369    depends on DMESG
    2470    help
    2571      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 "<#>".
     72      The syslog level is a string prefixed to every line with the form
     73      "<#>".
    2774
    2875      With this option you will see:
     
    4087config FBSET
    4188    bool "fbset"
    42     default n
     89    default y
     90    depends on PLATFORM_LINUX
    4391    help
    4492      fbset is used to show or change the settings of a Linux frame buffer
    45       device.  The frame buffer device provides a simple and unique
    46       interface to access a graphics display.  Enable this option
     93      device. The frame buffer device provides a simple and unique
     94      interface to access a graphics display. Enable this option
    4795      if you wish to enable the 'fbset' utility.
    4896
    4997config FEATURE_FBSET_FANCY
    5098    bool "Turn on extra fbset options"
    51     default n
     99    default y
    52100    depends on FBSET
    53101    help
    54102      This option enables extended fbset options, allowing one to set the
    55       framebuffer size, color depth, etc.  interface to access a graphics
    56       display.  Enable this option if you wish to enable extended fbset
     103      framebuffer size, color depth, etc. interface to access a graphics
     104      display. Enable this option if you wish to enable extended fbset
    57105      options.
    58106
    59107config FEATURE_FBSET_READMODE
    60108    bool "Turn on fbset readmode support"
    61     default n
     109    default y
    62110    depends on FBSET
    63111    help
     
    68116config FDFLUSH
    69117    bool "fdflush"
    70     default n
     118    default y
     119    depends on PLATFORM_LINUX
    71120    help
    72121      fdflush is only needed when changing media on slightly-broken
    73       removable media drives.  It is used to make Linux believe that a
     122      removable media drives. It is used to make Linux believe that a
    74123      hardware disk-change switch has been actuated, which causes Linux to
    75       forget anything it has cached from the previous media.  If you have
     124      forget anything it has cached from the previous media. If you have
    76125      such a slightly-broken drive, you will need to run fdflush every time
    77       you change a disk.  Most people have working hardware and can safely
     126      you change a disk. Most people have working hardware and can safely
    78127      leave this disabled.
    79128
    80129config FDFORMAT
    81130    bool "fdformat"
    82     default n
     131    default y
     132    depends on PLATFORM_LINUX
    83133    help
    84134      fdformat is used to low-level format a floppy disk.
     
    86136config FDISK
    87137    bool "fdisk"
    88     default n
     138    default y
     139    depends on PLATFORM_LINUX
    89140    help
    90141      The fdisk utility is used to divide hard disks into one or more
    91       logical disks, which are generally called partitions.  This utility
     142      logical disks, which are generally called partitions. This utility
    92143      can be used to list and edit the set of partitions or BSD style
    93144      'disk slices' that are defined on a hard drive.
    94145
    95146config FDISK_SUPPORT_LARGE_DISKS
    96     bool "support over 4GB disks"
     147    bool "Support over 4GB disks"
    97148    default y
    98149    depends on FDISK
     
    106157    help
    107158      Enabling this option allows you to create or change a partition table
    108       and write those changes out to disk.  If you leave this option
     159      and write those changes out to disk. If you leave this option
    109160      disabled, you will only be able to view the partition table.
    110161
     
    141192      and define and edit BSD disk slices.
    142193
     194config FEATURE_GPT_LABEL
     195    bool "Support GPT disklabels"
     196    default n
     197    depends on FDISK && FEATURE_FDISK_WRITABLE
     198    help
     199      Enabling this option allows you to view GUID Partition Table
     200      disklabels.
     201
    143202config FEATURE_FDISK_ADVANCED
    144203    bool "Support expert mode"
    145     default n
     204    default y
    146205    depends on FDISK && FEATURE_FDISK_WRITABLE
    147206    help
    148207      Enabling this option allows you to do terribly unsafe things like
    149208      define arbitrary drive geometry, move the beginning of data in a
    150       partition, and similarly evil things.  Unless you have a very good
     209      partition, and similarly evil things. Unless you have a very good
    151210      reason you would be wise to leave this disabled.
     211
     212config FINDFS
     213    bool "findfs"
     214    default y
     215    depends on PLATFORM_LINUX
     216    select VOLUMEID
     217    help
     218      Prints the name of a filesystem with given label or UUID.
     219      WARNING:
     220      With all submodules selected, it will add ~8k to busybox.
     221
     222config FLOCK
     223    bool "flock"
     224    default y
     225    help
     226      Manage locks from shell scripts
    152227
    153228config FREERAMDISK
    154229    bool "freeramdisk"
    155     default n
    156     help
    157       Linux allows you to create ramdisks.  This utility allows you to
     230    default y
     231    depends on PLATFORM_LINUX
     232    help
     233      Linux allows you to create ramdisks. This utility allows you to
    158234      delete them and completely free all memory that was used for the
    159       ramdisk.  For example, if you boot Linux into a ramdisk and later
     235      ramdisk. For example, if you boot Linux into a ramdisk and later
    160236      pivot_root, you may want to free the memory that is allocated to the
    161       ramdisk.  If you have no use for freeing memory from a ramdisk, leave
     237      ramdisk. If you have no use for freeing memory from a ramdisk, leave
    162238      this disabled.
    163239
    164240config FSCK_MINIX
    165241    bool "fsck_minix"
    166     default n
     242    default y
    167243    help
    168244      The minix filesystem is a nice, small, compact, read-write filesystem
    169       with little overhead.  It is not a journaling filesystem however and
     245      with little overhead. It is not a journaling filesystem however and
    170246      can experience corruption if it is not properly unmounted or if the
    171       power goes off in the middle of a write.  This utility allows you to
     247      power goes off in the middle of a write. This utility allows you to
    172248      check for and attempt to repair any corruption that occurs to a minix
    173249      filesystem.
    174250
     251config MKFS_EXT2
     252    bool "mkfs_ext2"
     253    default y
     254    depends on PLATFORM_LINUX
     255    help
     256      Utility to create EXT2 filesystems.
     257
    175258config MKFS_MINIX
    176259    bool "mkfs_minix"
    177     default n
     260    default y
     261    depends on PLATFORM_LINUX
    178262    help
    179263      The minix filesystem is a nice, small, compact, read-write filesystem
    180       with little overhead.  If you wish to be able to create minix filesystems
    181       this utility will do the job for you.
    182 
    183 comment "Minix filesystem support"
    184     depends on FSCK_MINIX || MKFS_MINIX
     264      with little overhead. If you wish to be able to create minix
     265      filesystems this utility will do the job for you.
    185266
    186267config FEATURE_MINIX2
     
    189270    depends on FSCK_MINIX || MKFS_MINIX
    190271    help
    191       If you wish to be able to create version 2 minix filesystems, enable this.
    192       If you enabled 'mkfs_minix' then you almost certainly want to be using the
    193       version 2 filesystem support.
     272      If you wish to be able to create version 2 minix filesystems, enable
     273      this. If you enabled 'mkfs_minix' then you almost certainly want to
     274      be using the version 2 filesystem support.
     275
     276config MKFS_REISER
     277    bool "mkfs_reiser"
     278    default n
     279    depends on PLATFORM_LINUX
     280    help
     281      Utility to create ReiserFS filesystems.
     282      Note: this applet needs a lot of testing and polishing.
     283
     284config MKFS_VFAT
     285    bool "mkfs_vfat"
     286    default y
     287    depends on PLATFORM_LINUX
     288    help
     289      Utility to create FAT32 filesystems.
    194290
    195291config GETOPT
    196292    bool "getopt"
    197     default n
     293    default y
    198294    help
    199295      The getopt utility is used to break up (parse) options in command
    200296      lines to make it easy to write complex shell scripts that also check
    201       for legal (and illegal) options.  If you want to write horribly
     297      for legal (and illegal) options. If you want to write horribly
    202298      complex shell scripts, or use some horribly complex shell script
    203       written by others, this utility may be for you.  Most people will
     299      written by others, this utility may be for you. Most people will
    204300      wisely leave this disabled.
     301
     302config FEATURE_GETOPT_LONG
     303    bool "Support option -l"
     304    default y if LONG_OPTS
     305    depends on GETOPT
     306    help
     307      Enable support for long options (option -l).
    205308
    206309config HEXDUMP
    207310    bool "hexdump"
    208     default n
     311    default y
    209312    help
    210313      The hexdump utility is used to display binary data in a readable
    211314      way that is comparable to the output from most hex editors.
    212315
     316config FEATURE_HEXDUMP_REVERSE
     317    bool "Support -R, reverse of 'hexdump -Cv'"
     318    default y
     319    depends on HEXDUMP
     320    help
     321      The hexdump utility is used to display binary data in an ascii
     322      readable way. This option creates binary data from an ascii input.
     323      NB: this option is non-standard. It's unwise to use it in scripts
     324      aimed to be portable.
     325
     326config HD
     327    bool "hd"
     328    default y
     329    depends on HEXDUMP
     330    help
     331      hd is an alias to hexdump -C.
     332
    213333config HWCLOCK
    214334    bool "hwclock"
    215     default n
     335    default y
     336    depends on PLATFORM_LINUX
    216337    help
    217338      The hwclock utility is used to read and set the hardware clock
    218       on a system.  This is primarily used to set the current time on
     339      on a system. This is primarily used to set the current time on
    219340      shutdown in the hardware clock, so the hardware will keep the
    220341      correct time when Linux is _not_ running.
     
    222343config FEATURE_HWCLOCK_LONG_OPTIONS
    223344    bool "Support long options (--hctosys,...)"
    224     default n
    225     depends on HWCLOCK && GETOPT_LONG
    226     help
    227       By default, the hwclock utility only uses short options.  If you
     345    default y
     346    depends on HWCLOCK && LONG_OPTS
     347    help
     348      By default, the hwclock utility only uses short options. If you
    228349      are overly fond of its long options, such as --hctosys, --utc, etc)
    229350      then enable this option.
     
    231352config FEATURE_HWCLOCK_ADJTIME_FHS
    232353    bool "Use FHS /var/lib/hwclock/adjtime"
    233     default y
     354    default n  # util-linux-ng in Fedora 13 still uses /etc/adjtime
    234355    depends on HWCLOCK
    235356    help
    236357      Starting with FHS 2.3, the adjtime state file is supposed to exist
    237       at /var/lib/hwclock/adjtime instead of /etc/adjtime.  If you wish
     358      at /var/lib/hwclock/adjtime instead of /etc/adjtime. If you wish
    238359      to use the FHS behavior, answer Y here, otherwise answer N for the
    239360      classic /etc/adjtime path.
    240361
    241       http://www.pathname.com/fhs/pub/fhs-2.3.html#VARLIBHWCLOCKSTATEDIRECTORYFORHWCLO
     362      pathname.com/fhs/pub/fhs-2.3.html#VARLIBHWCLOCKSTATEDIRECTORYFORHWCLO
    242363
    243364config IPCRM
    244365    bool "ipcrm"
    245     default n
    246     select FEATURE_SUID
     366    default y
    247367    help
    248368      The ipcrm utility allows the removal of System V interprocess
     
    252372config IPCS
    253373    bool "ipcs"
    254     default n
    255     select FEATURE_SUID
     374    default y
     375    depends on PLATFORM_LINUX
    256376    help
    257377      The ipcs utility is used to provide information on the currently
     
    260380config LOSETUP
    261381    bool "losetup"
    262     default n
     382    default y
     383    depends on PLATFORM_LINUX
    263384    help
    264385      losetup is used to associate or detach a loop device with a regular
    265       file or block device, and to query the status of a loop device.  This
     386      file or block device, and to query the status of a loop device. This
    266387      version does not currently support enabling data encryption.
     388
     389config LSPCI
     390    bool "lspci"
     391    default y
     392    #depends on PLATFORM_LINUX
     393    help
     394      lspci is a utility for displaying information about PCI buses in the
     395      system and devices connected to them.
     396
     397      This version uses sysfs (/sys/bus/pci/devices) only.
     398
     399config LSUSB
     400    bool "lsusb"
     401    default y
     402    #depends on PLATFORM_LINUX
     403    help
     404      lsusb is a utility for displaying information about USB buses in the
     405      system and devices connected to them.
     406
     407      This version uses sysfs (/sys/bus/usb/devices) only.
    267408
    268409config MDEV
    269410    bool "mdev"
    270     default n
     411    default y
     412    depends on PLATFORM_LINUX
    271413    help
    272414      mdev is a mini-udev implementation for dynamically creating device
     
    277419config FEATURE_MDEV_CONF
    278420    bool "Support /etc/mdev.conf"
    279     default n
     421    default y
    280422    depends on MDEV
    281423    help
     
    285427      For more information, please see docs/mdev.txt
    286428
     429config FEATURE_MDEV_RENAME
     430    bool "Support subdirs/symlinks"
     431    default y
     432    depends on FEATURE_MDEV_CONF
     433    help
     434      Add support for renaming devices and creating symlinks.
     435
     436      For more information, please see docs/mdev.txt
     437
     438config FEATURE_MDEV_RENAME_REGEXP
     439    bool "Support regular expressions substitutions when renaming device"
     440    default y
     441    depends on FEATURE_MDEV_RENAME
     442    help
     443      Add support for regular expressions substitutions when renaming
     444      device.
     445
    287446config FEATURE_MDEV_EXEC
    288447    bool "Support command execution at device addition/removal"
    289     default n
     448    default y
    290449    depends on FEATURE_MDEV_CONF
    291450    help
     
    297456config FEATURE_MDEV_LOAD_FIRMWARE
    298457    bool "Support loading of firmwares"
    299     default n
     458    default y
    300459    depends on MDEV
    301460    help
     
    308467config MKSWAP
    309468    bool "mkswap"
    310     default n
     469    default y
    311470    help
    312471      The mkswap utility is used to configure a file or disk partition as
    313       Linux swap space.  This allows Linux to use the entire file or
     472      Linux swap space. This allows Linux to use the entire file or
    314473      partition as if it were additional RAM, which can greatly increase
    315       the capability of low-memory machines.  This additional memory is
     474      the capability of low-memory machines. This additional memory is
    316475      much slower than real RAM, but can be very helpful at preventing your
    317476      applications being killed by the Linux out of memory (OOM) killer.
     
    319478      the swap space using the 'swapon' utility.
    320479
    321 config FEATURE_MKSWAP_V0
    322     bool "version 0 support"
    323     default n
     480config FEATURE_MKSWAP_UUID
     481    bool "UUID support"
     482    default y
    324483    depends on MKSWAP
    325 #   depends on MKSWAP && DEPRECATED
    326     help
    327       Enable support for the old v0 style.
    328       If your kernel is older than 2.1.117, then v0 support is the
    329       only option.
     484    help
     485      Generate swap spaces with universally unique identifiers.
    330486
    331487config MORE
    332488    bool "more"
    333     default n
     489    default y
    334490    help
    335491      more is a simple utility which allows you to read text one screen
    336       sized page at a time.  If you want to read text that is larger than
     492      sized page at a time. If you want to read text that is larger than
    337493      the screen, and you are using anything faster than a 300 baud modem,
    338       you will probably find this utility very helpful.  If you don't have
     494      you will probably find this utility very helpful. If you don't have
    339495      any need to reading text files, you can leave this disabled.
    340 
    341 config FEATURE_USE_TERMIOS
    342     bool "Use termios to manipulate the screen"
    343     default y
    344     depends on MORE
    345     help
    346       This option allows utilities such as 'more' and 'top' to determine
    347       the size of the screen.  If you leave this disabled, your utilities
    348       that display things on the screen will be especially primitive and
    349       will be unable to determine the current screen size, and will be
    350       unable to move the cursor.
    351496
    352497config MOUNT
    353498    bool "mount"
     499    default y
     500    depends on PLATFORM_LINUX
     501    help
     502      All files and filesystems in Unix are arranged into one big directory
     503      tree. The 'mount' utility is used to graft a filesystem onto a
     504      particular part of the tree. A filesystem can either live on a block
     505      device, or it can be accessible over the network, as is the case with
     506      NFS filesystems. Most people using BusyBox will also want to enable
     507      the 'mount' utility.
     508
     509config FEATURE_MOUNT_FAKE
     510    bool "Support option -f"
     511    default y
     512    depends on MOUNT
     513    help
     514      Enable support for faking a file system mount.
     515
     516config FEATURE_MOUNT_VERBOSE
     517    bool "Support option -v"
     518    default y
     519    depends on MOUNT
     520    help
     521      Enable multi-level -v[vv...] verbose messages. Useful if you
     522      debug mount problems and want to see what is exactly passed
     523      to the kernel.
     524
     525config FEATURE_MOUNT_HELPERS
     526    bool "Support mount helpers"
    354527    default n
    355     help
    356       All files and filesystems in Unix are arranged into one big directory
    357       tree.  The 'mount' utility is used to graft a filesystem onto a
    358       particular part of the tree.  A filesystem can either live on a block
    359       device, or it can be accessible over the network, as is the case with
    360       NFS filesystems.  Most people using BusyBox will also want to enable
    361       the 'mount' utility.
     528    depends on MOUNT
     529    help
     530      Enable mounting of virtual file systems via external helpers.
     531      E.g. "mount obexfs#-b00.11.22.33.44.55 /mnt" will in effect call
     532      "obexfs -b00.11.22.33.44.55 /mnt"
     533      Also "mount -t sometype [-o opts] fs /mnt" will try
     534      "sometype [-o opts] fs /mnt" if simple mount syscall fails.
     535      The idea is to use such virtual filesystems in /etc/fstab.
     536
     537config FEATURE_MOUNT_LABEL
     538    bool "Support specifying devices by label or UUID"
     539    default y
     540    depends on MOUNT
     541    select VOLUMEID
     542    help
     543      This allows for specifying a device by label or uuid, rather than by
     544      name. This feature utilizes the same functionality as blkid/findfs.
     545      This also enables label or uuid support for swapon.
    362546
    363547config FEATURE_MOUNT_NFS
    364548    bool "Support mounting NFS file systems"
    365     default n
     549    default y
    366550    depends on MOUNT
    367551    select FEATURE_HAVE_RPC
     
    372556config FEATURE_MOUNT_CIFS
    373557    bool "Support mounting CIFS/SMB file systems"
    374     default n
     558    default y
    375559    depends on MOUNT
    376560    help
     
    382566    default y
    383567    help
    384       Without this, mount only supports ro/rw/remount.  With this, it
     568      Without this, mount only supports ro/rw/remount. With this, it
    385569      supports nosuid, suid, dev, nodev, exec, noexec, sync, async, atime,
    386570      noatime, diratime, nodiratime, loud, bind, move, shared, slave,
     
    396580config PIVOT_ROOT
    397581    bool "pivot_root"
    398     default n
     582    default y
     583    depends on PLATFORM_LINUX
    399584    help
    400585      The pivot_root utility swaps the mount points for the root filesystem
    401       with some other mounted filesystem.  This allows you to do all sorts
     586      with some other mounted filesystem. This allows you to do all sorts
    402587      of wild and crazy things with your Linux system and is far more
    403588      powerful than 'chroot'.
    404589
    405       Note: This is for initrd in linux 2.4.  Under initramfs (introduced
     590      Note: This is for initrd in linux 2.4. Under initramfs (introduced
    406591      in linux 2.6) use switch_root instead.
    407592
    408593config RDATE
    409594    bool "rdate"
    410     default n
     595    default y
    411596    help
    412597      The rdate utility allows you to synchronize the date and time of your
     
    415600      systems.
    416601
     602config RDEV
     603    bool "rdev"
     604    default y
     605    help
     606      Print the device node associated with the filesystem mounted at '/'.
     607
    417608config READPROFILE
    418609    bool "readprofile"
    419     default n
     610    default y
     611    #depends on PLATFORM_LINUX
    420612    help
    421613      This allows you to parse /proc/profile for basic profiling.
     614
     615config RTCWAKE
     616    bool "rtcwake"
     617    default y
     618    depends on PLATFORM_LINUX
     619    help
     620      Enter a system sleep state until specified wakeup time.
     621
     622config SCRIPT
     623    bool "script"
     624    default y
     625    help
     626      The script makes typescript of terminal session.
     627
     628config SCRIPTREPLAY
     629    bool "scriptreplay"
     630    default y
     631    help
     632      This program replays a typescript, using timing information
     633      given by script -t.
    422634
    423635config SETARCH
    424636    bool "setarch"
    425     default n
     637    default y
     638    depends on PLATFORM_LINUX
    426639    help
    427640      The linux32 utility is used to create a 32bit environment for the
    428       specified program (usually a shell).  It only makes sense to have
     641      specified program (usually a shell). It only makes sense to have
    429642      this util on a system that supports both 64bit and 32bit userland
    430643      (like amd64/x86, ppc64/ppc, sparc64/sparc, etc...).
     
    432645config SWAPONOFF
    433646    bool "swaponoff"
    434     default n
     647    default y
     648    depends on PLATFORM_LINUX
    435649    help
    436650      This option enables both the 'swapon' and the 'swapoff' utilities.
    437651      Once you have created some swap space using 'mkswap', you also need
    438       to enable your swap space with the 'swapon' utility.  The 'swapoff'
     652      to enable your swap space with the 'swapon' utility. The 'swapoff'
    439653      utility is used, typically at system shutdown, to disable any swap
    440       space.  If you are not using any swap space, you can leave this
     654      space. If you are not using any swap space, you can leave this
    441655      option disabled.
     656
     657config FEATURE_SWAPON_PRI
     658    bool "Support priority option -p"
     659    default y
     660    depends on SWAPONOFF
     661    help
     662      Enable support for setting swap device priority in swapon.
    442663
    443664config SWITCH_ROOT
    444665    bool "switch_root"
    445     default n
     666    default y
     667    depends on PLATFORM_LINUX
    446668    help
    447669      The switch_root utility is used from initramfs to select a new
    448       root device.  Under initramfs, you have to use this instead of
    449       pivot_root.  (Stop reading here if you don't care why.)
     670      root device. Under initramfs, you have to use this instead of
     671      pivot_root. (Stop reading here if you don't care why.)
    450672
    451673      Booting with initramfs extracts a gzipped cpio archive into rootfs
    452       (which is a variant of ramfs/tmpfs).  Because rootfs can't be moved
    453       or unmounted*, pivot_root will not work from initramfs.  Instead,
     674      (which is a variant of ramfs/tmpfs). Because rootfs can't be moved
     675      or unmounted*, pivot_root will not work from initramfs. Instead,
    454676      switch_root deletes everything out of rootfs (including itself),
    455677      does a mount --move that overmounts rootfs with the new root, and
     
    458680      * Because the Linux kernel uses rootfs internally as the starting
    459681      and ending point for searching through the kernel's doubly linked
    460       list of active mount points.  That's why.
     682      list of active mount points. That's why.
    461683
    462684config UMOUNT
    463685    bool "umount"
    464     default n
    465     help
    466       When you want to remove a mounted filesystem from its current mount point,
    467       for example when you are shutting down the system, the 'umount' utility is
    468       the tool to use.  If you enabled the 'mount' utility, you almost certainly
    469       also want to enable 'umount'.
     686    default y
     687    depends on PLATFORM_LINUX
     688    help
     689      When you want to remove a mounted filesystem from its current mount
     690      point, for example when you are shutting down the system, the
     691      'umount' utility is the tool to use. If you enabled the 'mount'
     692      utility, you almost certainly also want to enable 'umount'.
    470693
    471694config FEATURE_UMOUNT_ALL
    472     bool "umount -a option"
    473     default n
     695    bool "Support option -a"
     696    default y
    474697    depends on UMOUNT
    475698    help
     
    481704config FEATURE_MOUNT_LOOP
    482705    bool "Support loopback mounts"
    483     default n
     706    default y
    484707    depends on MOUNT || UMOUNT
    485708    help
    486709      Enabling this feature allows automatic mounting of files (containing
    487       filesystem images) via the linux kernel's loopback devices.  The mount
    488       command will detect you are trying to mount a file instead of a block
    489       device, and transparently associate the file with a loopback device.
    490       The umount command will also free that loopback device.
     710      filesystem images) via the linux kernel's loopback devices.
     711      The mount command will detect you are trying to mount a file instead
     712      of a block device, and transparently associate the file with a
     713      loopback device. The umount command will also free that loopback
     714      device.
    491715
    492716      You can still use the 'losetup' utility (to manually associate files
     
    495719      (If you don't want umount to free the loop device, use "umount -D".)
    496720
     721config FEATURE_MOUNT_LOOP_CREATE
     722    bool "Create new loopback devices if needed"
     723    default y
     724    depends on FEATURE_MOUNT_LOOP
     725    help
     726      Linux kernels >= 2.6.24 support unlimited loopback devices. They are
     727      allocated for use when trying to use a loop device. The loop device
     728      must however exist.
     729
     730      This feature lets mount to try to create next /dev/loopN device
     731      if it does not find a free one.
     732
    497733config FEATURE_MTAB_SUPPORT
    498734    bool "Support for the old /etc/mtab file"
    499735    default n
    500736    depends on MOUNT || UMOUNT
     737    select FEATURE_MOUNT_FAKE
    501738    help
    502739      Historically, Unix systems kept track of the currently mounted
    503       partitions in the file "/etc/mtab".  These days, the kernel exports
     740      partitions in the file "/etc/mtab". These days, the kernel exports
    504741      the list of currently mounted partitions in "/proc/mounts", rendering
    505       the old mtab file obsolete.  (In modern systems, /etc/mtab should be
     742      the old mtab file obsolete. (In modern systems, /etc/mtab should be
    506743      a symlink to /proc/mounts.)
    507744
     
    511748      example a mount under chroot won't update it), can't handle modern
    512749      features like separate per-process filesystem namespaces, requires
    513       that your /etc directory be writeable, tends to get easily confused
     750      that your /etc directory be writable, tends to get easily confused
    514751      by --bind or --move mounts, won't update if you rename a directory
    515       that contains a mount point, and so on.  (In brief: avoid.)
     752      that contains a mount point, and so on. (In brief: avoid.)
    516753
    517754      About the only reason to use this is if you've removed /proc from
    518755      your kernel.
    519756
     757config VOLUMEID
     758    bool #No description makes it a hidden option
     759    default n
     760
     761menu "Filesystem/Volume identification"
     762    depends on VOLUMEID
     763
     764config FEATURE_VOLUMEID_EXT
     765    bool "Ext filesystem"
     766    default y
     767    depends on VOLUMEID
     768    help
     769      TODO
     770
     771config FEATURE_VOLUMEID_BTRFS
     772    bool "btrfs filesystem"
     773    default y
     774    depends on VOLUMEID
     775    help
     776      TODO
     777
     778config FEATURE_VOLUMEID_REISERFS
     779    bool "Reiser filesystem"
     780    default y
     781    depends on VOLUMEID
     782    help
     783      TODO
     784
     785config FEATURE_VOLUMEID_FAT
     786    bool "fat filesystem"
     787    default y
     788    depends on VOLUMEID
     789    help
     790      TODO
     791
     792config FEATURE_VOLUMEID_HFS
     793    bool "hfs filesystem"
     794    default y
     795    depends on VOLUMEID
     796    help
     797      TODO
     798
     799config FEATURE_VOLUMEID_JFS
     800    bool "jfs filesystem"
     801    default y
     802    depends on VOLUMEID
     803    help
     804      TODO
     805
     806### config FEATURE_VOLUMEID_UFS
     807### bool "ufs filesystem"
     808### default y
     809### depends on VOLUMEID
     810### help
     811###   TODO
     812
     813config FEATURE_VOLUMEID_XFS
     814    bool "xfs filesystem"
     815    default y
     816    depends on VOLUMEID
     817    help
     818      TODO
     819
     820config FEATURE_VOLUMEID_NTFS
     821    bool "ntfs filesystem"
     822    default y
     823    depends on VOLUMEID
     824    help
     825      TODO
     826
     827config FEATURE_VOLUMEID_ISO9660
     828    bool "iso9660 filesystem"
     829    default y
     830    depends on VOLUMEID
     831    help
     832      TODO
     833
     834config FEATURE_VOLUMEID_UDF
     835    bool "udf filesystem"
     836    default y
     837    depends on VOLUMEID
     838    help
     839      TODO
     840
     841config FEATURE_VOLUMEID_LUKS
     842    bool "luks filesystem"
     843    default y
     844    depends on VOLUMEID
     845    help
     846      TODO
     847
     848config FEATURE_VOLUMEID_LINUXSWAP
     849    bool "linux swap filesystem"
     850    default y
     851    depends on VOLUMEID
     852    help
     853      TODO
     854
     855### config FEATURE_VOLUMEID_LVM
     856### bool "lvm"
     857### default y
     858### depends on VOLUMEID
     859### help
     860###   TODO
     861
     862config FEATURE_VOLUMEID_CRAMFS
     863    bool "cramfs filesystem"
     864    default y
     865    depends on VOLUMEID
     866    help
     867      TODO
     868
     869### config FEATURE_VOLUMEID_HPFS
     870### bool "hpfs filesystem"
     871### default y
     872### depends on VOLUMEID
     873### help
     874###   TODO
     875
     876config FEATURE_VOLUMEID_ROMFS
     877    bool "romfs filesystem"
     878    default y
     879    depends on VOLUMEID
     880    help
     881      TODO
     882
     883config FEATURE_VOLUMEID_SYSV
     884    bool "sysv filesystem"
     885    default y
     886    depends on VOLUMEID
     887    help
     888      TODO
     889
     890### config FEATURE_VOLUMEID_MINIX
     891### bool "minix filesystem"
     892### default y
     893### depends on VOLUMEID
     894### help
     895###   TODO
     896
     897### These only detect partition tables - not used (yet?)
     898### config FEATURE_VOLUMEID_MAC
     899### bool "mac filesystem"
     900### default y
     901### depends on VOLUMEID
     902### help
     903###   TODO
     904###
     905### config FEATURE_VOLUMEID_MSDOS
     906### bool "msdos filesystem"
     907### default y
     908### depends on VOLUMEID
     909### help
     910###   TODO
     911
     912config FEATURE_VOLUMEID_OCFS2
     913    bool "ocfs2 filesystem"
     914    default y
     915    depends on VOLUMEID
     916    help
     917      TODO
     918
     919### config FEATURE_VOLUMEID_HIGHPOINTRAID
     920### bool "highpoint raid"
     921### default y
     922### depends on VOLUMEID
     923### help
     924###   TODO
     925
     926### config FEATURE_VOLUMEID_ISWRAID
     927### bool "intel raid"
     928### default y
     929### depends on VOLUMEID
     930### help
     931###   TODO
     932
     933### config FEATURE_VOLUMEID_LSIRAID
     934### bool "lsi raid"
     935### default y
     936### depends on VOLUMEID
     937### help
     938###   TODO
     939
     940### config FEATURE_VOLUMEID_VIARAID
     941### bool "via raid"
     942### default y
     943### depends on VOLUMEID
     944### help
     945###   TODO
     946
     947### config FEATURE_VOLUMEID_SILICONRAID
     948### bool "silicon raid"
     949### default y
     950### depends on VOLUMEID
     951### help
     952###   TODO
     953
     954### config FEATURE_VOLUMEID_NVIDIARAID
     955### bool "nvidia raid"
     956### default y
     957### depends on VOLUMEID
     958### help
     959###   TODO
     960
     961### config FEATURE_VOLUMEID_PROMISERAID
     962### bool "promise raid"
     963### default y
     964### depends on VOLUMEID
     965### help
     966###   TODO
     967
     968config FEATURE_VOLUMEID_LINUXRAID
     969    bool "linuxraid"
     970    default y
     971    depends on VOLUMEID
     972    help
     973      TODO
     974
    520975endmenu
    521976
     977endmenu
  • branches/2.2.9/mindi-busybox/util-linux/Kbuild

    r1765 r2725  
     1# DO NOT EDIT. This file is generated from Kbuild.src
    12# Makefile for busybox
    23#
    34# Copyright (C) 1999-2005 by Erik Andersen <andersen@codepoet.org>
    45#
    5 # Licensed under the GPL v2, see the file LICENSE in this tarball.
     6# Licensed under GPLv2, see file LICENSE in this source tree.
    67
    78lib-y:=
    8 lib-$(CONFIG_DMESG)     +=dmesg.o
    9 lib-$(CONFIG_FBSET)     +=fbset.o
    10 lib-$(CONFIG_FDFLUSH)       +=freeramdisk.o
    11 lib-$(CONFIG_FDFORMAT)      +=fdformat.o
    12 lib-$(CONFIG_FDISK)     +=fdisk.o
    13 lib-$(CONFIG_FREERAMDISK)   +=freeramdisk.o
    14 lib-$(CONFIG_FSCK_MINIX)    +=fsck_minix.o
    15 lib-$(CONFIG_GETOPT)        +=getopt.o
    16 lib-$(CONFIG_HEXDUMP)       +=hexdump.o
    17 lib-$(CONFIG_HWCLOCK)       +=hwclock.o
    18 lib-$(CONFIG_IPCRM)     +=ipcrm.o
    19 lib-$(CONFIG_IPCS)      +=ipcs.o
    20 lib-$(CONFIG_LOSETUP)       +=losetup.o
    21 lib-$(CONFIG_MDEV)      +=mdev.o
    22 lib-$(CONFIG_MKFS_MINIX)    +=mkfs_minix.o
    23 lib-$(CONFIG_MKSWAP)        +=mkswap.o
    24 lib-$(CONFIG_MORE)      +=more.o
    25 lib-$(CONFIG_MOUNT)     +=mount.o
    26 lib-$(CONFIG_PIVOT_ROOT)    +=pivot_root.o
    27 lib-$(CONFIG_RDATE)     +=rdate.o
    28 lib-$(CONFIG_READPROFILE)   +=readprofile.o
    29 lib-$(CONFIG_SETARCH)       +=setarch.o
    30 lib-$(CONFIG_SWAPONOFF)     +=swaponoff.o
    31 lib-$(CONFIG_SWITCH_ROOT)   +=switch_root.o
    32 lib-$(CONFIG_UMOUNT)        +=umount.o
     9
     10lib-$(CONFIG_BLOCKDEV) += blockdev.o
     11lib-$(CONFIG_REV) += rev.o
     12lib-$(CONFIG_ACPID)             += acpid.o
     13lib-$(CONFIG_BLKID)             += blkid.o
     14lib-$(CONFIG_DMESG)             += dmesg.o
     15lib-$(CONFIG_FBSET)             += fbset.o
     16lib-$(CONFIG_FDFLUSH)           += freeramdisk.o
     17lib-$(CONFIG_FDFORMAT)          += fdformat.o
     18lib-$(CONFIG_FDISK)             += fdisk.o
     19lib-$(CONFIG_FINDFS)            += findfs.o
     20lib-$(CONFIG_FLOCK)             += flock.o
     21lib-$(CONFIG_FREERAMDISK)       += freeramdisk.o
     22lib-$(CONFIG_FSCK_MINIX)        += fsck_minix.o
     23lib-$(CONFIG_GETOPT)            += getopt.o
     24lib-$(CONFIG_HEXDUMP)           += hexdump.o
     25lib-$(CONFIG_HWCLOCK)           += hwclock.o
     26lib-$(CONFIG_IPCRM)             += ipcrm.o
     27lib-$(CONFIG_IPCS)              += ipcs.o
     28lib-$(CONFIG_LOSETUP)           += losetup.o
     29lib-$(CONFIG_LSPCI)             += lspci.o
     30lib-$(CONFIG_LSUSB)             += lsusb.o
     31lib-$(CONFIG_MDEV)              += mdev.o
     32lib-$(CONFIG_MKFS_EXT2)         += mkfs_ext2.o
     33lib-$(CONFIG_MKFS_MINIX)        += mkfs_minix.o
     34lib-$(CONFIG_MKFS_REISER)       += mkfs_reiser.o
     35lib-$(CONFIG_MKFS_VFAT)         += mkfs_vfat.o
     36lib-$(CONFIG_MKSWAP)            += mkswap.o
     37lib-$(CONFIG_MORE)              += more.o
     38lib-$(CONFIG_MOUNT)             += mount.o
     39lib-$(CONFIG_PIVOT_ROOT)        += pivot_root.o
     40lib-$(CONFIG_RDATE)             += rdate.o
     41lib-$(CONFIG_RDEV)              += rdev.o
     42lib-$(CONFIG_READPROFILE)       += readprofile.o
     43lib-$(CONFIG_RTCWAKE)           += rtcwake.o
     44lib-$(CONFIG_SCRIPT)            += script.o
     45lib-$(CONFIG_SCRIPTREPLAY)      += scriptreplay.o
     46lib-$(CONFIG_SETARCH)           += setarch.o
     47lib-$(CONFIG_SWAPONOFF)         += swaponoff.o
     48lib-$(CONFIG_SWITCH_ROOT)       += switch_root.o
     49lib-$(CONFIG_UMOUNT)            += umount.o
  • branches/2.2.9/mindi-busybox/util-linux/dmesg.c

    r1765 r2725  
    55 *
    66 * Copyright 2006 Rob Landley <rob@landley.net>
    7  * Copyright 2006 Bernhard Fischer <rep.nop@aon.at>
     7 * Copyright 2006 Bernhard Reutner-Fischer <rep.nop@aon.at>
    88 *
    9  * Licensed under GPLv2, see file LICENSE in this tarball for details.
     9 * Licensed under GPLv2, see file LICENSE in this source tree.
    1010 */
    11 
    1211#include <sys/klog.h>
    1312#include "libbb.h"
    1413
    15 int dmesg_main(int argc, char **argv);
    16 int dmesg_main(int argc, char **argv)
     14int dmesg_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     15int dmesg_main(int argc UNUSED_PARAM, char **argv)
    1716{
    18     char *size, *level;
    19     int flags = getopt32(argv, "cs:n:", &size, &level);
     17    int len, level;
     18    char *buf;
     19    unsigned opts;
     20    enum {
     21        OPT_c = 1 << 0,
     22        OPT_s = 1 << 1,
     23        OPT_n = 1 << 2
     24    };
    2025
    21     if (flags & 4) {
    22         if (klogctl(8, NULL, xatoul_range(level, 0, 10)))
     26    opt_complementary = "s+:n+"; /* numeric */
     27    opts = getopt32(argv, "cs:n:", &len, &level);
     28    if (opts & OPT_n) {
     29        if (klogctl(8, NULL, (long) level))
    2330            bb_perror_msg_and_die("klogctl");
    24     } else {
    25         int len;
    26         char *buf;
    27 
    28         len = (flags & 2) ? xatoul_range(size, 2, INT_MAX) : 16384;
    29         buf = xmalloc(len);
    30         if (0 > (len = klogctl(3 + (flags & 1), buf, len)))
    31             bb_perror_msg_and_die("klogctl");
    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);
     31        return EXIT_SUCCESS;
    5032    }
    5133
    52     return 0;
     34    if (!(opts & OPT_s))
     35        len = klogctl(10, NULL, 0); /* read ring buffer size */
     36    if (len < 16*1024)
     37        len = 16*1024;
     38    if (len > 16*1024*1024)
     39        len = 16*1024*1024;
     40
     41    buf = xmalloc(len);
     42    len = klogctl(3 + (opts & OPT_c), buf, len); /* read ring buffer */
     43    if (len < 0)
     44        bb_perror_msg_and_die("klogctl");
     45    if (len == 0)
     46        return EXIT_SUCCESS;
     47
     48
     49    if (ENABLE_FEATURE_DMESG_PRETTY) {
     50        int last = '\n';
     51        int in = 0;
     52
     53        /* Skip <#> at the start of lines */
     54        while (1) {
     55            if (last == '\n' && buf[in] == '<') {
     56                in += 3;
     57                if (in >= len)
     58                    break;
     59            }
     60            last = buf[in];
     61            putchar(last);
     62            in++;
     63            if (in >= len)
     64                break;
     65        }
     66        /* Make sure we end with a newline */
     67        if (last != '\n')
     68            bb_putchar('\n');
     69    } else {
     70        full_write(STDOUT_FILENO, buf, len);
     71        if (buf[len-1] != '\n')
     72            bb_putchar('\n');
     73    }
     74
     75    if (ENABLE_FEATURE_CLEAN_UP) free(buf);
     76
     77    return EXIT_SUCCESS;
    5378}
  • branches/2.2.9/mindi-busybox/util-linux/fbset.c

    r1765 r2725  
    55 * Copyright (C) 1999 by Randolph Chung <tausq@debian.org>
    66 *
    7  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    88 *
    99 * This is a from-scratch implementation of fbset; but the de facto fbset
     
    1818#define DEFAULTFBMODE "/etc/fb.modes"
    1919
     20/* Stuff stolen from the kernel's fb.h */
     21#define FB_ACTIVATE_ALL 64
    2022enum {
    21     OPT_CHANGE   = (1 << 0),
    22     OPT_INFO     = (1 << 1),
    23     OPT_READMODE = (1 << 2),
    24     OPT_ALL      = (1 << 9),
    25 
     23    FBIOGET_VSCREENINFO = 0x4600,
     24    FBIOPUT_VSCREENINFO = 0x4601
     25};
     26
     27struct fb_bitfield {
     28    uint32_t offset;                /* beginning of bitfield */
     29    uint32_t length;                /* length of bitfield */
     30    uint32_t msb_right;             /* !=0: Most significant bit is right */
     31};
     32struct fb_var_screeninfo {
     33    uint32_t xres;                  /* visible resolution */
     34    uint32_t yres;
     35    uint32_t xres_virtual;          /* virtual resolution */
     36    uint32_t yres_virtual;
     37    uint32_t xoffset;               /* offset from virtual to visible */
     38    uint32_t yoffset;               /* resolution */
     39
     40    uint32_t bits_per_pixel;
     41    uint32_t grayscale;             /* !=0 Graylevels instead of colors */
     42
     43    struct fb_bitfield red;         /* bitfield in fb mem if true color, */
     44    struct fb_bitfield green;       /* else only length is significant */
     45    struct fb_bitfield blue;
     46    struct fb_bitfield transp;      /* transparency */
     47
     48    uint32_t nonstd;                /* !=0 Non standard pixel format */
     49
     50    uint32_t activate;              /* see FB_ACTIVATE_x */
     51
     52    uint32_t height;                /* height of picture in mm */
     53    uint32_t width;                 /* width of picture in mm */
     54
     55    uint32_t accel_flags;           /* acceleration flags (hints) */
     56
     57    /* Timing: All values in pixclocks, except pixclock (of course) */
     58    uint32_t pixclock;              /* pixel clock in ps (pico seconds) */
     59    uint32_t left_margin;           /* time from sync to picture */
     60    uint32_t right_margin;          /* time from picture to sync */
     61    uint32_t upper_margin;          /* time from sync to picture */
     62    uint32_t lower_margin;
     63    uint32_t hsync_len;             /* length of horizontal sync */
     64    uint32_t vsync_len;             /* length of vertical sync */
     65    uint32_t sync;                  /* see FB_SYNC_x */
     66    uint32_t vmode;                 /* see FB_VMODE_x */
     67    uint32_t reserved[6];           /* Reserved for future compatibility */
     68};
     69
     70static void copy_if_gt0(uint32_t *src, uint32_t *dst, unsigned cnt)
     71{
     72    do {
     73        if ((int32_t) *src > 0)
     74            *dst = *src;
     75        src++;
     76        dst++;
     77    } while (--cnt);
     78}
     79
     80static NOINLINE void copy_changed_values(
     81        struct fb_var_screeninfo *base,
     82        struct fb_var_screeninfo *set)
     83{
     84    //if ((int32_t) set->xres > 0) base->xres = set->xres;
     85    //if ((int32_t) set->yres > 0) base->yres = set->yres;
     86    //if ((int32_t) set->xres_virtual > 0)   base->xres_virtual = set->xres_virtual;
     87    //if ((int32_t) set->yres_virtual > 0)   base->yres_virtual = set->yres_virtual;
     88    copy_if_gt0(&set->xres, &base->xres, 4);
     89
     90    if ((int32_t) set->bits_per_pixel > 0) base->bits_per_pixel = set->bits_per_pixel;
     91    //copy_if_gt0(&set->bits_per_pixel, &base->bits_per_pixel, 1);
     92
     93    //if ((int32_t) set->pixclock > 0)       base->pixclock = set->pixclock;
     94    //if ((int32_t) set->left_margin > 0)    base->left_margin = set->left_margin;
     95    //if ((int32_t) set->right_margin > 0)   base->right_margin = set->right_margin;
     96    //if ((int32_t) set->upper_margin > 0)   base->upper_margin = set->upper_margin;
     97    //if ((int32_t) set->lower_margin > 0)   base->lower_margin = set->lower_margin;
     98    //if ((int32_t) set->hsync_len > 0) base->hsync_len = set->hsync_len;
     99    //if ((int32_t) set->vsync_len > 0) base->vsync_len = set->vsync_len;
     100    //if ((int32_t) set->sync > 0)  base->sync = set->sync;
     101    //if ((int32_t) set->vmode > 0) base->vmode = set->vmode;
     102    copy_if_gt0(&set->pixclock, &base->pixclock, 9);
     103}
     104
     105
     106enum {
    26107    CMD_FB = 1,
    27108    CMD_DB = 2,
     
    36117    CMD_ALL = 11,
    37118    CMD_INFO = 12,
    38     CMD_CHANGE = 13,
     119    CMD_SHOW = 13,
     120    CMD_CHANGE = 14,
    39121
    40122#if ENABLE_FEATURE_FBSET_FANCY
     
    62144};
    63145
    64 static unsigned g_options;
    65 
    66 /* Stuff stolen from the kernel's fb.h */
    67 #define FB_ACTIVATE_ALL 64
    68 enum {
    69     FBIOGET_VSCREENINFO = 0x4600,
    70     FBIOPUT_VSCREENINFO = 0x4601
    71 };
    72 struct fb_bitfield {
    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 */
    76 };
    77 struct fb_var_screeninfo {
    78     uint32_t xres;                  /* visible resolution */
    79     uint32_t yres;
    80     uint32_t xres_virtual;          /* virtual resolution */
    81     uint32_t yres_virtual;
    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 */
    90     struct fb_bitfield blue;
    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 */
    99 
    100     uint32_t accel_flags;       /* acceleration flags (hints)   */
    101 
    102     /* Timing: All values in pixclocks, except pixclock (of course) */
    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 */
    107     uint32_t lower_margin;
    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 */
    113 };
    114 
    115 
    116146static const struct cmdoptions_t {
    117     const char name[10];
     147    const char name[9];
    118148    const unsigned char param_count;
    119149    const unsigned char code;
    120150} g_cmdoptions[] = {
    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 },
     151    /*"12345678" + NUL */
     152    { "fb"      , 1, CMD_FB       },
     153    { "db"      , 1, CMD_DB       },
     154    { "a"       , 0, CMD_ALL      },
     155    { "i"       , 0, CMD_INFO     },
     156    { "g"       , 5, CMD_GEOMETRY },
     157    { "t"       , 7, CMD_TIMING   },
     158    { "accel"   , 1, CMD_ACCEL    },
     159    { "hsync"   , 1, CMD_HSYNC    },
     160    { "vsync"   , 1, CMD_VSYNC    },
     161    { "laced"   , 1, CMD_LACED    },
     162    { "double"  , 1, CMD_DOUBLE   },
     163    { "show"    , 0, CMD_SHOW     },
     164    { "s"       , 0, CMD_SHOW     },
    133165#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
     166    { "all"     , 0, CMD_ALL      },
     167    { "xres"    , 1, CMD_XRES     },
     168    { "yres"    , 1, CMD_YRES     },
     169    { "vxres"   , 1, CMD_VXRES    },
     170    { "vyres"   , 1, CMD_VYRES    },
     171    { "depth"   , 1, CMD_DEPTH    },
     172    { "match"   , 0, CMD_MATCH    },
     173    { "geometry", 5, CMD_GEOMETRY },
     174    { "pixclock", 1, CMD_PIXCLOCK },
     175    { "left"    , 1, CMD_LEFT     },
     176    { "right"   , 1, CMD_RIGHT    },
     177    { "upper"   , 1, CMD_UPPER    },
     178    { "lower"   , 1, CMD_LOWER    },
     179    { "hslen"   , 1, CMD_HSLEN    },
     180    { "vslen"   , 1, CMD_VSLEN    },
     181    { "timings" , 7, CMD_TIMING   },
     182    { "csync"   , 1, CMD_CSYNC    },
     183    { "gsync"   , 1, CMD_GSYNC    },
     184    { "extsync" , 1, CMD_EXTSYNC  },
     185    { "bcast"   , 1, CMD_BCAST    },
     186    { "rgba"    , 1, CMD_RGBA     },
     187    { "step"    , 1, CMD_STEP     },
     188    { "move"    , 1, CMD_MOVE     },
     189#endif
     190};
     191
    162192/* taken from linux/fb.h */
    163193enum {
    164     FB_VMODE_INTERLACED = 1,    /* interlaced   */
    165     FB_VMODE_DOUBLE = 2,    /* double scan */
    166     FB_SYNC_HOR_HIGH_ACT = 1,   /* horizontal sync high active  */
    167     FB_SYNC_VERT_HIGH_ACT = 2,  /* vertical sync high active    */
    168     FB_SYNC_EXT = 4,    /* external sync        */
    169     FB_SYNC_COMP_HIGH_ACT = 8   /* composite sync high active   */
    170 };
    171 #endif
    172 
    173 static int readmode(struct fb_var_screeninfo *base, const char *fn,
     194    FB_SYNC_HOR_HIGH_ACT = 1,       /* horizontal sync high active */
     195    FB_SYNC_VERT_HIGH_ACT = 2,      /* vertical sync high active */
     196#if ENABLE_FEATURE_FBSET_READMODE
     197    FB_VMODE_INTERLACED = 1,        /* interlaced */
     198    FB_VMODE_DOUBLE = 2,            /* double scan */
     199    FB_SYNC_EXT = 4,                /* external sync */
     200    FB_SYNC_COMP_HIGH_ACT = 8,      /* composite sync high active */
     201#endif
     202};
     203
     204#if ENABLE_FEATURE_FBSET_READMODE
     205static void ss(uint32_t *x, uint32_t flag, char *buf, const char *what)
     206{
     207    if (strcmp(buf, what) == 0)
     208        *x &= ~flag;
     209    else
     210        *x |= flag;
     211}
     212
     213/* Mode db file contains mode definitions like this:
     214 * mode "800x600-48-lace"
     215 *     # D: 36.00 MHz, H: 33.835 kHz, V: 96.39 Hz
     216 *     geometry 800 600 800 600 8
     217 *     timings 27778 56 80 79 11 128 12
     218 *     laced true
     219 *     hsync high
     220 *     vsync high
     221 * endmode
     222 */
     223static int read_mode_db(struct fb_var_screeninfo *base, const char *fn,
    174224                    const char *mode)
    175225{
    176 #if ENABLE_FEATURE_FBSET_READMODE
    177     FILE *f;
    178     char buf[256];
    179     char *p = buf;
    180 
    181     f = xfopen(fn, "r");
    182     while (!feof(f)) {
    183         fgets(buf, sizeof(buf), f);
    184         if (!(p = strstr(buf, "mode ")) && !(p = strstr(buf, "mode\t")))
     226    char *token[2], *p, *s;
     227    parser_t *parser = config_open(fn);
     228
     229    while (config_read(parser, token, 2, 1, "# \t\r", PARSE_NORMAL)) {
     230        if (strcmp(token[0], "mode") != 0 || !token[1])
    185231            continue;
    186         p += 5;
    187         if (!(p = strstr(buf, mode)))
     232        p = strstr(token[1], mode);
     233        if (!p)
    188234            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 */
     235        s = p + strlen(mode);
     236        //bb_info_msg("CHECK[%s][%s][%d]", mode, p-1, *s);
     237        /* exact match? */
     238        if (((!*s || isspace(*s)) && '"' != s[-1]) /* end-of-token */
     239         || ('"' == *s && '"' == p[-1]) /* ends with " but starts with " too! */
     240        ) {
     241            //bb_info_msg("FOUND[%s][%s][%s][%d]", token[1], p, mode, isspace(*s));
     242            break;
     243        }
     244    }
     245
     246    if (!token[0])
     247        return 0;
     248
     249    while (config_read(parser, token, 2, 1, "# \t", PARSE_NORMAL)) {
     250        int i;
     251
     252//bb_info_msg("???[%s][%s]", token[0], token[1]);
     253        if (strcmp(token[0], "endmode") == 0) {
     254//bb_info_msg("OK[%s]", mode);
     255            return 1;
     256        }
     257        p = token[1];
     258        i = index_in_strings(
     259            "geometry\0timings\0interlaced\0double\0vsync\0hsync\0csync\0extsync\0",
     260            token[0]);
     261        switch (i) {
     262        case 0:
     263            if (sizeof(int) == sizeof(base->xres)) {
    199264                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;
     265                    &base->xres, &base->yres,
     266                    &base->xres_virtual, &base->yres_virtual,
     267                    &base->bits_per_pixel);
     268            } else {
     269                int base_xres, base_yres;
     270                int base_xres_virtual, base_yres_virtual;
     271                int base_bits_per_pixel;
     272                sscanf(p, "%d %d %d %d %d",
     273                    &base_xres, &base_yres,
     274                    &base_xres_virtual, &base_yres_virtual,
     275                    &base_bits_per_pixel);
     276                base->xres = base_xres;
     277                base->yres = base_yres;
     278                base->xres_virtual = base_xres_virtual;
     279                base->yres_virtual = base_yres_virtual;
     280                base->bits_per_pixel = base_bits_per_pixel;
     281            }
     282//bb_info_msg("GEO[%s]", p);
     283            break;
     284        case 1:
     285            if (sizeof(int) == sizeof(base->xres)) {
    205286                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                 }
     287                    &base->pixclock,
     288                    &base->left_margin, &base->right_margin,
     289                    &base->upper_margin, &base->lower_margin,
     290                    &base->hsync_len, &base->vsync_len);
     291            } else {
     292                int base_pixclock;
     293                int base_left_margin, base_right_margin;
     294                int base_upper_margin, base_lower_margin;
     295                int base_hsync_len, base_vsync_len;
     296                sscanf(p, "%d %d %d %d %d %d %d",
     297                    &base_pixclock,
     298                    &base_left_margin, &base_right_margin,
     299                    &base_upper_margin, &base_lower_margin,
     300                    &base_hsync_len, &base_vsync_len);
     301                base->pixclock = base_pixclock;
     302                base->left_margin = base_left_margin;
     303                base->right_margin = base_right_margin;
     304                base->upper_margin = base_upper_margin;
     305                base->lower_margin = base_lower_margin;
     306                base->hsync_len = base_hsync_len;
     307                base->vsync_len = base_vsync_len;
    252308            }
    253 
    254             if (strstr(buf, "endmode"))
    255                 return 1;
    256         }
    257     }
    258 #else
    259     bb_error_msg("mode reading not compiled in");
    260 #endif
     309//bb_info_msg("TIM[%s]", p);
     310            break;
     311        case 2:
     312        case 3: {
     313            static const uint32_t syncs[] = {FB_VMODE_INTERLACED, FB_VMODE_DOUBLE};
     314            ss(&base->vmode, syncs[i-2], p, "false");
     315//bb_info_msg("VMODE[%s]", p);
     316            break;
     317        }
     318        case 4:
     319        case 5:
     320        case 6: {
     321            static const uint32_t syncs[] = {FB_SYNC_VERT_HIGH_ACT, FB_SYNC_HOR_HIGH_ACT, FB_SYNC_COMP_HIGH_ACT};
     322            ss(&base->sync, syncs[i-4], p, "low");
     323//bb_info_msg("SYNC[%s]", p);
     324            break;
     325        }
     326        case 7:
     327            ss(&base->sync, FB_SYNC_EXT, p, "false");
     328//bb_info_msg("EXTSYNC[%s]", p);
     329            break;
     330        }
     331    }
    261332    return 0;
    262333}
    263 
    264 static inline void setmode(struct fb_var_screeninfo *base,
    265                     struct fb_var_screeninfo *set)
    266 {
    267     if ((int) set->xres > 0)
    268         base->xres = set->xres;
    269     if ((int) set->yres > 0)
    270         base->yres = set->yres;
    271     if ((int) set->xres_virtual > 0)
    272         base->xres_virtual = set->xres_virtual;
    273     if ((int) set->yres_virtual > 0)
    274         base->yres_virtual = set->yres_virtual;
    275     if ((int) set->bits_per_pixel > 0)
    276         base->bits_per_pixel = set->bits_per_pixel;
    277 }
    278 
    279 static inline void showmode(struct fb_var_screeninfo *v)
     334#endif
     335
     336static NOINLINE void showmode(struct fb_var_screeninfo *v)
    280337{
    281338    double drate = 0, hrate = 0, vrate = 0;
     
    307364}
    308365
    309 #ifdef STANDALONE
    310 int main(int argc, char **argv)
    311 #else
    312 int fbset_main(int argc, char **argv);
     366int fbset_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
    313367int fbset_main(int argc, char **argv)
    314 #endif
    315 {
    316     struct fb_var_screeninfo var, varset;
     368{
     369    enum {
     370        OPT_CHANGE   = (1 << 0),
     371        OPT_SHOW     = (1 << 1),
     372        OPT_READMODE = (1 << 2),
     373        OPT_ALL      = (1 << 9),
     374    };
     375    struct fb_var_screeninfo var_old, var_set;
    317376    int fh, i;
     377    unsigned options = 0;
     378
    318379    const char *fbdev = DEFAULTFBDEV;
    319380    const char *modefile = DEFAULTFBMODE;
    320     char *thisarg, *mode = NULL;
    321 
    322     memset(&varset, 0xFF, sizeof(varset));
     381    char *thisarg;
     382    char *mode = mode; /* for compiler */
     383
     384    memset(&var_set, 0xff, sizeof(var_set)); /* set all to -1 */
    323385
    324386    /* parse cmd args.... why do they have to make things so difficult? */
    325387    argv++;
    326388    argc--;
    327     for (; argc > 0 && (thisarg = *argv); argc--, argv++) {
    328         for (i = 0; g_cmdoptions[i].name[0]; i++) {
    329             if (strcmp(thisarg, g_cmdoptions[i].name))
     389    for (; argc > 0 && (thisarg = *argv) != NULL; argc--, argv++) {
     390        if (thisarg[0] == '-') for (i = 0; i < ARRAY_SIZE(g_cmdoptions); i++) {
     391            if (strcmp(thisarg + 1, g_cmdoptions[i].name) != 0)
    330392                continue;
    331             if (argc-1 < g_cmdoptions[i].param_count)
     393            if (argc <= g_cmdoptions[i].param_count)
    332394                bb_show_usage();
    333395
     
    339401                modefile = argv[1];
    340402                break;
     403            case CMD_ALL:
     404                options |= OPT_ALL;
     405                break;
     406            case CMD_SHOW:
     407                options |= OPT_SHOW;
     408                break;
    341409            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]);
     410                var_set.xres = xatou32(argv[1]);
     411                var_set.yres = xatou32(argv[2]);
     412                var_set.xres_virtual = xatou32(argv[3]);
     413                var_set.yres_virtual = xatou32(argv[4]);
     414                var_set.bits_per_pixel = xatou32(argv[5]);
    347415                break;
    348416            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;
     417                var_set.pixclock = xatou32(argv[1]);
     418                var_set.left_margin = xatou32(argv[2]);
     419                var_set.right_margin = xatou32(argv[3]);
     420                var_set.upper_margin = xatou32(argv[4]);
     421                var_set.lower_margin = xatou32(argv[5]);
     422                var_set.hsync_len = xatou32(argv[6]);
     423                var_set.vsync_len = xatou32(argv[7]);
     424                break;
     425            case CMD_ACCEL:
     426                break;
     427            case CMD_HSYNC:
     428                var_set.sync |= FB_SYNC_HOR_HIGH_ACT;
     429                break;
     430            case CMD_VSYNC:
     431                var_set.sync |= FB_SYNC_VERT_HIGH_ACT;
    362432                break;
    363433#if ENABLE_FEATURE_FBSET_FANCY
    364434            case CMD_XRES:
    365                 varset.xres = xatou32(argv[1]);
     435                var_set.xres = xatou32(argv[1]);
    366436                break;
    367437            case CMD_YRES:
    368                 varset.yres = xatou32(argv[1]);
     438                var_set.yres = xatou32(argv[1]);
    369439                break;
    370440            case CMD_DEPTH:
    371                 varset.bits_per_pixel = xatou32(argv[1]);
    372                 break;
    373 #endif
     441                var_set.bits_per_pixel = xatou32(argv[1]);
     442                break;
     443#endif
     444            }
     445            switch (g_cmdoptions[i].code) {
     446            case CMD_FB:
     447            case CMD_DB:
     448            case CMD_ALL:
     449            case CMD_SHOW:
     450                break;
     451            default:
     452                /* other commands imply changes */
     453                options |= OPT_CHANGE;
    374454            }
    375455            argc -= g_cmdoptions[i].param_count;
    376456            argv += g_cmdoptions[i].param_count;
    377             break;
    378         }
    379         if (!g_cmdoptions[i].name[0]) {
    380             if (argc != 1)
    381                 bb_show_usage();
    382             mode = *argv;
    383             g_options |= OPT_READMODE;
    384         }
     457            goto contin;
     458        }
     459        if (!ENABLE_FEATURE_FBSET_READMODE || argc != 1)
     460            bb_show_usage();
     461        mode = *argv;
     462        options |= OPT_READMODE;
     463 contin: ;
    385464    }
    386465
    387466    fh = xopen(fbdev, O_RDONLY);
    388     xioctl(fh, FBIOGET_VSCREENINFO, &var);
    389     if (g_options & OPT_READMODE) {
    390         if (!readmode(&var, modefile, mode)) {
     467    xioctl(fh, FBIOGET_VSCREENINFO, &var_old);
     468
     469    if (options & OPT_READMODE) {
     470#if ENABLE_FEATURE_FBSET_READMODE
     471        if (!read_mode_db(&var_old, modefile, mode)) {
    391472            bb_error_msg_and_die("unknown video mode '%s'", mode);
    392473        }
    393     }
    394 
    395     setmode(&var, &varset);
    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     }
    401     showmode(&var);
    402     /* Don't close the file, as exiting will take care of that */
    403     /* close(fh); */
     474#endif
     475    }
     476
     477    if (options & OPT_CHANGE) {
     478        copy_changed_values(&var_old, &var_set);
     479        if (options & OPT_ALL)
     480            var_old.activate = FB_ACTIVATE_ALL;
     481        xioctl(fh, FBIOPUT_VSCREENINFO, &var_old);
     482    }
     483
     484    if (options == 0 || (options & OPT_SHOW))
     485        showmode(&var_old);
     486
     487    if (ENABLE_FEATURE_CLEAN_UP)
     488        close(fh);
    404489
    405490    return EXIT_SUCCESS;
  • branches/2.2.9/mindi-busybox/util-linux/fdformat.c

    r1765 r2725  
    11/* vi: set sw=4 ts=4: */
    2 /* fdformat.c  -  Low-level formats a floppy disk - Werner Almesberger */
    3 
    4 /* 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
    5  * - added Native Language Support
    6  * 1999-03-20 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
    7  * - more i18n/nls translatable strings marked
     2/* fdformat.c  -  Low-level formats a floppy disk - Werner Almesberger
     3 * 5 July 2003 -- modified for Busybox by Erik Andersen
    84 *
    9  * 5 July 2003 -- modified for Busybox by Erik Andersen
     5 * Licensed under GPLv2, see file LICENSE in this source tree.
    106 */
    117
     
    4137};
    4238#define FDFMTBEG _IO(2,0x47)
    43 #define FDFMTTRK _IOW(2,0x48, struct format_descr)
     39#define FDFMTTRK _IOW(2,0x48, struct format_descr)
    4440#define FDFMTEND _IO(2,0x49)
    4541#define FDGETPRM _IOR(2, 0x04, struct floppy_struct)
    4642#define FD_FILL_BYTE 0xF6 /* format fill byte. */
    4743
    48 int fdformat_main(int argc,char **argv);
    49 int fdformat_main(int argc,char **argv)
     44int fdformat_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     45int fdformat_main(int argc UNUSED_PARAM, char **argv)
    5046{
    5147    int fd, n, cyl, read_bytes, verify;
     
    5551    struct format_descr descr;
    5652
    57     if (argc < 2) {
    58         bb_show_usage();
    59     }
     53    opt_complementary = "=1"; /* must have 1 param */
    6054    verify = !getopt32(argv, "n");
    6155    argv += optind;
     
    117111            while (--read_bytes >= 0) {
    118112                if (data[read_bytes] != FD_FILL_BYTE) {
    119                      printf("bad data in cyl %d\nContinuing... ",cyl);
     113                     printf("bad data in cyl %d\nContinuing... ", cyl);
    120114                }
    121115            }
  • branches/2.2.9/mindi-busybox/util-linux/fdisk.c

    r1765 r2725  
    55 * Copyright (C) 2001,2002 Vladimir Oleynik <dzo@simtreas.ru> (initial bb port)
    66 *
    7  * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
     7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    88 */
    99
    1010#ifndef _LARGEFILE64_SOURCE
    1111/* For lseek64 */
    12 #define _LARGEFILE64_SOURCE
     12# define _LARGEFILE64_SOURCE
    1313#endif
    1414#include <assert.h>             /* assert */
     15#include <sys/mount.h>
     16#if !defined(BLKSSZGET)
     17# define BLKSSZGET _IO(0x12, 104)
     18#endif
     19#if !defined(BLKGETSIZE64)
     20# define BLKGETSIZE64 _IOR(0x12,114,size_t)
     21#endif
    1522#include "libbb.h"
     23
     24#if BB_LITTLE_ENDIAN
     25# define inline_if_little_endian ALWAYS_INLINE
     26#else
     27# define inline_if_little_endian /* nothing */
     28#endif
     29
    1630
    1731/* Looks like someone forgot to add this to config system */
    1832#ifndef ENABLE_FEATURE_FDISK_BLKSIZE
    1933# define ENABLE_FEATURE_FDISK_BLKSIZE 0
    20 # define USE_FEATURE_FDISK_BLKSIZE(a)
    21 #endif
    22 
    23 #define DEFAULT_SECTOR_SIZE     512
    24 #define MAX_SECTOR_SIZE 2048
    25 #define SECTOR_SIZE     512     /* still used in osf/sgi/sun code */
    26 #define MAXIMUM_PARTS   60
    27 
    28 #define ACTIVE_FLAG     0x80
    29 
    30 #define EXTENDED        0x05
    31 #define WIN98_EXTENDED  0x0f
    32 #define LINUX_PARTITION 0x81
    33 #define LINUX_SWAP      0x82
    34 #define LINUX_NATIVE    0x83
    35 #define LINUX_EXTENDED  0x85
    36 #define LINUX_LVM       0x8e
    37 #define LINUX_RAID      0xfd
    38 
    39 /* Used for sector numbers. Today's disk sizes make it necessary */
     34# define IF_FEATURE_FDISK_BLKSIZE(a)
     35#endif
     36
     37#define DEFAULT_SECTOR_SIZE      512
     38#define DEFAULT_SECTOR_SIZE_STR "512"
     39#define MAX_SECTOR_SIZE         2048
     40#define SECTOR_SIZE              512 /* still used in osf/sgi/sun code */
     41#define MAXIMUM_PARTS             60
     42
     43#define ACTIVE_FLAG             0x80
     44
     45#define EXTENDED                0x05
     46#define WIN98_EXTENDED          0x0f
     47#define LINUX_PARTITION         0x81
     48#define LINUX_SWAP              0x82
     49#define LINUX_NATIVE            0x83
     50#define LINUX_EXTENDED          0x85
     51#define LINUX_LVM               0x8e
     52#define LINUX_RAID              0xfd
     53
     54
     55enum {
     56    OPT_b = 1 << 0,
     57    OPT_C = 1 << 1,
     58    OPT_H = 1 << 2,
     59    OPT_l = 1 << 3,
     60    OPT_S = 1 << 4,
     61    OPT_u = 1 << 5,
     62    OPT_s = (1 << 6) * ENABLE_FEATURE_FDISK_BLKSIZE,
     63};
     64
     65
    4066typedef unsigned long long ullong;
     67/* Used for sector numbers. Partition formats we know
     68 * do not support more than 2^32 sectors
     69 */
     70typedef uint32_t sector_t;
     71#if UINT_MAX == 4294967295
     72# define SECT_FMT ""
     73#elif ULONG_MAX == 4294967295
     74# define SECT_FMT "l"
     75#else
     76# error Cant detect sizeof(uint32_t)
     77#endif
    4178
    4279struct hd_geometry {
     
    5592
    5693static const char msg_part_already_defined[] ALIGN1 =
    57 "Partition %d is already defined, delete it before re-adding\n";
    58 
    59 
    60 static unsigned sector_size = DEFAULT_SECTOR_SIZE;
    61 static unsigned user_set_sector_size;
    62 static unsigned sector_offset = 1;
    63 
    64 #if ENABLE_FEATURE_OSF_LABEL
    65 static int possibly_osf_label;
    66 #endif
    67 
    68 static unsigned heads, sectors, cylinders;
    69 static void update_units(void);
     94"Partition %u is already defined, delete it before re-adding\n";
    7095
    7196
     
    75100    unsigned char sector;           /* starting sector */
    76101    unsigned char cyl;              /* starting cylinder */
    77     unsigned char sys_ind;          /* What partition type */
     102    unsigned char sys_ind;          /* what partition type */
    78103    unsigned char end_head;         /* end head */
    79104    unsigned char end_sector;       /* end sector */
     
    81106    unsigned char start4[4];        /* starting sector counting from 0 */
    82107    unsigned char size4[4];         /* nr of sectors in partition */
    83 } ATTRIBUTE_PACKED;
    84 
    85 static const char unable_to_open[] ALIGN1 = "cannot open %s";
    86 static const char unable_to_read[] ALIGN1 = "cannot read from %s";
    87 static const char unable_to_seek[] ALIGN1 = "cannot seek on %s";
    88 static const char unable_to_write[] ALIGN1 = "cannot write to %s";
    89 static const char ioctl_error[] ALIGN1 = "BLKGETSIZE ioctl failed on %s";
    90 static void fdisk_fatal(const char *why) ATTRIBUTE_NORETURN;
    91 
    92 enum label_type {
    93     label_dos, label_sun, label_sgi, label_aix, label_osf
    94 };
    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
    129 
    130 enum action { fdisk, require, try_only, create_empty_dos, create_empty_sun };
    131 
    132 static enum label_type current_label_type;
    133 
    134 static const char *disk_device;
    135 static int fd;                  /* the disk */
    136 static int partitions = 4;      /* maximum partition + 1 */
    137 static int display_in_cyl_units = 1;
    138 static unsigned units_per_sector = 1;
    139 #if ENABLE_FEATURE_FDISK_WRITABLE
    140 static void change_units(void);
    141 static void reread_partition_table(int leave);
    142 static void delete_partition(int i);
    143 static int get_partition(int warn, int max);
    144 static void list_types(const char *const *sys);
    145 static unsigned read_int(unsigned low, unsigned dflt, unsigned high, unsigned base, const char *mesg);
    146 #endif
    147 static const char *partition_type(unsigned char type);
    148 static void get_geometry(void);
    149 static int get_boot(enum action what);
    150 
    151 #define PLURAL   0
    152 #define SINGULAR 1
    153 
    154 static unsigned get_start_sect(const struct partition *p);
    155 static unsigned get_nr_sects(const struct partition *p);
     108} PACKED;
    156109
    157110/*
     
    166119    struct partition *part_table;   /* points into sectorbuffer */
    167120    struct partition *ext_pointer;  /* points into sectorbuffer */
    168     ullong offset;          /* disk sector number */
    169     char *sectorbuffer;     /* disk sector contents */
     121    sector_t offset_from_dev_start; /* disk sector number */
     122    char *sectorbuffer;             /* disk sector contents */
    170123#if ENABLE_FEATURE_FDISK_WRITABLE
    171     char changed;           /* boolean */
     124    char changed;                   /* boolean */
    172125#endif
    173126};
     127
     128#define unable_to_open "can't open '%s'"
     129#define unable_to_read "can't read from %s"
     130#define unable_to_seek "can't seek on %s"
     131
     132enum label_type {
     133    LABEL_DOS, LABEL_SUN, LABEL_SGI, LABEL_AIX, LABEL_OSF, LABEL_GPT
     134};
     135
     136#define LABEL_IS_DOS    (LABEL_DOS == current_label_type)
     137
     138#if ENABLE_FEATURE_SUN_LABEL
     139#define LABEL_IS_SUN    (LABEL_SUN == current_label_type)
     140#define STATIC_SUN static
     141#else
     142#define LABEL_IS_SUN    0
     143#define STATIC_SUN extern
     144#endif
     145
     146#if ENABLE_FEATURE_SGI_LABEL
     147#define LABEL_IS_SGI    (LABEL_SGI == current_label_type)
     148#define STATIC_SGI static
     149#else
     150#define LABEL_IS_SGI    0
     151#define STATIC_SGI extern
     152#endif
     153
     154#if ENABLE_FEATURE_AIX_LABEL
     155#define LABEL_IS_AIX    (LABEL_AIX == current_label_type)
     156#define STATIC_AIX static
     157#else
     158#define LABEL_IS_AIX    0
     159#define STATIC_AIX extern
     160#endif
     161
     162#if ENABLE_FEATURE_OSF_LABEL
     163#define LABEL_IS_OSF    (LABEL_OSF == current_label_type)
     164#define STATIC_OSF static
     165#else
     166#define LABEL_IS_OSF    0
     167#define STATIC_OSF extern
     168#endif
     169
     170#if ENABLE_FEATURE_GPT_LABEL
     171#define LABEL_IS_GPT    (LABEL_GPT == current_label_type)
     172#define STATIC_GPT static
     173#else
     174#define LABEL_IS_GPT    0
     175#define STATIC_GPT extern
     176#endif
     177
     178enum action { OPEN_MAIN, TRY_ONLY, CREATE_EMPTY_DOS, CREATE_EMPTY_SUN };
     179
     180static void update_units(void);
     181#if ENABLE_FEATURE_FDISK_WRITABLE
     182static void change_units(void);
     183static void reread_partition_table(int leave);
     184static void delete_partition(int i);
     185static unsigned get_partition(int warn, unsigned max);
     186static void list_types(const char *const *sys);
     187static sector_t read_int(sector_t low, sector_t dflt, sector_t high, sector_t base, const char *mesg);
     188#endif
     189static const char *partition_type(unsigned char type);
     190static void get_geometry(void);
     191static void read_pte(struct pte *pe, sector_t offset);
     192#if ENABLE_FEATURE_SUN_LABEL || ENABLE_FEATURE_FDISK_WRITABLE
     193static int get_boot(enum action what);
     194#else
     195static int get_boot(void);
     196#endif
     197
     198#define PLURAL   0
     199#define SINGULAR 1
     200
     201static sector_t get_start_sect(const struct partition *p);
     202static sector_t get_nr_sects(const struct partition *p);
    174203
    175204/* DOS partition types */
     
    278307};
    279308
     309enum {
     310    dev_fd = 3                  /* the disk */
     311};
    280312
    281313/* Globals */
    282 
    283314struct globals {
    284315    char *line_ptr;
     316
     317    const char *disk_device;
     318    int g_partitions; // = 4;       /* maximum partition + 1 */
     319    unsigned units_per_sector; // = 1;
     320    unsigned sector_size; // = DEFAULT_SECTOR_SIZE;
     321    unsigned user_set_sector_size;
     322    unsigned sector_offset; // = 1;
     323    unsigned g_heads, g_sectors, g_cylinders;
     324    smallint /* enum label_type */ current_label_type;
     325    smallint display_in_cyl_units; // = 1;
     326#if ENABLE_FEATURE_OSF_LABEL
     327    smallint possibly_osf_label;
     328#endif
     329
     330    smallint listing;               /* no aborts for fdisk -l */
     331    smallint dos_compatible_flag; // = 1;
     332#if ENABLE_FEATURE_FDISK_WRITABLE
     333    //int dos_changed;
     334    smallint nowarn;                /* no warnings for fdisk -l/-s */
     335#endif
     336    int ext_index;                  /* the prime extended partition */
     337    unsigned user_cylinders, user_heads, user_sectors;
     338    unsigned pt_heads, pt_sectors;
     339    unsigned kern_heads, kern_sectors;
     340    sector_t extended_offset;       /* offset of link pointers */
     341    sector_t total_number_of_sectors;
     342
     343    jmp_buf listingbuf;
    285344    char line_buffer[80];
    286345    char partname_buffer[80];
    287     jmp_buf listingbuf;
    288346    /* Raw disk label. For DOS-type partition tables the MBR,
    289347     * with descriptions of the primary partitions. */
     
    292350    struct pte ptes[MAXIMUM_PARTS];
    293351};
    294 /* bb_common_bufsiz1 is too small for this on 64 bit CPUs */
    295352#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)
     353#define line_ptr             (G.line_ptr            )
     354#define disk_device          (G.disk_device         )
     355#define g_partitions         (G.g_partitions        )
     356#define units_per_sector     (G.units_per_sector    )
     357#define sector_size          (G.sector_size         )
     358#define user_set_sector_size (G.user_set_sector_size)
     359#define sector_offset        (G.sector_offset       )
     360#define g_heads              (G.g_heads             )
     361#define g_sectors            (G.g_sectors           )
     362#define g_cylinders          (G.g_cylinders         )
     363#define current_label_type   (G.current_label_type  )
     364#define display_in_cyl_units (G.display_in_cyl_units)
     365#define possibly_osf_label   (G.possibly_osf_label  )
     366#define listing                 (G.listing                )
     367#define dos_compatible_flag     (G.dos_compatible_flag    )
     368#define nowarn                  (G.nowarn                 )
     369#define ext_index               (G.ext_index              )
     370#define user_cylinders          (G.user_cylinders         )
     371#define user_heads              (G.user_heads             )
     372#define user_sectors            (G.user_sectors           )
     373#define pt_heads                (G.pt_heads               )
     374#define pt_sectors              (G.pt_sectors             )
     375#define kern_heads              (G.kern_heads             )
     376#define kern_sectors            (G.kern_sectors           )
     377#define extended_offset         (G.extended_offset        )
     378#define total_number_of_sectors (G.total_number_of_sectors)
     379#define listingbuf      (G.listingbuf     )
     380#define line_buffer     (G.line_buffer    )
    300381#define partname_buffer (G.partname_buffer)
    301 #define MBRbuffer       (G.MBRbuffer)
    302 #define ptes            (G.ptes)
    303 
    304 
    305 /* Code */
     382#define MBRbuffer       (G.MBRbuffer      )
     383#define ptes            (G.ptes           )
     384#define INIT_G() do { \
     385    SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
     386    sector_size = DEFAULT_SECTOR_SIZE; \
     387    sector_offset = 1; \
     388    g_partitions = 4; \
     389    display_in_cyl_units = 1; \
     390    units_per_sector = 1; \
     391    dos_compatible_flag = 1; \
     392} while (0)
     393
     394
     395/* TODO: move to libbb? */
     396/* TODO: return unsigned long long, FEATURE_FDISK_BLKSIZE _can_ handle
     397 * disks > 2^32 sectors
     398 */
     399static sector_t bb_BLKGETSIZE_sectors(int fd)
     400{
     401    uint64_t v64;
     402    unsigned long longsectors;
     403
     404    if (ioctl(fd, BLKGETSIZE64, &v64) == 0) {
     405        /* Got bytes, convert to 512 byte sectors */
     406        v64 >>= 9;
     407        if (v64 != (sector_t)v64) {
     408 ret_trunc:
     409            /* Not only DOS, but all other partition tables
     410             * we support can't record more than 32 bit
     411             * sector counts or offsets
     412             */
     413            bb_error_msg("device has more than 2^32 sectors, can't use all of them");
     414            v64 = (uint32_t)-1L;
     415        }
     416        return v64;
     417    }
     418    /* Needs temp of type long */
     419    if (ioctl(fd, BLKGETSIZE, &longsectors)) {
     420        /* Perhaps this is a disk image */
     421        off_t sz = lseek(fd, 0, SEEK_END);
     422        longsectors = 0;
     423        if (sz > 0)
     424            longsectors = (uoff_t)sz / sector_size;
     425        lseek(fd, 0, SEEK_SET);
     426    }
     427    if (sizeof(long) > sizeof(sector_t)
     428     && longsectors != (sector_t)longsectors
     429    ) {
     430        goto ret_trunc;
     431    }
     432    return longsectors;
     433}
     434
    306435
    307436#define IS_EXTENDED(i) \
     
    322451    (sector(s) - 1 + sectors * ((h) + heads * cylinder(s,c)))
    323452
    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 */
    336 static int
    337 read_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
     453static void
     454close_dev_fd(void)
     455{
     456    /* Not really closing, but making sure it is open, and to harmless place */
     457    xmove_fd(xopen(bb_dev_null, O_RDONLY), dev_fd);
     458}
    354459
    355460/*
    356  * return partition name - uses static storage
     461 * Return partition name - uses static storage
    357462 */
    358463static const char *
     
    384489    if (lth) {
    385490        snprintf(bufp, bufsiz, "%*.*s%s%-2u",
    386              lth-wp-2, w, dev, p, pno);
     491            lth-wp-2, w, dev, p, pno);
    387492    } else {
    388493        snprintf(bufp, bufsiz, "%.*s%s%-2u", w, dev, p, pno);
     
    390495    return bufp;
    391496}
    392 
    393 #if ENABLE_FEATURE_FDISK_WRITABLE
    394 static void
    395 set_all_unchanged(void)
    396 {
    397     int i;
    398 
    399     for (i = 0; i < MAXIMUM_PARTS; i++)
    400         ptes[i].changed = 0;
    401 }
    402 
    403 static ALWAYS_INLINE void
    404 set_changed(int i)
    405 {
    406     ptes[i].changed = 1;
    407 }
    408 #endif /* FEATURE_FDISK_WRITABLE */
    409497
    410498static ALWAYS_INLINE struct partition *
     
    428516}
    429517
     518static void fdisk_fatal(const char *why)
     519{
     520    if (listing) {
     521        close_dev_fd();
     522        longjmp(listingbuf, 1);
     523    }
     524    bb_error_msg_and_die(why, disk_device);
     525}
     526
     527static void
     528seek_sector(sector_t secno)
     529{
     530#if ENABLE_FDISK_SUPPORT_LARGE_DISKS
     531    off64_t off = (off64_t)secno * sector_size;
     532    if (lseek64(dev_fd, off, SEEK_SET) == (off64_t) -1)
     533        fdisk_fatal(unable_to_seek);
     534#else
     535    uint64_t off = (uint64_t)secno * sector_size;
     536    if (off > MAXINT(off_t)
     537     || lseek(dev_fd, (off_t)off, SEEK_SET) == (off_t) -1
     538    ) {
     539        fdisk_fatal(unable_to_seek);
     540    }
     541#endif
     542}
     543
    430544#if ENABLE_FEATURE_FDISK_WRITABLE
     545/* Read line; return 0 or first printable char */
     546static int
     547read_line(const char *prompt)
     548{
     549    int sz;
     550
     551    sz = read_line_input(prompt, line_buffer, sizeof(line_buffer), NULL);
     552    if (sz <= 0)
     553        exit(EXIT_SUCCESS); /* Ctrl-D or Ctrl-C */
     554
     555    if (line_buffer[sz-1] == '\n')
     556        line_buffer[--sz] = '\0';
     557
     558    line_ptr = line_buffer;
     559    while (*line_ptr != '\0' && (unsigned char)*line_ptr <= ' ')
     560        line_ptr++;
     561    return *line_ptr;
     562}
     563
     564static void
     565set_all_unchanged(void)
     566{
     567    int i;
     568
     569    for (i = 0; i < MAXIMUM_PARTS; i++)
     570        ptes[i].changed = 0;
     571}
     572
     573static ALWAYS_INLINE void
     574set_changed(int i)
     575{
     576    ptes[i].changed = 1;
     577}
     578
    431579static ALWAYS_INLINE void
    432580write_part_table_flag(char *b)
     
    439587read_nonempty(const char *mesg)
    440588{
    441     while (!read_line(mesg)) /* repeat */;
     589    while (!read_line(mesg))
     590        continue;
    442591    return *line_ptr;
    443592}
     
    460609    while (1) {
    461610        read_nonempty("Hex code (type L to list codes): ");
    462         if (*line_ptr == 'l' || *line_ptr == 'L') {
     611        if ((line_ptr[0] | 0x20) == 'l') {
    463612            list_types(sys);
    464613            continue;
    465614        }
    466615        v = bb_strtoul(line_ptr, NULL, 16);
    467         if (v > 0xff)
    468             /* Bad input also triggers this */
    469             continue;
    470         return v;
    471     }
     616        if (v <= 0xff)
     617            return v;
     618    }
     619}
     620
     621static void
     622write_sector(sector_t secno, const void *buf)
     623{
     624    seek_sector(secno);
     625    xwrite(dev_fd, buf, sector_size);
    472626}
    473627#endif /* FEATURE_FDISK_WRITABLE */
    474628
     629
    475630#include "fdisk_aix.c"
    476631
    477 typedef struct {
     632struct sun_partition {
    478633    unsigned char info[128];   /* Informative text string */
    479634    unsigned char spare0[14];
     
    501656    unsigned short magic;      /* Magic number */
    502657    unsigned short csum;       /* Label xor'd checksum */
    503 } sun_partition;
     658} FIX_ALIASING;
     659typedef struct sun_partition sun_partition;
    504660#define sunlabel ((sun_partition *)MBRbuffer)
    505661STATIC_OSF void bsd_select(void);
    506662STATIC_OSF void xbsd_print_disklabel(int);
    507663#include "fdisk_osf.c"
     664
     665STATIC_GPT void gpt_list_table(int xtra);
     666#include "fdisk_gpt.c"
    508667
    509668#if ENABLE_FEATURE_SGI_LABEL || ENABLE_FEATURE_SUN_LABEL
     
    561720#include "fdisk_sun.c"
    562721
     722
     723static inline_if_little_endian unsigned
     724read4_little_endian(const unsigned char *cp)
     725{
     726    uint32_t v;
     727    move_from_unaligned32(v, cp);
     728    return SWAP_LE32(v);
     729}
     730
     731static sector_t
     732get_start_sect(const struct partition *p)
     733{
     734    return read4_little_endian(p->start4);
     735}
     736
     737static sector_t
     738get_nr_sects(const struct partition *p)
     739{
     740    return read4_little_endian(p->size4);
     741}
     742
    563743#if ENABLE_FEATURE_FDISK_WRITABLE
    564744/* start_sect and nr_sects are stored little endian on all machines */
    565745/* moreover, they are not aligned correctly */
    566 static void
     746static inline_if_little_endian void
    567747store4_little_endian(unsigned char *cp, unsigned val)
    568748{
    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 
    576 static unsigned
    577 read4_little_endian(const unsigned char *cp)
    578 {
    579     return cp[0] + (cp[1] << 8) + (cp[2] << 16) + (cp[3] << 24);
    580 }
    581 
    582 #if ENABLE_FEATURE_FDISK_WRITABLE
     749    uint32_t v = SWAP_LE32(val);
     750    move_to_unaligned32(cp, v);
     751}
     752
    583753static void
    584754set_start_sect(struct partition *p, unsigned start_sect)
     
    586756    store4_little_endian(p->start4, start_sect);
    587757}
    588 #endif
    589 
    590 static unsigned
    591 get_start_sect(const struct partition *p)
    592 {
    593     return read4_little_endian(p->start4);
    594 }
    595 
    596 #if ENABLE_FEATURE_FDISK_WRITABLE
     758
    597759static void
    598760set_nr_sects(struct partition *p, unsigned nr_sects)
     
    602764#endif
    603765
    604 static unsigned
    605 get_nr_sects(const struct partition *p)
    606 {
    607     return read4_little_endian(p->size4);
    608 }
    609 
    610 /* normally O_RDWR, -l option gives O_RDONLY */
    611 static int type_open = O_RDWR;
    612 
    613 static int ext_index;               /* the prime extended partition */
    614 static int listing;                 /* no aborts for fdisk -l */
    615 static int dos_compatible_flag = ~0;
    616 #if ENABLE_FEATURE_FDISK_WRITABLE
    617 static int dos_changed;
    618 static int nowarn;            /* no warnings for fdisk -l/-s */
    619 #endif
    620 
    621 static unsigned user_cylinders, user_heads, user_sectors;
    622 static unsigned pt_heads, pt_sectors;
    623 static unsigned kern_heads, kern_sectors;
    624 
    625 static ullong extended_offset;            /* offset of link pointers */
    626 static ullong total_number_of_sectors;
    627 
    628 static void fdisk_fatal(const char *why)
    629 {
    630     if (listing) {
    631         close(fd);
    632         longjmp(listingbuf, 1);
    633     }
    634     bb_error_msg_and_die(why, disk_device);
    635 }
    636 
    637 static void
    638 seek_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)
    643         fdisk_fatal(unable_to_seek);
    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
    654 static void
    655 write_sector(ullong secno, char *buf)
    656 {
    657     seek_sector(secno);
    658     if (write(fd, buf, sector_size) != sector_size)
    659         fdisk_fatal(unable_to_write);
    660 }
    661 #endif
    662 
    663766/* Allocate a buffer and read a partition table sector */
    664767static void
    665 read_pte(struct pte *pe, ullong offset)
    666 {
    667     pe->offset = offset;
    668     pe->sectorbuffer = xmalloc(sector_size);
     768read_pte(struct pte *pe, sector_t offset)
     769{
     770    pe->offset_from_dev_start = offset;
     771    pe->sectorbuffer = xzalloc(sector_size);
    669772    seek_sector(offset);
    670     if (read(fd, pe->sectorbuffer, sector_size) != sector_size)
     773    /* xread would make us abort - bad for fdisk -l */
     774    if (full_read(dev_fd, pe->sectorbuffer, sector_size) != sector_size)
    671775        fdisk_fatal(unable_to_read);
    672776#if ENABLE_FEATURE_FDISK_WRITABLE
     
    676780}
    677781
    678 static unsigned
    679 get_partition_start(const struct pte *pe)
    680 {
    681     return pe->offset + get_start_sect(pe->part_table);
     782static sector_t
     783get_partition_start_from_dev_start(const struct pte *pe)
     784{
     785    return pe->offset_from_dev_start + get_start_sect(pe->part_table);
    682786}
    683787
     
    689793 * for "is probably nondos partition".
    690794 */
     795#ifdef UNUSED
    691796static int
    692797is_dos_partition(int t)
     
    698803        t == 0xc1 || t == 0xc4 || t == 0xc6);
    699804}
     805#endif
    700806
    701807static void
     
    738844    } else if (LABEL_IS_AIX) {
    739845        puts("o\tcreate a new empty DOS partition table");
     846        puts("q\tquit without saving changes");
     847        puts("s\tcreate a new empty Sun disklabel");  /* sun */
     848    } else if (LABEL_IS_GPT) {
     849        puts("o\tcreate a new empty DOS partition table");
     850        puts("p\tprint the partition table");
    740851        puts("q\tquit without saving changes");
    741852        puts("s\tcreate a new empty Sun disklabel");  /* sun */
     
    840951#else
    841952#define get_sys_types() i386_sys_types
    842 #endif /* FEATURE_FDISK_WRITABLE */
     953#endif
    843954
    844955static const char *
     
    855966}
    856967
     968static int
     969is_cleared_partition(const struct partition *p)
     970{
     971    /* We consider partition "cleared" only if it has only zeros */
     972    const char *cp = (const char *)p;
     973    int cnt = sizeof(*p);
     974    char bits = 0;
     975    while (--cnt >= 0)
     976        bits |= *cp++;
     977    return (bits == 0);
     978}
     979
     980static void
     981clear_partition(struct partition *p)
     982{
     983    if (p)
     984        memset(p, 0, sizeof(*p));
     985}
    857986
    858987#if ENABLE_FEATURE_FDISK_WRITABLE
     
    8741003    int i;
    8751004
    876     for (size = 0; sys[size]; size++) /* */;
     1005    for (size = 0; sys[size]; size++)
     1006        continue;
    8771007
    8781008    done = 0;
     
    8931023        }
    8941024    } while (done < last[0]);
    895     putchar('\n');
    896 }
    897 #endif /* FEATURE_FDISK_WRITABLE */
    898 
    899 static int
    900 is_cleared_partition(const struct partition *p)
    901 {
    902     return !(!p || p->boot_ind || p->head || p->sector || p->cyl ||
    903          p->sys_ind || p->end_head || p->end_sector || p->end_cyl ||
    904          get_start_sect(p) || get_nr_sects(p));
    905 }
    906 
    907 static void
    908 clear_partition(struct partition *p)
    909 {
    910     if (!p)
    911         return;
    912     memset(p, 0, sizeof(struct partition));
    913 }
    914 
    915 #if ENABLE_FEATURE_FDISK_WRITABLE
    916 static void
    917 set_partition(int i, int doext, ullong start, ullong stop, int sysid)
     1025    bb_putchar('\n');
     1026}
     1027
     1028#define set_hsc(h, s, c, sector) do \
     1029{ \
     1030    s = sector % g_sectors + 1;  \
     1031    sector /= g_sectors;         \
     1032    h = sector % g_heads;        \
     1033    sector /= g_heads;           \
     1034    c = sector & 0xff;           \
     1035    s |= (sector >> 2) & 0xc0;   \
     1036} while (0)
     1037
     1038static void set_hsc_start_end(struct partition *p, sector_t start, sector_t stop)
     1039{
     1040    if (dos_compatible_flag && (start / (g_sectors * g_heads) > 1023))
     1041        start = g_heads * g_sectors * 1024 - 1;
     1042    set_hsc(p->head, p->sector, p->cyl, start);
     1043
     1044    if (dos_compatible_flag && (stop / (g_sectors * g_heads) > 1023))
     1045        stop = g_heads * g_sectors * 1024 - 1;
     1046    set_hsc(p->end_head, p->end_sector, p->end_cyl, stop);
     1047}
     1048
     1049static void
     1050set_partition(int i, int doext, sector_t start, sector_t stop, int sysid)
    9181051{
    9191052    struct partition *p;
    920     ullong offset;
     1053    sector_t offset;
    9211054
    9221055    if (doext) {
     
    9251058    } else {
    9261059        p = ptes[i].part_table;
    927         offset = ptes[i].offset;
     1060        offset = ptes[i].offset_from_dev_start;
    9281061    }
    9291062    p->boot_ind = 0;
     
    9311064    set_start_sect(p, start - offset);
    9321065    set_nr_sects(p, stop - start + 1);
    933     if (dos_compatible_flag && (start/(sectors*heads) > 1023))
    934         start = heads*sectors*1024 - 1;
    935     set_hsc(p->head, p->sector, p->cyl, start);
    936     if (dos_compatible_flag && (stop/(sectors*heads) > 1023))
    937         stop = heads*sectors*1024 - 1;
    938     set_hsc(p->end_head, p->end_sector, p->end_cyl, stop);
     1066    set_hsc_start_end(p, start, stop);
    9391067    ptes[i].changed = 1;
    9401068}
     
    9441072warn_geometry(void)
    9451073{
    946     if (heads && sectors && cylinders)
     1074    if (g_heads && g_sectors && g_cylinders)
    9471075        return 0;
    9481076
    9491077    printf("Unknown value(s) for:");
    950     if (!heads)
     1078    if (!g_heads)
    9511079        printf(" heads");
    952     if (!sectors)
     1080    if (!g_sectors)
    9531081        printf(" sectors");
    954     if (!cylinders)
     1082    if (!g_cylinders)
    9551083        printf(" cylinders");
    9561084    printf(
     
    9651093update_units(void)
    9661094{
    967     int cyl_units = heads * sectors;
     1095    int cyl_units = g_heads * g_sectors;
    9681096
    9691097    if (display_in_cyl_units && cyl_units)
     
    9771105warn_cylinders(void)
    9781106{
    979     if (LABEL_IS_DOS && cylinders > 1024 && !nowarn)
     1107    if (LABEL_IS_DOS && g_cylinders > 1024 && !nowarn)
    9801108        printf("\n"
    981 "The number of cylinders for this disk is set to %d.\n"
     1109"The number of cylinders for this disk is set to %u.\n"
    9821110"There is nothing wrong with that, but this is larger than 1024,\n"
    9831111"and could in certain setups cause problems with:\n"
     
    9851113"2) booting and partitioning software from other OSs\n"
    9861114"   (e.g., DOS FDISK, OS/2 FDISK)\n",
    987             cylinders);
     1115            g_cylinders);
    9881116}
    9891117#endif
     
    10071135
    10081136    while (IS_EXTENDED(p->sys_ind)) {
    1009         struct pte *pe = &ptes[partitions];
    1010 
    1011         if (partitions >= MAXIMUM_PARTS) {
     1137        struct pte *pe = &ptes[g_partitions];
     1138
     1139        if (g_partitions >= MAXIMUM_PARTS) {
    10121140            /* This is not a Linux restriction, but
    10131141               this program uses arrays of size MAXIMUM_PARTS.
    10141142               Do not try to 'improve' this test. */
    1015             struct pte *pre = &ptes[partitions-1];
     1143            struct pte *pre = &ptes[g_partitions - 1];
    10161144#if ENABLE_FEATURE_FDISK_WRITABLE
    1017             printf("Warning: deleting partitions after %d\n",
    1018                 partitions);
     1145            printf("Warning: deleting partitions after %u\n",
     1146                g_partitions);
    10191147            pre->changed = 1;
    10201148#endif
     
    10341162                    printf("Warning: extra link "
    10351163                        "pointer in partition table"
    1036                         " %d\n", partitions + 1);
     1164                        " %u\n", g_partitions + 1);
    10371165                else
    10381166                    pe->ext_pointer = p;
     
    10411169                    printf("Warning: ignoring extra "
    10421170                          "data in partition table"
    1043                           " %d\n", partitions + 1);
     1171                          " %u\n", g_partitions + 1);
    10441172                else
    10451173                    pe->part_table = p;
     
    10621190
    10631191        p = pe->ext_pointer;
    1064         partitions++;
     1192        g_partitions++;
    10651193    }
    10661194
     
    10681196    /* remove empty links */
    10691197 remove:
    1070     for (i = 4; i < partitions; i++) {
     1198    for (i = 4; i < g_partitions; i++) {
    10711199        struct pte *pe = &ptes[i];
    10721200
    10731201        if (!get_nr_sects(pe->part_table)
    1074          && (partitions > 5 || ptes[4].part_table->sys_ind)
     1202         && (g_partitions > 5 || ptes[4].part_table->sys_ind)
    10751203        ) {
    1076             printf("Omitting empty partition (%d)\n", i+1);
     1204            printf("Omitting empty partition (%u)\n", i+1);
    10771205            delete_partition(i);
    10781206            goto remove;    /* numbering changed */
     
    10861214create_doslabel(void)
    10871215{
    1088     int i;
    1089 
    10901216    printf(msg_building_new_label, "DOS disklabel");
    10911217
    1092     current_label_type = label_dos;
    1093 
     1218    current_label_type = LABEL_DOS;
    10941219#if ENABLE_FEATURE_OSF_LABEL
    10951220    possibly_osf_label = 0;
    10961221#endif
    1097     partitions = 4;
    1098 
    1099     for (i = 510-64; i < 510; i++)
    1100         MBRbuffer[i] = 0;
     1222    g_partitions = 4;
     1223
     1224    memset(&MBRbuffer[510 - 4*16], 0, 4*16);
    11011225    write_part_table_flag(MBRbuffer);
    11021226    extended_offset = 0;
    11031227    set_all_unchanged();
    11041228    set_changed(0);
    1105     get_boot(create_empty_dos);
    1106 }
    1107 #endif /* FEATURE_FDISK_WRITABLE */
     1229    get_boot(CREATE_EMPTY_DOS);
     1230}
     1231#endif
    11081232
    11091233static void
     
    11121236    if (!user_set_sector_size) {
    11131237        int arg;
    1114         if (ioctl(fd, BLKSSZGET, &arg) == 0)
     1238        if (ioctl(dev_fd, BLKSSZGET, &arg) == 0)
    11151239            sector_size = arg;
    11161240        if (sector_size != DEFAULT_SECTOR_SIZE)
    1117             printf("Note: sector size is %d (not %d)\n",
    1118                    sector_size, DEFAULT_SECTOR_SIZE);
     1241            printf("Note: sector size is %u "
     1242                "(not " DEFAULT_SECTOR_SIZE_STR ")\n",
     1243                sector_size);
    11191244    }
    11201245}
     
    11251250    struct hd_geometry geometry;
    11261251
    1127     if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
     1252    if (!ioctl(dev_fd, HDIO_GETGEO, &geometry)) {
    11281253        kern_heads = geometry.heads;
    11291254        kern_sectors = geometry.sectors;
     
    11691294{
    11701295    int sec_fac;
    1171     uint64_t v64;
    11721296
    11731297    get_sectorsize();
     
    11761300    guess_device_type();
    11771301#endif
    1178     heads = cylinders = sectors = 0;
     1302    g_heads = g_cylinders = g_sectors = 0;
    11791303    kern_heads = kern_sectors = 0;
    11801304    pt_heads = pt_sectors = 0;
     
    11831307    get_partition_table_geometry();
    11841308
    1185     heads = user_heads ? user_heads :
     1309    g_heads = user_heads ? user_heads :
    11861310        pt_heads ? pt_heads :
    11871311        kern_heads ? kern_heads : 255;
    1188     sectors = user_sectors ? user_sectors :
     1312    g_sectors = user_sectors ? user_sectors :
    11891313        pt_sectors ? pt_sectors :
    11901314        kern_sectors ? kern_sectors : 63;
    1191     if (ioctl(fd, BLKGETSIZE64, &v64) == 0) {
    1192         /* got bytes, convert to 512 byte sectors */
    1193         total_number_of_sectors = (v64 >> 9);
    1194     } else {
    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     }
     1315    total_number_of_sectors = bb_BLKGETSIZE_sectors(dev_fd);
    12001316
    12011317    sector_offset = 1;
    12021318    if (dos_compatible_flag)
    1203         sector_offset = sectors;
    1204 
    1205     cylinders = total_number_of_sectors / (heads * sectors * sec_fac);
    1206     if (!cylinders)
    1207         cylinders = user_cylinders;
     1319        sector_offset = g_sectors;
     1320
     1321    g_cylinders = total_number_of_sectors / (g_heads * g_sectors * sec_fac);
     1322    if (!g_cylinders)
     1323        g_cylinders = user_cylinders;
    12081324}
    12091325
    12101326/*
    1211  * Read MBR.  Returns:
     1327 * Opens disk_device and optionally reads MBR.
     1328 *    If what == OPEN_MAIN:
     1329 *      Open device, read MBR.  Abort program on short read.  Create empty
     1330 *      disklabel if the on-disk structure is invalid (WRITABLE mode).
     1331 *    If what == TRY_ONLY:
     1332 *      Open device, read MBR.  Return an error if anything is out of place.
     1333 *      Do not create an empty disklabel.  This is used for the "list"
     1334 *      operations: "fdisk -l /dev/sda" and "fdisk -l" (all devices).
     1335 *    If what == CREATE_EMPTY_*:
     1336 *      This means that get_boot() was called recursively from create_*label().
     1337 *      Do not re-open the device; just set up the ptes array and print
     1338 *      geometry warnings.
     1339 *
     1340 * Returns:
    12121341 *   -1: no 0xaa55 flag present (possibly entire disk BSD)
    12131342 *    0: found or created label
    12141343 *    1: I/O error
    12151344 */
    1216 static int
    1217 get_boot(enum action what)
    1218 {
    1219     int i;
    1220 
    1221     partitions = 4;
    1222 
     1345#if ENABLE_FEATURE_SUN_LABEL || ENABLE_FEATURE_FDISK_WRITABLE
     1346static int get_boot(enum action what)
     1347#else
     1348static int get_boot(void)
     1349#define get_boot(what) get_boot()
     1350#endif
     1351{
     1352    int i, fd;
     1353
     1354    g_partitions = 4;
    12231355    for (i = 0; i < 4; i++) {
    12241356        struct pte *pe = &ptes[i];
    1225 
    12261357        pe->part_table = pt_offset(MBRbuffer, i);
    12271358        pe->ext_pointer = NULL;
    1228         pe->offset = 0;
     1359        pe->offset_from_dev_start = 0;
    12291360        pe->sectorbuffer = MBRbuffer;
    12301361#if ENABLE_FEATURE_FDISK_WRITABLE
    1231         pe->changed = (what == create_empty_dos);
    1232 #endif
    1233     }
    1234 
    1235 #if ENABLE_FEATURE_SUN_LABEL
    1236     if (what == create_empty_sun && check_sun_label())
    1237         return 0;
    1238 #endif
    1239 
    1240     memset(MBRbuffer, 0, 512);
     1362        pe->changed = (what == CREATE_EMPTY_DOS);
     1363#endif
     1364    }
    12411365
    12421366#if ENABLE_FEATURE_FDISK_WRITABLE
    1243     if (what == create_empty_dos)
    1244         goto got_dos_table;             /* skip reading disk */
    1245 
    1246     fd = open(disk_device, type_open);
     1367// ALERT! highly idiotic design!
     1368// We end up here when we call get_boot() recursively
     1369// via get_boot() [table is bad] -> create_doslabel() -> get_boot(CREATE_EMPTY_DOS).
     1370// or get_boot() [table is bad] -> create_sunlabel() -> get_boot(CREATE_EMPTY_SUN).
     1371// (just factor out re-init of ptes[0,1,2,3] in a separate fn instead?)
     1372// So skip opening device _again_...
     1373    if (what == CREATE_EMPTY_DOS  IF_FEATURE_SUN_LABEL(|| what == CREATE_EMPTY_SUN))
     1374        goto created_table;
     1375
     1376    fd = open(disk_device, (option_mask32 & OPT_l) ? O_RDONLY : O_RDWR);
     1377
    12471378    if (fd < 0) {
    12481379        fd = open(disk_device, O_RDONLY);
    12491380        if (fd < 0) {
    1250             if (what == try_only)
     1381            if (what == TRY_ONLY)
    12511382                return 1;
    12521383            fdisk_fatal(unable_to_open);
    1253         } else
    1254             printf("You will not be able to write "
    1255                 "the partition table\n");
    1256     }
    1257 
    1258     if (512 != read(fd, MBRbuffer, 512)) {
    1259         if (what == try_only)
     1384        }
     1385        printf("'%s' is opened for read only\n", disk_device);
     1386    }
     1387    xmove_fd(fd, dev_fd);
     1388    if (512 != full_read(dev_fd, MBRbuffer, 512)) {
     1389        if (what == TRY_ONLY) {
     1390            close_dev_fd();
    12601391            return 1;
     1392        }
    12611393        fdisk_fatal(unable_to_read);
    12621394    }
     
    12651397    if (fd < 0)
    12661398        return 1;
    1267     if (512 != read(fd, MBRbuffer, 512))
     1399    if (512 != full_read(fd, MBRbuffer, 512)) {
     1400        close(fd);
    12681401        return 1;
     1402    }
     1403    xmove_fd(fd, dev_fd);
    12691404#endif
    12701405
    12711406    get_geometry();
    1272 
    12731407    update_units();
    12741408
     
    12771411        return 0;
    12781412#endif
    1279 
    12801413#if ENABLE_FEATURE_SGI_LABEL
    12811414    if (check_sgi_label())
    12821415        return 0;
    12831416#endif
    1284 
    12851417#if ENABLE_FEATURE_AIX_LABEL
    12861418    if (check_aix_label())
    12871419        return 0;
    12881420#endif
    1289 
     1421#if ENABLE_FEATURE_GPT_LABEL
     1422    if (check_gpt_label())
     1423        return 0;
     1424#endif
    12901425#if ENABLE_FEATURE_OSF_LABEL
    12911426    if (check_osf_label()) {
    12921427        possibly_osf_label = 1;
    12931428        if (!valid_part_table_flag(MBRbuffer)) {
    1294             current_label_type = label_osf;
     1429            current_label_type = LABEL_OSF;
    12951430            return 0;
    12961431        }
     
    13001435#endif
    13011436
    1302 #if ENABLE_FEATURE_FDISK_WRITABLE
    1303  got_dos_table:
    1304 #endif
    1305 
    1306     if (!valid_part_table_flag(MBRbuffer)) {
    13071437#if !ENABLE_FEATURE_FDISK_WRITABLE
     1438    if (!valid_part_table_flag(MBRbuffer))
    13081439        return -1;
    13091440#else
    1310         switch (what) {
    1311         case fdisk:
     1441    if (!valid_part_table_flag(MBRbuffer)) {
     1442        if (what == OPEN_MAIN) {
    13121443            printf("Device contains neither a valid DOS "
    1313                   "partition table, nor Sun, SGI or OSF "
     1444                  "partition table, nor Sun, SGI, OSF or GPT "
    13141445                  "disklabel\n");
    13151446#ifdef __sparc__
    1316 #if ENABLE_FEATURE_SUN_LABEL
    1317             create_sunlabel();
    1318 #endif
     1447            IF_FEATURE_SUN_LABEL(create_sunlabel();)
    13191448#else
    13201449            create_doslabel();
    13211450#endif
    13221451            return 0;
    1323         case try_only:
    1324             return -1;
    1325         case create_empty_dos:
    1326 #if ENABLE_FEATURE_SUN_LABEL
    1327         case create_empty_sun:
    1328 #endif
    1329             break;
    1330         default:
    1331             bb_error_msg_and_die("internal error");
    1332         }
     1452        }
     1453        /* TRY_ONLY: */
     1454        return -1;
     1455    }
     1456 created_table:
    13331457#endif /* FEATURE_FDISK_WRITABLE */
    1334     }
    1335 
    1336 #if ENABLE_FEATURE_FDISK_WRITABLE
    1337     warn_cylinders();
    1338 #endif
     1458
     1459
     1460    IF_FEATURE_FDISK_WRITABLE(warn_cylinders();)
    13391461    warn_geometry();
    13401462
    13411463    for (i = 0; i < 4; i++) {
    1342         struct pte *pe = &ptes[i];
    1343 
    1344         if (IS_EXTENDED(pe->part_table->sys_ind)) {
    1345             if (partitions != 4)
     1464        if (IS_EXTENDED(ptes[i].part_table->sys_ind)) {
     1465            if (g_partitions != 4)
    13461466                printf("Ignoring extra extended "
    1347                     "partition %d\n", i + 1);
     1467                    "partition %u\n", i + 1);
    13481468            else
    13491469                read_extended(i);
     
    13511471    }
    13521472
    1353     for (i = 3; i < partitions; i++) {
     1473    for (i = 3; i < g_partitions; i++) {
    13541474        struct pte *pe = &ptes[i];
    1355 
    13561475        if (!valid_part_table_flag(pe->sectorbuffer)) {
    13571476            printf("Warning: invalid flag 0x%02x,0x%02x of partition "
    1358                 "table %d will be corrected by w(rite)\n",
     1477                "table %u will be corrected by w(rite)\n",
    13591478                pe->sectorbuffer[510],
    13601479                pe->sectorbuffer[511],
    13611480                i + 1);
    1362 #if ENABLE_FEATURE_FDISK_WRITABLE
    1363             pe->changed = 1;
    1364 #endif
     1481            IF_FEATURE_FDISK_WRITABLE(pe->changed = 1;)
    13651482        }
    13661483    }
     
    13771494 * There is no default if DFLT is not between LOW and HIGH.
    13781495 */
    1379 static unsigned
    1380 read_int(unsigned low, unsigned dflt, unsigned high, unsigned base, const char *mesg)
    1381 {
    1382     unsigned i;
     1496static sector_t
     1497read_int(sector_t low, sector_t dflt, sector_t high, sector_t base, const char *mesg)
     1498{
     1499    sector_t value;
    13831500    int default_ok = 1;
    13841501    const char *fmt = "%s (%u-%u, default %u): ";
     
    14031520            int absolute = 0;
    14041521
    1405             i = atoi(line_ptr + 1);
    1406 
     1522            value = atoi(line_ptr + 1);
     1523
     1524            /* (1) if 2nd char is digit, use_default = 0.
     1525             * (2) move line_ptr to first non-digit. */
    14071526            while (isdigit(*++line_ptr))
    14081527                use_default = 0;
     
    14121531            case 'C':
    14131532                if (!display_in_cyl_units)
    1414                     i *= heads * sectors;
     1533                    value *= g_heads * g_sectors;
    14151534                break;
    14161535            case 'K':
     
    14351554                unsigned long unit;
    14361555
    1437                 bytes = (ullong) i * absolute;
     1556                bytes = (ullong) value * absolute;
    14381557                unit = sector_size * units_per_sector;
    14391558                bytes += unit/2; /* round */
    14401559                bytes /= unit;
    1441                 i = bytes;
     1560                value = bytes;
    14421561            }
    14431562            if (minus)
    1444                 i = -i;
    1445             i += base;
     1563                value = -value;
     1564            value += base;
    14461565        } else {
    1447             i = atoi(line_ptr);
     1566            value = atoi(line_ptr);
    14481567            while (isdigit(*line_ptr)) {
    14491568                line_ptr++;
     
    14521571        }
    14531572        if (use_default) {
    1454             i = dflt;
    1455             printf("Using default value %u\n", i);
    1456         }
    1457         if (i >= low && i <= high)
     1573            value = dflt;
     1574            printf("Using default value %u\n", value);
     1575        }
     1576        if (value >= low && value <= high)
    14581577            break;
    14591578        printf("Value is out of range\n");
    14601579    }
    1461     return i;
    1462 }
    1463 
    1464 static int
    1465 get_partition(int warn, int max)
     1580    return value;
     1581}
     1582
     1583static unsigned
     1584get_partition(int warn, unsigned max)
    14661585{
    14671586    struct pte *pe;
    1468     int i;
     1587    unsigned i;
    14691588
    14701589    i = read_int(1, 0, max, 0, "Partition number") - 1;
     
    14761595         || (LABEL_IS_SGI && !sgi_get_num_sectors(i))
    14771596        ) {
    1478             printf("Warning: partition %d has empty type\n", i+1);
     1597            printf("Warning: partition %u has empty type\n", i+1);
    14791598        }
    14801599    }
     
    14831602
    14841603static int
    1485 get_existing_partition(int warn, int max)
     1604get_existing_partition(int warn, unsigned max)
    14861605{
    14871606    int pno = -1;
    1488     int i;
     1607    unsigned i;
    14891608
    14901609    for (i = 0; i < max; i++) {
     
    14991618    }
    15001619    if (pno >= 0) {
    1501         printf("Selected partition %d\n", pno+1);
     1620        printf("Selected partition %u\n", pno+1);
    15021621        return pno;
    15031622    }
     
    15101629
    15111630static int
    1512 get_nonexisting_partition(int warn, int max)
     1631get_nonexisting_partition(int warn, unsigned max)
    15131632{
    15141633    int pno = -1;
    1515     int i;
     1634    unsigned i;
    15161635
    15171636    for (i = 0; i < max; i++) {
     
    15261645    }
    15271646    if (pno >= 0) {
    1528         printf("Selected partition %d\n", pno+1);
     1647        printf("Selected partition %u\n", pno+1);
    15291648        return pno;
    15301649    }
     
    15531672
    15541673    if (IS_EXTENDED(p->sys_ind) && !p->boot_ind)
    1555         printf("WARNING: Partition %d is an extended partition\n", i + 1);
     1674        printf("WARNING: Partition %u is an extended partition\n", i + 1);
    15561675    p->boot_ind = (p->boot_ind ? 0 : ACTIVE_FLAG);
    15571676    pe->changed = 1;
     
    15611680toggle_dos_compatibility_flag(void)
    15621681{
    1563     dos_compatible_flag = ~dos_compatible_flag;
     1682    dos_compatible_flag = 1 - dos_compatible_flag;
    15641683    if (dos_compatible_flag) {
    1565         sector_offset = sectors;
     1684        sector_offset = g_sectors;
    15661685        printf("DOS Compatibility flag is set\n");
    15671686    } else {
     
    15971716    if (i < 4) {
    15981717        if (IS_EXTENDED(p->sys_ind) && i == ext_index) {
    1599             partitions = 4;
     1718            g_partitions = 4;
    16001719            ptes[ext_index].ext_pointer = NULL;
    16011720            extended_offset = 0;
     
    16071726    if (!q->sys_ind && i > 4) {
    16081727        /* the last one in the chain - just delete */
    1609         --partitions;
     1728        --g_partitions;
    16101729        --i;
    16111730        clear_partition(ptes[i].ext_pointer);
     
    16201739            set_nr_sects(p, get_nr_sects(q));
    16211740            ptes[i-1].changed = 1;
    1622         } else if (partitions > 5) {    /* 5 will be moved to 4 */
     1741        } else if (g_partitions > 5) {    /* 5 will be moved to 4 */
    16231742            /* the first logical in a longer chain */
    16241743            pe = &ptes[5];
     
    16261745            if (pe->part_table) /* prevent SEGFAULT */
    16271746                set_start_sect(pe->part_table,
    1628                            get_partition_start(pe) -
    1629                            extended_offset);
    1630             pe->offset = extended_offset;
     1747                        get_partition_start_from_dev_start(pe) -
     1748                        extended_offset);
     1749            pe->offset_from_dev_start = extended_offset;
    16311750            pe->changed = 1;
    16321751        }
    16331752
    1634         if (partitions > 5) {
    1635             partitions--;
    1636             while (i < partitions) {
     1753        if (g_partitions > 5) {
     1754            g_partitions--;
     1755            while (i < g_partitions) {
    16371756                ptes[i] = ptes[i+1];
    16381757                i++;
    16391758            }
    1640         } else
     1759        } else {
    16411760            /* the only logical: clear only */
    16421761            clear_partition(ptes[i].part_table);
     1762        }
    16431763    }
    16441764}
     
    16541774       only works for Linux like partition tables. */
    16551775    if (!LABEL_IS_SGI) {
    1656         i = get_existing_partition(0, partitions);
     1776        i = get_existing_partition(0, g_partitions);
    16571777    } else {
    1658         i = get_partition(0, partitions);
     1778        i = get_partition(0, g_partitions);
    16591779    }
    16601780    if (i == -1)
     
    16661786       the reverse change must be allowed, too */
    16671787    if (!sys && !LABEL_IS_SGI && !LABEL_IS_SUN && !get_nr_sects(p)) {
    1668         printf("Partition %d does not exist yet!\n", i + 1);
     1788        printf("Partition %u does not exist yet!\n", i + 1);
    16691789        return;
    16701790    }
     
    17171837                p->sys_ind = sys;
    17181838
    1719             printf("Changed system type of partition %d "
     1839            printf("Changed system type of partition %u "
    17201840                "to %x (%s)\n", i + 1, sys,
    17211841                partition_type(sys));
    17221842            ptes[i].changed = 1;
    1723             if (is_dos_partition(origsys) ||
    1724                 is_dos_partition(sys))
    1725                 dos_changed = 1;
     1843            //if (is_dos_partition(origsys) || is_dos_partition(sys))
     1844            //  dos_changed = 1;
    17261845            break;
    17271846        }
     
    17391858linear2chs(unsigned ls, unsigned *c, unsigned *h, unsigned *s)
    17401859{
    1741     int spc = heads * sectors;
     1860    int spc = g_heads * g_sectors;
    17421861
    17431862    *c = ls / spc;
    17441863    ls = ls % spc;
    1745     *h = ls / sectors;
    1746     *s = ls % sectors + 1;  /* sectors count from 1 */
     1864    *h = ls / g_sectors;
     1865    *s = ls % g_sectors + 1;  /* sectors count from 1 */
    17471866}
    17481867
     
    17551874    unsigned lec, leh, les;          /* logical ending c, h, s */
    17561875
    1757     if (!heads || !sectors || (partition >= 4))
     1876    if (!g_heads || !g_sectors || (partition >= 4))
    17581877        return;         /* do not check extended partitions */
    17591878
     
    17751894
    17761895/* Same physical / logical beginning? */
    1777     if (cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) {
    1778         printf("Partition %d has different physical/logical "
     1896    if (g_cylinders <= 1024 && (pbc != lbc || pbh != lbh || pbs != lbs)) {
     1897        printf("Partition %u has different physical/logical "
    17791898            "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);
     1899        printf("     phys=(%u, %u, %u) ", pbc, pbh, pbs);
     1900        printf("logical=(%u, %u, %u)\n", lbc, lbh, lbs);
    17821901    }
    17831902
    17841903/* Same physical / logical ending? */
    1785     if (cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) {
    1786         printf("Partition %d has different physical/logical "
     1904    if (g_cylinders <= 1024 && (pec != lec || peh != leh || pes != les)) {
     1905        printf("Partition %u has different physical/logical "
    17871906            "endings:\n", partition + 1);
    1788         printf("     phys=(%d, %d, %d) ", pec, peh, pes);
    1789         printf("logical=(%d, %d, %d)\n", lec, leh, les);
     1907        printf("     phys=(%u, %u, %u) ", pec, peh, pes);
     1908        printf("logical=(%u, %u, %u)\n", lec, leh, les);
    17901909    }
    17911910
    17921911/* Ending on cylinder boundary? */
    1793     if (peh != (heads - 1) || pes != sectors) {
    1794         printf("Partition %i does not end on cylinder boundary\n",
     1912    if (peh != (g_heads - 1) || pes != g_sectors) {
     1913        printf("Partition %u does not end on cylinder boundary\n",
    17951914            partition + 1);
    17961915    }
     
    18001919list_disk_geometry(void)
    18011920{
    1802     long long bytes = (total_number_of_sectors << 9);
    1803     long megabytes = bytes/1000000;
     1921    ullong bytes = ((ullong)total_number_of_sectors << 9);
     1922    long megabytes = bytes / 1000000;
    18041923
    18051924    if (megabytes < 10000)
    1806         printf("\nDisk %s: %ld MB, %lld bytes\n",
    1807                disk_device, megabytes, bytes);
     1925        printf("\nDisk %s: %lu MB, %llu bytes\n",
     1926            disk_device, megabytes, bytes);
    18081927    else
    1809         printf("\nDisk %s: %ld.%ld GB, %lld bytes\n",
    1810                disk_device, megabytes/1000, (megabytes/100)%10, bytes);
    1811     printf("%d heads, %d sectors/track, %d cylinders",
    1812            heads, sectors, cylinders);
     1928        printf("\nDisk %s: %lu.%lu GB, %llu bytes\n",
     1929            disk_device, megabytes/1000, (megabytes/100)%10, bytes);
     1930    printf("%u heads, %u sectors/track, %u cylinders",
     1931           g_heads, g_sectors, g_cylinders);
    18131932    if (units_per_sector == 1)
    1814         printf(", total %llu sectors",
    1815                total_number_of_sectors / (sector_size/512));
    1816     printf("\nUnits = %s of %d * %d = %d bytes\n\n",
    1817            str_units(PLURAL),
    1818            units_per_sector, sector_size, units_per_sector * sector_size);
     1933        printf(", total %"SECT_FMT"u sectors",
     1934            total_number_of_sectors / (sector_size/512));
     1935    printf("\nUnits = %s of %u * %u = %u bytes\n\n",
     1936        str_units(PLURAL),
     1937        units_per_sector, sector_size, units_per_sector * sector_size);
    18191938}
    18201939
     
    18291948    const struct pte *pe;
    18301949    const struct partition *p;
    1831     ullong last_p_start_pos = 0, p_start_pos;
    1832     int i, last_i = 0;
    1833 
    1834     for (i = 0; i < partitions; i++) {
     1950    sector_t last_p_start_pos = 0, p_start_pos;
     1951    unsigned i, last_i = 0;
     1952
     1953    for (i = 0; i < g_partitions; i++) {
    18351954        if (i == 4) {
    18361955            last_i = 4;
     
    18381957        }
    18391958        pe = &ptes[i];
    1840         if ((p = pe->part_table)->sys_ind) {
    1841             p_start_pos = get_partition_start(pe);
     1959        p = pe->part_table;
     1960        if (p->sys_ind) {
     1961            p_start_pos = get_partition_start_from_dev_start(pe);
    18421962
    18431963            if (last_p_start_pos > p_start_pos) {
     
    18771997    /* (Its sector is the global extended_offset.) */
    18781998 stage1:
    1879     for (j = 5; j < partitions-1; j++) {
    1880         oj = ptes[j].offset;
    1881         ojj = ptes[j+1].offset;
     1999    for (j = 5; j < g_partitions - 1; j++) {
     2000        oj = ptes[j].offset_from_dev_start;
     2001        ojj = ptes[j+1].offset_from_dev_start;
    18822002        if (oj > ojj) {
    1883             ptes[j].offset = ojj;
    1884             ptes[j+1].offset = oj;
     2003            ptes[j].offset_from_dev_start = ojj;
     2004            ptes[j+1].offset_from_dev_start = oj;
    18852005            pj = ptes[j].part_table;
    18862006            set_start_sect(pj, get_start_sect(pj)+oj-ojj);
     
    18972017    /* Stage 2: sort starting sectors */
    18982018 stage2:
    1899     for (j = 4; j < partitions-1; j++) {
     2019    for (j = 4; j < g_partitions - 1; j++) {
    19002020        pj = ptes[j].part_table;
    19012021        pjj = ptes[j+1].part_table;
    19022022        sj = get_start_sect(pj);
    19032023        sjj = get_start_sect(pjj);
    1904         oj = ptes[j].offset;
    1905         ojj = ptes[j+1].offset;
     2024        oj = ptes[j].offset_from_dev_start;
     2025        ojj = ptes[j+1].offset_from_dev_start;
    19062026        if (oj+sj > ojj+sjj) {
    19072027            tmp = *pj;
     
    19152035
    19162036    /* Probably something was changed */
    1917     for (j = 4; j < partitions; j++)
     2037    for (j = 4; j < g_partitions; j++)
    19182038        ptes[j].changed = 1;
    19192039}
     
    19562076
    19572077    printf("Done.\n");
    1958 
    19592078}
    19602079#endif
     
    19702089        return;
    19712090    }
    1972     if (LABEL_IS_SUN) {
     2091    if (LABEL_IS_SGI) {
    19732092        sgi_list_table(xtra);
     2093        return;
     2094    }
     2095    if (LABEL_IS_GPT) {
     2096        gpt_list_table(xtra);
    19742097        return;
    19752098    }
     
    19952118           w+1, "Device");
    19962119
    1997     for (i = 0; i < partitions; i++) {
     2120    for (i = 0; i < g_partitions; i++) {
    19982121        const struct pte *pe = &ptes[i];
    1999         ullong psects;
    2000         ullong pblocks;
     2122        sector_t psects;
     2123        sector_t pblocks;
    20012124        unsigned podd;
    20022125
     
    20162139            pblocks *= (sector_size / 1024);
    20172140
    2018         printf("%s  %c %11llu %11llu %11llu%c %2x %s\n",
     2141        printf("%s  %c %11"SECT_FMT"u %11"SECT_FMT"u %11"SECT_FMT"u%c %2x %s\n",
    20192142            partname(disk_device, i+1, w+2),
    20202143            !p->boot_ind ? ' ' : p->boot_ind == ACTIVE_FLAG /* boot flag */
    20212144                ? '*' : '?',
    2022             (ullong) cround(get_partition_start(pe)),           /* start */
    2023             (ullong) cround(get_partition_start(pe) + psects    /* end */
     2145            cround(get_partition_start_from_dev_start(pe)),           /* start */
     2146            cround(get_partition_start_from_dev_start(pe) + psects    /* end */
    20242147                - (psects ? 1 : 0)),
    2025             (ullong) pblocks, podd ? '+' : ' ', /* odd flag on end */
     2148            pblocks, podd ? '+' : ' ', /* odd flag on end */
    20262149            p->sys_ind,                                     /* type id */
    20272150            partition_type(p->sys_ind));                    /* type name */
     
    20312154
    20322155    /* Is partition table in disk order? It need not be, but... */
    2033     /* partition table entries are not checked for correct order if this
    2034        is a sgi, sun or aix labeled disk... */
     2156    /* partition table entries are not checked for correct order
     2157     * if this is a sgi, sun or aix labeled disk... */
    20352158    if (LABEL_IS_DOS && wrong_p_order(NULL)) {
    20362159        /* FIXME */
     
    20472170    int i;
    20482171
    2049     printf("\nDisk %s: %d heads, %d sectors, %d cylinders\n\n",
    2050         disk_device, heads, sectors, cylinders);
     2172    printf("\nDisk %s: %u heads, %u sectors, %u cylinders\n\n",
     2173        disk_device, g_heads, g_sectors, g_cylinders);
    20512174    printf("Nr AF  Hd Sec  Cyl  Hd Sec  Cyl      Start       Size ID\n");
    2052     for (i = 0; i < partitions; i++) {
     2175    for (i = 0; i < g_partitions; i++) {
    20532176        pe = &ptes[i];
    20542177        p = (extend ? pe->ext_pointer : pe->part_table);
    20552178        if (p != NULL) {
    2056             printf("%2d %02x%4d%4d%5d%4d%4d%5d%11u%11u %02x\n",
     2179            printf("%2u %02x%4u%4u%5u%4u%4u%5u%11"SECT_FMT"u%11"SECT_FMT"u %02x\n",
    20572180                i + 1, p->boot_ind, p->head,
    20582181                sector(p->sector),
     
    20602183                sector(p->end_sector),
    20612184                cylinder(p->end_sector, p->end_cyl),
    2062                 get_start_sect(p), get_nr_sects(p), p->sys_ind);
     2185                get_start_sect(p), get_nr_sects(p),
     2186                p->sys_ind);
    20632187            if (p->sys_ind)
    20642188                check_consistency(p, i);
     
    20702194#if ENABLE_FEATURE_FDISK_WRITABLE
    20712195static void
    2072 fill_bounds(ullong *first, ullong *last)
    2073 {
    2074     int i;
     2196fill_bounds(sector_t *first, sector_t *last)
     2197{
     2198    unsigned i;
    20752199    const struct pte *pe = &ptes[0];
    20762200    const struct partition *p;
    20772201
    2078     for (i = 0; i < partitions; pe++,i++) {
     2202    for (i = 0; i < g_partitions; pe++,i++) {
    20792203        p = pe->part_table;
    20802204        if (!p->sys_ind || IS_EXTENDED(p->sys_ind)) {
     
    20822206            last[i] = 0;
    20832207        } else {
    2084             first[i] = get_partition_start(pe);
     2208            first[i] = get_partition_start_from_dev_start(pe);
    20852209            last[i] = first[i] + get_nr_sects(p) - 1;
    20862210        }
     
    20892213
    20902214static void
    2091 check(int n, unsigned h, unsigned s, unsigned c, ullong start)
    2092 {
    2093     ullong total, real_s, real_c;
     2215check(int n, unsigned h, unsigned s, unsigned c, sector_t start)
     2216{
     2217    sector_t total, real_s, real_c;
    20942218
    20952219    real_s = sector(s) - 1;
    20962220    real_c = cylinder(s, c);
    2097     total = (real_c * sectors + real_s) * heads + h;
     2221    total = (real_c * g_sectors + real_s) * g_heads + h;
    20982222    if (!total)
    2099         printf("Partition %d contains sector 0\n", n);
    2100     if (h >= heads)
    2101         printf("Partition %d: head %d greater than maximum %d\n",
    2102             n, h + 1, heads);
    2103     if (real_s >= sectors)
    2104         printf("Partition %d: sector %d greater than "
    2105             "maximum %d\n", n, s, sectors);
    2106     if (real_c >= cylinders)
    2107         printf("Partition %d: cylinder %llu greater than "
    2108             "maximum %d\n", n, real_c + 1, cylinders);
    2109     if (cylinders <= 1024 && start != total)
    2110         printf("Partition %d: previous sectors %llu disagrees with "
    2111             "total %llu\n", n, start, total);
     2223        printf("Partition %u contains sector 0\n", n);
     2224    if (h >= g_heads)
     2225        printf("Partition %u: head %u greater than maximum %u\n",
     2226            n, h + 1, g_heads);
     2227    if (real_s >= g_sectors)
     2228        printf("Partition %u: sector %u greater than "
     2229            "maximum %u\n", n, s, g_sectors);
     2230    if (real_c >= g_cylinders)
     2231        printf("Partition %u: cylinder %"SECT_FMT"u greater than "
     2232            "maximum %u\n", n, real_c + 1, g_cylinders);
     2233    if (g_cylinders <= 1024 && start != total)
     2234        printf("Partition %u: previous sectors %"SECT_FMT"u disagrees with "
     2235            "total %"SECT_FMT"u\n", n, start, total);
    21122236}
    21132237
     
    21162240{
    21172241    int i, j;
    2118     unsigned total = 1;
    2119     ullong first[partitions], last[partitions];
     2242    sector_t total = 1;
     2243    sector_t first[g_partitions], last[g_partitions];
    21202244    struct partition *p;
    21212245
     
    21332257
    21342258    fill_bounds(first, last);
    2135     for (i = 0; i < partitions; i++) {
     2259    for (i = 0; i < g_partitions; i++) {
    21362260        struct pte *pe = &ptes[i];
    21372261
     
    21392263        if (p->sys_ind && !IS_EXTENDED(p->sys_ind)) {
    21402264            check_consistency(p, i);
    2141             if (get_partition_start(pe) < first[i])
     2265            if (get_partition_start_from_dev_start(pe) < first[i])
    21422266                printf("Warning: bad start-of-data in "
    2143                     "partition %d\n", i + 1);
     2267                    "partition %u\n", i + 1);
    21442268            check(i + 1, p->end_head, p->end_sector, p->end_cyl,
    21452269                last[i]);
     
    21482272                if ((first[i] >= first[j] && first[i] <= last[j])
    21492273                 || ((last[i] <= last[j] && last[i] >= first[j]))) {
    2150                     printf("Warning: partition %d overlaps "
    2151                         "partition %d\n", j + 1, i + 1);
     2274                    printf("Warning: partition %u overlaps "
     2275                        "partition %u\n", j + 1, i + 1);
    21522276                    total += first[i] >= first[j] ?
    21532277                        first[i] : first[j];
     
    21612285    if (extended_offset) {
    21622286        struct pte *pex = &ptes[ext_index];
    2163         ullong e_last = get_start_sect(pex->part_table) +
     2287        sector_t e_last = get_start_sect(pex->part_table) +
    21642288            get_nr_sects(pex->part_table) - 1;
    21652289
    2166         for (i = 4; i < partitions; i++) {
     2290        for (i = 4; i < g_partitions; i++) {
    21672291            total++;
    21682292            p = ptes[i].part_table;
    21692293            if (!p->sys_ind) {
    2170                 if (i != 4 || i + 1 < partitions)
    2171                     printf("Warning: partition %d "
     2294                if (i != 4 || i + 1 < g_partitions)
     2295                    printf("Warning: partition %u "
    21722296                        "is empty\n", i + 1);
    21732297            } 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);
     2298                printf("Logical partition %u not entirely in "
     2299                    "partition %u\n", i + 1, ext_index + 1);
    21762300            }
    21772301        }
    21782302    }
    21792303
    2180     if (total > heads * sectors * cylinders)
    2181         printf("Total allocated sectors %d greater than the maximum "
    2182             "%d\n", total, heads * sectors * cylinders);
     2304    if (total > g_heads * g_sectors * g_cylinders)
     2305        printf("Total allocated sectors %u greater than the maximum "
     2306            "%u\n", total, g_heads * g_sectors * g_cylinders);
    21832307    else {
    2184         total = heads * sectors * cylinders - total;
     2308        total = g_heads * g_sectors * g_cylinders - total;
    21852309        if (total != 0)
    2186             printf("%d unallocated sectors\n", total);
     2310            printf("%"SECT_FMT"u unallocated sectors\n", total);
    21872311    }
    21882312}
     
    21952319    struct partition *p = ptes[n].part_table;
    21962320    struct partition *q = ptes[ext_index].part_table;
    2197     ullong limit, temp;
    2198     ullong start, stop = 0;
    2199     ullong first[partitions], last[partitions];
     2321    sector_t limit, temp;
     2322    sector_t start, stop = 0;
     2323    sector_t first[g_partitions], last[g_partitions];
    22002324
    22012325    if (p && p->sys_ind) {
     
    22072331        start = sector_offset;
    22082332        if (display_in_cyl_units || !total_number_of_sectors)
    2209             limit = (ullong) heads * sectors * cylinders - 1;
     2333            limit = (sector_t) g_heads * g_sectors * g_cylinders - 1;
    22102334        else
    22112335            limit = total_number_of_sectors - 1;
     
    22202344    }
    22212345    if (display_in_cyl_units)
    2222         for (i = 0; i < partitions; i++)
     2346        for (i = 0; i < g_partitions; i++)
    22232347            first[i] = (cround(first[i]) - 1) * units_per_sector;
    22242348
     
    22262350    do {
    22272351        temp = start;
    2228         for (i = 0; i < partitions; i++) {
     2352        for (i = 0; i < g_partitions; i++) {
    22292353            int lastplusoff;
    22302354
    2231             if (start == ptes[i].offset)
     2355            if (start == ptes[i].offset_from_dev_start)
    22322356                start += sector_offset;
    22332357            lastplusoff = last[i] + ((n < 4) ? 0 : sector_offset);
     
    22382362            break;
    22392363        if (start >= temp+units_per_sector && num_read) {
    2240             printf("Sector %lld is already allocated\n", temp);
     2364            printf("Sector %"SECT_FMT"u is already allocated\n", temp);
    22412365            temp = start;
    22422366            num_read = 0;
    22432367        }
    22442368        if (!num_read && start == temp) {
    2245             ullong saved_start;
     2369            sector_t saved_start;
    22462370
    22472371            saved_start = start;
    2248             start = read_int(cround(saved_start), cround(saved_start), cround(limit),
    2249                      0, mesg);
     2372            start = read_int(cround(saved_start), cround(saved_start), cround(limit), 0, mesg);
    22502373            if (display_in_cyl_units) {
    22512374                start = (start - 1) * units_per_sector;
    2252                 if (start < saved_start) start = saved_start;
     2375                if (start < saved_start)
     2376                    start = saved_start;
    22532377            }
    22542378            num_read = 1;
     
    22582382        struct pte *pe = &ptes[n];
    22592383
    2260         pe->offset = start - sector_offset;
    2261         if (pe->offset == extended_offset) { /* must be corrected */
    2262             pe->offset++;
     2384        pe->offset_from_dev_start = start - sector_offset;
     2385        if (pe->offset_from_dev_start == extended_offset) { /* must be corrected */
     2386            pe->offset_from_dev_start++;
    22632387            if (sector_offset == 1)
    22642388                start++;
     
    22662390    }
    22672391
    2268     for (i = 0; i < partitions; i++) {
     2392    for (i = 0; i < g_partitions; i++) {
    22692393        struct pte *pe = &ptes[i];
    22702394
    2271         if (start < pe->offset && limit >= pe->offset)
    2272             limit = pe->offset - 1;
     2395        if (start < pe->offset_from_dev_start && limit >= pe->offset_from_dev_start)
     2396            limit = pe->offset_from_dev_start - 1;
    22732397        if (start < first[i] && limit >= first[i])
    22742398            limit = first[i] - 1;
     
    22772401        printf("No free sectors available\n");
    22782402        if (n > 4)
    2279             partitions--;
     2403            g_partitions--;
    22802404        return;
    22812405    }
     
    22862410             "Last %s or +size or +sizeM or +sizeK",
    22872411             str_units(SINGULAR));
    2288         stop = read_int(cround(start), cround(limit), cround(limit),
    2289                 cround(start), mesg);
     2412        stop = read_int(cround(start), cround(limit), cround(limit), cround(start), mesg);
    22902413        if (display_in_cyl_units) {
    22912414            stop = stop * units_per_sector - 1;
     
    22972420    set_partition(n, 0, start, stop, sys);
    22982421    if (n > 4)
    2299         set_partition(n - 1, 1, ptes[n].offset, stop, EXTENDED);
     2422        set_partition(n - 1, 1, ptes[n].offset_from_dev_start, stop, EXTENDED);
    23002423
    23012424    if (IS_EXTENDED(sys)) {
     
    23052428        ext_index = n;
    23062429        pen->ext_pointer = p;
    2307         pe4->offset = extended_offset = start;
     2430        pe4->offset_from_dev_start = extended_offset = start;
    23082431        pe4->sectorbuffer = xzalloc(sector_size);
    23092432        pe4->part_table = pt_offset(pe4->sectorbuffer, 0);
    23102433        pe4->ext_pointer = pe4->part_table + 1;
    23112434        pe4->changed = 1;
    2312         partitions = 5;
     2435        g_partitions = 5;
    23132436    }
    23142437}
     
    23172440add_logical(void)
    23182441{
    2319     if (partitions > 5 || ptes[4].part_table->sys_ind) {
    2320         struct pte *pe = &ptes[partitions];
     2442    if (g_partitions > 5 || ptes[4].part_table->sys_ind) {
     2443        struct pte *pe = &ptes[g_partitions];
    23212444
    23222445        pe->sectorbuffer = xzalloc(sector_size);
    23232446        pe->part_table = pt_offset(pe->sectorbuffer, 0);
    23242447        pe->ext_pointer = pe->part_table + 1;
    2325         pe->offset = 0;
     2448        pe->offset_from_dev_start = 0;
    23262449        pe->changed = 1;
    2327         partitions++;
    2328     }
    2329     add_partition(partitions - 1, LINUX_NATIVE);
     2450        g_partitions++;
     2451    }
     2452    add_partition(g_partitions - 1, LINUX_NATIVE);
    23302453}
    23312454
     
    23392462
    23402463    if (LABEL_IS_SUN) {
    2341         add_sun_partition(get_partition(0, partitions), LINUX_NATIVE);
     2464        add_sun_partition(get_partition(0, g_partitions), LINUX_NATIVE);
    23422465        return;
    23432466    }
    23442467    if (LABEL_IS_SGI) {
    2345         sgi_add_partition(get_partition(0, partitions), LINUX_NATIVE);
     2468        sgi_add_partition(get_partition(0, g_partitions), LINUX_NATIVE);
    23462469        return;
    23472470    }
     
    23562479        free_primary += !ptes[i].part_table->sys_ind;
    23572480
    2358     if (!free_primary && partitions >= MAXIMUM_PARTS) {
     2481    if (!free_primary && g_partitions >= MAXIMUM_PARTS) {
    23592482        printf("The maximum number of partitions has been created\n");
    23602483        return;
     
    23772500        while (1) {
    23782501            c = read_nonempty(line);
    2379             if (c == 'p' || c == 'P') {
     2502            if ((c | 0x20) == 'p') {
    23802503                i = get_nonexisting_partition(0, 4);
    23812504                if (i >= 0)
     
    24082531            if (ptes[i].changed)
    24092532                ptes[3].changed = 1;
    2410         for (i = 3; i < partitions; i++) {
     2533        for (i = 3; i < g_partitions; i++) {
    24112534            struct pte *pe = &ptes[i];
    24122535
    24132536            if (pe->changed) {
    24142537                write_part_table_flag(pe->sectorbuffer);
    2415                 write_sector(pe->offset, pe->sectorbuffer);
     2538                write_sector(pe->offset_from_dev_start, pe->sectorbuffer);
    24162539            }
    24172540        }
     
    24432566    sync();
    24442567    /* sleep(2); Huh? */
    2445     i = ioctl_or_perror(fd, BLKRRPART, NULL,
     2568    i = ioctl_or_perror(dev_fd, BLKRRPART, NULL,
    24462569            "WARNING: rereading partition table "
    24472570            "failed, kernel still uses old table");
     
    24562579    if (leave) {
    24572580        if (ENABLE_FEATURE_CLEAN_UP)
    2458             close(fd);
     2581            close_dev_fd();
    24592582        exit(i != 0);
    24602583    }
     
    24742597        printf(" %02X", (unsigned char) pbuffer[i]);
    24752598        if (l == MAX_PER_LINE - 1) {
    2476             puts("");
     2599            bb_putchar('\n');
    24772600            l = -1;
    24782601        }
    24792602    }
    24802603    if (l > 0)
    2481         puts("");
    2482     puts("");
     2604        bb_putchar('\n');
     2605    bb_putchar('\n');
    24832606}
    24842607
     
    24922615        print_buffer(MBRbuffer);
    24932616    else {
    2494         for (i = 3; i < partitions; i++)
     2617        for (i = 3; i < g_partitions; i++)
    24952618            print_buffer(ptes[i].sectorbuffer);
    24962619    }
     
    24982621
    24992622static void
    2500 move_begin(int i)
     2623move_begin(unsigned i)
    25012624{
    25022625    struct pte *pe = &ptes[i];
    25032626    struct partition *p = pe->part_table;
    2504     ullong new, first;
     2627    sector_t new, first, nr_sects;
    25052628
    25062629    if (warn_geometry())
    25072630        return;
    2508     if (!p->sys_ind || !get_nr_sects(p) || IS_EXTENDED(p->sys_ind)) {
    2509         printf("Partition %d has no data area\n", i + 1);
     2631    nr_sects = get_nr_sects(p);
     2632    if (!p->sys_ind || !nr_sects || IS_EXTENDED(p->sys_ind)) {
     2633        printf("Partition %u has no data area\n", i + 1);
    25102634        return;
    25112635    }
    2512     first = get_partition_start(pe);
    2513     new = read_int(first, first, first + get_nr_sects(p) - 1, first,
    2514                "New beginning of data") - pe->offset;
    2515 
    2516     if (new != get_nr_sects(p)) {
    2517         first = get_nr_sects(p) + get_start_sect(p) - new;
    2518         set_nr_sects(p, first);
    2519         set_start_sect(p, new);
     2636    first = get_partition_start_from_dev_start(pe); /* == pe->offset_from_dev_start + get_start_sect(p) */
     2637    new = read_int(0 /*was:first*/, first, first + nr_sects - 1, first, "New beginning of data");
     2638    if (new != first) {
     2639        sector_t new_relative = new - pe->offset_from_dev_start;
     2640        nr_sects += (get_start_sect(p) - new_relative);
     2641        set_start_sect(p, new_relative);
     2642        set_nr_sects(p, nr_sects);
     2643        read_nonempty("Recalculate C/H/S values? (Y/N): ");
     2644        if ((line_ptr[0] | 0x20) == 'y')
     2645            set_hsc_start_end(p, new, new + nr_sects - 1);
    25202646        pe->changed = 1;
    25212647    }
     
    25282654
    25292655    while (1) {
    2530         putchar('\n');
    2531         c = tolower(read_nonempty("Expert command (m for help): "));
     2656        bb_putchar('\n');
     2657        c = 0x20 | read_nonempty("Expert command (m for help): ");
    25322658        switch (c) {
    25332659        case 'a':
     
    25372663        case 'b':
    25382664            if (LABEL_IS_DOS)
    2539                 move_begin(get_partition(0, partitions));
     2665                move_begin(get_partition(0, g_partitions));
    25402666            break;
    25412667        case 'c':
    2542             user_cylinders = cylinders =
    2543                 read_int(1, cylinders, 1048576, 0,
     2668            user_cylinders = g_cylinders =
     2669                read_int(1, g_cylinders, 1048576, 0,
    25442670                    "Number of cylinders");
    25452671            if (LABEL_IS_SUN)
    2546                 sun_set_ncyl(cylinders);
     2672                sun_set_ncyl(g_cylinders);
    25472673            if (LABEL_IS_DOS)
    25482674                warn_cylinders();
     
    25692695            break;
    25702696        case 'h':
    2571             user_heads = heads = read_int(1, heads, 256, 0,
    2572                     "Number of heads");
     2697            user_heads = g_heads = read_int(1, g_heads, 256, 0, "Number of heads");
    25732698            update_units();
    25742699            break;
     
    25882713            break;
    25892714        case 'q':
    2590             close(fd);
    2591             puts("");
    2592             exit(0);
     2715            if (ENABLE_FEATURE_CLEAN_UP)
     2716                close_dev_fd();
     2717            bb_putchar('\n');
     2718            exit(EXIT_SUCCESS);
    25932719        case 'r':
    25942720            return;
    25952721        case 's':
    2596             user_sectors = sectors = read_int(1, sectors, 63, 0,
    2597                        "Number of sectors");
     2722            user_sectors = g_sectors = read_int(1, g_sectors, 63, 0, "Number of sectors");
    25982723            if (dos_compatible_flag) {
    2599                 sector_offset = sectors;
     2724                sector_offset = g_sectors;
    26002725                printf("Warning: setting sector offset for DOS "
    26012726                    "compatiblity\n");
     
    26392764
    26402765    snprintf(buf, sizeof(buf), "/proc/ide/%s/media", device+5);
    2641     procf = fopen(buf, "r");
     2766    procf = fopen_for_read(buf);
    26422767    if (procf != NULL && fgets(buf, sizeof(buf), procf))
    26432768        is_ide = (!strncmp(buf, "cdrom", 5) ||
     
    26562781
    26572782static void
    2658 trydev(const char *device, int user_specified)
     2783open_list_and_close(const char *device, int user_specified)
    26592784{
    26602785    int gb;
     
    26662791        if (is_ide_cdrom_or_tape(device))
    26672792            return;
    2668     fd = open(disk_device, type_open);
    2669     if (fd >= 0) {
    2670         gb = get_boot(try_only);
    2671         if (gb > 0) {   /* I/O error */
    2672             close(fd);
    2673         } else if (gb < 0) { /* no DOS signature */
    2674             list_disk_geometry();
    2675             if (LABEL_IS_AIX) {
    2676                 return;
    2677             }
    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);
    2683             close(fd);
    2684         } else {
    2685             close(fd);
    2686             list_table(0);
    2687 #if ENABLE_FEATURE_FDISK_WRITABLE
    2688             if (!LABEL_IS_SUN && partitions > 4){
    2689                 delete_partition(ext_index);
    2690             }
    2691 #endif
    2692         }
    2693     } else {
     2793
     2794    /* Open disk_device, save file descriptor to dev_fd */
     2795    errno = 0;
     2796    gb = get_boot(TRY_ONLY);
     2797    if (gb > 0) {   /* I/O error */
    26942798        /* Ignore other errors, since we try IDE
    26952799           and SCSI hard disks which may not be
    26962800           installed on the system. */
    2697         if (errno == EACCES) {
    2698             printf("Cannot open %s\n", device);
    2699             return;
    2700         }
    2701     }
     2801        if (user_specified || errno == EACCES)
     2802            bb_perror_msg("can't open '%s'", device);
     2803        return;
     2804    }
     2805
     2806    if (gb < 0) { /* no DOS signature */
     2807        list_disk_geometry();
     2808        if (LABEL_IS_AIX)
     2809            goto ret;
     2810#if ENABLE_FEATURE_OSF_LABEL
     2811        if (bsd_trydev(device) < 0)
     2812#endif
     2813            printf("Disk %s doesn't contain a valid "
     2814                "partition table\n", device);
     2815    } else {
     2816        list_table(0);
     2817#if ENABLE_FEATURE_FDISK_WRITABLE
     2818        if (!LABEL_IS_SUN && g_partitions > 4) {
     2819            delete_partition(ext_index);
     2820        }
     2821#endif
     2822    }
     2823 ret:
     2824    close_dev_fd();
    27022825}
    27032826
     
    27052828   that look like a partition name (do not end in a digit) */
    27062829static void
    2707 tryprocpt(void)
     2830list_devs_in_proc_partititons(void)
    27082831{
    27092832    FILE *procpt;
     
    27142837
    27152838    while (fgets(line, sizeof(line), procpt)) {
    2716         if (sscanf(line, " %d %d %d %[^\n ]",
     2839        if (sscanf(line, " %u %u %u %[^\n ]",
    27172840                &ma, &mi, &sz, ptname) != 4)
    27182841            continue;
    2719         for (s = ptname; *s; s++);
    2720         if (isdigit(s[-1]))
     2842        for (s = ptname; *s; s++)
     2843            continue;
     2844        /* note: excluding '0': e.g. mmcblk0 is not a partition name! */
     2845        if (s[-1] >= '1' && s[-1] <= '9')
    27212846            continue;
    27222847        sprintf(devname, "/dev/%s", ptname);
    2723         trydev(devname, 0);
     2848        open_list_and_close(devname, 0);
    27242849    }
    27252850#if ENABLE_FEATURE_CLEAN_UP
     
    27362861#endif
    27372862
    2738 int fdisk_main(int argc, char **argv);
    2739 int fdisk_main(int argc, char **argv)
    2740 {
    2741     char *str_b, *str_C, *str_H, *str_S;
     2863int fdisk_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     2864int fdisk_main(int argc UNUSED_PARAM, char **argv)
     2865{
    27422866    unsigned opt;
    27432867    /*
     
    27492873     * Options -C, -H, -S set the geometry.
    27502874     */
    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;
     2875    INIT_G();
     2876
     2877    close_dev_fd(); /* needed: fd 3 must not stay closed */
     2878
     2879    opt_complementary = "b+:C+:H+:S+"; /* numeric params */
     2880    opt = getopt32(argv, "b:C:H:lS:u" IF_FEATURE_FDISK_BLKSIZE("s"),
     2881                &sector_size, &user_cylinders, &user_heads, &user_sectors);
    27662882    argv += optind;
    2767     if (opt & OPT_b) { // -b
     2883    if (opt & OPT_b) {
    27682884        /* 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)
     2885         * so cannot be combined with multiple disks,
     2886         * and the same goes for the C/H/S options.
     2887         */
     2888        if (sector_size < 512
     2889         || sector_size > 0x10000
     2890         || (sector_size & (sector_size-1)) /* not power of 2 */
     2891        ) {
    27752892            bb_show_usage();
     2893        }
    27762894        sector_offset = 2;
    27772895        user_set_sector_size = 1;
    27782896    }
    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");
     2897    if (user_heads <= 0 || user_heads >= 256)
     2898        user_heads = 0;
     2899    if (user_sectors <= 0 || user_sectors >= 64)
     2900        user_sectors = 0;
     2901    if (opt & OPT_u)
     2902        display_in_cyl_units = 0; // -u
    27972903
    27982904#if ENABLE_FEATURE_FDISK_WRITABLE
     
    28002906        nowarn = 1;
    28012907#endif
    2802         type_open = O_RDONLY;
    2803         if (argc > 0) {
    2804             int k;
    2805 #if defined(__GNUC__)
    2806             /* avoid gcc warning:
    2807                variable `k' might be clobbered by `longjmp' */
    2808             (void)&k;
    2809 #endif
     2908        if (*argv) {
    28102909            listing = 1;
    2811             for (k = 0; k < argc; k++)
    2812                 trydev(argv[k], 1);
     2910            do {
     2911                open_list_and_close(*argv, 1);
     2912            } while (*++argv);
    28132913        } else {
    2814             /* we no longer have default device names */
    2815             /* but, we can use /proc/partitions instead */
    2816             tryprocpt();
     2914            /* we don't have device names, */
     2915            /* use /proc/partitions instead */
     2916            list_devs_in_proc_partititons();
    28172917        }
    28182918        return 0;
     
    28232923#if ENABLE_FEATURE_FDISK_BLKSIZE
    28242924    if (opt & OPT_s) {
    2825         long size;
    28262925        int j;
    28272926
    28282927        nowarn = 1;
    2829         type_open = O_RDONLY;
    2830 
    2831         if (argc <= 0)
     2928        if (!argv[0])
    28322929            bb_show_usage();
    2833 
    2834         for (j = 0; j < argc; j++) {
    2835             disk_device = argv[j];
    2836             fd = open(disk_device, type_open);
    2837             if (fd < 0)
    2838                 fdisk_fatal(unable_to_open);
    2839             if (ioctl(fd, BLKGETSIZE, &size))
    2840                 fdisk_fatal(ioctl_error);
     2930        for (j = 0; argv[j]; j++) {
     2931            unsigned long long size;
     2932            fd = xopen(argv[j], O_RDONLY);
     2933            size = bb_BLKGETSIZE_sectors(fd) / 2;
    28412934            close(fd);
    2842             if (argc == 1)
    2843                 printf("%ld\n", size/2);
     2935            if (argv[1])
     2936                printf("%llu\n", size);
    28442937            else
    2845                 printf("%s: %ld\n", argv[j], size/2);
     2938                printf("%s: %llu\n", argv[j], size);
    28462939        }
    28472940        return 0;
     
    28502943
    28512944#if ENABLE_FEATURE_FDISK_WRITABLE
    2852     if (argc != 1)
     2945    if (!argv[0] || argv[1])
    28532946        bb_show_usage();
    28542947
    28552948    disk_device = argv[0];
    2856     get_boot(fdisk);
     2949    get_boot(OPEN_MAIN);
    28572950
    28582951    if (LABEL_IS_OSF) {
     
    28622955        bsd_select();
    28632956        /*Why do we do this?  It seems to be counter-intuitive*/
    2864         current_label_type = label_dos;
     2957        current_label_type = LABEL_DOS;
    28652958        /* If we return we may want to make an empty DOS label? */
    28662959    }
     
    28682961    while (1) {
    28692962        int c;
    2870         putchar('\n');
    2871         c = tolower(read_nonempty("Command (m for help): "));
     2963        bb_putchar('\n');
     2964        c = 0x20 | read_nonempty("Command (m for help): ");
    28722965        switch (c) {
    28732966        case 'a':
    28742967            if (LABEL_IS_DOS)
    2875                 toggle_active(get_partition(1, partitions));
     2968                toggle_active(get_partition(1, g_partitions));
    28762969            else if (LABEL_IS_SUN)
    2877                 toggle_sunflags(get_partition(1, partitions),
     2970                toggle_sunflags(get_partition(1, g_partitions),
    28782971                        0x01);
    28792972            else if (LABEL_IS_SGI)
    28802973                sgi_set_bootpartition(
    2881                     get_partition(1, partitions));
     2974                    get_partition(1, g_partitions));
    28822975            else
    28832976                unknown_command(c);
     
    29022995                toggle_dos_compatibility_flag();
    29032996            else if (LABEL_IS_SUN)
    2904                 toggle_sunflags(get_partition(1, partitions),
     2997                toggle_sunflags(get_partition(1, g_partitions),
    29052998                        0x10);
    29062999            else if (LABEL_IS_SGI)
    29073000                sgi_set_swappartition(
    2908                         get_partition(1, partitions));
     3001                        get_partition(1, g_partitions));
    29093002            else
    29103003                unknown_command(c);
     
    29183011               partition tables */
    29193012                if (!LABEL_IS_SGI) {
    2920                     j = get_existing_partition(1, partitions);
     3013                    j = get_existing_partition(1, g_partitions);
    29213014                } else {
    2922                     j = get_partition(1, partitions);
     3015                    j = get_partition(1, g_partitions);
    29233016                }
    29243017                if (j >= 0)
     
    29473040            break;
    29483041        case 'q':
    2949             close(fd);
    2950             puts("");
     3042            if (ENABLE_FEATURE_CLEAN_UP)
     3043                close_dev_fd();
     3044            bb_putchar('\n');
    29513045            return 0;
    29523046        case 's':
  • branches/2.2.9/mindi-busybox/util-linux/fdisk_aix.c

    r1765 r2725  
    22/*
    33 * Copyright (C) Andreas Neuper, Sep 1998.
    4  *      This file may be redistributed under
    5  *      the terms of the GNU Public License.
     4 *
     5 * Licensed under GPLv2, see file LICENSE in this source tree.
    66 */
    77
     
    3030*/
    3131
    32 static int aix_other_endian;
    33 static short aix_volumes = 1;
     32static smallint aix_other_endian; /* bool */
     33static smallint aix_volumes = 1; /* max 15 */
    3434
    3535/*
     
    5555check_aix_label(void)
    5656{
    57     if (aixlabel->magic != AIX_LABEL_MAGIC &&
    58         aixlabel->magic != AIX_LABEL_MAGIC_SWAPPED) {
     57    if (aixlabel->magic != AIX_LABEL_MAGIC
     58     && aixlabel->magic != AIX_LABEL_MAGIC_SWAPPED
     59    ) {
    5960        current_label_type = 0;
    6061        aix_other_endian = 0;
     
    6364    aix_other_endian = (aixlabel->magic == AIX_LABEL_MAGIC_SWAPPED);
    6465    update_units();
    65     current_label_type = label_aix;
    66     partitions = 1016;
     66    current_label_type = LABEL_AIX;
     67    g_partitions = 1016;
    6768    aix_volumes = 15;
    6869    aix_info();
  • branches/2.2.9/mindi-busybox/util-linux/fdisk_osf.c

    r1765 r2725  
    1 #if ENABLE_FEATURE_OSF_LABEL
    21/*
    32 * Copyright (c) 1987, 1988 Regents of the University of California.
     
    3332 */
    3433
     34#if ENABLE_FEATURE_OSF_LABEL
    3535
    3636#ifndef BSD_DISKMAGIC
     
    4646#if defined(i386) || defined(__sparc__) || defined(__arm__) \
    4747 || defined(__m68k__) || defined(__mips__) || defined(__s390__) \
    48  || defined(__sh__) || defined(__x86_64__)
    49 #define BSD_LABELSECTOR   1
    50 #define BSD_LABELOFFSET   0
     48 || defined(__s390__) || defined(__s390x__) \
     49 || defined(__sh__) || defined(__x86_64__) || defined(__avr32__) \
     50 || defined(__nds32__)
     51# define BSD_LABELSECTOR   1
     52# define BSD_LABELOFFSET   0
    5153#elif defined(__alpha__) || defined(__powerpc__) || defined(__ia64__) \
    5254 || defined(__hppa__)
    53 #define BSD_LABELSECTOR   0
    54 #define BSD_LABELOFFSET   64
    55 #elif defined(__s390__) || defined(__s390x__)
    56 #define BSD_LABELSECTOR   1
    57 #define BSD_LABELOFFSET   0
    58 #else
    59 #error unknown architecture
     55# define BSD_LABELSECTOR   0
     56# define BSD_LABELOFFSET   64
     57#else
     58# error unknown architecture
    6059#endif
    6160
     
    6867    int16_t    d_subtype;              /* controller/d_type specific */
    6968    char       d_typename[16];         /* type name, e.g. "eagle" */
    70     char       d_packname[16];                 /* pack identifier */
    71             /* disk geometry: */
     69    char       d_packname[16];         /* pack identifier */
     70    /* disk geometry: */
    7271    uint32_t   d_secsize;              /* # of bytes per sector */
    7372    uint32_t   d_nsectors;             /* # of data sectors per track */
     
    9089    uint32_t   d_acylinders;           /* # of alt. cylinders per unit */
    9190
    92             /* hardware characteristics: */
     91    /* hardware characteristics: */
    9392    /*
    9493     * d_interleave, d_trackskew and d_cylskew describe perturbations
     
    120119    uint32_t   d_magic2;               /* the magic number (again) */
    121120    uint16_t   d_checksum;             /* xor of data incl. partitions */
    122             /* filesystem and partition information: */
     121    /* filesystem and partition information: */
    123122    uint16_t   d_npartitions;          /* number of partitions in following */
    124123    uint32_t   d_bbsize;               /* size of boot area at sn0, bytes */
    125124    uint32_t   d_sbsize;               /* max size of fs superblock, bytes */
    126     struct xbsd_partition    {      /* the partition table */
     125    struct xbsd_partition { /* the partition table */
    127126        uint32_t   p_size;         /* number of sectors in partition */
    128127        uint32_t   p_offset;       /* starting sector */
     
    241240*/
    242241
    243 static int possibly_osf_label;
    244 
    245242#define FREEBSD_PARTITION       0xa5
    246243#define NETBSD_PARTITION        0xa9
     
    372369                return;
    373370            }
    374                 printf("Reading disklabel of %s at sector %d\n",
     371                printf("Reading disklabel of %s at sector %u\n",
    375372                    partname(disk_device, t+1, 0), ss + BSD_LABELSECTOR);
    376373            if (xbsd_readlabel(xbsd_part) == 0)
     
    395392
    396393    while (1) {
    397         putchar('\n');
     394        bb_putchar('\n');
    398395        switch (tolower(read_nonempty("BSD disklabel command (m for help): "))) {
    399396        case 'd':
     
    416413            break;
    417414        case 'q':
    418             close(fd);
     415            if (ENABLE_FEATURE_CLEAN_UP)
     416                close_dev_fd();
    419417            exit(EXIT_SUCCESS);
    420418        case 'r':
     
    504502
    505503    if (show_all) {
     504        static const int d_masks[] = { BSD_D_REMOVABLE, BSD_D_ECC, BSD_D_BADSECT };
     505
    506506#if defined(__alpha__)
    507507        printf("# %s:\n", disk_device);
     
    512512            printf("type: %s\n", xbsd_dktypenames[lp->d_type]);
    513513        else
    514             printf("type: %d\n", lp->d_type);
     514            printf("type: %u\n", lp->d_type);
    515515        printf("disk: %.*s\n", (int) sizeof(lp->d_typename), lp->d_typename);
    516516        printf("label: %.*s\n", (int) sizeof(lp->d_packname), lp->d_packname);
    517         printf("flags:");
    518         if (lp->d_flags & BSD_D_REMOVABLE)
    519             printf(" removable");
    520         if (lp->d_flags & BSD_D_ECC)
    521             printf(" ecc");
    522         if (lp->d_flags & BSD_D_BADSECT)
    523             printf(" badsect");
    524         puts("");
     517        printf("flags: ");
     518        print_flags_separated(d_masks, "removable\0""ecc\0""badsect\0", lp->d_flags, " ");
     519        bb_putchar('\n');
    525520        /* On various machines the fields of *lp are short/int/long */
    526521        /* In order to avoid problems, we cast them all to long. */
    527         printf("bytes/sector: %ld\n", (long) lp->d_secsize);
    528         printf("sectors/track: %ld\n", (long) lp->d_nsectors);
    529         printf("tracks/cylinder: %ld\n", (long) lp->d_ntracks);
    530         printf("sectors/cylinder: %ld\n", (long) lp->d_secpercyl);
    531         printf("cylinders: %ld\n", (long) lp->d_ncylinders);
    532         printf("rpm: %d\n", lp->d_rpm);
    533         printf("interleave: %d\n", lp->d_interleave);
    534         printf("trackskew: %d\n", lp->d_trackskew);
    535         printf("cylinderskew: %d\n", lp->d_cylskew);
    536         printf("headswitch: %ld\t\t# milliseconds\n",
     522        printf("bytes/sector: %lu\n", (long) lp->d_secsize);
     523        printf("sectors/track: %lu\n", (long) lp->d_nsectors);
     524        printf("tracks/cylinder: %lu\n", (long) lp->d_ntracks);
     525        printf("sectors/cylinder: %lu\n", (long) lp->d_secpercyl);
     526        printf("cylinders: %lu\n", (long) lp->d_ncylinders);
     527        printf("rpm: %u\n", lp->d_rpm);
     528        printf("interleave: %u\n", lp->d_interleave);
     529        printf("trackskew: %u\n", lp->d_trackskew);
     530        printf("cylinderskew: %u\n", lp->d_cylskew);
     531        printf("headswitch: %lu\t\t# milliseconds\n",
    537532            (long) lp->d_headswitch);
    538         printf("track-to-track seek: %ld\t# milliseconds\n",
     533        printf("track-to-track seek: %lu\t# milliseconds\n",
    539534            (long) lp->d_trkseek);
    540535        printf("drivedata: ");
     
    545540            i = 0;
    546541        for (j = 0; j <= i; j++)
    547             printf("%ld ", (long) lp->d_drivedata[j]);
    548     }
    549     printf("\n%d partitions:\n", lp->d_npartitions);
     542            printf("%lu ", (long) lp->d_drivedata[j]);
     543    }
     544    printf("\n%u partitions:\n", lp->d_npartitions);
    550545    printf("#       start       end      size     fstype   [fsize bsize   cpg]\n");
    551546    pp = lp->d_partitions;
     
    553548        if (pp->p_size) {
    554549            if (display_in_cyl_units && lp->d_secpercyl) {
    555                 printf("  %c: %8ld%c %8ld%c %8ld%c  ",
     550                printf("  %c: %8lu%c %8lu%c %8lu%c  ",
    556551                    'a' + i,
    557                     (long) pp->p_offset / lp->d_secpercyl + 1,
     552                    (unsigned long) pp->p_offset / lp->d_secpercyl + 1,
    558553                    (pp->p_offset % lp->d_secpercyl) ? '*' : ' ',
    559                     (long) (pp->p_offset + pp->p_size + lp->d_secpercyl - 1) / lp->d_secpercyl,
     554                    (unsigned long) (pp->p_offset + pp->p_size + lp->d_secpercyl - 1) / lp->d_secpercyl,
    560555                    ((pp->p_offset + pp->p_size) % lp->d_secpercyl) ? '*' : ' ',
    561556                    (long) pp->p_size / lp->d_secpercyl,
     
    563558                );
    564559            } else {
    565                 printf("  %c: %8ld  %8ld  %8ld   ",
     560                printf("  %c: %8lu  %8lu  %8lu   ",
    566561                    'a' + i,
    567562                    (long) pp->p_offset,
     
    578573            switch (pp->p_fstype) {
    579574            case BSD_FS_UNUSED:
    580                 printf("    %5ld %5ld %5.5s ",
     575                printf("    %5lu %5lu %5.5s ",
    581576                    (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, "");
    582577                break;
    583578            case BSD_FS_BSDFFS:
    584                 printf("    %5ld %5ld %5d ",
     579                printf("    %5lu %5lu %5u ",
    585580                    (long) pp->p_fsize, (long) pp->p_fsize * pp->p_frag, pp->p_cpg);
    586581                break;
     
    589584                break;
    590585            }
    591             puts("");
     586            bb_putchar('\n');
    592587        }
    593588    }
     
    622617    while (1) {
    623618        c = read_nonempty("Do you want to create a disklabel? (y/n) ");
    624         if (c == 'y' || c == 'Y') {
     619        if ((c|0x20) == 'y') {
    625620            if (xbsd_initlabel(
    626621#if defined(__alpha__) || defined(__powerpc__) || defined(__hppa__) || \
     
    630625                xbsd_part
    631626#endif
    632                 ) == 1) {
     627            ) == 1) {
    633628                xbsd_print_disklabel(1);
    634629                return 1;
    635             } else
    636                 return 0;
    637         } else if (c == 'n')
     630            }
    638631            return 0;
     632        }
     633        if ((c|0x20) == 'n')
     634            return 0;
    639635    }
    640636}
     
    643639edit_int(int def, const char *mesg)
    644640{
    645     mesg = xasprintf("%s (%d): ", mesg, def);
     641    mesg = xasprintf("%s (%u): ", mesg, def);
    646642    do {
    647643        if (!read_line(mesg))
     
    692688    int fdb;
    693689
    694     fdb = open(path, O_RDONLY);
     690    fdb = open_or_warn(path, O_RDONLY);
    695691    if (fdb < 0) {
    696         perror(path);
    697692        return 0;
    698693    }
    699     if (read(fdb, ptr, size) < 0) {
    700         perror(path);
     694    if (full_read(fdb, ptr, size) < 0) {
     695        bb_simple_perror_msg(path);
    701696        close(fdb);
    702697        return 0;
     
    769764#endif
    770765
    771     if (lseek(fd, sector * SECTOR_SIZE, SEEK_SET) == -1)
    772         fdisk_fatal(unable_to_seek);
    773     if (BSD_BBSIZE != write(fd, disklabelbuffer, BSD_BBSIZE))
    774         fdisk_fatal(unable_to_write);
     766    seek_sector(sector);
     767    xwrite(dev_fd, disklabelbuffer, BSD_BBSIZE);
    775768
    776769#if defined(__alpha__)
     
    877870#endif
    878871    d->d_secsize = SECTOR_SIZE;           /* bytes/sector  */
    879     d->d_nsectors = sectors;              /* sectors/track */
    880     d->d_ntracks = heads;                 /* tracks/cylinder (heads) */
    881     d->d_ncylinders = cylinders;
    882     d->d_secpercyl  = sectors * heads;    /* sectors/cylinder */
     872    d->d_nsectors = g_sectors;            /* sectors/track */
     873    d->d_ntracks = g_heads;               /* tracks/cylinder (heads) */
     874    d->d_ncylinders = g_cylinders;
     875    d->d_secpercyl  = g_sectors * g_heads;/* sectors/cylinder */
    883876    if (d->d_secpercyl == 0)
    884877        d->d_secpercyl = 1;           /* avoid segfaults */
     
    942935#endif
    943936
    944     if (lseek(fd, sector * SECTOR_SIZE, SEEK_SET) == -1)
    945         fdisk_fatal(unable_to_seek);
    946     if (BSD_BBSIZE != read(fd, disklabelbuffer, BSD_BBSIZE))
     937    seek_sector(sector);
     938    if (BSD_BBSIZE != full_read(dev_fd, disklabelbuffer, BSD_BBSIZE))
    947939        fdisk_fatal(unable_to_read);
    948940
     
    960952
    961953    if (d->d_npartitions > BSD_MAXPARTITIONS)
    962         printf("Warning: too many partitions (%d, maximum is %d)\n",
     954        printf("Warning: too many partitions (%u, maximum is %u)\n",
    963955            d->d_npartitions, BSD_MAXPARTITIONS);
    964956    return 1;
     
    974966    sector = get_start_sect(p) + BSD_LABELSECTOR;
    975967#else
     968    (void)p; /* silence warning */
    976969    sector = BSD_LABELSECTOR;
    977970#endif
     
    988981#if defined(__alpha__) && BSD_LABELSECTOR == 0
    989982    alpha_bootblock_checksum(disklabelbuffer);
    990     if (lseek(fd, 0, SEEK_SET) == -1)
    991         fdisk_fatal(unable_to_seek);
    992     if (BSD_BBSIZE != write(fd, disklabelbuffer, BSD_BBSIZE))
    993         fdisk_fatal(unable_to_write);
    994 #else
    995     if (lseek(fd, sector * SECTOR_SIZE + BSD_LABELOFFSET, SEEK_SET) == -1)
    996         fdisk_fatal(unable_to_seek);
    997     if (sizeof(struct xbsd_disklabel) != write(fd, d, sizeof(struct xbsd_disklabel)))
    998         fdisk_fatal(unable_to_write);
     983    seek_sector(0);
     984    xwrite(dev_fd, disklabelbuffer, BSD_BBSIZE);
     985#else
     986    seek_sector(sector);
     987    lseek(dev_fd, BSD_LABELOFFSET, SEEK_CUR);
     988    xwrite(dev_fd, d, sizeof(*d));
    999989#endif
    1000990    sync_disks();
     
    10281018    struct partition *p;
    10291019
    1030     k = get_partition(1, partitions);
     1020    k = get_partition(1, g_partitions);
    10311021
    10321022    if (!xbsd_check_new_partition(&i))
  • branches/2.2.9/mindi-busybox/util-linux/fdisk_sgi.c

    r1765 r2725  
    1 #if ENABLE_FEATURE_SGI_LABEL
    2 
    31/*
    42 * Copyright (C) Andreas Neuper, Sep 1998.
    5  *      This file may be modified and redistributed under
    6  *      the terms of the GNU Public License.
     3 *
     4 * Licensed under GPLv2, see file LICENSE in this source tree.
    75 */
     6
     7#if ENABLE_FEATURE_SGI_LABEL
     8
     9#define SGI_DEBUG 0
    810
    911#define SGI_VOLHDR      0x00
     
    3537    unsigned short bytes;
    3638    unsigned short ilfact;
    37     unsigned int   flags;           /* controller flags */
     39    unsigned int   flags;   /* controller flags */
    3840    unsigned int   datarate;
    3941    unsigned int   retries_on_error;
     
    6971        unsigned int  vol_file_size;    /* number of bytes */
    7072    } directory[15];
    71     struct sgi_partinfo {                  /* 16 * 12 bytes */
     73    struct sgi_partinfo {                   /* 16 * 12 bytes */
    7274        unsigned int num_sectors;       /* number of blocks */
    7375        unsigned int start_sector;      /* must be cylinder aligned */
     
    118120
    119121
    120 static int sgi_other_endian;
    121 static int debug;
    122 static short sgi_volumes = 1;
     122static smallint sgi_other_endian; /* bool */
     123static smallint sgi_volumes = 1; /* max 15 */
    123124
    124125/*
     
    235236     && sgilabel->magic != SGI_LABEL_MAGIC_SWAPPED
    236237    ) {
    237         current_label_type = label_dos;
     238        current_label_type = LABEL_DOS;
    238239        return 0;
    239240    }
     
    248249    }
    249250    update_units();
    250     current_label_type = label_sgi;
    251     partitions = 16;
     251    current_label_type = LABEL_SGI;
     252    g_partitions = 16;
    252253    sgi_volumes = 15;
    253254    return 1;
     
    291292
    292293    if (xtra) {
    293         printf("\nDisk %s (SGI disk label): %d heads, %d sectors\n"
    294             "%d cylinders, %d physical cylinders\n"
    295             "%d extra sects/cyl, interleave %d:1\n"
     294        printf("\nDisk %s (SGI disk label): %u heads, %u sectors\n"
     295            "%u cylinders, %u physical cylinders\n"
     296            "%u extra sects/cyl, interleave %u:1\n"
    296297            "%s\n"
    297             "Units = %s of %d * 512 bytes\n\n",
    298             disk_device, heads, sectors, cylinders,
     298            "Units = %s of %u * 512 bytes\n\n",
     299            disk_device, g_heads, g_sectors, g_cylinders,
    299300            SGI_SSWAP16(sgiparam.pcylcount),
    300301            SGI_SSWAP16(sgiparam.sparecyl),
     
    304305    } else {
    305306        printf("\nDisk %s (SGI disk label): "
    306             "%d heads, %d sectors, %d cylinders\n"
    307             "Units = %s of %d * 512 bytes\n\n",
    308             disk_device, heads, sectors, cylinders,
     307            "%u heads, %u sectors, %u cylinders\n"
     308            "Units = %s of %u * 512 bytes\n\n",
     309            disk_device, g_heads, g_sectors, g_cylinders,
    309310            str_units(PLURAL), units_per_sector );
    310311    }
     
    318319        "Pt# %*s  Info     Start       End   Sectors  Id  System\n",
    319320        w + 2, "Device");
    320     for (i = 0; i < partitions; i++) {
    321         if (sgi_get_num_sectors(i) || debug ) {
     321    for (i = 0; i < g_partitions; i++) {
     322        if (sgi_get_num_sectors(i) || SGI_DEBUG) {
    322323            uint32_t start = sgi_get_start_sector(i);
    323324            uint32_t len = sgi_get_num_sectors(i);
    324325            kpi++;              /* only count nonempty partitions */
    325326            printf(
    326             "%2d: %s %4s %9ld %9ld %9ld  %2x  %s\n",
     327            "%2u: %s %4s %9lu %9lu %9lu  %2x  %s\n",
    327328/* fdisk part number */ i+1,
    328329/* device */            partname(disk_device, kpi, w+3),
     
    345346            unsigned char *name = sgilabel->directory[i].vol_file_name;
    346347
    347             printf("%2d: %-10s sector%5u size%8u\n",
     348            printf("%2u: %-10s sector%5u size%8u\n",
    348349                i, (char*)name, (unsigned int) start, (unsigned int) len);
    349350        }
     
    360361sgi_get_lastblock(void)
    361362{
    362     return heads * sectors * cylinders;
     363    return g_heads * g_sectors * g_cylinders;
    363364}
    364365
     
    439440        (unsigned int*)sgilabel, sizeof(*sgilabel)) == 0);
    440441
    441     if (lseek(fd, 0, SEEK_SET) < 0)
    442         fdisk_fatal(unable_to_seek);
    443     if (write(fd, sgilabel, SECTOR_SIZE) != SECTOR_SIZE)
    444         fdisk_fatal(unable_to_write);
     442    write_sector(0, sgilabel);
    445443    if (!strncmp((char*)sgilabel->directory[0].vol_file_name, "sgilabel", 8)) {
    446444        /*
     
    450448        sgiinfo *info = fill_sgiinfo();
    451449        int infostartblock = SGI_SSWAP32(sgilabel->directory[0].vol_file_start);
    452         if (lseek(fd, infostartblock*SECTOR_SIZE, SEEK_SET) < 0)
    453             fdisk_fatal(unable_to_seek);
    454         if (write(fd, info, SECTOR_SIZE) != SECTOR_SIZE)
    455             fdisk_fatal(unable_to_write);
     450        write_sector(infostartblock, info);
    456451        free(info);
    457452    }
     
    513508            printf("The entire disk partition should start "
    514509                "at block 0,\n"
    515                 "not at diskblock %d\n",
     510                "not at diskblock %u\n",
    516511                sgi_get_start_sector(Index[0]));
    517         if (debug)      /* I do not understand how some disks fulfil it */
     512        if (SGI_DEBUG)      /* I do not understand how some disks fulfil it */
    518513            if ((sgi_get_num_sectors(Index[0]) != lastblock) && verbose)
    519                 printf("The entire disk partition is only %d diskblock large,\n"
    520                     "but the disk is %d diskblocks long\n",
     514                printf("The entire disk partition is only %u diskblock large,\n"
     515                    "but the disk is %u diskblocks long\n",
    521516                    sgi_get_num_sectors(Index[0]), lastblock);
    522517            lastblock = sgi_get_num_sectors(Index[0]);
     
    524519        if (verbose)
    525520            printf("One Partition (#11) should cover the entire disk\n");
    526         if (debug > 2)
    527             printf("sysid=%d\tpartition=%d\n",
     521        if (SGI_DEBUG > 2)
     522            printf("sysid=%u\tpartition=%u\n",
    528523                sgi_get_sysid(Index[0]), Index[0]+1);
    529524    }
     
    532527
    533528        if ((sgi_get_start_sector(Index[i]) % cylsize) != 0) {
    534             if (debug)      /* I do not understand how some disks fulfil it */
     529            if (SGI_DEBUG)      /* I do not understand how some disks fulfil it */
    535530                if (verbose)
    536                     printf("Partition %d does not start on cylinder boundary\n",
     531                    printf("Partition %u does not start on cylinder boundary\n",
    537532                        Index[i]+1);
    538533        }
    539534        if (sgi_get_num_sectors(Index[i]) % cylsize != 0) {
    540             if (debug)      /* I do not understand how some disks fulfil it */
     535            if (SGI_DEBUG)      /* I do not understand how some disks fulfil it */
    541536                if (verbose)
    542                     printf("Partition %d does not end on cylinder boundary\n",
     537                    printf("Partition %u does not end on cylinder boundary\n",
    543538                        Index[i]+1);
    544539        }
     
    547542        if (start > sgi_get_start_sector(Index[i])) {
    548543            if (verbose)
    549                 printf("Partitions %d and %d overlap by %d sectors\n",
     544                printf("Partitions %u and %u overlap by %u sectors\n",
    550545                    Index[i-1]+1, Index[i]+1,
    551546                    start - sgi_get_start_sector(Index[i]));
     
    555550        if (start < sgi_get_start_sector(Index[i])) {
    556551            if (verbose)
    557                 printf("Unused gap of %8u sectors - sectors %8u-%8u\n",
     552                printf("Unused gap of %u sectors - sectors %u-%u\n",
    558553                    sgi_get_start_sector(Index[i]) - start,
    559554                    start, sgi_get_start_sector(Index[i])-1);
     
    563558        start = sgi_get_start_sector(Index[i])
    564559               + sgi_get_num_sectors(Index[i]);
    565         if (debug > 1) {
     560        if (SGI_DEBUG > 1) {
    566561            if (verbose)
    567                 printf("%2d:%12d\t%12d\t%12d\n", Index[i],
     562                printf("%2u:%12u\t%12u\t%12u\n", Index[i],
    568563                    sgi_get_start_sector(Index[i]),
    569564                    sgi_get_num_sectors(Index[i]),
     
    573568    if (start < lastblock) {
    574569        if (verbose)
    575             printf("Unused gap of %8u sectors - sectors %8u-%8u\n",
     570            printf("Unused gap of %u sectors - sectors %u-%u\n",
    576571                lastblock - start, start, lastblock-1);
    577572        gap += lastblock - start;
     
    661656    int n;
    662657
    663     for (n = 10; n < partitions; n++) {
     658    for (n = 10; n < g_partitions; n++) {
    664659        if (!sgi_get_num_sectors(n) ) {
    665660            sgi_set_partition(n, 0, sgi_get_lastblock(), SGI_VOLUME);
     
    674669    int n;
    675670
    676     for (n = 8; n < partitions; n++) {
     671    for (n = 8; n < g_partitions; n++) {
    677672    if (!sgi_get_num_sectors(n)) {
    678673        /*
     
    682677         * sectors.
    683678         */
    684         if (heads * sectors * 5 < sgi_get_lastblock())
    685             sgi_set_partition(n, 0, heads * sectors * 5, SGI_VOLHDR);
     679        if (g_heads * g_sectors * 5 < sgi_get_lastblock())
     680            sgi_set_partition(n, 0, g_heads * g_sectors * 5, SGI_VOLHDR);
    686681            break;
    687682        }
     
    781776    printf(msg_building_new_label, "SGI disklabel");
    782777
    783     sgi_other_endian = (BYTE_ORDER == LITTLE_ENDIAN);
    784     res = ioctl(fd, BLKGETSIZE, &longsectors);
    785     if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
    786         heads = geometry.heads;
    787         sectors = geometry.sectors;
     778    sgi_other_endian = BB_LITTLE_ENDIAN;
     779    res = ioctl(dev_fd, BLKGETSIZE, &longsectors);
     780    if (!ioctl(dev_fd, HDIO_GETGEO, &geometry)) {
     781        g_heads = geometry.heads;
     782        g_sectors = geometry.sectors;
    788783        if (res == 0) {
    789784            /* the get device size ioctl was successful */
    790             cylinders = longsectors / (heads * sectors);
    791             cylinders /= sec_fac;
     785            g_cylinders = longsectors / (g_heads * g_sectors);
     786            g_cylinders /= sec_fac;
    792787        } else {
    793788            /* otherwise print error and use truncated version */
    794             cylinders = geometry.cylinders;
     789            g_cylinders = geometry.cylinders;
    795790            printf(
    796 "Warning: BLKGETSIZE ioctl failed on %s.  Using geometry cylinder value of %d.\n"
    797 "This value may be truncated for devices > 33.8 GB.\n", disk_device, cylinders);
     791"Warning: BLKGETSIZE ioctl failed on %s.  Using geometry cylinder value of %u.\n"
     792"This value may be truncated for devices > 33.8 GB.\n", disk_device, g_cylinders);
    798793        }
    799794    }
     
    805800                old[i].start = get_start_sect(get_part_table(i));
    806801                old[i].nsect = get_nr_sects(get_part_table(i));
    807                 printf("Trying to keep parameters of partition %d\n", i);
    808                 if (debug)
    809                     printf("ID=%02x\tSTART=%d\tLENGTH=%d\n",
     802                printf("Trying to keep parameters of partition %u\n", i);
     803                if (SGI_DEBUG)
     804                    printf("ID=%02x\tSTART=%u\tLENGTH=%u\n",
    810805                old[i].sysid, old[i].start, old[i].nsect);
    811806            }
     
    851846    //memset( &(sgilabel->directory), 0, sizeof(struct volume_directory)*15 );
    852847    //memset( &(sgilabel->partitions), 0, sizeof(struct sgi_partinfo)*16 );
    853     current_label_type = label_sgi;
    854     partitions = 16;
     848    current_label_type = LABEL_SGI;
     849    g_partitions = 16;
    855850    sgi_volumes = 15;
    856851    sgi_set_entire();
  • branches/2.2.9/mindi-busybox/util-linux/fdisk_sun.c

    r1765 r2725  
    1 #if ENABLE_FEATURE_SUN_LABEL
    2 
    3 #define SUNOS_SWAP 3
    4 #define SUN_WHOLE_DISK 5
    5 
    6 #define SUN_LABEL_MAGIC          0xDABE
    7 #define SUN_LABEL_MAGIC_SWAPPED  0xBEDA
    8 #define SUN_SSWAP16(x) (sun_other_endian ? fdisk_swap16(x) : (uint16_t)(x))
    9 #define SUN_SSWAP32(x) (sun_other_endian ? fdisk_swap32(x) : (uint32_t)(x))
    10 
    11 /* Copied from linux/major.h */
    12 #define FLOPPY_MAJOR    2
    13 
    14 #define SCSI_IOCTL_GET_IDLUN 0x5382
    15 
    161/*
    17  * fdisksunlabel.c
     2 * fdisk_sun.c
    183 *
    194 * I think this is mostly, or entirely, due to
     
    249 * Sat Mar 20 EST 1999 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
    2510 *      Internationalization
     11 *
     12 * Licensed under GPLv2, see file LICENSE in this source tree.
    2613 */
    2714
    28 
    29 static int sun_other_endian;
    30 static int scsi_disk;
    31 static int floppy;
     15#if ENABLE_FEATURE_SUN_LABEL
     16
     17#define SUNOS_SWAP 3
     18#define SUN_WHOLE_DISK 5
     19
     20#define SUN_LABEL_MAGIC          0xDABE
     21#define SUN_LABEL_MAGIC_SWAPPED  0xBEDA
     22#define SUN_SSWAP16(x) (sun_other_endian ? fdisk_swap16(x) : (uint16_t)(x))
     23#define SUN_SSWAP32(x) (sun_other_endian ? fdisk_swap32(x) : (uint32_t)(x))
     24
     25/* Copied from linux/major.h */
     26#define FLOPPY_MAJOR    2
     27
     28#define SCSI_IOCTL_GET_IDLUN 0x5382
     29
     30static smallint sun_other_endian;
     31static smallint scsi_disk;
     32static smallint floppy;
    3233
    3334#ifndef IDE0_MAJOR
     
    4344    struct stat bootstat;
    4445
    45     if (fstat(fd, &bootstat) < 0) {
     46    if (fstat(dev_fd, &bootstat) < 0) {
    4647        scsi_disk = 0;
    4748        floppy = 0;
     
    8182
    8283static void
    83 set_sun_partition(int i, uint start, uint stop, int sysid)
     84set_sun_partition(int i, unsigned start, unsigned stop, int sysid)
    8485{
    8586    sunlabel->infos[i].id = sysid;
    8687    sunlabel->partitions[i].start_cylinder =
    87         SUN_SSWAP32(start / (heads * sectors));
     88        SUN_SSWAP32(start / (g_heads * g_sectors));
    8889    sunlabel->partitions[i].num_sectors =
    8990        SUN_SSWAP32(stop - start);
     
    9899
    99100    if (sunlabel->magic != SUN_LABEL_MAGIC
    100      && sunlabel->magic != SUN_LABEL_MAGIC_SWAPPED) {
    101         current_label_type = label_dos;
     101     && sunlabel->magic != SUN_LABEL_MAGIC_SWAPPED
     102    ) {
     103        current_label_type = LABEL_DOS;
    102104        sun_other_endian = 0;
    103105        return 0;
     
    112114"or force a fresh label (s command in main menu)\n");
    113115    } else {
    114         heads = SUN_SSWAP16(sunlabel->ntrks);
    115         cylinders = SUN_SSWAP16(sunlabel->ncyl);
    116         sectors = SUN_SSWAP16(sunlabel->nsect);
     116        g_heads = SUN_SSWAP16(sunlabel->ntrks);
     117        g_cylinders = SUN_SSWAP16(sunlabel->ncyl);
     118        g_sectors = SUN_SSWAP16(sunlabel->nsect);
    117119    }
    118120    update_units();
    119     current_label_type = label_sun;
    120     partitions = 8;
     121    current_label_type = LABEL_SUN;
     122    g_partitions = 8;
    121123    return 1;
    122124}
     
    169171    int i;
    170172
    171     if (ioctl(fd, SCSI_IOCTL_GET_IDLUN, &id))
     173    if (ioctl(dev_fd, SCSI_IOCTL_GET_IDLUN, &id))
    172174        return NULL;
    173175
    174176    sprintf(buffer,
    175         "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n",
     177        "Host: scsi%u Channel: %02u Id: %02u Lun: %02u\n",
    176178        /* This is very wrong (works only if you have one HBA),
    177179           but I haven't found a way how to get hostno
     
    182184        (id[0]>>8) & 0xff
    183185    );
    184     pfd = fopen("/proc/scsi/scsi", "r");
     186    pfd = fopen_for_read("/proc/scsi/scsi");
    185187    if (!pfd) {
    186188        return NULL;
     
    231233{
    232234    struct hd_geometry geometry;
    233     unsigned int ndiv;
    234     int i;
     235    unsigned ndiv;
    235236    unsigned char c;
    236237    const struct sun_predefined_drives *p = NULL;
     
    242243    sunlabel->magic = SUN_SSWAP16(SUN_LABEL_MAGIC);
    243244    if (!floppy) {
     245        unsigned i;
    244246        puts("Drive type\n"
    245247         "   ?   auto configure\n"
     
    273275    }
    274276    if (!p || floppy) {
    275         if (!ioctl(fd, HDIO_GETGEO, &geometry)) {
    276             heads = geometry.heads;
    277             sectors = geometry.sectors;
    278             cylinders = geometry.cylinders;
     277        if (!ioctl(dev_fd, HDIO_GETGEO, &geometry)) {
     278            g_heads = geometry.heads;
     279            g_sectors = geometry.sectors;
     280            g_cylinders = geometry.cylinders;
    279281        } else {
    280             heads = 0;
    281             sectors = 0;
    282             cylinders = 0;
     282            g_heads = 0;
     283            g_sectors = 0;
     284            g_cylinders = 0;
    283285        }
    284286        if (floppy) {
    285287            sunlabel->nacyl = 0;
    286             sunlabel->pcylcount = SUN_SSWAP16(cylinders);
     288            sunlabel->pcylcount = SUN_SSWAP16(g_cylinders);
    287289            sunlabel->rspeed = SUN_SSWAP16(300);
    288290            sunlabel->ilfact = SUN_SSWAP16(1);
    289291            sunlabel->sparecyl = 0;
    290292        } else {
    291             heads = read_int(1, heads, 1024, 0, "Heads");
    292             sectors = read_int(1, sectors, 1024, 0, "Sectors/track");
    293         if (cylinders)
    294             cylinders = read_int(1, cylinders-2, 65535, 0, "Cylinders");
     293            g_heads = read_int(1, g_heads, 1024, 0, "Heads");
     294            g_sectors = read_int(1, g_sectors, 1024, 0, "Sectors/track");
     295        if (g_cylinders)
     296            g_cylinders = read_int(1, g_cylinders - 2, 65535, 0, "Cylinders");
    295297        else
    296             cylinders = read_int(1, 0, 65535, 0, "Cylinders");
     298            g_cylinders = read_int(1, 0, 65535, 0, "Cylinders");
    297299            sunlabel->nacyl = SUN_SSWAP16(read_int(0, 2, 65535, 0, "Alternate cylinders"));
    298             sunlabel->pcylcount = SUN_SSWAP16(read_int(0, cylinders+SUN_SSWAP16(sunlabel->nacyl), 65535, 0, "Physical cylinders"));
     300            sunlabel->pcylcount = SUN_SSWAP16(read_int(0, g_cylinders + SUN_SSWAP16(sunlabel->nacyl), 65535, 0, "Physical cylinders"));
    299301            sunlabel->rspeed = SUN_SSWAP16(read_int(1, 5400, 100000, 0, "Rotation speed (rpm)"));
    300302            sunlabel->ilfact = SUN_SSWAP16(read_int(1, 1, 32, 0, "Interleave factor"));
    301             sunlabel->sparecyl = SUN_SSWAP16(read_int(0, 0, sectors, 0, "Extra sectors per cylinder"));
     303            sunlabel->sparecyl = SUN_SSWAP16(read_int(0, 0, g_sectors, 0, "Extra sectors per cylinder"));
    302304        }
    303305    } else {
     
    310312        sunlabel->rspeed = SUN_SSWAP16(p->rspeed);
    311313        sunlabel->ilfact = SUN_SSWAP16(1);
    312         cylinders = p->ncyl;
    313         heads = p->ntrks;
    314         sectors = p->nsect;
     314        g_cylinders = p->ncyl;
     315        g_heads = p->ntrks;
     316        g_sectors = p->nsect;
    315317        puts("You may change all the disk params from the x menu");
    316318    }
    317319
    318320    snprintf((char *)(sunlabel->info), sizeof(sunlabel->info),
    319         "%s%s%s cyl %d alt %d hd %d sec %d",
     321        "%s%s%s cyl %u alt %u hd %u sec %u",
    320322        p ? p->vendor : "", (p && *p->vendor) ? " " : "",
    321323        p ? p->model : (floppy ? "3,5\" floppy" : "Linux custom"),
    322         cylinders, SUN_SSWAP16(sunlabel->nacyl), heads, sectors);
    323 
    324     sunlabel->ntrks = SUN_SSWAP16(heads);
    325     sunlabel->nsect = SUN_SSWAP16(sectors);
    326     sunlabel->ncyl = SUN_SSWAP16(cylinders);
     324        g_cylinders, SUN_SSWAP16(sunlabel->nacyl), g_heads, g_sectors);
     325
     326    sunlabel->ntrks = SUN_SSWAP16(g_heads);
     327    sunlabel->nsect = SUN_SSWAP16(g_sectors);
     328    sunlabel->ncyl = SUN_SSWAP16(g_cylinders);
    327329    if (floppy)
    328         set_sun_partition(0, 0, cylinders * heads * sectors, LINUX_NATIVE);
     330        set_sun_partition(0, 0, g_cylinders * g_heads * g_sectors, LINUX_NATIVE);
    329331    else {
    330         if (cylinders * heads * sectors >= 150 * 2048) {
    331             ndiv = cylinders - (50 * 2048 / (heads * sectors)); /* 50M swap */
     332        if (g_cylinders * g_heads * g_sectors >= 150 * 2048) {
     333            ndiv = g_cylinders - (50 * 2048 / (g_heads * g_sectors)); /* 50M swap */
    332334        } else
    333             ndiv = cylinders * 2 / 3;
    334         set_sun_partition(0, 0, ndiv * heads * sectors, LINUX_NATIVE);
    335         set_sun_partition(1, ndiv * heads * sectors, cylinders * heads * sectors, LINUX_SWAP);
     335            ndiv = g_cylinders * 2 / 3;
     336        set_sun_partition(0, 0, ndiv * g_heads * g_sectors, LINUX_NATIVE);
     337        set_sun_partition(1, ndiv * g_heads * g_sectors, g_cylinders * g_heads * g_sectors, LINUX_SWAP);
    336338        sunlabel->infos[1].flags |= 0x01; /* Not mountable */
    337339    }
    338     set_sun_partition(2, 0, cylinders * heads * sectors, SUN_WHOLE_DISK);
     340    set_sun_partition(2, 0, g_cylinders * g_heads * g_sectors, SUN_WHOLE_DISK);
    339341    {
    340342        unsigned short *ush = (unsigned short *)sunlabel;
     
    347349    set_all_unchanged();
    348350    set_changed(0);
    349     get_boot(create_empty_sun);
     351    get_boot(CREATE_EMPTY_SUN);
    350352}
    351353
     
    361363
    362364static void
    363 fetch_sun(uint *starts, uint *lens, uint *start, uint *stop)
     365fetch_sun(unsigned *starts, unsigned *lens, unsigned *start, unsigned *stop)
    364366{
    365367    int i, continuous = 1;
    366368
    367369    *start = 0;
    368     *stop = cylinders * heads * sectors;
    369     for (i = 0; i < partitions; i++) {
     370    *stop = g_cylinders * g_heads * g_sectors;
     371    for (i = 0; i < g_partitions; i++) {
    370372        if (sunlabel->partitions[i].num_sectors
    371373         && sunlabel->infos[i].id
    372374         && sunlabel->infos[i].id != SUN_WHOLE_DISK) {
    373             starts[i] = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
     375            starts[i] = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * g_heads * g_sectors;
    374376            lens[i] = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
    375377            if (continuous) {
     
    390392}
    391393
    392 static uint *verify_sun_starts;
     394static unsigned *verify_sun_starts;
    393395
    394396static int
     
    404406verify_sun(void)
    405407{
    406     uint starts[8], lens[8], start, stop;
     408    unsigned starts[8], lens[8], start, stop;
    407409    int i,j,k,starto,endo;
    408410    int array[8];
    409411
    410412    verify_sun_starts = starts;
    411     fetch_sun(starts,lens,&start,&stop);
     413    fetch_sun(starts, lens, &start, &stop);
    412414    for (k = 0; k < 7; k++) {
    413415        for (i = 0; i < 8; i++) {
    414             if (k && (lens[i] % (heads * sectors))) {
    415                 printf("Partition %d doesn't end on cylinder boundary\n", i+1);
     416            if (k && (lens[i] % (g_heads * g_sectors))) {
     417                printf("Partition %u doesn't end on cylinder boundary\n", i+1);
    416418            }
    417419            if (lens[i]) {
     
    433435                                if (starts[j]+lens[j] < endo)
    434436                                    endo = starts[j]+lens[j];
    435                                 printf("Partition %d overlaps with others in "
    436                                     "sectors %d-%d\n", i+1, starto, endo);
     437                                printf("Partition %u overlaps with others in "
     438                                    "sectors %u-%u\n", i+1, starto, endo);
    437439                            }
    438440                        }
     
    453455        return;
    454456    }
    455     stop = cylinders * heads * sectors;
     457    stop = g_cylinders * g_heads * g_sectors;
    456458    if (starts[array[0]])
    457         printf("Unused gap - sectors 0-%d\n", starts[array[0]]);
     459        printf("Unused gap - sectors %u-%u\n", 0, starts[array[0]]);
    458460    for (i = 0; i < 7 && array[i+1] != -1; i++) {
    459         printf("Unused gap - sectors %d-%d\n", starts[array[i]]+lens[array[i]], starts[array[i+1]]);
     461        printf("Unused gap - sectors %u-%u\n", starts[array[i]]+lens[array[i]], starts[array[i+1]]);
    460462    }
    461463    start = starts[array[i]] + lens[array[i]];
    462464    if (start < stop)
    463         printf("Unused gap - sectors %d-%d\n", start, stop);
     465        printf("Unused gap - sectors %u-%u\n", start, stop);
    464466}
    465467
     
    467469add_sun_partition(int n, int sys)
    468470{
    469     uint start, stop, stop2;
    470     uint starts[8], lens[8];
     471    unsigned start, stop, stop2;
     472    unsigned starts[8], lens[8];
    471473    int whole_disk = 0;
    472474
     
    479481    }
    480482
    481     fetch_sun(starts,lens,&start,&stop);
     483    fetch_sun(starts, lens, &start, &stop);
    482484    if (stop <= start) {
    483485        if (n == 2)
     
    500502        else
    501503            /* Starting sector has to be properly aligned */
    502             first = (first + heads * sectors - 1) / (heads * sectors);
     504            first = (first + g_heads * g_sectors - 1) / (g_heads * g_sectors);
    503505        if (n == 2 && first != 0)
    504506            printf("\
     
    521523           starting at block 0 in an md, or the label will
    522524           be trashed. */
    523         for (i = 0; i < partitions; i++)
     525        for (i = 0; i < g_partitions; i++)
    524526            if (lens[i] && starts[i] <= first && starts[i] + lens[i] > first)
    525527                break;
    526         if (i < partitions && !whole_disk) {
     528        if (i < g_partitions && !whole_disk) {
    527529            if (n == 2 && !first) {
    528530                whole_disk = 1;
    529531                break;
    530532            }
    531             printf("Sector %d is already allocated\n", first);
     533            printf("Sector %u is already allocated\n", first);
    532534        } else
    533535            break;
    534536    }
    535     stop = cylinders * heads * sectors;
     537    stop = g_cylinders * g_heads * g_sectors;
    536538    stop2 = stop;
    537     for (i = 0; i < partitions; i++) {
     539    for (i = 0; i < g_partitions; i++) {
    538540        if (starts[i] > first && starts[i] < stop)
    539541            stop = starts[i];
     
    560562            printf(
    561563"You haven't covered the whole disk with the 3rd partition,\n"
    562 "but your value %d %s covers some other partition.\n"
    563 "Your entry has been changed to %d %s\n",
     564"but your value %u %s covers some other partition.\n"
     565"Your entry has been changed to %u %s\n",
    564566                scround(last), str_units(SINGULAR),
    565567                scround(stop), str_units(SINGULAR));
     
    582584     && sunlabel->infos[i].id == SUN_WHOLE_DISK
    583585     && !sunlabel->partitions[i].start_cylinder
    584      && (nsec = SUN_SSWAP32(sunlabel->partitions[i].num_sectors)) == heads * sectors * cylinders)
     586     && (nsec = SUN_SSWAP32(sunlabel->partitions[i].num_sectors)) == g_heads * g_sectors * g_cylinders)
    585587        printf("If you want to maintain SunOS/Solaris compatibility, "
    586588            "consider leaving this\n"
     
    627629    if (xtra)
    628630        printf(
    629         "\nDisk %s (Sun disk label): %d heads, %d sectors, %d rpm\n"
    630         "%d cylinders, %d alternate cylinders, %d physical cylinders\n"
    631         "%d extra sects/cyl, interleave %d:1\n"
     631        "\nDisk %s (Sun disk label): %u heads, %u sectors, %u rpm\n"
     632        "%u cylinders, %u alternate cylinders, %u physical cylinders\n"
     633        "%u extra sects/cyl, interleave %u:1\n"
    632634        "%s\n"
    633         "Units = %s of %d * 512 bytes\n\n",
    634             disk_device, heads, sectors, SUN_SSWAP16(sunlabel->rspeed),
    635             cylinders, SUN_SSWAP16(sunlabel->nacyl),
     635        "Units = %s of %u * 512 bytes\n\n",
     636            disk_device, g_heads, g_sectors, SUN_SSWAP16(sunlabel->rspeed),
     637            g_cylinders, SUN_SSWAP16(sunlabel->nacyl),
    636638            SUN_SSWAP16(sunlabel->pcylcount),
    637639            SUN_SSWAP16(sunlabel->sparecyl),
     
    641643    else
    642644        printf(
    643     "\nDisk %s (Sun disk label): %d heads, %d sectors, %d cylinders\n"
    644     "Units = %s of %d * 512 bytes\n\n",
    645             disk_device, heads, sectors, cylinders,
     645    "\nDisk %s (Sun disk label): %u heads, %u sectors, %u cylinders\n"
     646    "Units = %s of %u * 512 bytes\n\n",
     647            disk_device, g_heads, g_sectors, g_cylinders,
    646648            str_units(PLURAL), units_per_sector);
    647649
    648650    printf("%*s Flag    Start       End    Blocks   Id  System\n",
    649651        w + 1, "Device");
    650     for (i = 0; i < partitions; i++) {
     652    for (i = 0; i < g_partitions; i++) {
    651653        if (sunlabel->partitions[i].num_sectors) {
    652             uint32_t start = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * heads * sectors;
     654            uint32_t start = SUN_SSWAP32(sunlabel->partitions[i].start_cylinder) * g_heads * g_sectors;
    653655            uint32_t len = SUN_SSWAP32(sunlabel->partitions[i].num_sectors);
    654             printf("%s %c%c %9ld %9ld %9ld%c  %2x  %s\n",
    655                 partname(disk_device, i+1, w),          /* device */
     656            printf("%s %c%c %9lu %9lu %9lu%c  %2x  %s\n",
     657                partname(disk_device, i+1, w),                  /* device */
    656658                (sunlabel->infos[i].flags & 0x01) ? 'u' : ' ',  /* flags */
    657659                (sunlabel->infos[i].flags & 0x10) ? 'r' : ' ',
     
    685687{
    686688    sunlabel->sparecyl =
    687         SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->sparecyl), sectors, 0,
     689        SUN_SSWAP16(read_int(0, SUN_SSWAP16(sunlabel->sparecyl), g_sectors, 0,
    688690                "Extra sectors per cylinder"));
    689691}
     
    723725        csum ^= *ush++;
    724726    sunlabel->csum = csum;
    725     if (lseek(fd, 0, SEEK_SET) < 0)
    726         fdisk_fatal(unable_to_seek);
    727     if (write(fd, sunlabel, SECTOR_SIZE) != SECTOR_SIZE)
    728         fdisk_fatal(unable_to_write);
     727    write_sector(0, sunlabel);
    729728}
    730729#endif /* SUN_LABEL */
  • branches/2.2.9/mindi-busybox/util-linux/freeramdisk.c

    r1765 r2725  
    77 * Unified with fdflush by Tito Ragusa <farmatito@tiscali.it>
    88 *
    9  * Licensed under GPLv2, see file LICENSE in this tarball for details.
     9 * Licensed under GPLv2, see file LICENSE in this source tree.
    1010 */
    11 
     11#include <sys/mount.h>
    1212#include "libbb.h"
    1313
     
    1515#define FDFLUSH  _IO(2,0x4b)
    1616
    17 int freeramdisk_main(int argc, char **argv);
    18 int freeramdisk_main(int argc, char **argv)
     17int freeramdisk_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     18int freeramdisk_main(int argc UNUSED_PARAM, char **argv)
    1919{
    2020    int fd;
    2121
    22     if (argc != 2) bb_show_usage();
    23 
    24     fd = xopen(argv[1], O_RDWR);
     22    fd = xopen(single_argv(argv), O_RDWR);
    2523
    2624    // Act like freeramdisk, fdflush, or both depending on configuration.
    27     ioctl_or_perror_and_die(fd, (ENABLE_FREERAMDISK && applet_name[1]=='r')
     25    ioctl_or_perror_and_die(fd, (ENABLE_FREERAMDISK && applet_name[1] == 'r')
    2826            || !ENABLE_FDFLUSH ? BLKFLSBUF : FDFLUSH, NULL, "%s", argv[1]);
    2927
  • branches/2.2.9/mindi-busybox/util-linux/fsck_minix.c

    r1765 r2725  
    55 * (C) 1991, 1992 Linus Torvalds.
    66 *
    7  * Licensed under GPLv2, see file LICENSE in this tarball for details.
     7 * Licensed under GPLv2, see file LICENSE in this source tree.
    88 */
    99
     
    3030 *
    3131 * Sat Mar  6 18:59:42 1993, faith@cs.unc.edu: Output namelen with
    32  *                           super-block information
     32 *                           superblock information
    3333 *
    3434 * Sat Oct  9 11:17:11 1993, faith@cs.unc.edu: make exit status conform
     
    6565 *             Andreas Schwab.
    6666 *
    67  * 1999-02-22 Arkadiusz Mikiewicz <misiek@misiek.eu.org>
     67 * 1999-02-22 Arkadiusz Mickiewicz <misiek@misiek.eu.org>
    6868 * - added Native Language Support
    6969 *
     
    8080 *  -r for repairs (interactive) (not implemented)
    8181 *  -v for verbose (tells how many files)
    82  *  -s for super-block info
     82 *  -s for superblock info
    8383 *  -m for minix-like "mode not cleared" warnings
    8484 *  -f force filesystem check even if filesystem marked as valid
     
    9595#define BLKGETSIZE _IO(0x12,96)    /* return device size */
    9696#endif
     97
     98struct BUG_bad_inode_size {
     99    char BUG_bad_inode1_size[(INODE_SIZE1 * MINIX1_INODES_PER_BLOCK != BLOCK_SIZE) ? -1 : 1];
     100#if ENABLE_FEATURE_MINIX2
     101    char BUG_bad_inode2_size[(INODE_SIZE2 * MINIX2_INODES_PER_BLOCK != BLOCK_SIZE) ? -1 : 1];
     102#endif
     103};
    97104
    98105enum {
     
    108115};
    109116
     117
    110118#if !ENABLE_FEATURE_MINIX2
    111119enum { version2 = 0 };
     
    114122enum { MAX_DEPTH = 32 };
    115123
     124enum { dev_fd = 3 };
     125
    116126struct globals {
    117     int dev_fd;
    118127#if ENABLE_FEATURE_MINIX2
    119128    smallint version2;
    120129#endif
    121     smallint repair, automatic, verbose, list, show, warn_mode, force;
    122130    smallint changed;  /* is filesystem modified? */
    123131    smallint errors_uncorrected;  /* flag if some error was not corrected */
     
    125133    smallint dirsize;
    126134    smallint namelen;
    127     char *device_name;
     135    const char *device_name;
    128136    int directory, regular, blockdev, chardev, links, symlinks, total;
    129137    char *inode_buffer;
     
    141149    /* Bigger stuff */
    142150    struct termios sv_termios;
    143     char super_block_buffer[BLOCK_SIZE];
     151    char superblock_buffer[BLOCK_SIZE];
    144152    char add_zone_ind_blk[BLOCK_SIZE];
    145153    char add_zone_dind_blk[BLOCK_SIZE];
    146     USE_FEATURE_MINIX2(char add_zone_tind_blk[BLOCK_SIZE];)
     154    IF_FEATURE_MINIX2(char add_zone_tind_blk[BLOCK_SIZE];)
    147155    char check_file_blk[BLOCK_SIZE];
    148156
     
    150158    char current_name[MAX_DEPTH * MINIX_NAME_MAX];
    151159};
    152 
    153160#define G (*ptr_to_globals)
    154 #define dev_fd             (G.dev_fd             )
    155161#if ENABLE_FEATURE_MINIX2
    156162#define version2           (G.version2           )
    157163#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              )
    165164#define changed            (G.changed            )
    166165#define errors_uncorrected (G.errors_uncorrected )
     
    184183#define name_component     (G.name_component     )
    185184#define sv_termios         (G.sv_termios         )
    186 #define super_block_buffer (G.super_block_buffer )
     185#define superblock_buffer  (G.superblock_buffer )
    187186#define add_zone_ind_blk   (G.add_zone_ind_blk   )
    188187#define add_zone_dind_blk  (G.add_zone_dind_blk  )
     
    191190#define current_name       (G.current_name       )
    192191#define INIT_G() do { \
    193     PTR_TO_GLOBALS = xzalloc(sizeof(G)); \
     192    SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
    194193    dirsize = 16; \
    195194    namelen = 14; \
     
    199198} while (0)
    200199
     200
     201#define OPTION_STR "larvsmf"
     202enum {
     203    OPT_l = (1 << 0),
     204    OPT_a = (1 << 1),
     205    OPT_r = (1 << 2),
     206    OPT_v = (1 << 3),
     207    OPT_s = (1 << 4),
     208    OPT_w = (1 << 5),
     209    OPT_f = (1 << 6),
     210};
     211#define OPT_list      (option_mask32 & OPT_l)
     212#define OPT_automatic (option_mask32 & OPT_a)
     213#define OPT_repair    (option_mask32 & OPT_r)
     214#define OPT_verbose   (option_mask32 & OPT_v)
     215#define OPT_show      (option_mask32 & OPT_s)
     216#define OPT_warn_mode (option_mask32 & OPT_w)
     217#define OPT_force     (option_mask32 & OPT_f)
     218/* non-automatic repairs requested? */
     219#define OPT_manual    ((option_mask32 & (OPT_a|OPT_r)) == OPT_r)
     220
     221
    201222#define Inode1 (((struct minix1_inode *) inode_buffer)-1)
    202223#define Inode2 (((struct minix2_inode *) inode_buffer)-1)
    203224
    204 #define Super (*(struct minix_super_block *)(super_block_buffer))
     225#define Super (*(struct minix_superblock *)(superblock_buffer))
    205226
    206227#if ENABLE_FEATURE_MINIX2
     
    223244}
    224245
    225 #if ENABLE_FEATURE_MINIX2
    226 #define INODE_BLOCKS div_roundup(INODES, (version2 ? MINIX2_INODES_PER_BLOCK \
    227                     : MINIX1_INODES_PER_BLOCK))
     246#if !ENABLE_FEATURE_MINIX2
     247#define INODE_BLOCKS            div_roundup(INODES, MINIX1_INODES_PER_BLOCK)
    228248#else
    229 #define INODE_BLOCKS div_roundup(INODES, MINIX1_INODES_PER_BLOCK)
    230 #endif
    231 
    232 #define INODE_BUFFER_SIZE (INODE_BLOCKS * BLOCK_SIZE)
    233 #define NORM_FIRSTZONE    (2 + IMAPS + ZMAPS + INODE_BLOCKS)
     249#define INODE_BLOCKS            div_roundup(INODES, \
     250                                (version2 ? MINIX2_INODES_PER_BLOCK : MINIX1_INODES_PER_BLOCK))
     251#endif
     252
     253#define INODE_BUFFER_SIZE       (INODE_BLOCKS * BLOCK_SIZE)
     254#define NORM_FIRSTZONE          (2 + IMAPS + ZMAPS + INODE_BLOCKS)
    234255
    235256/* Before you ask "where they come from?": */
     
    268289#endif
    269290
    270 static void die(const char *str) ATTRIBUTE_NORETURN;
     291static void die(const char *str) NORETURN;
    271292static void die(const char *str)
    272293{
    273294    if (termios_set)
    274         tcsetattr(0, TCSANOW, &sv_termios);
     295        tcsetattr_stdin_TCSANOW(&sv_termios);
    275296    bb_error_msg_and_die("%s", str);
    276297}
     
    307328    int c;
    308329
    309     if (!repair) {
    310         puts("");
     330    if (!OPT_repair) {
     331        bb_putchar('\n');
    311332        errors_uncorrected = 1;
    312333        return 0;
    313334    }
    314     if (automatic) {
    315         puts("");
     335    if (OPT_automatic) {
     336        bb_putchar('\n');
    316337        if (!def)
    317338            errors_uncorrected = 1;
     
    320341    printf(def ? "%s (y/n)? " : "%s (n/y)? ", string);
    321342    for (;;) {
    322         fflush(stdout);
     343        fflush_all();
    323344        c = getchar();
    324345        if (c == EOF) {
     
    327348            return def;
    328349        }
    329         c = toupper(c);
    330         if (c == 'Y') {
     350        if (c == '\n')
     351            break;
     352        c |= 0x20; /* tolower */
     353        if (c == 'y') {
    331354            def = 1;
    332355            break;
    333         } else if (c == 'N') {
     356        }
     357        if (c == 'n') {
    334358            def = 0;
    335359            break;
    336         } else if (c == ' ' || c == '\n')
    337             break;
     360        }
    338361    }
    339362    if (def)
     
    353376static void check_mount(void)
    354377{
    355     FILE *f;
    356     struct mntent *mnt;
    357     int cont;
    358     int fd;
    359 
    360     f = setmntent(MOUNTED, "r");
    361     if (f == NULL)
    362         return;
    363     while ((mnt = getmntent(f)) != NULL)
    364         if (strcmp(device_name, mnt->mnt_fsname) == 0)
    365             break;
    366     endmntent(f);
    367     if (!mnt)
    368         return;
    369 
    370     /*
    371      * If the root is mounted read-only, then /etc/mtab is
    372      * probably not correct; so we won't issue a warning based on
    373      * it.
    374      */
    375     fd = open(MOUNTED, O_RDWR);
    376     if (fd < 0 && errno == EROFS)
    377         return;
    378     close(fd);
    379 
    380     printf("%s is mounted. ", device_name);
    381     cont = 0;
    382     if (isatty(0) && isatty(1))
    383         cont = ask("Do you really want to continue", 0);
    384     if (!cont) {
    385         printf("Check aborted\n");
    386         exit(0);
     378    if (find_mount_point(device_name, 0)) {
     379        int cont;
     380#if ENABLE_FEATURE_MTAB_SUPPORT
     381        /*
     382         * If the root is mounted read-only, then /etc/mtab is
     383         * probably not correct; so we won't issue a warning based on
     384         * it.
     385         */
     386        int fd = open(bb_path_mtab_file, O_RDWR);
     387
     388        if (fd < 0 && errno == EROFS)
     389            return;
     390        close(fd);
     391#endif
     392        printf("%s is mounted. ", device_name);
     393        cont = 0;
     394        if (isatty(0) && isatty(1))
     395            cont = ask("Do you really want to continue", 0);
     396        if (!cont) {
     397            printf("Check aborted\n");
     398            exit(EXIT_SUCCESS);
     399        }
    387400    }
    388401}
     
    424437 * read-block reads block nr into the buffer at addr.
    425438 */
    426 static void read_block(unsigned nr, char *addr)
     439static void read_block(unsigned nr, void *addr)
    427440{
    428441    if (!nr) {
     
    430443        return;
    431444    }
    432     if (BLOCK_SIZE * nr != lseek(dev_fd, BLOCK_SIZE * nr, SEEK_SET)) {
    433         printf("%s: cannot seek to block in file '%s'\n",
    434                 bb_msg_read_error, current_name);
    435         errors_uncorrected = 1;
    436         memset(addr, 0, BLOCK_SIZE);
    437     } else if (BLOCK_SIZE != read(dev_fd, addr, BLOCK_SIZE)) {
    438         printf("%s: bad block in file '%s'\n",
    439                 bb_msg_read_error, current_name);
     445    xlseek(dev_fd, BLOCK_SIZE * nr, SEEK_SET);
     446    if (BLOCK_SIZE != full_read(dev_fd, addr, BLOCK_SIZE)) {
     447        printf("%s: bad block %u in file '%s'\n",
     448                bb_msg_read_error, nr, current_name);
    440449        errors_uncorrected = 1;
    441450        memset(addr, 0, BLOCK_SIZE);
     
    446455 * write_block writes block nr to disk.
    447456 */
    448 static void write_block(unsigned nr, char *addr)
     457static void write_block(unsigned nr, void *addr)
    449458{
    450459    if (!nr)
     
    456465        return;
    457466    }
    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)) {
    461         printf("%s: bad block in file '%s'\n",
    462                 bb_msg_write_error, current_name);
     467    xlseek(dev_fd, BLOCK_SIZE * nr, SEEK_SET);
     468    if (BLOCK_SIZE != full_write(dev_fd, addr, BLOCK_SIZE)) {
     469        printf("%s: bad block %u in file '%s'\n",
     470                bb_msg_write_error, nr, current_name);
    463471        errors_uncorrected = 1;
    464472    }
     
    473481{
    474482    uint16_t ind[BLOCK_SIZE >> 1];
    475     uint16_t dind[BLOCK_SIZE >> 1];
    476483    int block, result;
    477484    smallint blk_chg;
     
    482489    if (blknr < 512) {
    483490        block = check_zone_nr(inode->i_zone + 7, &changed);
    484         read_block(block, (char *) ind);
    485         blk_chg = 0;
    486         result = check_zone_nr(blknr + ind, &blk_chg);
    487         if (blk_chg)
    488             write_block(block, (char *) ind);
    489         return result;
     491        goto common;
    490492    }
    491493    blknr -= 512;
    492494    block = check_zone_nr(inode->i_zone + 8, &changed);
    493     read_block(block, (char *) dind);
     495    read_block(block, ind); /* double indirect */
    494496    blk_chg = 0;
    495     result = check_zone_nr(dind + (blknr / 512), &blk_chg);
     497    result = check_zone_nr(&ind[blknr / 512], &blk_chg);
    496498    if (blk_chg)
    497         write_block(block, (char *) dind);
     499        write_block(block, ind);
    498500    block = result;
    499     read_block(block, (char *) ind);
     501 common:
     502    read_block(block, ind);
    500503    blk_chg = 0;
    501     result = check_zone_nr(ind + (blknr % 512), &blk_chg);
     504    result = check_zone_nr(&ind[blknr % 512], &blk_chg);
    502505    if (blk_chg)
    503         write_block(block, (char *) ind);
     506        write_block(block, ind);
    504507    return result;
    505508}
     
    509512{
    510513    uint32_t ind[BLOCK_SIZE >> 2];
    511     uint32_t dind[BLOCK_SIZE >> 2];
    512     uint32_t tind[BLOCK_SIZE >> 2];
    513514    int block, result;
    514515    smallint blk_chg;
     
    519520    if (blknr < 256) {
    520521        block = check_zone_nr2(inode->i_zone + 7, &changed);
    521         read_block(block, (char *) ind);
    522         blk_chg = 0;
    523         result = check_zone_nr2(blknr + ind, &blk_chg);
    524         if (blk_chg)
    525             write_block(block, (char *) ind);
    526         return result;
     522        goto common2;
    527523    }
    528524    blknr -= 256;
    529     if (blknr >= 256 * 256) {
     525    if (blknr < 256 * 256) {
    530526        block = check_zone_nr2(inode->i_zone + 8, &changed);
    531         read_block(block, (char *) dind);
    532         blk_chg = 0;
    533         result = check_zone_nr2(dind + blknr / 256, &blk_chg);
    534         if (blk_chg)
    535             write_block(block, (char *) dind);
    536         block = result;
    537         read_block(block, (char *) ind);
    538         blk_chg = 0;
    539         result = check_zone_nr2(ind + blknr % 256, &blk_chg);
    540         if (blk_chg)
    541             write_block(block, (char *) ind);
    542         return result;
     527        goto common1;
    543528    }
    544529    blknr -= 256 * 256;
    545530    block = check_zone_nr2(inode->i_zone + 9, &changed);
    546     read_block(block, (char *) tind);
     531    read_block(block, ind); /* triple indirect */
    547532    blk_chg = 0;
    548     result = check_zone_nr2(tind + blknr / (256 * 256), &blk_chg);
     533    result = check_zone_nr2(&ind[blknr / (256 * 256)], &blk_chg);
    549534    if (blk_chg)
    550         write_block(block, (char *) tind);
     535        write_block(block, ind);
    551536    block = result;
    552     read_block(block, (char *) dind);
     537 common1:
     538    read_block(block, ind); /* double indirect */
    553539    blk_chg = 0;
    554     result = check_zone_nr2(dind + (blknr / 256) % 256, &blk_chg);
     540    result = check_zone_nr2(&ind[(blknr / 256) % 256], &blk_chg);
    555541    if (blk_chg)
    556         write_block(block, (char *) dind);
     542        write_block(block, ind);
    557543    block = result;
    558     read_block(block, (char *) ind);
     544 common2:
     545    read_block(block, ind);
    559546    blk_chg = 0;
    560     result = check_zone_nr2(ind + blknr % 256, &blk_chg);
     547    result = check_zone_nr2(&ind[blknr % 256], &blk_chg);
    561548    if (blk_chg)
    562         write_block(block, (char *) ind);
     549        write_block(block, ind);
    563550    return result;
    564551}
    565552#endif
    566553
    567 static void write_super_block(void)
     554static void write_superblock(void)
    568555{
    569556    /*
     
    576563        Super.s_state &= ~MINIX_ERROR_FS;
    577564
    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");
     565    xlseek(dev_fd, BLOCK_SIZE, SEEK_SET);
     566    if (BLOCK_SIZE != full_write(dev_fd, superblock_buffer, BLOCK_SIZE))
     567        die("can't write superblock");
    582568}
    583569
    584570static void write_tables(void)
    585571{
    586     write_super_block();
     572    write_superblock();
    587573
    588574    if (IMAPS * BLOCK_SIZE != write(dev_fd, inode_map, IMAPS * BLOCK_SIZE))
    589         die("cannot write inode map");
     575        die("can't write inode map");
    590576    if (ZMAPS * BLOCK_SIZE != write(dev_fd, zone_map, ZMAPS * BLOCK_SIZE))
    591         die("cannot write zone map");
     577        die("can't write zone map");
    592578    if (INODE_BUFFER_SIZE != write(dev_fd, inode_buffer, INODE_BUFFER_SIZE))
    593         die("cannot write inodes");
     579        die("can't write inodes");
    594580}
    595581
     
    619605static void read_superblock(void)
    620606{
    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");
     607    xlseek(dev_fd, BLOCK_SIZE, SEEK_SET);
     608    if (BLOCK_SIZE != full_read(dev_fd, superblock_buffer, BLOCK_SIZE))
     609        die("can't read superblock");
    625610    /* already initialized to:
    626611    namelen = 14;
     
    641626#endif
    642627    } else
    643         die("bad magic number in super-block");
     628        die("bad magic number in superblock");
    644629    if (ZONESIZE != 0 || BLOCK_SIZE != 1024)
    645630        die("only 1k blocks/zones supported");
    646631    if (IMAPS * BLOCK_SIZE * 8 < INODES + 1)
    647         die("bad s_imap_blocks field in super-block");
     632        die("bad s_imap_blocks field in superblock");
    648633    if (ZMAPS * BLOCK_SIZE * 8 < ZONES - FIRSTZONE + 1)
    649         die("bad s_zmap_blocks field in super-block");
     634        die("bad s_zmap_blocks field in superblock");
    650635}
    651636
     
    658643    zone_count = xmalloc(ZONES);
    659644    if (IMAPS * BLOCK_SIZE != read(dev_fd, inode_map, IMAPS * BLOCK_SIZE))
    660         die("cannot read inode map");
     645        die("can't read inode map");
    661646    if (ZMAPS * BLOCK_SIZE != read(dev_fd, zone_map, ZMAPS * BLOCK_SIZE))
    662         die("cannot read zone map");
     647        die("can't read zone map");
    663648    if (INODE_BUFFER_SIZE != read(dev_fd, inode_buffer, INODE_BUFFER_SIZE))
    664         die("cannot read inodes");
     649        die("can't read inodes");
    665650    if (NORM_FIRSTZONE != FIRSTZONE) {
    666651        printf("warning: firstzone!=norm_firstzone\n");
     
    668653    }
    669654    get_dirsize();
    670     if (show) {
     655    if (OPT_show) {
    671656        printf("%u inodes\n"
    672657            "%u blocks\n"
     
    686671}
    687672
    688 static struct minix1_inode *get_inode(unsigned nr)
    689 {
    690     struct minix1_inode *inode;
    691 
    692     if (!nr || nr > INODES)
    693         return NULL;
     673static void get_inode_common(unsigned nr, uint16_t i_mode)
     674{
    694675    total++;
    695     inode = Inode1 + nr;
    696676    if (!inode_count[nr]) {
    697677        if (!inode_in_use(nr)) {
    698678            printf("Inode %d is marked as 'unused', but it is used "
    699679                    "for file '%s'\n", nr, current_name);
    700             if (repair) {
     680            if (OPT_repair) {
    701681                if (ask("Mark as 'in use'", 1))
    702682                    mark_inode(nr);
     
    705685            }
    706686        }
    707         if (S_ISDIR(inode->i_mode))
     687        if (S_ISDIR(i_mode))
    708688            directory++;
    709         else if (S_ISREG(inode->i_mode))
     689        else if (S_ISREG(i_mode))
    710690            regular++;
    711         else if (S_ISCHR(inode->i_mode))
     691        else if (S_ISCHR(i_mode))
    712692            chardev++;
    713         else if (S_ISBLK(inode->i_mode))
     693        else if (S_ISBLK(i_mode))
    714694            blockdev++;
    715         else if (S_ISLNK(inode->i_mode))
     695        else if (S_ISLNK(i_mode))
    716696            symlinks++;
    717         else if (S_ISSOCK(inode->i_mode));
    718         else if (S_ISFIFO(inode->i_mode));
     697        else if (S_ISSOCK(i_mode));
     698        else if (S_ISFIFO(i_mode));
    719699        else {
    720             printf("%s has mode %05o\n", current_name, inode->i_mode);
    721         }
    722 
     700            printf("%s has mode %05o\n", current_name, i_mode);
     701        }
    723702    } else
    724703        links++;
     
    728707        errors_uncorrected = 1;
    729708    }
    730     return inode;
    731 }
    732 
    733 #if ENABLE_FEATURE_MINIX2
    734 static struct minix2_inode *get_inode2(unsigned nr)
    735 {
    736     struct minix2_inode *inode;
     709}
     710
     711static struct minix1_inode *get_inode(unsigned nr)
     712{
     713    struct minix1_inode *inode;
    737714
    738715    if (!nr || nr > INODES)
    739716        return NULL;
    740     total++;
     717    inode = Inode1 + nr;
     718    get_inode_common(nr, inode->i_mode);
     719    return inode;
     720}
     721
     722#if ENABLE_FEATURE_MINIX2
     723static struct minix2_inode *get_inode2(unsigned nr)
     724{
     725    struct minix2_inode *inode;
     726
     727    if (!nr || nr > INODES)
     728        return NULL;
    741729    inode = Inode2 + nr;
    742     if (!inode_count[nr]) {
    743         if (!inode_in_use(nr)) {
    744             printf("Inode %d is marked as 'unused', but it is used "
    745                     "for file '%s'\n", nr, current_name);
    746             if (repair) {
    747                 if (ask("Mark as 'in use'", 1))
    748                     mark_inode(nr);
    749                 else
    750                     errors_uncorrected = 1;
    751             }
    752         }
    753         if (S_ISDIR(inode->i_mode))
    754             directory++;
    755         else if (S_ISREG(inode->i_mode))
    756             regular++;
    757         else if (S_ISCHR(inode->i_mode))
    758             chardev++;
    759         else if (S_ISBLK(inode->i_mode))
    760             blockdev++;
    761         else if (S_ISLNK(inode->i_mode))
    762             symlinks++;
    763         else if (S_ISSOCK(inode->i_mode));
    764         else if (S_ISFIFO(inode->i_mode));
    765         else {
    766             printf("%s has mode %05o\n", current_name, inode->i_mode);
    767         }
    768     } else
    769         links++;
    770     if (!++inode_count[nr]) {
    771         printf("Warning: inode count too big\n");
    772         inode_count[nr]--;
    773         errors_uncorrected = 1;
    774     }
     730    get_inode_common(nr, inode->i_mode);
    775731    return inode;
    776732}
     
    797753#endif
    798754
    799 static int add_zone(uint16_t *znr, smallint *corrected)
    800 {
    801     int result;
    802     int block;
    803 
    804     result = 0;
    805     block = check_zone_nr(znr, corrected);
     755static int add_zone_common(int block, smallint *corrected)
     756{
    806757    if (!block)
    807758        return 0;
     
    810761                current_name);
    811762        if (ask("Clear", 1)) {
    812             *znr = 0;
    813763            block = 0;
    814764            *corrected = 1;
    815             return 0;
     765            return -1; /* "please zero out *znr" */
    816766        }
    817767    }
     
    827777}
    828778
     779static int add_zone(uint16_t *znr, smallint *corrected)
     780{
     781    int block;
     782
     783    block = check_zone_nr(znr, corrected);
     784    block = add_zone_common(block, corrected);
     785    if (block == -1) {
     786        *znr = 0;
     787        block = 0;
     788    }
     789    return block;
     790}
     791
    829792#if ENABLE_FEATURE_MINIX2
    830793static int add_zone2(uint32_t *znr, smallint *corrected)
    831794{
    832     int result;
    833795    int block;
    834796
    835     result = 0;
    836797    block = check_zone_nr2(znr, corrected);
    837     if (!block)
    838         return 0;
    839     if (zone_count[block]) {
    840         printf("Already used block is reused in file '%s'. ",
    841                 current_name);
    842         if (ask("Clear", 1)) {
    843             *znr = 0;
    844             block = 0;
    845             *corrected = 1;
    846             return 0;
    847         }
    848     }
    849     if (!zone_in_use(block)) {
    850         printf("Block %d in file '%s' is marked as 'unused'. ",
    851                 block, current_name);
    852         if (ask("Correct", 1))
    853             mark_zone(block);
    854     }
    855     if (!++zone_count[block])
    856         zone_count[block]--;
     798    block = add_zone_common(block, corrected);
     799    if (block == -1) {
     800        *znr = 0;
     801        block = 0;
     802    }
    857803    return block;
    858804}
     
    952898        return;
    953899    inode = Inode1 + i;
    954     if (!S_ISDIR(inode->i_mode) && !S_ISREG(inode->i_mode) &&
    955         !S_ISLNK(inode->i_mode)) return;
     900    if (!S_ISDIR(inode->i_mode)
     901     && !S_ISREG(inode->i_mode)
     902     && !S_ISLNK(inode->i_mode)
     903    ) {
     904        return;
     905    }
    956906    for (i = 0; i < 7; i++)
    957907        add_zone(i + inode->i_zone, &changed);
     
    1019969        return;
    1020970    push_filename(name);
    1021     if (list) {
    1022         if (verbose)
     971    if (OPT_list) {
     972        if (OPT_verbose)
    1023973            printf("%6d %07o %3d ", ino, inode->i_mode, inode->i_nlinks);
    1024974        printf("%s%s\n", current_name, S_ISDIR(inode->i_mode) ? ":" : "");
     
    10691019        return;
    10701020    push_filename(name);
    1071     if (list) {
    1072         if (verbose)
     1021    if (OPT_list) {
     1022        if (OPT_verbose)
    10731023            printf("%6d %07o %3d ", ino, inode->i_mode, inode->i_nlinks);
    10741024        printf("%s%s\n", current_name, S_ISDIR(inode->i_mode) ? ":" : "");
     
    11191069    char buffer[BLOCK_SIZE];
    11201070
    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));
     1071    xlseek(dev_fd, BLOCK_SIZE * i, SEEK_SET);
     1072    return (BLOCK_SIZE != full_read(dev_fd, buffer, BLOCK_SIZE));
    11241073}
    11251074
     
    11291078
    11301079    for (i = 1; i <= INODES; i++) {
    1131         if (warn_mode && Inode1[i].i_mode && !inode_in_use(i)) {
     1080        if (OPT_warn_mode && Inode1[i].i_mode && !inode_in_use(i)) {
    11321081            printf("Inode %d has non-zero mode. ", i);
    11331082            if (ask("Clear", 1)) {
     
    11811130
    11821131    for (i = 1; i <= INODES; i++) {
    1183         if (warn_mode && Inode2[i].i_mode && !inode_in_use(i)) {
     1132        if (OPT_warn_mode && Inode2[i].i_mode && !inode_in_use(i)) {
    11841133            printf("Inode %d has non-zero mode. ", i);
    11851134            if (ask("Clear", 1)) {
     
    12501199#endif
    12511200
    1252 int fsck_minix_main(int argc, char **argv);
    1253 int fsck_minix_main(int argc, char **argv)
     1201int fsck_minix_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     1202int fsck_minix_main(int argc UNUSED_PARAM, char **argv)
    12541203{
    12551204    struct termios tmp;
     
    12601209    INIT_G();
    12611210
    1262     if (INODE_SIZE1 * MINIX1_INODES_PER_BLOCK != BLOCK_SIZE)
    1263         die("bad inode size");
    1264 #if ENABLE_FEATURE_MINIX2
    1265     if (INODE_SIZE2 * MINIX2_INODES_PER_BLOCK != BLOCK_SIZE)
    1266         die("bad v2 inode size");
    1267 #endif
    1268     while (--argc != 0) {
    1269         argv++;
    1270         if (argv[0][0] != '-') {
    1271             if (device_name)
    1272                 bb_show_usage();
    1273             device_name = argv[0];
    1274         } else {
    1275             while (*++argv[0]) {
    1276                 switch (argv[0][0]) {
    1277                 case 'l':
    1278                     list = 1;
    1279                     break;
    1280                 case 'a':
    1281                     automatic = 1;
    1282                     repair = 1;
    1283                     break;
    1284                 case 'r':
    1285                     automatic = 0;
    1286                     repair = 1;
    1287                     break;
    1288                 case 'v':
    1289                     verbose = 1;
    1290                     break;
    1291                 case 's':
    1292                     show = 1;
    1293                     break;
    1294                 case 'm':
    1295                     warn_mode = 1;
    1296                     break;
    1297                 case 'f':
    1298                     force = 1;
    1299                     break;
    1300                 default:
    1301                     bb_show_usage();
    1302                 }
    1303             }
    1304         }
    1305     }
    1306     if (!device_name)
    1307         bb_show_usage();
    1308 
    1309     check_mount();              /* trying to check a mounted filesystem? */
    1310     if (repair && !automatic) {
     1211    opt_complementary = "=1:ar"; /* one argument; -a assumes -r */
     1212    getopt32(argv, OPTION_STR);
     1213    argv += optind;
     1214    device_name = argv[0];
     1215
     1216    check_mount();  /* trying to check a mounted filesystem? */
     1217    if (OPT_manual) {
    13111218        if (!isatty(0) || !isatty(1))
    13121219            die("need terminal for interactive repairs");
    13131220    }
    1314     dev_fd = xopen(device_name, repair ? O_RDWR : O_RDONLY);
     1221    xmove_fd(xopen(device_name, OPT_repair ? O_RDWR : O_RDONLY), dev_fd);
    13151222
    13161223    /*sync(); paranoia? */
     
    13261233
    13271234    if (!(Super.s_state & MINIX_ERROR_FS)
    1328      && (Super.s_state & MINIX_VALID_FS) && !force
     1235     && (Super.s_state & MINIX_VALID_FS) && !OPT_force
    13291236    ) {
    1330         if (repair)
     1237        if (OPT_repair)
    13311238            printf("%s is clean, check is skipped\n", device_name);
    13321239        return 0;
    1333     } else if (force)
     1240    } else if (OPT_force)
    13341241        printf("Forcing filesystem check on %s\n", device_name);
    1335     else if (repair)
     1242    else if (OPT_repair)
    13361243        printf("Filesystem on %s is dirty, needs checking\n",
    13371244               device_name);
     
    13391246    read_tables();
    13401247
    1341     if (repair && !automatic) {
     1248    if (OPT_manual) {
    13421249        tcgetattr(0, &sv_termios);
    13431250        tmp = sv_termios;
    13441251        tmp.c_lflag &= ~(ICANON | ECHO);
    1345         tcsetattr(0, TCSANOW, &tmp);
     1252        tcsetattr_stdin_TCSANOW(&tmp);
    13461253        termios_set = 1;
    13471254    }
     
    13551262    }
    13561263
    1357     if (verbose) {
     1264    if (OPT_verbose) {
    13581265        int i, free_cnt;
    13591266
     
    13841291        printf("FILE SYSTEM HAS BEEN CHANGED\n");
    13851292        sync();
    1386     } else if (repair)
    1387         write_super_block();
    1388 
    1389     if (repair && !automatic)
    1390         tcsetattr(0, TCSANOW, &sv_termios);
     1293    } else if (OPT_repair)
     1294        write_superblock();
     1295
     1296    if (OPT_manual)
     1297        tcsetattr_stdin_TCSANOW(&sv_termios);
    13911298
    13921299    if (changed)
  • branches/2.2.9/mindi-busybox/util-linux/getopt.c

    r1765 r2725  
    44 *   Copyright (c) 1997, 1998, 1999, 2000  Frodo Looijaard <frodol@dds.nl>
    55 *
    6  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     6 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    77 */
    88
     
    2323 *   No important changes
    2424 * Version 1.1.0: Tue Jun 30 2000
    25  *   Added NLS support (partly written by Arkadiusz Mi<B6>kiewicz
     25 *   Added NLS support (partly written by Arkadiusz Mickiewicz
    2626 *     <misiek@misiek.eu.org>)
    2727 * Ported to Busybox - Alfred M. Szmidt <ams@trillian.itslinux.org>
     
    3939enum {
    4040    NON_OPT = 1,
    41 #if ENABLE_GETOPT_LONG
     41#if ENABLE_FEATURE_GETOPT_LONG
    4242/* LONG_OPT is the code that is returned when a long option is found. */
    4343    LONG_OPT = 2
     
    5454    OPT_T   = 0x20, // -T
    5555    OPT_u   = 0x40, // -u
    56 #if ENABLE_GETOPT_LONG
     56#if ENABLE_FEATURE_GETOPT_LONG
    5757    OPT_a   = 0x80, // -a
    5858    OPT_l   = 0x100, // -l
     
    142142 * Other settings are found in global variables.
    143143 */
    144 #if !ENABLE_GETOPT_LONG
    145 #define generate_output(argv,argc,optstr,longopts) generate_output(argv,argc,optstr)
     144#if !ENABLE_FEATURE_GETOPT_LONG
     145#define generate_output(argv,argc,optstr,longopts) \
     146    generate_output(argv,argc,optstr)
    146147#endif
    147148static int generate_output(char **argv, int argc, const char *optstr, const struct option *longopts)
    148149{
    149150    int exit_code = 0; /* We assume everything will be OK */
    150     unsigned opt;
    151 #if ENABLE_GETOPT_LONG
     151    int opt;
     152#if ENABLE_FEATURE_GETOPT_LONG
    152153    int longindex;
    153154#endif
     
    156157    if (quiet_errors) /* No error reporting from getopt(3) */
    157158        opterr = 0;
    158     optind = 0; /* Reset getopt(3) */
     159
     160    /* We used it already in main() in getopt32(),
     161     * we *must* reset getopt(3): */
     162#ifdef __GLIBC__
     163    optind = 0;
     164#else /* BSD style */
     165    optind = 1;
     166    /* optreset = 1; */
     167#endif
    159168
    160169    while (1) {
    161170        opt =
    162 #if ENABLE_GETOPT_LONG
     171#if ENABLE_FEATURE_GETOPT_LONG
    163172            alternative ?
    164173            getopt_long_only(argc, argv, optstr, longopts, &longindex) :
     
    167176            getopt(argc, argv, optstr);
    168177#endif
    169         if (opt == EOF)
     178        if (opt == -1)
    170179            break;
    171180        if (opt == '?' || opt == ':' )
    172181            exit_code = 1;
    173182        else if (!quiet_output) {
    174 #if ENABLE_GETOPT_LONG
     183#if ENABLE_FEATURE_GETOPT_LONG
    175184            if (opt == LONG_OPT) {
    176185                printf(" --%s", longopts[longindex].name);
     
    184193            else {
    185194                printf(" -%c", opt);
    186                 charptr = strchr(optstr,opt);
     195                charptr = strchr(optstr, opt);
    187196                if (charptr != NULL && *++charptr == ':')
    188197                    printf(" %s",
     
    196205        while (optind < argc)
    197206            printf(" %s", normalize(argv[optind++]));
    198         puts("");
     207        bb_putchar('\n');
    199208    }
    200209    return exit_code;
    201210}
    202211
    203 #if ENABLE_GETOPT_LONG
     212#if ENABLE_FEATURE_GETOPT_LONG
    204213/*
    205214 * Register several long options. options is a string of long options,
     
    232241                    bb_error_msg_and_die("empty long option specified");
    233242            }
    234             long_options = xrealloc(long_options,
    235                     sizeof(long_options[0]) * (long_nr+2));
     243            long_options = xrealloc_vector(long_options, 4, long_nr);
    236244            long_options[long_nr].has_arg = arg_opt;
    237             long_options[long_nr].flag = NULL;
     245            /*long_options[long_nr].flag = NULL; - xrealloc_vector did it */
    238246            long_options[long_nr].val = LONG_OPT;
    239247            long_options[long_nr].name = xstrdup(tokptr);
    240248            long_nr++;
    241             memset(&long_options[long_nr], 0, sizeof(long_options[0]));
     249            /*memset(&long_options[long_nr], 0, sizeof(long_options[0])); - xrealloc_vector did it */
    242250        }
    243251        tokptr = strtok(NULL, ", \t\n");
     
    249257static void set_shell(const char *new_shell)
    250258{
    251     if (!strcmp(new_shell,"bash") || !strcmp(new_shell,"sh"))
     259    if (!strcmp(new_shell, "bash") || !strcmp(new_shell, "sh"))
    252260        return;
    253     if (!strcmp(new_shell,"tcsh") || !strcmp(new_shell,"csh"))
     261    if (!strcmp(new_shell, "tcsh") || !strcmp(new_shell, "csh"))
    254262        option_mask32 |= SHELL_IS_TCSH;
    255263    else
     
    266274 */
    267275
    268 #if ENABLE_GETOPT_LONG
     276#if ENABLE_FEATURE_GETOPT_LONG
    269277static const char getopt_longopts[] ALIGN1 =
    270278    "options\0"      Required_argument "o"
     
    280288#endif
    281289
    282 int getopt_main(int argc, char *argv[]);
    283 int getopt_main(int argc, char *argv[])
     290int getopt_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     291int getopt_main(int argc, char **argv)
    284292{
    285293    char *optstr = NULL;
     
    288296    const char *compatible;
    289297    char *s_arg;
    290 #if ENABLE_GETOPT_LONG
     298#if ENABLE_FEATURE_GETOPT_LONG
    291299    struct option *long_options = NULL;
    292300    llist_t *l_arg = NULL;
     
    314322    }
    315323
    316 #if !ENABLE_GETOPT_LONG
     324#if !ENABLE_FEATURE_GETOPT_LONG
    317325    opt = getopt32(argv, "+o:n:qQs:Tu", &optstr, &name, &s_arg);
    318326#else
     
    323331    /* Effectuate the read options for the applet itself */
    324332    while (l_arg) {
    325         long_options = add_long_options(long_options, l_arg->data);
    326         l_arg = l_arg->link;
     333        long_options = add_long_options(long_options, llist_pop(&l_arg));
    327334    }
    328335#endif
  • branches/2.2.9/mindi-busybox/util-linux/hexdump.c

    r1765 r2725  
    55 *
    66 * Copyright (c) 1989
    7  *  The Regents of the University of California.  All rights reserved.
     7 * The Regents of the University of California.  All rights reserved.
    88 *
    9  * Licensed under GPLv2 or later, see file License in this tarball for details.
     9 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    1010 */
    1111
    12 #include <getopt.h>
    1312#include "libbb.h"
    1413#include "dump.h"
     
    1615/* This is a NOEXEC applet. Be very careful! */
    1716
    18 
    19 static void bb_dump_addfile(char *name)
     17static void bb_dump_addfile(dumper_t *dumper, char *name)
    2018{
    2119    char *p;
     
    2321    char *buf;
    2422
    25     fp = xfopen(name, "r");
    26 
    27     while ((buf = xmalloc_getline(fp)) != NULL) {
     23    fp = xfopen_for_read(name);
     24    while ((buf = xmalloc_fgetline(fp)) != NULL) {
    2825        p = skip_whitespace(buf);
    29 
    3026        if (*p && (*p != '#')) {
    31             bb_dump_add(p);
     27            bb_dump_add(dumper, p);
    3228        }
    3329        free(buf);
     
    3733
    3834static 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 */
     35    "\"%07.7_ax \" 16/1 \"%03o \" \"\\n\"",   /* b */
     36    "\"%07.7_ax \" 16/1 \"%3_c \" \"\\n\"",   /* c */
     37    "\"%07.7_ax \" 8/2 \"  %05u \" \"\\n\"",  /* d */
     38    "\"%07.7_ax \" 8/2 \" %06o \" \"\\n\"",   /* o */
     39    "\"%07.7_ax \" 8/2 \"   %04x \" \"\\n\"", /* x */
    4440};
    4541
    4642static const char add_first[] ALIGN1 = "\"%07.7_Ax\n\"";
    4743
    48 static const char hexdump_opts[] ALIGN1 = "bcdoxCe:f:n:s:v";
     44static const char hexdump_opts[] ALIGN1 = "bcdoxCe:f:n:s:v" IF_FEATURE_HEXDUMP_REVERSE("R");
    4945
    5046static const struct suffix_mult suffixes[] = {
     
    5248    { "k", 1024 },
    5349    { "m", 1024*1024 },
    54     { }
     50    { "", 0 }
    5551};
    5652
    57 int hexdump_main(int argc, char **argv);
     53int hexdump_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
    5854int hexdump_main(int argc, char **argv)
    5955{
     56    dumper_t *dumper = alloc_dumper();
    6057    const char *p;
    6158    int ch;
     59#if ENABLE_FEATURE_HEXDUMP_REVERSE
     60    FILE *fp;
     61    smallint rdump = 0;
     62#endif
    6263
    63     bb_dump_vflag = FIRST;
    64     bb_dump_length = -1;
     64    if (ENABLE_HD && !applet_name[2]) { /* we are "hd" */
     65        ch = 'C';
     66        goto hd_applet;
     67    }
    6568
     69    /* We cannot use getopt32: in hexdump options are cumulative.
     70     * E.g. "hexdump -C -C file" should dump each line twice */
    6671    while ((ch = getopt(argc, argv, hexdump_opts)) > 0) {
    6772        p = strchr(hexdump_opts, ch);
     
    6974            bb_show_usage();
    7075        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;
    93             }
     76            bb_dump_add(dumper, add_first);
     77            bb_dump_add(dumper, add_strings[(int)(p - hexdump_opts)]);
    9478        }
     79        /* Save a little bit of space below by omitting the 'else's. */
     80        if (ch == 'C') {
     81 hd_applet:
     82            bb_dump_add(dumper, "\"%08.8_Ax\n\"");
     83            bb_dump_add(dumper, "\"%08.8_ax  \" 8/1 \"%02x \" \"  \" 8/1 \"%02x \" ");
     84            bb_dump_add(dumper, "\"  |\" 16/1 \"%_p\" \"|\\n\"");
     85        }
     86        if (ch == 'e') {
     87            bb_dump_add(dumper, optarg);
     88        } /* else */
     89        if (ch == 'f') {
     90            bb_dump_addfile(dumper, optarg);
     91        } /* else */
     92        if (ch == 'n') {
     93            dumper->dump_length = xatoi_positive(optarg);
     94        } /* else */
     95        if (ch == 's') { /* compat: -s accepts hex numbers too */
     96            dumper->dump_skip = xstrtoul_range_sfx(optarg, /*base:*/ 0, /*lo:*/ 0, /*hi:*/ LONG_MAX, suffixes);
     97        } /* else */
     98        if (ch == 'v') {
     99            dumper->dump_vflag = ALL;
     100        }
     101#if ENABLE_FEATURE_HEXDUMP_REVERSE
     102        if (ch == 'R') {
     103            rdump = 1;
     104        }
     105#endif
    95106    }
    96107
    97     if (!bb_dump_fshead) {
    98         bb_dump_add(add_first);
    99         bb_dump_add("\"%07.7_ax \" 8/2 \"%04x \" \"\\n\"");
     108    if (!dumper->fshead) {
     109        bb_dump_add(dumper, add_first);
     110        bb_dump_add(dumper, "\"%07.7_ax \" 8/2 \"%04x \" \"\\n\"");
    100111    }
    101112
    102113    argv += optind;
    103114
    104     return bb_dump_dump(argv);
     115#if !ENABLE_FEATURE_HEXDUMP_REVERSE
     116    return bb_dump_dump(dumper, argv);
     117#else
     118    if (!rdump) {
     119        return bb_dump_dump(dumper, argv);
     120    }
     121
     122    /* -R: reverse of 'hexdump -Cv' */
     123    fp = stdin;
     124    if (!*argv) {
     125        argv--;
     126        goto jump_in;
     127    }
     128
     129    do {
     130        char *buf;
     131        fp = xfopen_for_read(*argv);
     132 jump_in:
     133        while ((buf = xmalloc_fgetline(fp)) != NULL) {
     134            p = buf;
     135            while (1) {
     136                /* skip address or previous byte */
     137                while (isxdigit(*p)) p++;
     138                while (*p == ' ') p++;
     139                /* '|' char will break the line */
     140                if (!isxdigit(*p) || sscanf(p, "%x ", &ch) != 1)
     141                    break;
     142                putchar(ch);
     143            }
     144            free(buf);
     145        }
     146        fclose(fp);
     147    } while (*++argv);
     148
     149    fflush_stdout_and_exit(EXIT_SUCCESS);
     150#endif
    105151}
  • branches/2.2.9/mindi-busybox/util-linux/hwclock.c

    r1765 r2725  
    55 * Copyright (C) 2002 Robert Griebl <griebl@gmx.de>
    66 *
    7  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    88*/
    99
     10#include "libbb.h"
     11/* After libbb.h, since it needs sys/types.h on some systems */
    1012#include <sys/utsname.h>
    11 #include <getopt.h>
    12 #include "libbb.h"
    13 
    14 /* Copied from linux/rtc.h to eliminate the kernel dependency */
    15 struct linux_rtc_time {
    16     int tm_sec;
    17     int tm_min;
    18     int tm_hour;
    19     int tm_mday;
    20     int tm_mon;
    21     int tm_year;
    22     int tm_wday;
    23     int tm_yday;
    24     int tm_isdst;
    25 };
    26 
    27 #define RTC_SET_TIME   _IOW('p', 0x0a, struct linux_rtc_time) /* Set RTC time    */
    28 #define RTC_RD_TIME    _IOR('p', 0x09, struct linux_rtc_time) /* Read RTC time   */
    29 
    30 #if ENABLE_FEATURE_HWCLOCK_LONG_OPTIONS
    31 # ifndef _GNU_SOURCE
    32 #  define _GNU_SOURCE
    33 # endif
    34 #endif
    35 
    36 static const char *rtcname;
    37 
    38 static 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 
    54 static time_t read_rtc(int utc)
    55 {
    56     struct tm tm;
    57     char *oldtz = 0;
    58     time_t t = 0;
    59     int rtc = xopen_rtc(O_RDONLY);
    60 
    61     memset(&tm, 0, sizeof(struct tm));
    62     xioctl(rtc, RTC_RD_TIME, &tm);
    63     tm.tm_isdst = -1; /* not known */
    64 
    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();
    80     }
    81     return t;
    82 }
    83 
    84 static void write_rtc(time_t t, int utc)
    85 {
    86     struct tm tm;
    87     int rtc = xopen_rtc(O_WRONLY);
    88 
    89     tm = *(utc ? gmtime(&t) : localtime(&t));
    90     tm.tm_isdst = 0;
    91 
    92     xioctl(rtc, RTC_SET_TIME, &tm);
    93 
    94     close(rtc);
    95 }
    96 
    97 static void show_clock(int utc)
    98 {
    99     //struct tm *ptm;
     13#include "rtc_.h"
     14
     15/* diff code is disabled: it's not sys/hw clock diff, it's some useless
     16 * "time between hwclock was started and we saw CMOS tick" quantity.
     17 * It's useless since hwclock is started at a random moment,
     18 * thus the quantity is also random, useless. Showing 0.000000 does not
     19 * deprive us from any useful info.
     20 *
     21 * SHOW_HWCLOCK_DIFF code in this file shows the difference between system
     22 * and hw clock. It is useful, but not compatible with standard hwclock.
     23 * Thus disabled.
     24 */
     25#define SHOW_HWCLOCK_DIFF 0
     26
     27
     28#if !SHOW_HWCLOCK_DIFF
     29# define read_rtc(pp_rtcname, sys_tv, utc) read_rtc(pp_rtcname, utc)
     30#endif
     31static time_t read_rtc(const char **pp_rtcname, struct timeval *sys_tv, int utc)
     32{
     33    struct tm tm_time;
     34    int fd;
     35
     36    fd = rtc_xopen(pp_rtcname, O_RDONLY);
     37
     38    rtc_read_tm(&tm_time, fd);
     39
     40#if SHOW_HWCLOCK_DIFF
     41    {
     42        int before = tm_time.tm_sec;
     43        while (1) {
     44            rtc_read_tm(&tm_time, fd);
     45            gettimeofday(sys_tv, NULL);
     46            if (before != tm_time.tm_sec)
     47                break;
     48        }
     49    }
     50#endif
     51
     52    if (ENABLE_FEATURE_CLEAN_UP)
     53        close(fd);
     54
     55    return rtc_tm2time(&tm_time, utc);
     56}
     57
     58static void show_clock(const char **pp_rtcname, int utc)
     59{
     60#if SHOW_HWCLOCK_DIFF
     61    struct timeval sys_tv;
     62#endif
    10063    time_t t;
    10164    char *cp;
    10265
    103     t = read_rtc(utc);
    104     //ptm = localtime(&t);  /* Sets 'tzname[]' */
    105 
     66    t = read_rtc(pp_rtcname, &sys_tv, utc);
    10667    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]));
     68    strchrnul(cp, '\n')[0] = '\0';
     69#if !SHOW_HWCLOCK_DIFF
    11170    printf("%s  0.000000 seconds\n", cp);
    112 }
    113 
    114 static void to_sys_clock(int utc)
     71#else
     72    {
     73        long diff = sys_tv.tv_sec - t;
     74        if (diff < 0 /*&& tv.tv_usec != 0*/) {
     75            /* Why? */
     76            /* diff >= 0 is ok:   diff < 0, can't just use tv.tv_usec: */
     77            /*   45.520820          43.520820 */
     78            /* - 44.000000        - 45.000000 */
     79            /* =  1.520820        = -1.479180, not -2.520820! */
     80            diff++;
     81            /* should be 1000000 - tv.tv_usec, but then we must check tv.tv_usec != 0 */
     82            sys_tv.tv_usec = 999999 - sys_tv.tv_usec;
     83        }
     84        printf("%s  %ld.%06lu seconds\n", cp, diff, (unsigned long)sys_tv.tv_usec);
     85    }
     86#endif
     87}
     88
     89static void to_sys_clock(const char **pp_rtcname, int utc)
    11590{
    11691    struct timeval tv;
    117     const struct timezone tz = { timezone/60 - 60*daylight, 0 };
    118 
    119     tv.tv_sec = read_rtc(utc);
     92    struct timezone tz;
     93
     94    tz.tz_minuteswest = timezone/60 - 60*daylight;
     95    tz.tz_dsttime = 0;
     96
     97    tv.tv_sec = read_rtc(pp_rtcname, NULL, utc);
    12098    tv.tv_usec = 0;
    12199    if (settimeofday(&tv, &tz))
    122         bb_perror_msg_and_die("settimeofday() failed");
    123 }
    124 
    125 static void from_sys_clock(int utc)
    126 {
     100        bb_perror_msg_and_die("settimeofday");
     101}
     102
     103static void from_sys_clock(const char **pp_rtcname, int utc)
     104{
     105#if 1
    127106    struct timeval tv;
    128 
     107    struct tm tm_time;
     108    int rtc;
     109
     110    rtc = rtc_xopen(pp_rtcname, O_WRONLY);
    129111    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
    136 # define ADJTIME_PATH "/var/lib/hwclock/adjtime"
     112    /* Prepare tm_time */
     113    if (sizeof(time_t) == sizeof(tv.tv_sec)) {
     114        if (utc)
     115            gmtime_r((time_t*)&tv.tv_sec, &tm_time);
     116        else
     117            localtime_r((time_t*)&tv.tv_sec, &tm_time);
     118    } else {
     119        time_t t = tv.tv_sec;
     120        if (utc)
     121            gmtime_r(&t, &tm_time);
     122        else
     123            localtime_r(&t, &tm_time);
     124    }
    137125#else
    138 # define ADJTIME_PATH "/etc/adjtime"
    139 #endif
    140 static int check_utc(void)
    141 {
    142     int utc = 0;
    143     FILE *f = fopen(ADJTIME_PATH, "r");
    144 
    145     if (f) {
    146         RESERVE_CONFIG_BUFFER(buffer, 128);
    147 
    148         while (fgets(buffer, sizeof(buffer), f)) {
    149             int len = strlen(buffer);
    150 
    151             while (len && isspace(buffer[len - 1]))
    152                 len--;
    153 
    154             buffer[len] = 0;
    155 
    156             if (strncmp(buffer, "UTC", 3) == 0) {
    157                 utc = 1;
    158                 break;
    159             }
    160         }
    161         fclose(f);
    162         RELEASE_CONFIG_BUFFER(buffer);
    163     }
    164     return utc;
     126/* Bloated code which tries to set hw clock with better precision.
     127 * On x86, even though code does set hw clock within <1ms of exact
     128 * whole seconds, apparently hw clock (at least on some machines)
     129 * doesn't reset internal fractional seconds to 0,
     130 * making all this a pointless excercise.
     131 */
     132    /* If we see that we are N usec away from whole second,
     133     * we'll sleep for N-ADJ usecs. ADJ corrects for the fact
     134     * that CPU is not infinitely fast.
     135     * On infinitely fast CPU, next wakeup would be
     136     * on (exactly_next_whole_second - ADJ). On real CPUs,
     137     * this difference between current time and whole second
     138     * is less than ADJ (assuming system isn't heavily loaded).
     139     */
     140    /* Small value of 256us gives very precise sync for 2+ GHz CPUs.
     141     * Slower CPUs will fail to sync and will go to bigger
     142     * ADJ values. qemu-emulated armv4tl with ~100 MHz
     143     * performance ends up using ADJ ~= 4*1024 and it takes
     144     * 2+ secs (2 tries with successively larger ADJ)
     145     * to sync. Even straced one on the same qemu (very slow)
     146     * takes only 4 tries.
     147     */
     148#define TWEAK_USEC 256
     149    unsigned adj = TWEAK_USEC;
     150    struct tm tm_time;
     151    struct timeval tv;
     152    int rtc = rtc_xopen(pp_rtcname, O_WRONLY);
     153
     154    /* Try to catch the moment when whole second is close */
     155    while (1) {
     156        unsigned rem_usec;
     157        time_t t;
     158
     159        gettimeofday(&tv, NULL);
     160
     161        t = tv.tv_sec;
     162        rem_usec = 1000000 - tv.tv_usec;
     163        if (rem_usec < adj) {
     164            /* Close enough */
     165 small_rem:
     166            t++;
     167        }
     168
     169        /* Prepare tm_time from t */
     170        if (utc)
     171            gmtime_r(&t, &tm_time); /* may read /etc/xxx (it takes time) */
     172        else
     173            localtime_r(&t, &tm_time); /* same */
     174
     175        if (adj >= 32*1024) {
     176            break; /* 32 ms diff and still no luck?? give up trying to sync */
     177        }
     178
     179        /* gmtime/localtime took some time, re-get cur time */
     180        gettimeofday(&tv, NULL);
     181
     182        if (tv.tv_sec < t /* we are still in old second */
     183         || (tv.tv_sec == t && tv.tv_usec < adj) /* not too far into next second */
     184        ) {
     185            break; /* good, we are in sync! */
     186        }
     187
     188        rem_usec = 1000000 - tv.tv_usec;
     189        if (rem_usec < adj) {
     190            t = tv.tv_sec;
     191            goto small_rem; /* already close to next sec, don't sleep */
     192        }
     193
     194        /* Try to sync up by sleeping */
     195        usleep(rem_usec - adj);
     196
     197        /* Jump to 1ms diff, then increase fast (x2): EVERY loop
     198         * takes ~1 sec, people won't like slowly converging code here!
     199         */
     200    //bb_error_msg("adj:%d tv.tv_usec:%d", adj, (int)tv.tv_usec);
     201        if (adj < 512)
     202            adj = 512;
     203        /* ... and if last "overshoot" does not look insanely big,
     204         * just use it as adj increment. This makes convergence faster.
     205         */
     206        if (tv.tv_usec < adj * 8) {
     207            adj += tv.tv_usec;
     208            continue;
     209        }
     210        adj *= 2;
     211    }
     212    /* Debug aid to find "optimal" TWEAK_USEC with nearly exact sync.
     213     * Look for a value which makes tv_usec close to 999999 or 0.
     214     * For 2.20GHz Intel Core 2: optimal TWEAK_USEC ~= 200
     215     */
     216    //bb_error_msg("tv.tv_usec:%d", (int)tv.tv_usec);
     217#endif
     218
     219    tm_time.tm_isdst = 0;
     220    xioctl(rtc, RTC_SET_TIME, &tm_time);
     221
     222    if (ENABLE_FEATURE_CLEAN_UP)
     223        close(rtc);
    165224}
    166225
     
    172231#define HWCLOCK_OPT_RTCFILE     0x20
    173232
    174 int hwclock_main(int argc, char **argv);
    175 int hwclock_main(int argc, char **argv)
    176 {
     233int hwclock_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     234int hwclock_main(int argc UNUSED_PARAM, char **argv)
     235{
     236    const char *rtcname = NULL;
    177237    unsigned opt;
    178238    int utc;
     
    194254    /* If -u or -l wasn't given check if we are using utc */
    195255    if (opt & (HWCLOCK_OPT_UTC | HWCLOCK_OPT_LOCALTIME))
    196         utc = opt & HWCLOCK_OPT_UTC;
     256        utc = (opt & HWCLOCK_OPT_UTC);
    197257    else
    198         utc = check_utc();
    199 
    200     if (opt & HWCLOCK_OPT_HCTOSYS) {
    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);
     258        utc = rtc_adjtime_is_utc();
     259
     260    if (opt & HWCLOCK_OPT_HCTOSYS)
     261        to_sys_clock(&rtcname, utc);
     262    else if (opt & HWCLOCK_OPT_SYSTOHC)
     263        from_sys_clock(&rtcname, utc);
     264    else
     265        /* default HWCLOCK_OPT_SHOW */
     266        show_clock(&rtcname, utc);
     267
    210268    return 0;
    211269}
  • branches/2.2.9/mindi-busybox/util-linux/ipcrm.c

    r1765 r2725  
    66 * Adapted for busybox from util-linux-2.12a.
    77 *
    8  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     8 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    99 */
    1010
     
    2525    int val;
    2626    struct semid_ds *buf;
    27     unsigned short int *array;
     27    unsigned short *array;
    2828    struct seminfo *__buf;
    2929};
     
    4141} type_id;
    4242
    43 static int remove_ids(type_id type, int argc, char **argv)
     43static int remove_ids(type_id type, char **argv)
    4444{
    4545    unsigned long id;
    46     int ret = 0;        /* silence gcc */
    4746    int nb_errors = 0;
    4847    union semun arg;
     
    5049    arg.val = 0;
    5150
    52     while (argc) {
     51    while (argv[0]) {
    5352        id = bb_strtoul(argv[0], NULL, 10);
    5453        if (errno || id > INT_MAX) {
     
    5655            nb_errors++;
    5756        } else {
     57            int ret = 0;
    5858            if (type == SEM)
    5959                ret = semctl(id, 0, IPC_RMID, arg);
     
    6464
    6565            if (ret) {
    66                 bb_perror_msg("cannot remove id %s", argv[0]);
     66                bb_perror_msg("can't remove id %s", argv[0]);
    6767                nb_errors++;
    6868            }
    6969        }
    70         argc--;
    7170        argv++;
    7271    }
     
    7776
    7877
    79 int ipcrm_main(int argc, char **argv);
     78int ipcrm_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
    8079int ipcrm_main(int argc, char **argv)
    8180{
     
    9392        char w;
    9493
    95         w=argv[1][0];
     94        w = argv[1][0];
    9695        if ( ((w == 'm' && argv[1][1] == 's' && argv[1][2] == 'g')
    9796               || (argv[1][0] == 's'
    98                    && ((w=argv[1][1]) == 'h' || w == 'e')
     97                   && ((w = argv[1][1]) == 'h' || w == 'e')
    9998                   && argv[1][2] == 'm')
    10099             ) && argv[1][3] == '\0'
    101100        ) {
    102 
    103101            if (argc < 3)
    104102                bb_show_usage();
     
    111109                what = SEM;
    112110
    113             if (remove_ids(what, argc-2, &argv[2]))
    114                 fflush_stdout_and_exit(1);
     111            if (remove_ids(what, &argv[2]))
     112                fflush_stdout_and_exit(EXIT_FAILURE);
    115113            printf("resource(s) deleted\n");
    116114            return 0;
     
    123121        int result;
    124122        int id = 0;
    125         int iskey = (isupper)(c);
     123        int iskey = isupper(c);
    126124
    127125        /* needed to delete semaphores */
  • branches/2.2.9/mindi-busybox/util-linux/ipcs.c

    r1765 r2725  
    66 * Adapted for busybox from util-linux-2.12a.
    77 *
    8  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     8 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    99 */
    1010
     
    6969    int val;
    7070    struct semid_ds *buf;
    71     unsigned short int *array;
     71    unsigned short *array;
    7272    struct seminfo *__buf;
    7373};
     
    100100    printf("%-10d %-10o", id, ipcp->mode & 0777);
    101101
    102     if ((pw = getpwuid(ipcp->cuid)))
    103         printf(" %-10s", pw->pw_name);
    104     else
    105         printf(" %-10d", ipcp->cuid);
    106     if ((gr = getgrgid(ipcp->cgid)))
    107         printf(" %-10s", gr->gr_name);
    108     else
    109         printf(" %-10d", ipcp->cgid);
    110 
    111     if ((pw = getpwuid(ipcp->uid)))
    112         printf(" %-10s", pw->pw_name);
    113     else
    114         printf(" %-10d", ipcp->uid);
    115     if ((gr = getgrgid(ipcp->gid)))
    116         printf(" %-10s\n", gr->gr_name);
    117     else
    118         printf(" %-10d\n", ipcp->gid);
    119 }
    120 
    121 
    122 static void do_shm(void)
     102    pw = getpwuid(ipcp->cuid);
     103    if (pw) printf(" %-10s", pw->pw_name);
     104    else    printf(" %-10d", ipcp->cuid);
     105    gr = getgrgid(ipcp->cgid);
     106    if (gr) printf(" %-10s", gr->gr_name);
     107    else    printf(" %-10d", ipcp->cgid);
     108
     109    pw = getpwuid(ipcp->uid);
     110    if (pw) printf(" %-10s", pw->pw_name);
     111    else    printf(" %-10d", ipcp->uid);
     112    gr = getgrgid(ipcp->gid);
     113    if (gr) printf(" %-10s\n", gr->gr_name);
     114    else    printf(" %-10d\n", ipcp->gid);
     115}
     116
     117
     118static NOINLINE void do_shm(void)
    123119{
    124120    int maxid, shmid, id;
     
    247243
    248244
    249 static void do_sem(void)
     245static NOINLINE void do_sem(void)
    250246{
    251247    int maxid, semid, id;
     
    353349
    354350
    355 static void do_msg(void)
     351static NOINLINE void do_msg(void)
    356352{
    357353    int maxid, msqid, id;
     
    560556        printf("%-10d %-10d %-10d %-10d %-10d\n", i, val, ncnt, zcnt, pid);
    561557    }
    562     puts("");
    563 }
    564 
    565 int ipcs_main(int argc, char **argv);
    566 int ipcs_main(int argc, char **argv)
     558    bb_putchar('\n');
     559}
     560
     561int ipcs_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     562int ipcs_main(int argc UNUSED_PARAM, char **argv)
    567563{
    568564    int id = 0;
     
    593589        if (flags & flag_shm) {
    594590            print_shm(id);
    595             fflush_stdout_and_exit(0);
     591            fflush_stdout_and_exit(EXIT_SUCCESS);
    596592        }
    597593        if (flags & flag_sem) {
    598594            print_sem(id);
    599             fflush_stdout_and_exit(0);
     595            fflush_stdout_and_exit(EXIT_SUCCESS);
    600596        }
    601597        if (flags & flag_msg) {
    602598            print_msg(id);
    603             fflush_stdout_and_exit(0);
     599            fflush_stdout_and_exit(EXIT_SUCCESS);
    604600        }
    605601        bb_show_usage();
     
    608604    if (!(flags & (flag_shm | flag_msg | flag_sem)))
    609605        flags |= flag_msg | flag_shm | flag_sem;
    610     puts("");
     606    bb_putchar('\n');
    611607
    612608    if (flags & flag_shm) {
    613609        do_shm();
    614         puts("");
     610        bb_putchar('\n');
    615611    }
    616612    if (flags & flag_sem) {
    617613        do_sem();
    618         puts("");
     614        bb_putchar('\n');
    619615    }
    620616    if (flags & flag_msg) {
    621617        do_msg();
    622         puts("");
    623     }
    624     fflush_stdout_and_exit(0);
    625 }
     618        bb_putchar('\n');
     619    }
     620    fflush_stdout_and_exit(EXIT_SUCCESS);
     621}
  • branches/2.2.9/mindi-busybox/util-linux/losetup.c

    r1765 r2725  
    55 * Copyright (C) 2002  Matt Kraai.
    66 *
    7  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    88 */
    9 
    10 #include <getopt.h>
    119
    1210#include "libbb.h"
    1311
    14 int losetup_main(int argc, char **argv);
    15 int losetup_main(int argc, char **argv)
     12int losetup_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     13int losetup_main(int argc UNUSED_PARAM, char **argv)
    1614{
    1715    unsigned opt;
     16    int n;
    1817    char *opt_o;
    1918    unsigned long long offset = 0;
     19    enum {
     20        OPT_d = (1 << 0),
     21        OPT_o = (1 << 1),
     22        OPT_f = (1 << 2),
     23    };
    2024
    21     opt = getopt32(argv, "do:", &opt_o);
    22     argc -= optind;
     25    /* max 2 args, all opts are mutually exclusive */
     26    opt_complementary = "?2:d--of:o--df:f--do";
     27    opt = getopt32(argv, "do:f", &opt_o);
    2328    argv += optind;
    2429
    25     if (opt == 0x3) // -d + -o (illegal)
    26         bb_show_usage();
     30    if (opt == OPT_o)
     31        offset = xatoull(opt_o);
    2732
    28     if (opt == 0x1) { // -d
    29         /* detach takes exactly one argument */
    30         if (argc != 1)
     33    if (opt == OPT_d) {
     34        /* -d BLOCKDEV */
     35        if (!argv[0] || argv[1])
    3136            bb_show_usage();
    32         if (!del_loop(argv[0]))
    33             return EXIT_SUCCESS;
    34         bb_perror_nomsg_and_die();
     37        if (del_loop(argv[0]))
     38            bb_simple_perror_msg_and_die(argv[0]);
     39        return EXIT_SUCCESS;
    3540    }
    3641
    37     if (opt == 0x2) // -o
    38         offset = xatoull(opt_o);
     42    if (argv[0]) {
     43        char *s;
    3944
    40     /* -o or no option */
     45        if (opt == OPT_f) /* -f should not have arguments */
     46            bb_show_usage();
    4147
    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]);
     48        if (argv[1]) {
     49            /* [-o OFS] BLOCKDEV FILE */
     50            if (set_loop(&argv[0], argv[1], offset) < 0)
     51                bb_simple_perror_msg_and_die(argv[0]);
     52            return EXIT_SUCCESS;
     53        }
     54        /* [-o OFS] BLOCKDEV */
     55        s = query_loop(argv[0]);
    4756        if (!s)
    48             bb_perror_nomsg_and_die();
     57            bb_simple_perror_msg_and_die(argv[0]);
    4958        printf("%s: %s\n", argv[0], s);
    5059        if (ENABLE_FEATURE_CLEAN_UP)
    5160            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) {
     61        return EXIT_SUCCESS;
     62    }
     63
     64    /* [-o OFS|-f] with no params */
     65    n = 0;
     66    while (1) {
     67        char *s;
     68        char dev[LOOP_NAMESIZE];
     69
     70        sprintf(dev, LOOP_FORMAT, n);
     71        s = query_loop(dev);
     72        n++;
     73        if (!s) {
     74            if (n > 9 && errno && errno != ENXIO)
     75                return EXIT_SUCCESS;
     76            if (opt == OPT_f) {
     77                puts(dev);
     78                return EXIT_SUCCESS;
     79            }
     80        } else {
     81            if (opt != OPT_f)
    6082                printf("%s: %s\n", dev, s);
    61                 if (ENABLE_FEATURE_CLEAN_UP)
    62                     free(s);
    63             }
     83            if (ENABLE_FEATURE_CLEAN_UP)
     84                free(s);
    6485        }
    6586    }
  • branches/2.2.9/mindi-busybox/util-linux/mdev.c

    r1765 r2725  
    11/* vi: set sw=4 ts=4: */
    22/*
    3  *
    43 * mdev - Mini udev for busybox
    54 *
     
    76 * Copyright 2005 Frank Sorenson <frank@tuxrocks.com>
    87 *
    9  * Licensed under GPL version 2, see file LICENSE in this tarball for details.
     8 * Licensed under GPLv2, see file LICENSE in this source tree.
    109 */
    11 
    1210#include "libbb.h"
    1311#include "xregex.h"
    1412
     13/* "mdev -s" scans /sys/class/xxx, looking for directories which have dev
     14 * file (it is of the form "M:m\n"). Example: /sys/class/tty/tty0/dev
     15 * contains "4:0\n". Directory name is taken as device name, path component
     16 * directly after /sys/class/ as subsystem. In this example, "tty0" and "tty".
     17 * Then mdev creates the /dev/device_name node.
     18 * If /sys/class/.../dev file does not exist, mdev still may act
     19 * on this device: see "@|$|*command args..." parameter in config file.
     20 *
     21 * mdev w/o parameters is called as hotplug helper. It takes device
     22 * and subsystem names from $DEVPATH and $SUBSYSTEM, extracts
     23 * maj,min from "/sys/$DEVPATH/dev" and also examines
     24 * $ACTION ("add"/"delete") and $FIRMWARE.
     25 *
     26 * If action is "add", mdev creates /dev/device_name similarly to mdev -s.
     27 * (todo: explain "delete" and $FIRMWARE)
     28 *
     29 * If /etc/mdev.conf exists, it may modify /dev/device_name's properties.
     30 * /etc/mdev.conf file format:
     31 *
     32 * [-][subsystem/]device  user:grp  mode  [>|=path] [@|$|*command args...]
     33 * [-]@maj,min[-min2]     user:grp  mode  [>|=path] [@|$|*command args...]
     34 * [-]$envvar=val         user:grp  mode  [>|=path] [@|$|*command args...]
     35 *
     36 * Leading minus in 1st field means "don't stop on this line", otherwise
     37 * search is stopped after the matching line is encountered.
     38 *
     39 * The device name or "subsystem/device" combo is matched against 1st field
     40 * (which is a regex), or maj,min is matched against 1st field,
     41 * or specified environment variable (as regex) is matched against 1st field.
     42 *
     43 * $envvar=val format is useful for loading modules for hot-plugged devices
     44 * which do not have driver loaded yet. In this case /sys/class/.../dev
     45 * does not exist, but $MODALIAS is set to needed module's name
     46 * (actually, an alias to it) by kernel. This rule instructs mdev
     47 * to load the module and exit:
     48 *    $MODALIAS=.* 0:0 660 @modprobe "$MODALIAS"
     49 * The kernel will generate another hotplug event when /sys/class/.../dev
     50 * file appears.
     51 *
     52 * When line matches, the device node is created, chmod'ed and chown'ed,
     53 * moved to path, and if >path, a symlink to moved node is created,
     54 * all this if /sys/class/.../dev exists.
     55 *    Examples:
     56 *    =loop/      - moves to /dev/loop
     57 *    >disk/sda%1 - moves to /dev/disk/sdaN, makes /dev/sdaN a symlink
     58 *
     59 * Then "command args..." is executed (via sh -c 'command args...').
     60 * @:execute on creation, $:on deletion, *:on both.
     61 * This happens regardless of /sys/class/.../dev existence.
     62 */
     63
    1564struct globals {
    1665    int root_major, root_minor;
    17 };
     66    char *subsystem;
     67} FIX_ALIASING;
    1868#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 */
    23 
    24 /* mknod in /dev based on a path like "/sys/block/hda/hda1" */
     69
     70/* Prevent infinite loops in /sys symlinks */
     71#define MAX_SYSFS_DEPTH 3
     72
     73/* We use additional 64+ bytes in make_device() */
     74#define SCRATCH_SIZE 80
     75
     76/* Builds an alias path.
     77 * This function potentionally reallocates the alias parameter.
     78 * Only used for ENABLE_FEATURE_MDEV_RENAME
     79 */
     80static char *build_alias(char *alias, const char *device_name)
     81{
     82    char *dest;
     83
     84    /* ">bar/": rename to bar/device_name */
     85    /* ">bar[/]baz": rename to bar[/]baz */
     86    dest = strrchr(alias, '/');
     87    if (dest) { /* ">bar/[baz]" ? */
     88        *dest = '\0'; /* mkdir bar */
     89        bb_make_directory(alias, 0755, FILEUTILS_RECUR);
     90        *dest = '/';
     91        if (dest[1] == '\0') { /* ">bar/" => ">bar/device_name" */
     92            dest = alias;
     93            alias = concat_path_file(alias, device_name);
     94            free(dest);
     95        }
     96    }
     97
     98    return alias;
     99}
     100
     101/* mknod in /dev based on a path like "/sys/block/hda/hda1"
     102 * NB1: path parameter needs to have SCRATCH_SIZE scratch bytes
     103 * after NUL, but we promise to not mangle (IOW: to restore if needed)
     104 * path string.
     105 * NB2: "mdev -s" may call us many times, do not leak memory/fds!
     106 */
    25107static void make_device(char *path, int delete)
    26108{
    27     const char *device_name;
     109    char *device_name, *subsystem_slash_devname;
    28110    int major, minor, type, len;
    29     int mode = 0660;
    30     uid_t uid = 0;
    31     gid_t gid = 0;
    32     char *temp = path + strlen(path);
    33     char *command = NULL;
     111    mode_t mode;
     112    parser_t *parser;
    34113
    35114    /* Try to read major/minor string.  Note that the kernel puts \n after
    36115     * the data, so we don't need to worry about null terminating the string
    37      * because sscanf() will stop at the first nondigit, which \n is.  We
    38      * also depend on path having writeable space after it. */
    39 
     116     * because sscanf() will stop at the first nondigit, which \n is.
     117     * We also depend on path having writeable space after it.
     118     */
     119    major = -1;
    40120    if (!delete) {
    41         strcat(path, "/dev");
    42         len = open_read_close(path, temp + 1, 64);
    43         *temp++ = 0;
    44         if (len < 1) return;
     121        char *dev_maj_min = path + strlen(path);
     122
     123        strcpy(dev_maj_min, "/dev");
     124        len = open_read_close(path, dev_maj_min + 1, 64);
     125        *dev_maj_min = '\0';
     126        if (len < 1) {
     127            if (!ENABLE_FEATURE_MDEV_EXEC)
     128                return;
     129            /* no "dev" file, but we can still run scripts
     130             * based on device name */
     131        } else if (sscanf(++dev_maj_min, "%u:%u", &major, &minor) != 2) {
     132            major = -1;
     133        }
    45134    }
     135    /* else: for delete, -1 still deletes the node, but < -1 suppresses that */
    46136
    47137    /* Determine device name, type, major and minor */
    48 
    49     device_name = bb_basename(path);
    50     type = path[5]=='c' ? S_IFCHR : S_IFBLK;
    51 
    52     /* If we have a config file, look up permissions for this device */
    53 
    54     if (ENABLE_FEATURE_MDEV_CONF) {
    55         char *conf, *pos, *end;
    56         int line, fd;
    57 
    58         /* mmap the config file */
    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++)
     138    device_name = (char*) bb_basename(path);
     139    /* http://kernel.org/doc/pending/hotplug.txt says that only
     140     * "/sys/block/..." is for block devices. "/sys/bus" etc is not.
     141     * But since 2.6.25 block devices are also in /sys/class/block.
     142     * We use strstr("/block/") to forestall future surprises. */
     143    type = S_IFCHR;
     144    if (strstr(path, "/block/") || (G.subsystem && strncmp(G.subsystem, "block", 5) == 0))
     145        type = S_IFBLK;
     146
     147    /* Make path point to "subsystem/device_name" */
     148    subsystem_slash_devname = NULL;
     149    /* Check for coldplug invocations first */
     150    if (strncmp(path, "/sys/block/", 11) == 0) /* legacy case */
     151        path += sizeof("/sys/") - 1;
     152    else if (strncmp(path, "/sys/class/", 11) == 0)
     153        path += sizeof("/sys/class/") - 1;
     154    else {
     155        /* Example of a hotplug invocation:
     156         * SUBSYSTEM="block"
     157         * DEVPATH="/sys" + "/devices/virtual/mtd/mtd3/mtdblock3"
     158         * ("/sys" is added by mdev_main)
     159         * - path does not contain subsystem
     160         */
     161        subsystem_slash_devname = concat_path_file(G.subsystem, device_name);
     162        path = subsystem_slash_devname;
     163    }
     164
     165    /* If we have config file, look up user settings */
     166    if (ENABLE_FEATURE_MDEV_CONF)
     167        parser = config_open2("/etc/mdev.conf", fopen_for_read);
     168
     169    do {
     170        int keep_matching;
     171        struct bb_uidgid_t ugid;
     172        char *tokens[4];
     173        char *command = NULL;
     174        char *alias = NULL;
     175        char aliaslink = aliaslink; /* for compiler */
     176
     177        /* Defaults in case we won't match any line */
     178        ugid.uid = ugid.gid = 0;
     179        keep_matching = 0;
     180        mode = 0660;
     181
     182        if (ENABLE_FEATURE_MDEV_CONF
     183         && config_read(parser, tokens, 4, 3, "# \t", PARSE_NORMAL)
     184        ) {
     185            char *val;
     186            char *str_to_match;
     187            regmatch_t off[1 + 9 * ENABLE_FEATURE_MDEV_RENAME_REGEXP];
     188
     189            val = tokens[0];
     190            keep_matching = ('-' == val[0]);
     191            val += keep_matching; /* swallow leading dash */
     192
     193            /* Match against either "subsystem/device_name"
     194             * or "device_name" alone */
     195            str_to_match = strchr(val, '/') ? path : device_name;
     196
     197            /* Fields: regex uid:gid mode [alias] [cmd] */
     198
     199            if (val[0] == '@') {
     200                /* @major,minor[-minor2] */
     201                /* (useful when name is ambiguous:
     202                 * "/sys/class/usb/lp0" and
     203                 * "/sys/class/printer/lp0") */
     204                int cmaj, cmin0, cmin1, sc;
     205                if (major < 0)
     206                    continue; /* no dev, no match */
     207                sc = sscanf(val, "@%u,%u-%u", &cmaj, &cmin0, &cmin1);
     208                if (sc < 1
     209                 || major != cmaj
     210                 || (sc == 2 && minor != cmin0)
     211                 || (sc == 3 && (minor < cmin0 || minor > cmin1))
     212                ) {
     213                    continue; /* this line doesn't match */
     214                }
     215                goto line_matches;
     216            }
     217            if (val[0] == '$') {
     218                /* regex to match an environment variable */
     219                char *eq = strchr(++val, '=');
     220                if (!eq)
     221                    continue;
     222                *eq = '\0';
     223                str_to_match = getenv(val);
     224                if (!str_to_match)
     225                    continue;
     226                str_to_match -= strlen(val) + 1;
     227                *eq = '=';
     228            }
     229            /* else: regex to match [subsystem/]device_name */
     230
    82231            {
    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++)
    116                         ;
    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;
     232                regex_t match;
     233                int result;
     234
     235                xregcomp(&match, val, REG_EXTENDED);
     236                result = regexec(&match, str_to_match, ARRAY_SIZE(off), off, 0);
     237                regfree(&match);
     238                //bb_error_msg("matches:");
     239                //for (int i = 0; i < ARRAY_SIZE(off); i++) {
     240                //  if (off[i].rm_so < 0) continue;
     241                //  bb_error_msg("match %d: '%.*s'\n", i,
     242                //      (int)(off[i].rm_eo - off[i].rm_so),
     243                //      device_name + off[i].rm_so);
     244                //}
     245
     246                /* If no match, skip rest of line */
     247                /* (regexec returns whole pattern as "range" 0) */
     248                if (result
     249                 || off[0].rm_so
     250                 || ((int)off[0].rm_eo != (int)strlen(str_to_match))
     251                ) {
     252                    continue; /* this line doesn't match */
     253                }
     254            }
     255 line_matches:
     256            /* This line matches. Stop parsing after parsing
     257             * the rest the line unless keep_matching == 1 */
     258
     259            /* 2nd field: uid:gid - device ownership */
     260            if (get_uidgid(&ugid, tokens[1], 1) == 0)
     261                bb_error_msg("unknown user/group %s on line %d", tokens[1], parser->lineno);
     262
     263            /* 3rd field: mode - device permissions */
     264            bb_parse_mode(tokens[2], &mode);
     265
     266            val = tokens[3];
     267            /* 4th field (opt): ">|=alias" or "!" to not create the node */
     268
     269            if (ENABLE_FEATURE_MDEV_RENAME && val) {
     270                char *a, *s, *st;
     271
     272                a = val;
     273                s = strchrnul(val, ' ');
     274                st = strchrnul(val, '\t');
     275                if (st < s)
     276                    s = st;
     277                st = (s[0] && s[1]) ? s+1 : NULL;
     278
     279                aliaslink = a[0];
     280                if (aliaslink == '!' && s == a+1) {
     281                    val = st;
     282                    /* "!": suppress node creation/deletion */
     283                    major = -2;
     284                }
     285                else if (aliaslink == '>' || aliaslink == '=') {
     286                    val = st;
     287                    s[0] = '\0';
     288                    if (ENABLE_FEATURE_MDEV_RENAME_REGEXP) {
     289                        char *p;
     290                        unsigned i, n;
     291
     292                        /* substitute %1..9 with off[1..9], if any */
     293                        n = 0;
     294                        s = a;
     295                        while (*s)
     296                            if (*s++ == '%')
     297                                n++;
     298
     299                        p = alias = xzalloc(strlen(a) + n * strlen(str_to_match));
     300                        s = a + 1;
     301                        while (*s) {
     302                            *p = *s;
     303                            if ('%' == *s) {
     304                                i = (s[1] - '0');
     305                                if (i <= 9 && off[i].rm_so >= 0) {
     306                                    n = off[i].rm_eo - off[i].rm_so;
     307                                    strncpy(p, str_to_match + off[i].rm_so, n);
     308                                    p += n - 1;
     309                                    s++;
     310                                }
     311                            }
     312                            p++;
     313                            s++;
     314                        }
     315                    } else {
     316                        alias = xstrdup(a + 1);
    128317                    }
    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                     }
    140                 }
    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;
    162             }
    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;
    171         }
    172         munmap(conf, len);
    173  end_parse: /* nothing */ ;
    174     }
    175 
    176     umask(0);
    177     if (!delete) {
    178         if (sscanf(temp, "%d:%d", &major, &minor) != 2) return;
    179         if (mknod(device_name, mode | type, makedev(major, minor)) && errno != EEXIST)
    180             bb_perror_msg_and_die("mknod %s", device_name);
    181 
    182         if (major == root_major && minor == root_minor)
    183             symlink(device_name, "root");
    184 
    185         if (ENABLE_FEATURE_MDEV_CONF) chown(device_name, uid, gid);
    186     }
    187     if (command) {
    188         /* setenv will leak memory, so use putenv */
    189         char *s = xasprintf("MDEV=%s", device_name);
    190         putenv(s);
    191         if (system(command) == -1)
    192             bb_perror_msg_and_die("cannot run %s", command);
    193         s[4] = '\0';
    194         unsetenv(s);
    195         free(s);
    196         free(command);
    197     }
    198     if (delete) unlink(device_name);
     318                }
     319            }
     320
     321            if (ENABLE_FEATURE_MDEV_EXEC && val) {
     322                const char *s = "$@*";
     323                const char *s2 = strchr(s, val[0]);
     324
     325                if (!s2) {
     326                    bb_error_msg("bad line %u", parser->lineno);
     327                    if (ENABLE_FEATURE_MDEV_RENAME)
     328                        free(alias);
     329                    continue;
     330                }
     331
     332                /* Are we running this command now?
     333                 * Run $cmd on delete, @cmd on create, *cmd on both
     334                 */
     335                if (s2 - s != delete) {
     336                    /* We are here if: '*',
     337                     * or: '@' and delete = 0,
     338                     * or: '$' and delete = 1
     339                     */
     340                    command = xstrdup(val + 1);
     341                }
     342            }
     343        }
     344
     345        /* End of field parsing */
     346
     347        /* "Execute" the line we found */
     348        {
     349            const char *node_name;
     350
     351            node_name = device_name;
     352            if (ENABLE_FEATURE_MDEV_RENAME && alias)
     353                node_name = alias = build_alias(alias, device_name);
     354
     355            if (!delete && major >= 0) {
     356                if (mknod(node_name, mode | type, makedev(major, minor)) && errno != EEXIST)
     357                    bb_perror_msg("can't create '%s'", node_name);
     358                if (major == G.root_major && minor == G.root_minor)
     359                    symlink(node_name, "root");
     360                if (ENABLE_FEATURE_MDEV_CONF) {
     361                    chmod(node_name, mode);
     362                    chown(node_name, ugid.uid, ugid.gid);
     363                }
     364                if (ENABLE_FEATURE_MDEV_RENAME && alias) {
     365                    if (aliaslink == '>')
     366                        symlink(node_name, device_name);
     367                }
     368            }
     369
     370            if (ENABLE_FEATURE_MDEV_EXEC && command) {
     371                /* setenv will leak memory, use putenv/unsetenv/free */
     372                char *s = xasprintf("%s=%s", "MDEV", node_name);
     373                char *s1 = xasprintf("%s=%s", "SUBSYSTEM", G.subsystem);
     374                putenv(s);
     375                putenv(s1);
     376                if (system(command) == -1)
     377                    bb_perror_msg("can't run '%s'", command);
     378                bb_unsetenv_and_free(s1);
     379                bb_unsetenv_and_free(s);
     380                free(command);
     381            }
     382
     383            if (delete && major >= -1) {
     384                if (ENABLE_FEATURE_MDEV_RENAME && alias) {
     385                    if (aliaslink == '>')
     386                        unlink(device_name);
     387                }
     388                unlink(node_name);
     389            }
     390
     391            if (ENABLE_FEATURE_MDEV_RENAME)
     392                free(alias);
     393        }
     394
     395        /* We found matching line.
     396         * Stop unless it was prefixed with '-' */
     397        if (ENABLE_FEATURE_MDEV_CONF && !keep_matching)
     398            break;
     399
     400    /* end of "while line is read from /etc/mdev.conf" */
     401    } while (ENABLE_FEATURE_MDEV_CONF);
     402
     403    if (ENABLE_FEATURE_MDEV_CONF)
     404        config_close(parser);
     405    free(subsystem_slash_devname);
    199406}
    200407
    201408/* File callback for /sys/ traversal */
    202 static int fileAction(const char *fileName, struct stat *statbuf,
    203                       void *userData, int depth)
     409static int FAST_FUNC fileAction(const char *fileName,
     410        struct stat *statbuf UNUSED_PARAM,
     411        void *userData,
     412        int depth UNUSED_PARAM)
    204413{
    205     size_t len = strlen(fileName) - 4;
     414    size_t len = strlen(fileName) - 4; /* can't underflow */
    206415    char *scratch = userData;
    207416
    208     if (strcmp(fileName + len, "/dev"))
     417    /* len check is for paranoid reasons */
     418    if (strcmp(fileName + len, "/dev") != 0 || len >= PATH_MAX)
    209419        return FALSE;
    210420
    211421    strcpy(scratch, fileName);
    212     scratch[len] = 0;
    213     make_device(scratch, 0);
     422    scratch[len] = '\0';
     423    make_device(scratch, /*delete:*/ 0);
    214424
    215425    return TRUE;
     
    217427
    218428/* Directory callback for /sys/ traversal */
    219 static int dirAction(const char *fileName, struct stat *statbuf,
    220                       void *userData, int depth)
     429static int FAST_FUNC dirAction(const char *fileName UNUSED_PARAM,
     430        struct stat *statbuf UNUSED_PARAM,
     431        void *userData UNUSED_PARAM,
     432        int depth)
    221433{
     434    /* Extract device subsystem -- the name of the directory
     435     * under /sys/class/ */
     436    if (1 == depth) {
     437        free(G.subsystem);
     438        G.subsystem = strrchr(fileName, '/');
     439        if (G.subsystem)
     440            G.subsystem = xstrdup(G.subsystem + 1);
     441    }
     442
    222443    return (depth >= MAX_SYSFS_DEPTH ? SKIP : TRUE);
    223444}
     
    234455 * - kernel loads firmware into device
    235456 */
    236 static void load_firmware(const char *const firmware, const char *const sysfs_path)
     457static void load_firmware(const char *firmware, const char *sysfs_path)
    237458{
    238459    int cnt;
    239460    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      */
    246461
    247462    /* check for /lib/firmware/$FIRMWARE */
     
    256471    for (cnt = 0; cnt < 30; ++cnt) {
    257472        loading_fd = open("loading", O_WRONLY);
    258         if (loading_fd == -1)
    259             sleep(1);
    260         else
    261             break;
     473        if (loading_fd != -1)
     474            goto loading;
     475        sleep(1);
    262476    }
    263     if (loading_fd == -1)
     477    goto out;
     478
     479 loading:
     480    /* tell kernel we're loading by "echo 1 > /sys/$DEVPATH/loading" */
     481    if (full_write(loading_fd, "1", 1) != 1)
    264482        goto out;
    265483
    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 */
     484    /* load firmware into /sys/$DEVPATH/data */
    271485    data_fd = open("data", O_WRONLY);
    272486    if (data_fd == -1)
     
    274488    cnt = bb_copyfd_eof(firmware_fd, data_fd);
    275489
    276     /* tell kernel result by `echo [0|-1] > /sys/$DEVPATH/loading` */
     490    /* tell kernel result by "echo [0|-1] > /sys/$DEVPATH/loading" */
    277491    if (cnt > 0)
    278         write(loading_fd, "0", 1);
     492        full_write(loading_fd, "0", 1);
    279493    else
    280         write(loading_fd, "-1", 2);
     494        full_write(loading_fd, "-1", 2);
    281495
    282496 out:
     
    288502}
    289503
    290 int mdev_main(int argc, char **argv);
    291 int mdev_main(int argc, char **argv)
     504int mdev_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     505int mdev_main(int argc UNUSED_PARAM, char **argv)
    292506{
    293     char *action;
    294     char *env_path;
    295     RESERVE_CONFIG_BUFFER(temp,PATH_MAX);
     507    RESERVE_CONFIG_BUFFER(temp, PATH_MAX + SCRATCH_SIZE);
     508
     509    /* We can be called as hotplug helper */
     510    /* Kernel cannot provide suitable stdio fds for us, do it ourself */
     511    bb_sanitize_stdio();
     512
     513    /* Force the configuration file settings exactly */
     514    umask(0);
    296515
    297516    xchdir("/dev");
    298517
    299     /* Scan */
    300 
    301     if (argc == 2 && !strcmp(argv[1],"-s")) {
     518    if (argv[1] && strcmp(argv[1], "-s") == 0) {
     519        /* Scan:
     520         * mdev -s
     521         */
    302522        struct stat st;
    303523
    304524        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 
     525        G.root_major = major(st.st_dev);
     526        G.root_minor = minor(st.st_dev);
     527
     528        /* ACTION_FOLLOWLINKS is needed since in newer kernels
     529         * /sys/block/loop* (for example) are symlinks to dirs,
     530         * not real directories.
     531         * (kernel's CONFIG_SYSFS_DEPRECATED makes them real dirs,
     532         * but we can't enforce that on users)
     533         */
     534        if (access("/sys/class/block", F_OK) != 0) {
     535            /* Scan obsolete /sys/block only if /sys/class/block
     536             * doesn't exist. Otherwise we'll have dupes.
     537             * Also, do not complain if it doesn't exist.
     538             * Some people configure kernel to have no blockdevs.
     539             */
     540            recursive_action("/sys/block",
     541                ACTION_RECURSE | ACTION_FOLLOWLINKS | ACTION_QUIET,
     542                fileAction, dirAction, temp, 0);
     543        }
    312544        recursive_action("/sys/class",
    313545            ACTION_RECURSE | ACTION_FOLLOWLINKS,
    314546            fileAction, dirAction, temp, 0);
    315 
    316     /* Hotplug */
    317 
    318547    } else {
     548        char *fw;
     549        char *seq;
     550        char *action;
     551        char *env_path;
     552        static const char keywords[] ALIGN1 = "remove\0add\0";
     553        enum { OP_remove = 0, OP_add };
     554        smalluint op;
     555
     556        /* Hotplug:
     557         * env ACTION=... DEVPATH=... SUBSYSTEM=... [SEQNUM=...] mdev
     558         * ACTION can be "add" or "remove"
     559         * DEVPATH is like "/block/sda" or "/class/input/mice"
     560         */
    319561        action = getenv("ACTION");
    320562        env_path = getenv("DEVPATH");
    321         if (!action || !env_path)
     563        G.subsystem = getenv("SUBSYSTEM");
     564        if (!action || !env_path /*|| !G.subsystem*/)
    322565            bb_show_usage();
    323 
    324         sprintf(temp, "/sys%s", env_path);
    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);
     566        fw = getenv("FIRMWARE");
     567        op = index_in_strings(keywords, action);
     568        /* If it exists, does /dev/mdev.seq match $SEQNUM?
     569         * If it does not match, earlier mdev is running
     570         * in parallel, and we need to wait */
     571        seq = getenv("SEQNUM");
     572        if (seq) {
     573            int timeout = 2000 / 32; /* 2000 msec */
     574            do {
     575                int seqlen;
     576                char seqbuf[sizeof(int)*3 + 2];
     577
     578                seqlen = open_read_close("mdev.seq", seqbuf, sizeof(seqbuf-1));
     579                if (seqlen < 0) {
     580                    seq = NULL;
     581                    break;
     582                }
     583                seqbuf[seqlen] = '\0';
     584                if (seqbuf[0] == '\n' /* seed file? */
     585                 || strcmp(seq, seqbuf) == 0 /* correct idx? */
     586                ) {
     587                    break;
     588                }
     589                usleep(32*1000);
     590            } while (--timeout);
     591        }
     592
     593        snprintf(temp, PATH_MAX, "/sys%s", env_path);
     594        if (op == OP_remove) {
     595            /* Ignoring "remove firmware". It was reported
     596             * to happen and to cause erroneous deletion
     597             * of device nodes. */
     598            if (!fw)
     599                make_device(temp, /*delete:*/ 1);
     600        }
     601        else if (op == OP_add) {
     602            make_device(temp, /*delete:*/ 0);
     603            if (ENABLE_FEATURE_MDEV_LOAD_FIRMWARE) {
     604                if (fw)
     605                    load_firmware(fw, temp);
     606            }
     607        }
     608
     609        if (seq) {
     610            xopen_xwrite_close("mdev.seq", utoa(xatou(seq) + 1));
    332611        }
    333612    }
    334613
    335     if (ENABLE_FEATURE_CLEAN_UP) RELEASE_CONFIG_BUFFER(temp);
    336     return 0;
     614    if (ENABLE_FEATURE_CLEAN_UP)
     615        RELEASE_CONFIG_BUFFER(temp);
     616
     617    return EXIT_SUCCESS;
    337618}
  • branches/2.2.9/mindi-busybox/util-linux/minix.h

    r1765 r2725  
    3232
    3333/*
    34  * minix super-block data on disk
     34 * minix superblock data on disk
    3535 */
    36 struct minix_super_block {
     36struct minix_superblock {
    3737    uint16_t s_ninodes;
    3838    uint16_t s_nzones;
     
    4949struct minix_dir_entry {
    5050    uint16_t inode;
    51     char name[0];
     51    char name[];
    5252};
    5353
  • branches/2.2.9/mindi-busybox/util-linux/mkfs_minix.c

    r1765 r2725  
    33 * mkfs.c - make a linux (minix) file-system.
    44 *
    5  * (C) 1991 Linus Torvalds. This file may be redistributed as per
    6  * the Linux copyright.
     5 * (C) 1991 Linus Torvalds.
     6 *
     7 * Licensed under GPLv2, see file LICENSE in this source tree.
    78 */
    89
     
    6869#include "minix.h"
    6970
    70 #define DEBUG 0
    71 
    72 /* If debugging, store the very same times/uids/gids for image consistency */
    73 #if DEBUG
     71/* Store the very same times/uids/gids for image consistency */
     72#if 1
    7473# define CUR_TIME 0
    7574# define GETUID 0
    7675# define GETGID 0
    7776#else
     77/* Was using this. Is it useful? NB: this will break testsuite */
    7878# define CUR_TIME time(NULL)
    7979# define GETUID getuid()
     
    9090#endif
    9191
     92enum { dev_fd = 3 };
     93
    9294struct globals {
    93     int dev_fd;
    94 
    9595#if ENABLE_FEATURE_MINIX2
    9696    smallint version2;
     
    110110    unsigned currently_testing;
    111111
    112 
    113112    char root_block[BLOCK_SIZE];
    114     char super_block_buffer[BLOCK_SIZE];
     113    char superblock_buffer[BLOCK_SIZE];
    115114    char boot_block_buffer[512];
    116115    unsigned short good_blocks_table[MAX_GOOD_BLOCKS];
    117116    /* check_blocks(): buffer[] was the biggest static in entire bbox */
    118117    char check_blocks_buffer[BLOCK_SIZE * TEST_BUFFER_BLOCKS];
     118
     119    unsigned short ind_block1[BLOCK_SIZE >> 1];
     120    unsigned short dind_block1[BLOCK_SIZE >> 1];
     121    unsigned long ind_block2[BLOCK_SIZE >> 2];
     122    unsigned long dind_block2[BLOCK_SIZE >> 2];
    119123};
    120 
    121124#define G (*ptr_to_globals)
     125#define INIT_G() do { \
     126    SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
     127} while (0)
    122128
    123129static ALWAYS_INLINE unsigned div_roundup(unsigned size, unsigned n)
     
    129135#define INODE_BUF2              (((struct minix2_inode*)G.inode_buffer) - 1)
    130136
    131 #define SB                      (*(struct minix_super_block*)G.super_block_buffer)
     137#define SB                      (*(struct minix_superblock*)G.superblock_buffer)
    132138
    133139#define SB_INODES               (SB.s_ninodes)
     
    145151# define SB_ZONES               (version2 ? SB.s_zones : SB.s_nzones)
    146152# define INODE_BLOCKS           div_roundup(SB_INODES, \
    147                                 version2 ? MINIX2_INODES_PER_BLOCK : MINIX1_INODES_PER_BLOCK)
     153                                (version2 ? MINIX2_INODES_PER_BLOCK : MINIX1_INODES_PER_BLOCK))
    148154#endif
    149155
     
    156162static int minix_bit(const char* a, unsigned i)
    157163{
    158       return a[i >> 3] & (1<<(i & 7));
     164    return a[i >> 3] & (1<<(i & 7));
    159165}
    160166
     
    231237static void write_tables(void)
    232238{
    233     /* Mark the super block valid. */
     239    /* Mark the superblock valid. */
    234240    SB.s_state |= MINIX_VALID_FS;
    235241    SB.s_state &= ~MINIX_ERROR_FS;
    236242
    237243    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);
     244    xlseek(dev_fd, 0, SEEK_SET);
     245
     246    msg_eol = "can't clear boot sector";
     247    xwrite(dev_fd, G.boot_block_buffer, 512);
    242248
    243249    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);
     250    xlseek(dev_fd, BLOCK_SIZE, SEEK_SET);
     251
     252    msg_eol = "can't write superblock";
     253    xwrite(dev_fd, G.superblock_buffer, BLOCK_SIZE);
     254
     255    msg_eol = "can't write inode map";
     256    xwrite(dev_fd, G.inode_map, SB_IMAPS * BLOCK_SIZE);
     257
     258    msg_eol = "can't write zone map";
     259    xwrite(dev_fd, G.zone_map, SB_ZMAPS * BLOCK_SIZE);
     260
     261    msg_eol = "can't write inodes";
     262    xwrite(dev_fd, G.inode_buffer, INODE_BUFFER_SIZE);
    257263
    258264    msg_eol = "\n";
     
    261267static void write_block(int blk, char *buffer)
    262268{
    263     xlseek(G.dev_fd, blk * BLOCK_SIZE, SEEK_SET);
    264     xwrite(G.dev_fd, buffer, BLOCK_SIZE);
     269    xlseek(dev_fd, blk * BLOCK_SIZE, SEEK_SET);
     270    xwrite(dev_fd, buffer, BLOCK_SIZE);
    265271}
    266272
     
    307313    int i, j, zone;
    308314    int ind = 0, dind = 0;
     315    /* moved to globals to reduce stack usage
    309316    unsigned short ind_block[BLOCK_SIZE >> 1];
    310317    unsigned short dind_block[BLOCK_SIZE >> 1];
     318    */
     319#define ind_block (G.ind_block1)
     320#define dind_block (G.dind_block1)
    311321
    312322#define NEXT_BAD (zone = next(zone))
     
    352362    if (dind)
    353363        write_block(dind, (char *) dind_block);
     364#undef ind_block
     365#undef dind_block
    354366}
    355367
     
    360372    int i, j, zone;
    361373    int ind = 0, dind = 0;
     374    /* moved to globals to reduce stack usage
    362375    unsigned long ind_block[BLOCK_SIZE >> 2];
    363376    unsigned long dind_block[BLOCK_SIZE >> 2];
     377    */
     378#define ind_block (G.ind_block2)
     379#define dind_block (G.dind_block2)
    364380
    365381    if (!G.badblocks)
     
    402418    if (dind)
    403419        write_block(dind, (char *) dind_block);
     420#undef ind_block
     421#undef dind_block
    404422}
    405423#else
     
    465483    /* Seek to the correct loc. */
    466484    msg_eol = "seek failed during testing of blocks";
    467     xlseek(G.dev_fd, current_block * BLOCK_SIZE, SEEK_SET);
     485    xlseek(dev_fd, current_block * BLOCK_SIZE, SEEK_SET);
    468486    msg_eol = "\n";
    469487
    470488    /* Try the read */
    471     got = read(G.dev_fd, buffer, try * BLOCK_SIZE);
     489    got = read(dev_fd, buffer, try * BLOCK_SIZE);
    472490    if (got < 0)
    473491        got = 0;
     
    479497}
    480498
    481 static void alarm_intr(int alnum)
     499static void alarm_intr(int alnum UNUSED_PARAM)
    482500{
    483501    if (G.currently_testing >= SB_ZONES)
     
    488506        return;
    489507    printf("%d ...", G.currently_testing);
    490     fflush(stdout);
     508    fflush_all();
    491509}
    492510
     
    500518    while (G.currently_testing < SB_ZONES) {
    501519        msg_eol = "seek failed in check_blocks";
    502         xlseek(G.dev_fd, G.currently_testing * BLOCK_SIZE, SEEK_SET);
     520        xlseek(dev_fd, G.currently_testing * BLOCK_SIZE, SEEK_SET);
    503521        msg_eol = "\n";
    504522        try = TEST_BUFFER_BLOCKS;
     
    524542    unsigned long blockno;
    525543
    526     listfile = xfopen(filename, "r");
     544    listfile = xfopen_for_read(filename);
    527545    while (!feof(listfile)) {
    528546        fscanf(listfile, "%ld\n", &blockno);
     
    540558    unsigned i;
    541559
    542     /* memset(G.super_block_buffer, 0, BLOCK_SIZE); */
     560    /* memset(G.superblock_buffer, 0, BLOCK_SIZE); */
    543561    /* memset(G.boot_block_buffer, 0, 512); */
    544562    SB_MAGIC = G.magic;
     
    604622}
    605623
    606 int mkfs_minix_main(int argc, char **argv);
    607 int mkfs_minix_main(int argc, char **argv)
    608 {
    609     struct mntent *mp;
     624int mkfs_minix_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     625int mkfs_minix_main(int argc UNUSED_PARAM, char **argv)
     626{
    610627    unsigned opt;
    611628    char *tmp;
    612629    struct stat statbuf;
    613     char *str_i, *str_n;
     630    char *str_i;
    614631    char *listfile = NULL;
    615632
    616     PTR_TO_GLOBALS = xzalloc(sizeof(G));
     633    INIT_G();
    617634/* default (changed to 30, per Linus's suggestion, Sun Nov 21 08:05:07 1993) */
    618635    G.namelen = 30;
     
    627644#endif
    628645
    629     opt = getopt32(argv, "ci:l:n:v", &str_i, &listfile, &str_n);
     646    opt_complementary = "n+"; /* -n N */
     647    opt = getopt32(argv, "ci:l:n:v", &str_i, &listfile, &G.namelen);
    630648    argv += optind;
    631649    //if (opt & 1) -c
     
    633651    //if (opt & 4) -l
    634652    if (opt & 8) { // -n
    635         G.namelen = xatoi_u(str_n);
    636653        if (G.namelen == 14) G.magic = MINIX1_SUPER_MAGIC;
    637654        else if (G.namelen == 30) G.magic = MINIX1_SUPER_MAGIC2;
     
    666683
    667684    /* 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);
     685    if (find_mount_point(G.device_name, 0))
     686        bb_error_msg_and_die("can't format mounted filesystem");
     687
     688    xmove_fd(xopen(G.device_name, O_RDWR), dev_fd);
     689    xfstat(dev_fd, &statbuf, G.device_name);
    677690    if (!S_ISBLK(statbuf.st_mode))
    678691        opt &= ~1; // clear -c (check)
  • branches/2.2.9/mindi-busybox/util-linux/mkswap.c

    r1765 r2725  
    44 * Copyright 2006 Rob Landley <rob@landley.net>
    55 *
    6  * Licensed under GPL version 2, see file LICENSE in this tarball for details.
     6 * Licensed under GPLv2, see file LICENSE in this source tree.
    77 */
    8 
    98#include "libbb.h"
    109
    11 int mkswap_main(int argc, char **argv);
    12 int mkswap_main(int argc, char **argv)
     10#if ENABLE_SELINUX
     11static void mkswap_selinux_setcontext(int fd, const char *path)
    1312{
    14     int fd, pagesize;
     13    struct stat stbuf;
     14
     15    if (!is_selinux_enabled())
     16        return;
     17
     18    xfstat(fd, &stbuf, path);
     19    if (S_ISREG(stbuf.st_mode)) {
     20        security_context_t newcon;
     21        security_context_t oldcon = NULL;
     22        context_t context;
     23
     24        if (fgetfilecon(fd, &oldcon) < 0) {
     25            if (errno != ENODATA)
     26                goto error;
     27            if (matchpathcon(path, stbuf.st_mode, &oldcon) < 0)
     28                goto error;
     29        }
     30        context = context_new(oldcon);
     31        if (!context || context_type_set(context, "swapfile_t"))
     32            goto error;
     33        newcon = context_str(context);
     34        if (!newcon)
     35            goto error;
     36        /* fsetfilecon_raw is hidden */
     37        if (strcmp(oldcon, newcon) != 0 && fsetfilecon(fd, newcon) < 0)
     38            goto error;
     39        if (ENABLE_FEATURE_CLEAN_UP) {
     40            context_free(context);
     41            freecon(oldcon);
     42        }
     43    }
     44    return;
     45 error:
     46    bb_perror_msg_and_die("SELinux relabeling failed");
     47}
     48#else
     49# define mkswap_selinux_setcontext(fd, path) ((void)0)
     50#endif
     51
     52/* from Linux 2.6.23 */
     53/*
     54 * Magic header for a swap area. ... Note that the first
     55 * kilobyte is reserved for boot loader or disk label stuff.
     56 */
     57struct swap_header_v1 {
     58/*  char     bootbits[1024];    Space for disklabel etc. */
     59    uint32_t version;        /* second kbyte, word 0 */
     60    uint32_t last_page;      /* 1 */
     61    uint32_t nr_badpages;    /* 2 */
     62    char     sws_uuid[16];   /* 3,4,5,6 */
     63    char     sws_volume[16]; /* 7,8,9,10 */
     64    uint32_t padding[117];   /* 11..127 */
     65    uint32_t badpages[1];    /* 128 */
     66    /* total 129 32-bit words in 2nd kilobyte */
     67} FIX_ALIASING;
     68
     69#define NWORDS 129
     70#define hdr ((struct swap_header_v1*)bb_common_bufsiz1)
     71
     72struct BUG_sizes {
     73    char swap_header_v1_wrong[sizeof(*hdr)  != (NWORDS * 4) ? -1 : 1];
     74    char bufsiz1_is_too_small[COMMON_BUFSIZE < (NWORDS * 4) ? -1 : 1];
     75};
     76
     77/* Stored without terminating NUL */
     78static const char SWAPSPACE2[sizeof("SWAPSPACE2")-1] ALIGN1 = "SWAPSPACE2";
     79
     80int mkswap_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     81int mkswap_main(int argc UNUSED_PARAM, char **argv)
     82{
     83    int fd;
     84    unsigned pagesize;
    1585    off_t len;
    16     unsigned int hdr[129];
     86    const char *label = "";
    1787
    18     // No options supported.
     88    opt_complementary = "-1"; /* at least one param */
     89    /* TODO: -p PAGESZ, -U UUID */
     90    getopt32(argv, "L:", &label);
     91    argv += optind;
    1992
    20     if (argc != 2) bb_show_usage();
     93    fd = xopen(argv[0], O_WRONLY);
    2194
    22     // Figure out how big the device is and announce our intentions.
     95    /* Figure out how big the device is */
     96    len = get_volume_size_in_bytes(fd, argv[1], 1024, /*extend:*/ 1);
     97    pagesize = getpagesize();
     98    len -= pagesize;
    2399
    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);
     100    /* Announce our intentions */
     101    printf("Setting up swapspace version 1, size = %"OFF_FMT"u bytes\n", len);
     102    mkswap_selinux_setcontext(fd, argv[0]);
    29103
    30     // Make a header.
     104    /* hdr is zero-filled so far. Clear the first kbyte, or else
     105     * mkswap-ing former FAT partition does NOT erase its signature.
     106     *
     107     * util-linux-ng 2.17.2 claims to erase it only if it does not see
     108     * a partition table and is not run on whole disk. -f forces it.
     109     */
     110    xwrite(fd, hdr, 1024);
    31111
    32     memset(hdr, 0, sizeof(hdr));
    33     hdr[0] = 1;
    34     hdr[1] = (len / pagesize) - 1;
     112    /* Fill the header. */
     113    hdr->version = 1;
     114    hdr->last_page = (uoff_t)len / pagesize;
    35115
    36     // Write the header.  Sync to disk because some kernel versions check
    37     // signature on disk (not in cache) during swapon.
     116    if (ENABLE_FEATURE_MKSWAP_UUID) {
     117        char uuid_string[32];
     118        generate_uuid((void*)hdr->sws_uuid);
     119        bin2hex(uuid_string, hdr->sws_uuid, 16);
     120        /* f.e. UUID=dfd9c173-be52-4d27-99a5-c34c6c2ff55f */
     121        printf("UUID=%.8s"  "-%.4s-%.4s-%.4s-%.12s\n",
     122            uuid_string,
     123            uuid_string+8,
     124            uuid_string+8+4,
     125            uuid_string+8+4+4,
     126            uuid_string+8+4+4+4
     127        );
     128    }
     129    safe_strncpy(hdr->sws_volume, label, 16);
    38130
    39     xlseek(fd, 1024, SEEK_SET);
    40     xwrite(fd, hdr, sizeof(hdr));
    41     xlseek(fd, pagesize-10, SEEK_SET);
    42     xwrite(fd, "SWAPSPACE2", 10);
     131    /* Write the header.  Sync to disk because some kernel versions check
     132     * signature on disk (not in cache) during swapon. */
     133    xwrite(fd, hdr, NWORDS * 4);
     134    xlseek(fd, pagesize - 10, SEEK_SET);
     135    xwrite(fd, SWAPSPACE2, 10);
    43136    fsync(fd);
    44137
    45     if (ENABLE_FEATURE_CLEAN_UP) close(fd);
     138    if (ENABLE_FEATURE_CLEAN_UP)
     139        close(fd);
    46140
    47141    return 0;
  • branches/2.2.9/mindi-busybox/util-linux/more.c

    r1765 r2725  
    1212 * Termios corrects by Vladimir Oleynik <dzo@simtreas.ru>
    1313 *
    14  * Licensed under GPLv2 or later, see file License in this tarball for details.
     14 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    1515 */
    1616
    1717#include "libbb.h"
    18 #if ENABLE_FEATURE_USE_TERMIOS
    19 #include <termios.h>
    20 #endif /* FEATURE_USE_TERMIOS */
    21 
    22 
    23 #if ENABLE_FEATURE_USE_TERMIOS
     18
     19/* Support for FEATURE_USE_TERMIOS */
    2420
    2521struct globals {
     
    2723    struct termios initial_settings;
    2824    struct termios new_settings;
    29 };
     25} FIX_ALIASING;
    3026#define G (*(struct globals*)bb_common_bufsiz1)
    31 //#define G (*ptr_to_globals)
    3227#define INIT_G() ((void)0)
    33 //#define INIT_G() PTR_TO_GLOBALS = xzalloc(sizeof(G))
    3428#define initial_settings (G.initial_settings)
    3529#define new_settings     (G.new_settings    )
    3630#define cin_fileno       (G.cin_fileno      )
    3731
    38 #define setTermSettings(fd, argp) tcsetattr(fd, TCSANOW, argp)
     32#define setTermSettings(fd, argp) \
     33do { \
     34    if (ENABLE_FEATURE_USE_TERMIOS) \
     35        tcsetattr(fd, TCSANOW, argp); \
     36} while (0)
    3937#define getTermSettings(fd, argp) tcgetattr(fd, argp)
    4038
    41 static void gotsig(int sig)
     39static void gotsig(int sig UNUSED_PARAM)
    4240{
    43     putchar('\n');
     41    /* bb_putchar_stderr doesn't use stdio buffering,
     42     * therefore it is safe in signal handler */
     43    bb_putchar_stderr('\n');
    4444    setTermSettings(cin_fileno, &initial_settings);
    45     exit(EXIT_FAILURE);
     45    _exit(EXIT_FAILURE);
    4646}
    4747
    48 #else /* !FEATURE_USE_TERMIOS */
    49 #define INIT_G() ((void)0)
    50 #define setTermSettings(fd, argp) ((void)0)
    51 #endif /* FEATURE_USE_TERMIOS */
    52 
    5348#define CONVERTED_TAB_SIZE 8
    5449
    55 int more_main(int argc, char **argv);
    56 int more_main(int argc, char **argv)
     50int more_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     51int more_main(int argc UNUSED_PARAM, char **argv)
    5752{
    58     int c = c; /* for gcc */
     53    int c = c; /* for compiler */
    5954    int lines;
    6055    int input = 0;
     
    6560    FILE *cin;
    6661    int len;
    67     int terminal_width;
    68     int terminal_height;
     62    unsigned terminal_width;
     63    unsigned terminal_height;
    6964
    7065    INIT_G();
     
    7570    if (!isatty(STDOUT_FILENO))
    7671        return bb_cat(argv);
    77     cin = fopen(CURRENT_TTY, "r");
     72    cin = fopen_for_read(CURRENT_TTY);
    7873    if (!cin)
    7974        return bb_cat(argv);
    8075
    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);
    93 #endif
     76    if (ENABLE_FEATURE_USE_TERMIOS) {
     77        cin_fileno = fileno(cin);
     78        getTermSettings(cin_fileno, &initial_settings);
     79        new_settings = initial_settings;
     80        new_settings.c_lflag &= ~ICANON;
     81        new_settings.c_lflag &= ~ECHO;
     82        new_settings.c_cc[VMIN] = 1;
     83        new_settings.c_cc[VTIME] = 0;
     84        setTermSettings(cin_fileno, &new_settings);
     85        bb_signals(0
     86            + (1 << SIGINT)
     87            + (1 << SIGQUIT)
     88            + (1 << SIGTERM)
     89            , gotsig);
     90    }
    9491
    9592    do {
     
    118115                len = printf("--More-- ");
    119116                if (st.st_size > 0) {
    120                     len += printf("(%d%% of %"OFF_FMT"d bytes)",
     117                    len += printf("(%u%% of %"OFF_FMT"u bytes)",
    121118                        (int) (ftello(file)*100 / st.st_size),
    122119                        st.st_size);
    123120                }
    124                 fflush(stdout);
     121                fflush_all();
    125122
    126123                /*
     
    131128                    input = getc(cin);
    132129                    input = tolower(input);
    133 #if !ENABLE_FEATURE_USE_TERMIOS
    134                     printf("\033[A"); /* up cursor */
    135 #endif
     130                    if (!ENABLE_FEATURE_USE_TERMIOS)
     131                        printf("\033[A"); /* cursor up */
    136132                    /* Erase the last message */
    137133                    printf("\r%*s\r", len, "");
     
    155151                /* The user may have resized the terminal.
    156152                 * 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
     153                if (ENABLE_FEATURE_USE_TERMIOS) {
     154                    get_terminal_width_height(cin_fileno, &terminal_width, &terminal_height);
     155                    terminal_height -= 1;
     156                }
    161157            }
    162158
     
    166162                spaces = CONVERTED_TAB_SIZE - 1;
    167163                c = ' ';
    168             }
     164            }
    169165
    170166            /*
     
    198194        }
    199195        fclose(file);
    200         fflush(stdout);
     196        fflush_all();
    201197    } while (*argv && *++argv);
    202198 end:
  • branches/2.2.9/mindi-busybox/util-linux/mount.c

    r1765 r2725  
    77 * Copyright (C) 2005-2006 by Rob Landley <rob@landley.net>
    88 *
    9  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     9 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    1010 */
    11 
    12 /* Design notes: There is no spec for mount.  Remind me to write one.
    13 
    14    mount_main() calls singlemount() which calls mount_it_now().
    15 
    16    mount_main() can loop through /etc/fstab for mount -a
    17    singlemount() can loop through /etc/filesystems for fstype detection.
    18    mount_it_now() does the actual mount.
    19 */
     11// Design notes: There is no spec for mount.  Remind me to write one.
     12//
     13// mount_main() calls singlemount() which calls mount_it_now().
     14//
     15// mount_main() can loop through /etc/fstab for mount -a
     16// singlemount() can loop through /etc/filesystems for fstype detection.
     17// mount_it_now() does the actual mount.
     18//
     19#include <mntent.h>
     20#include <syslog.h>
     21#include <sys/mount.h>
     22// Grab more as needed from util-linux's mount/mount_constants.h
     23#ifndef MS_DIRSYNC
     24# define MS_DIRSYNC     (1 << 7) // Directory modifications are synchronous
     25#endif
     26#ifndef MS_UNION
     27# define MS_UNION       (1 << 8)
     28#endif
     29#ifndef MS_BIND
     30# define MS_BIND        (1 << 12)
     31#endif
     32#ifndef MS_MOVE
     33# define MS_MOVE        (1 << 13)
     34#endif
     35#ifndef MS_RECURSIVE
     36# define MS_RECURSIVE   (1 << 14)
     37#endif
     38#ifndef MS_SILENT
     39# define MS_SILENT      (1 << 15)
     40#endif
     41// The shared subtree stuff, which went in around 2.6.15
     42#ifndef MS_UNBINDABLE
     43# define MS_UNBINDABLE  (1 << 17)
     44#endif
     45#ifndef MS_PRIVATE
     46# define MS_PRIVATE     (1 << 18)
     47#endif
     48#ifndef MS_SLAVE
     49# define MS_SLAVE       (1 << 19)
     50#endif
     51#ifndef MS_SHARED
     52# define MS_SHARED      (1 << 20)
     53#endif
     54#ifndef MS_RELATIME
     55# define MS_RELATIME    (1 << 21)
     56#endif
    2057
    2158#include "libbb.h"
    22 #include <mntent.h>
    23 
    24 /* Needed for nfs support only... */
    25 #include <syslog.h>
     59#if ENABLE_FEATURE_MOUNT_LABEL
     60# include "volume_id.h"
     61#else
     62# define resolve_mount_spec(fsname) ((void)0)
     63#endif
     64
     65// Needed for nfs support only
    2666#include <sys/utsname.h>
    2767#undef TRUE
    2868#undef FALSE
    29 #include <rpc/rpc.h>
    30 #include <rpc/pmap_prot.h>
    31 #include <rpc/pmap_clnt.h>
     69#if ENABLE_FEATURE_MOUNT_NFS
     70/* This is just a warning of a common mistake.  Possibly this should be a
     71 * uclibc faq entry rather than in busybox... */
     72# if defined(__UCLIBC__) && ! defined(__UCLIBC_HAS_RPC__)
     73#  error "You need to build uClibc with UCLIBC_HAS_RPC for NFS support"
     74# endif
     75# include <rpc/rpc.h>
     76# include <rpc/pmap_prot.h>
     77# include <rpc/pmap_clnt.h>
     78#endif
    3279
    3380
    3481#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... */
    38 struct mntent *getmntent_r(FILE* stream, struct mntent* result, char* buffer, int bufsize)
    39 {
    40     /* *** XXX FIXME WARNING: This hack is NOT thread safe. --Sampo */
     82// 16.12.2006, Sampo Kellomaki (sampo@iki.fi)
     83// dietlibc-0.30 does not have implementation of getmntent_r()
     84static struct mntent *getmntent_r(FILE* stream, struct mntent* result,
     85        char* buffer UNUSED_PARAM, int bufsize UNUSED_PARAM)
     86{
    4187    struct mntent* ment = getmntent(stream);
    42     memcpy(result, ment, sizeof(struct mntent));
    43     return result;
     88    return memcpy(result, ment, sizeof(*ment));
    4489}
    4590#endif
     
    4893// Not real flags, but we want to be able to check for this.
    4994enum {
    50     MOUNT_USERS  = (1<<28)*ENABLE_DESKTOP,
    51     MOUNT_NOAUTO = (1<<29),
    52     MOUNT_SWAP   = (1<<30),
     95    MOUNT_USERS  = (1 << 28) * ENABLE_DESKTOP,
     96    MOUNT_NOAUTO = (1 << 29),
     97    MOUNT_SWAP   = (1 << 30),
    5398};
     99
     100
     101#define OPTION_STR "o:t:rwanfvsiO:"
     102enum {
     103    OPT_o = (1 << 0),
     104    OPT_t = (1 << 1),
     105    OPT_r = (1 << 2),
     106    OPT_w = (1 << 3),
     107    OPT_a = (1 << 4),
     108    OPT_n = (1 << 5),
     109    OPT_f = (1 << 6),
     110    OPT_v = (1 << 7),
     111    OPT_s = (1 << 8),
     112    OPT_i = (1 << 9),
     113    OPT_O = (1 << 10),
     114};
     115
     116#if ENABLE_FEATURE_MTAB_SUPPORT
     117#define USE_MTAB (!(option_mask32 & OPT_n))
     118#else
     119#define USE_MTAB 0
     120#endif
     121
     122#if ENABLE_FEATURE_MOUNT_FAKE
     123#define FAKE_IT (option_mask32 & OPT_f)
     124#else
     125#define FAKE_IT 0
     126#endif
     127
     128#if ENABLE_FEATURE_MOUNT_HELPERS
     129#define HELPERS_ALLOWED (!(option_mask32 & OPT_i))
     130#else
     131#define HELPERS_ALLOWED 0
     132#endif
     133
     134
    54135// TODO: more "user" flag compatibility.
    55136// "user" option (from mount manpage):
     
    61142// the console user owner of this device.
    62143
    63 /* Standard mount options (from -o options or --options), with corresponding
    64  * flags */
    65 
    66 struct {
    67     const char *name;
    68     long flags;
    69 } static mount_options[] = {
     144// Standard mount options (from -o options or --options),
     145// with corresponding flags
     146static const int32_t mount_options[] = {
    70147    // MS_FLAGS set a bit.  ~MS_FLAGS disable that bit.  0 flags are NOPs.
    71148
    72     USE_FEATURE_MOUNT_LOOP(
    73         {"loop", 0},
     149    IF_FEATURE_MOUNT_LOOP(
     150        /* "loop" */ 0,
    74151    )
    75152
    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},)
     153    IF_FEATURE_MOUNT_FSTAB(
     154        /* "defaults" */ 0,
     155        /* "quiet" 0 - do not filter out, vfat wants to see it */
     156        /* "noauto" */ MOUNT_NOAUTO,
     157        /* "sw"     */ MOUNT_SWAP,
     158        /* "swap"   */ MOUNT_SWAP,
     159        IF_DESKTOP(/* "user"  */ MOUNT_USERS,)
     160        IF_DESKTOP(/* "users" */ MOUNT_USERS,)
     161        /* "_netdev" */ 0,
    84162    )
    85163
    86     USE_FEATURE_MOUNT_FLAGS(
     164    IF_FEATURE_MOUNT_FLAGS(
    87165        // 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},
     166        /* "nosuid"      */ MS_NOSUID,
     167        /* "suid"        */ ~MS_NOSUID,
     168        /* "dev"         */ ~MS_NODEV,
     169        /* "nodev"       */ MS_NODEV,
     170        /* "exec"        */ ~MS_NOEXEC,
     171        /* "noexec"      */ MS_NOEXEC,
     172        /* "sync"        */ MS_SYNCHRONOUS,
     173        /* "dirsync"     */ MS_DIRSYNC,
     174        /* "async"       */ ~MS_SYNCHRONOUS,
     175        /* "atime"       */ ~MS_NOATIME,
     176        /* "noatime"     */ MS_NOATIME,
     177        /* "diratime"    */ ~MS_NODIRATIME,
     178        /* "nodiratime"  */ MS_NODIRATIME,
     179        /* "mand"        */ MS_MANDLOCK,
     180        /* "nomand"      */ ~MS_MANDLOCK,
     181        /* "relatime"    */ MS_RELATIME,
     182        /* "norelatime"  */ ~MS_RELATIME,
     183        /* "loud"        */ ~MS_SILENT,
    101184
    102185        // 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},
     186        /* "union"       */ MS_UNION,
     187        /* "bind"        */ MS_BIND,
     188        /* "move"        */ MS_MOVE,
     189        /* "shared"      */ MS_SHARED,
     190        /* "slave"       */ MS_SLAVE,
     191        /* "private"     */ MS_PRIVATE,
     192        /* "unbindable"  */ MS_UNBINDABLE,
     193        /* "rshared"     */ MS_SHARED|MS_RECURSIVE,
     194        /* "rslave"      */ MS_SLAVE|MS_RECURSIVE,
     195        /* "rprivate"    */ MS_SLAVE|MS_RECURSIVE,
     196        /* "runbindable" */ MS_UNBINDABLE|MS_RECURSIVE,
    114197    )
    115198
    116199    // Always understood.
    117 
    118     {"ro", MS_RDONLY},        // vfs flag
    119     {"rw", ~MS_RDONLY},       // vfs flag
    120     {"remount", MS_REMOUNT},  // action flag
     200    /* "ro"      */ MS_RDONLY,  // vfs flag
     201    /* "rw"      */ ~MS_RDONLY, // vfs flag
     202    /* "remount" */ MS_REMOUNT  // action flag
    121203};
    122204
    123 
    124 /* Append mount options to string */
     205static const char mount_option_str[] =
     206    IF_FEATURE_MOUNT_LOOP(
     207        "loop\0"
     208    )
     209    IF_FEATURE_MOUNT_FSTAB(
     210        "defaults\0"
     211        // "quiet\0" - do not filter out, vfat wants to see it
     212        "noauto\0"
     213        "sw\0"
     214        "swap\0"
     215        IF_DESKTOP("user\0")
     216        IF_DESKTOP("users\0")
     217        "_netdev\0"
     218    )
     219    IF_FEATURE_MOUNT_FLAGS(
     220        // vfs flags
     221        "nosuid\0"
     222        "suid\0"
     223        "dev\0"
     224        "nodev\0"
     225        "exec\0"
     226        "noexec\0"
     227        "sync\0"
     228        "dirsync\0"
     229        "async\0"
     230        "atime\0"
     231        "noatime\0"
     232        "diratime\0"
     233        "nodiratime\0"
     234        "mand\0"
     235        "nomand\0"
     236        "relatime\0"
     237        "norelatime\0"
     238        "loud\0"
     239
     240        // action flags
     241        "union\0"
     242        "bind\0"
     243        "move\0"
     244        "shared\0"
     245        "slave\0"
     246        "private\0"
     247        "unbindable\0"
     248        "rshared\0"
     249        "rslave\0"
     250        "rprivate\0"
     251        "runbindable\0"
     252    )
     253
     254    // Always understood.
     255    "ro\0"        // vfs flag
     256    "rw\0"        // vfs flag
     257    "remount\0"   // action flag
     258;
     259
     260
     261struct globals {
     262#if ENABLE_FEATURE_MOUNT_NFS
     263    smalluint nfs_mount_version;
     264#endif
     265#if ENABLE_FEATURE_MOUNT_VERBOSE
     266    unsigned verbose;
     267#endif
     268    llist_t *fslist;
     269    char getmntent_buf[1];
     270} FIX_ALIASING;
     271enum { GETMNTENT_BUFSIZE = COMMON_BUFSIZE - offsetof(struct globals, getmntent_buf) };
     272#define G (*(struct globals*)&bb_common_bufsiz1)
     273#define nfs_mount_version (G.nfs_mount_version)
     274#if ENABLE_FEATURE_MOUNT_VERBOSE
     275#define verbose           (G.verbose          )
     276#else
     277#define verbose           0
     278#endif
     279#define fslist            (G.fslist           )
     280#define getmntent_buf     (G.getmntent_buf    )
     281
     282
     283#if ENABLE_FEATURE_MOUNT_VERBOSE
     284static int verbose_mount(const char *source, const char *target,
     285        const char *filesystemtype,
     286        unsigned long mountflags, const void *data)
     287{
     288    int rc;
     289
     290    errno = 0;
     291    rc = mount(source, target, filesystemtype, mountflags, data);
     292    if (verbose >= 2)
     293        bb_perror_msg("mount('%s','%s','%s',0x%08lx,'%s'):%d",
     294            source, target, filesystemtype,
     295            mountflags, (char*)data, rc);
     296    return rc;
     297}
     298#else
     299#define verbose_mount(...) mount(__VA_ARGS__)
     300#endif
     301
     302// Append mount options to string
    125303static void append_mount_options(char **oldopts, const char *newopts)
    126304{
    127305    if (*oldopts && **oldopts) {
    128         /* do not insert options which are already there */
     306        // Do not insert options which are already there
    129307        while (newopts[0]) {
    130308            char *p;
     
    135313            while (1) {
    136314                if (!strncmp(p, newopts, len)
    137                  && (p[len]==',' || p[len]==0))
     315                 && (p[len] == ',' || p[len] == '\0'))
    138316                    goto skip;
    139317                p = strchr(p,',');
     
    144322            free(*oldopts);
    145323            *oldopts = p;
    146 skip:
     324 skip:
    147325            newopts += len;
    148326            while (newopts[0] == ',') newopts++;
     
    154332}
    155333
    156 /* Use the mount_options list to parse options into flags.
    157  * Also return list of unrecognized options if unrecognized!=NULL */
    158 static int parse_mount_options(char *options, char **unrecognized)
    159 {
    160     int flags = MS_SILENT;
     334// Use the mount_options list to parse options into flags.
     335// Also update list of unrecognized options if unrecognized != NULL
     336static long parse_mount_options(char *options, char **unrecognized)
     337{
     338    long flags = MS_SILENT;
    161339
    162340    // Loop through options
    163341    for (;;) {
    164         int i;
     342        unsigned i;
    165343        char *comma = strchr(options, ',');
    166 
    167         if (comma) *comma = 0;
    168 
     344        const char *option_str = mount_option_str;
     345
     346        if (comma) *comma = '\0';
     347
     348// FIXME: use hasmntopt()
    169349        // Find this option in mount_options
    170350        for (i = 0; i < ARRAY_SIZE(mount_options); i++) {
    171             if (!strcasecmp(mount_options[i].name, options)) {
    172                 long fl = mount_options[i].flags;
    173                 if (fl < 0) flags &= fl;
    174                 else flags |= fl;
    175                 break;
     351            if (strcasecmp(option_str, options) == 0) {
     352                long fl = mount_options[i];
     353                if (fl < 0)
     354                    flags &= fl;
     355                else
     356                    flags |= fl;
     357                goto found;
    176358            }
    177         }
    178         // If unrecognized not NULL, append unrecognized mount options */
    179         if (unrecognized && i == ARRAY_SIZE(mount_options)) {
     359            option_str += strlen(option_str) + 1;
     360        }
     361        // We did not recognize this option.
     362        // If "unrecognized" is not NULL, append option there.
     363        // Note that we should not append *empty* option -
     364        // in this case we want to pass NULL, not "", to "data"
     365        // parameter of mount(2) syscall.
     366        // This is crucial for filesystems that don't accept
     367        // any arbitrary mount options, like cgroup fs:
     368        // "mount -t cgroup none /mnt"
     369        if (options[0] && unrecognized) {
    180370            // Add it to strflags, to pass on to kernel
    181             i = *unrecognized ? strlen(*unrecognized) : 0;
    182             *unrecognized = xrealloc(*unrecognized, i+strlen(options)+2);
     371            char *p = *unrecognized;
     372            unsigned len = p ? strlen(p) : 0;
     373            *unrecognized = p = xrealloc(p, len + strlen(options) + 2);
    183374
    184375            // Comma separated if it's not the first one
    185             if (i) (*unrecognized)[i++] = ',';
    186             strcpy((*unrecognized)+i, options);
    187         }
    188 
    189         // Advance to next option, or finish
    190         if (comma) {
    191             *comma = ',';
    192             options = ++comma;
    193         } else break;
     376            if (len) p[len++] = ',';
     377            strcpy(p + len, options);
     378        }
     379 found:
     380        if (!comma)
     381            break;
     382        // Advance to next option
     383        *comma = ',';
     384        options = ++comma;
    194385    }
    195386
     
    198389
    199390// Return a list of all block device backed filesystems
    200 
    201391static llist_t *get_block_backed_filesystems(void)
    202392{
     
    206396    };
    207397    char *fs, *buf;
    208     llist_t *list = 0;
     398    llist_t *list = NULL;
    209399    int i;
    210400    FILE *f;
    211401
    212402    for (i = 0; i < 2; i++) {
    213         f = fopen(filesystems[i], "r");
     403        f = fopen_for_read(filesystems[i]);
    214404        if (!f) continue;
    215405
    216         while ((buf = xmalloc_getline(f)) != 0) {
    217             if (!strncmp(buf, "nodev", 5) && isspace(buf[5]))
     406        while ((buf = xmalloc_fgetline(f)) != NULL) {
     407            if (strncmp(buf, "nodev", 5) == 0 && isspace(buf[5]))
    218408                continue;
    219409            fs = skip_whitespace(buf);
    220             if (*fs=='#' || *fs=='*' || !*fs) continue;
     410            if (*fs == '#' || *fs == '*' || !*fs)
     411                continue;
    221412
    222413            llist_add_to_end(&list, xstrdup(fs));
     
    229420}
    230421
    231 llist_t *fslist = 0;
    232 
    233422#if ENABLE_FEATURE_CLEAN_UP
    234423static void delete_block_backed_filesystems(void)
     
    240429#endif
    241430
    242 #if ENABLE_FEATURE_MTAB_SUPPORT
    243 static int useMtab = 1;
    244 static int fakeIt;
    245 #else
    246 #define useMtab 0
    247 #define fakeIt 0
    248 #endif
    249 
    250431// Perform actual mount of specific filesystem at specific location.
    251432// NB: mp->xxx fields may be trashed on exit
    252 static int mount_it_now(struct mntent *mp, int vfsflags, char *filteropts)
     433static int mount_it_now(struct mntent *mp, long vfsflags, char *filteropts)
    253434{
    254435    int rc = 0;
    255436
    256     if (fakeIt) goto mtab;
     437    if (FAKE_IT) {
     438        if (verbose >= 2)
     439            bb_error_msg("would do mount('%s','%s','%s',0x%08lx,'%s')",
     440                mp->mnt_fsname, mp->mnt_dir, mp->mnt_type,
     441                vfsflags, filteropts);
     442        goto mtab;
     443    }
    257444
    258445    // Mount, with fallback to read-only if necessary.
    259 
    260446    for (;;) {
    261         rc = mount(mp->mnt_fsname, mp->mnt_dir, mp->mnt_type,
     447        errno = 0;
     448        rc = verbose_mount(mp->mnt_fsname, mp->mnt_dir, mp->mnt_type,
    262449                vfsflags, filteropts);
    263         if (!rc || (vfsflags&MS_RDONLY) || (errno!=EACCES && errno!=EROFS))
     450
     451        // If mount failed, try
     452        // helper program mount.<mnt_type>
     453        if (HELPERS_ALLOWED && rc && mp->mnt_type) {
     454            char *args[8];
     455            int errno_save = errno;
     456            args[0] = xasprintf("mount.%s", mp->mnt_type);
     457            rc = 1;
     458            if (FAKE_IT)
     459                args[rc++] = (char *)"-f";
     460            if (ENABLE_FEATURE_MTAB_SUPPORT && !USE_MTAB)
     461                args[rc++] = (char *)"-n";
     462            args[rc++] = mp->mnt_fsname;
     463            args[rc++] = mp->mnt_dir;
     464            if (filteropts) {
     465                args[rc++] = (char *)"-o";
     466                args[rc++] = filteropts;
     467            }
     468            args[rc] = NULL;
     469            rc = spawn_and_wait(args);
     470            free(args[0]);
     471            if (!rc)
     472                break;
     473            errno = errno_save;
     474        }
     475
     476        if (!rc || (vfsflags & MS_RDONLY) || (errno != EACCES && errno != EROFS))
    264477            break;
    265         bb_error_msg("%s is write-protected, mounting read-only",
    266                 mp->mnt_fsname);
     478        if (!(vfsflags & MS_SILENT))
     479            bb_error_msg("%s is write-protected, mounting read-only",
     480                        mp->mnt_fsname);
    267481        vfsflags |= MS_RDONLY;
    268482    }
     
    273487        bb_error_msg_and_die(bb_msg_perm_denied_are_you_root);
    274488
    275     /* If the mount was successful, and we're maintaining an old-style
    276      * mtab file by hand, add the new entry to it now. */
     489    // If the mount was successful, and we're maintaining an old-style
     490    // mtab file by hand, add the new entry to it now.
    277491 mtab:
    278     if (ENABLE_FEATURE_MTAB_SUPPORT && useMtab && !rc && !(vfsflags & MS_REMOUNT)) {
     492    if (USE_MTAB && !rc && !(vfsflags & MS_REMOUNT)) {
    279493        char *fsname;
    280494        FILE *mountTable = setmntent(bb_path_mtab_file, "a+");
     495        const char *option_str = mount_option_str;
    281496        int i;
    282497
    283498        if (!mountTable) {
    284             bb_error_msg("no %s",bb_path_mtab_file);
     499            bb_error_msg("no %s", bb_path_mtab_file);
    285500            goto ret;
    286501        }
     
    288503        // Add vfs string flags
    289504
    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);
     505        for (i = 0; mount_options[i] != MS_REMOUNT; i++) {
     506            if (mount_options[i] > 0 && (mount_options[i] & vfsflags))
     507                append_mount_options(&(mp->mnt_opts), option_str);
     508            option_str += strlen(option_str) + 1;
     509        }
    293510
    294511        // Remove trailing / (if any) from directory we mounted on
    295512
    296513        i = strlen(mp->mnt_dir) - 1;
    297         if (i > 0 && mp->mnt_dir[i] == '/') mp->mnt_dir[i] = 0;
     514        if (i > 0 && mp->mnt_dir[i] == '/') mp->mnt_dir[i] = '\0';
    298515
    299516        // Convert to canonical pathnames as needed
     
    301518        mp->mnt_dir = bb_simplify_path(mp->mnt_dir);
    302519        fsname = 0;
    303         if (!mp->mnt_type || !*mp->mnt_type) { /* bind mount */
     520        if (!mp->mnt_type || !*mp->mnt_type) { // bind mount
    304521            mp->mnt_fsname = fsname = bb_simplify_path(mp->mnt_fsname);
    305522            mp->mnt_type = (char*)"bind";
     
    326543 * Copyright (C) 1993 Rick Sladkey <jrs@world.std.com>
    327544 *
    328  * Licensed under GPLv2, see file LICENSE in this tarball for details.
     545 * Licensed under GPLv2, see file LICENSE in this source tree.
    329546 *
    330547 * Wed Feb  8 12:51:48 1995, biro@yggdrasil.com (Ross Biro): allow all port
     
    337554 * Implemented the "bg", "fg" and "retry" mount options for NFS.
    338555 *
    339  * 1999-02-22 Arkadiusz Mikiewicz <misiek@misiek.eu.org>
     556 * 1999-02-22 Arkadiusz Mickiewicz <misiek@misiek.eu.org>
    340557 * - added Native Language Support
    341558 *
     
    343560 * plus NFSv3 stuff.
    344561 */
    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
    351562
    352563#define MOUNTPORT 635
     
    527738    NFS_MOUNT_VER3 = 0x0080,    /* 3 */
    528739    NFS_MOUNT_KERBEROS = 0x0100,    /* 3 */
    529     NFS_MOUNT_NONLM = 0x0200    /* 3 */
     740    NFS_MOUNT_NONLM = 0x0200,   /* 3 */
     741    NFS_MOUNT_NORDIRPLUS = 0x4000
    530742};
    531743
     
    539751 *  it cannot even be used as a struct tag or field name".
    540752 */
    541 
    542753#ifndef EDQUOT
    543 #define EDQUOT  ENOSPC
    544 #endif
    545 
    546 // Convert each NFSERR_BLAH into EBLAH
    547 
    548 static 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}
     754# define EDQUOT ENOSPC
     755#endif
     756/* Convert each NFSERR_BLAH into EBLAH */
     757static const uint8_t nfs_err_stat[] = {
     758     1,  2,  5,  6, 13, 17,
     759    19, 20, 21, 22, 27, 28,
     760    30, 63, 66, 69, 70, 71
    556761};
    557 
     762#if ( \
     763    EPERM | ENOENT      | EIO      | ENXIO | EACCES| EEXIST | \
     764    ENODEV| ENOTDIR     | EISDIR   | EINVAL| EFBIG | ENOSPC | \
     765    EROFS | ENAMETOOLONG| ENOTEMPTY| EDQUOT| ESTALE| EREMOTE) < 256
     766typedef uint8_t nfs_err_type;
     767#else
     768typedef uint16_t nfs_err_type;
     769#endif
     770static const nfs_err_type nfs_err_errnum[] = {
     771    EPERM , ENOENT      , EIO      , ENXIO , EACCES, EEXIST,
     772    ENODEV, ENOTDIR     , EISDIR   , EINVAL, EFBIG , ENOSPC,
     773    EROFS , ENAMETOOLONG, ENOTEMPTY, EDQUOT, ESTALE, EREMOTE
     774};
    558775static char *nfs_strerror(int status)
    559776{
    560777    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;
     778
     779    for (i = 0; i < ARRAY_SIZE(nfs_err_stat); i++) {
     780        if (nfs_err_stat[i] == status)
     781            return strerror(nfs_err_errnum[i]);
     782    }
     783    return xasprintf("unknown nfs status return value: %d", status);
    569784}
    570785
    571786static bool_t xdr_fhandle(XDR *xdrs, fhandle objp)
    572787{
    573     if (!xdr_opaque(xdrs, objp, FHSIZE))
    574          return FALSE;
    575     return TRUE;
     788    return xdr_opaque(xdrs, objp, FHSIZE);
    576789}
    577790
     
    580793    if (!xdr_u_int(xdrs, &objp->fhs_status))
    581794         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     }
     795    if (objp->fhs_status == 0)
     796        return xdr_fhandle(xdrs, objp->fhstatus_u.fhs_fhandle);
    590797    return TRUE;
    591798}
     
    593800static bool_t xdr_dirpath(XDR *xdrs, dirpath *objp)
    594801{
    595     if (!xdr_string(xdrs, objp, MNTPATHLEN))
    596          return FALSE;
    597     return TRUE;
     802    return xdr_string(xdrs, objp, MNTPATHLEN);
    598803}
    599804
    600805static bool_t xdr_fhandle3(XDR *xdrs, fhandle3 *objp)
    601806{
    602     if (!xdr_bytes(xdrs, (char **)&objp->fhandle3_val, (unsigned int *) &objp->fhandle3_len, FHSIZE3))
    603          return FALSE;
    604     return TRUE;
     807    return xdr_bytes(xdrs, (char **)&objp->fhandle3_val,
     808               (unsigned int *) &objp->fhandle3_len,
     809               FHSIZE3);
    605810}
    606811
     
    609814    if (!xdr_fhandle3(xdrs, &objp->fhandle))
    610815        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;
     816    return xdr_array(xdrs, &(objp->auth_flavours.auth_flavours_val),
     817               &(objp->auth_flavours.auth_flavours_len),
     818               ~0,
     819               sizeof(int),
     820               (xdrproc_t) xdr_int);
    615821}
    616822
    617823static bool_t xdr_mountstat3(XDR *xdrs, mountstat3 *objp)
    618824{
    619     if (!xdr_enum(xdrs, (enum_t *) objp))
    620          return FALSE;
    621     return TRUE;
     825    return xdr_enum(xdrs, (enum_t *) objp);
    622826}
    623827
     
    626830    if (!xdr_mountstat3(xdrs, &objp->fhs_status))
    627831        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     }
     832    if (objp->fhs_status == MNT_OK)
     833        return xdr_mountres3_ok(xdrs, &objp->mountres3_u.mountinfo);
    636834    return TRUE;
    637835}
    638836
    639837#define MAX_NFSPROT ((nfs_mount_version >= 4) ? 3 : 2)
    640 
    641 /*
    642  * nfs_mount_version according to the sources seen at compile time.
    643  */
    644 static int nfs_mount_version;
    645 static int kernel_version;
    646838
    647839/*
     
    659851find_kernel_nfs_mount_version(void)
    660852{
    661     if (kernel_version)
     853    int kernel_version;
     854
     855    if (nfs_mount_version)
    662856        return;
    663857
     
    666860    kernel_version = get_linux_version_code();
    667861    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)))
     862        if (kernel_version < KERNEL_VERSION(2,2,18))
    673863            nfs_mount_version = 3;
    674864        /* else v4 since 2.3.99pre4 */
     
    676866}
    677867
    678 static struct pmap *
    679 get_mountport(struct sockaddr_in *server_addr,
     868static void
     869get_mountport(struct pmap *pm_mnt,
     870    struct sockaddr_in *server_addr,
    680871    long unsigned prog,
    681872    long unsigned version,
     
    684875{
    685876    struct pmaplist *pmap;
    686     static struct pmap p = {0, 0, 0, 0};
    687877
    688878    server_addr->sin_port = PMAPPORT;
     
    695885    if (!prog)
    696886        prog = MOUNTPROG;
    697     p.pm_prog = prog;
    698     p.pm_vers = version;
    699     p.pm_prot = proto;
    700     p.pm_port = port;
     887    pm_mnt->pm_prog = prog;
     888    pm_mnt->pm_vers = version;
     889    pm_mnt->pm_prot = proto;
     890    pm_mnt->pm_port = port;
    701891
    702892    while (pmap) {
    703893        if (pmap->pml_map.pm_prog != prog)
    704894            goto next;
    705         if (!version && p.pm_vers > pmap->pml_map.pm_vers)
     895        if (!version && pm_mnt->pm_vers > pmap->pml_map.pm_vers)
    706896            goto next;
    707897        if (version > 2 && pmap->pml_map.pm_vers != version)
     
    709899        if (version && version <= 2 && pmap->pml_map.pm_vers > 2)
    710900            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))
     901        if (pmap->pml_map.pm_vers > MAX_NFSPROT
     902         || (proto && pm_mnt->pm_prot && pmap->pml_map.pm_prot != proto)
     903         || (port && pmap->pml_map.pm_port != port)
     904        ) {
    714905            goto next;
    715         memcpy(&p, &pmap->pml_map, sizeof(p));
    716 next:
     906        }
     907        memcpy(pm_mnt, &pmap->pml_map, sizeof(*pm_mnt));
     908 next:
    717909        pmap = pmap->pml_next;
    718910    }
    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 
     911    if (!pm_mnt->pm_vers)
     912        pm_mnt->pm_vers = MOUNTVERS;
     913    if (!pm_mnt->pm_port)
     914        pm_mnt->pm_port = MOUNTPORT;
     915    if (!pm_mnt->pm_prot)
     916        pm_mnt->pm_prot = IPPROTO_TCP;
     917}
     918
     919#if BB_MMU
    728920static int daemonize(void)
    729921{
    730     int fd;
    731922    int pid = fork();
    732923    if (pid < 0) /* error */
     
    735926        return 0;
    736927    /* 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--);
     928    close(0);
     929    xopen(bb_dev_null, O_RDWR);
     930    xdup2(0, 1);
     931    xdup2(0, 2);
    742932    setsid();
    743933    openlog(applet_name, LOG_PID, LOG_DAEMON);
     
    745935    return 1;
    746936}
    747 
    748 // TODO
    749 static inline int we_saw_this_host_before(const char *hostname)
     937#else
     938static inline int daemonize(void) { return -ENOSYS; }
     939#endif
     940
     941/* TODO */
     942static inline int we_saw_this_host_before(const char *hostname UNUSED_PARAM)
    750943{
    751944    return 0;
     
    765958}
    766959
    767 // NB: mp->xxx fields may be trashed on exit
    768 static int nfsmount(struct mntent *mp, int vfsflags, char *filteropts)
     960/* NB: mp->xxx fields may be trashed on exit */
     961static NOINLINE int nfsmount(struct mntent *mp, long vfsflags, char *filteropts)
    769962{
    770963    CLIENT *mclient;
     
    772965    char *pathname;
    773966    char *mounthost;
     967    /* prior to 2.6.23, kernel took NFS options in a form of this struct
     968     * only. 2.6.23+ looks at data->version, and if it's not 1..6,
     969     * then data pointer is interpreted as a string. */
    774970    struct nfs_mount_data data;
    775971    char *opt;
     
    787983    int mountport;
    788984    int proto;
    789     int bg;
    790     int soft;
    791     int intr;
    792     int posix;
    793     int nocto;
    794     int noac;
    795     int nolock;
     985#if BB_MMU
     986    smallint bg = 0;
     987#else
     988    enum { bg = 0 };
     989#endif
    796990    int retry;
    797     int tcp;
    798991    int mountprog;
    799992    int mountvers;
     
    801994    int nfsvers;
    802995    int retval;
     996    /* these all are one-bit really. gcc 4.3.1 likes this combination: */
     997    smallint tcp;
     998    smallint soft;
     999    int intr;
     1000    int posix;
     1001    int nocto;
     1002    int noac;
     1003    int nordirplus;
     1004    int nolock;
    8031005
    8041006    find_kernel_nfs_mount_version();
     
    8341036            goto fail;
    8351037        }
    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);
     1038        if (hp->h_length != (int)sizeof(struct in_addr)) {
     1039            bb_error_msg_and_die("only IPv4 is supported");
     1040        }
     1041        memcpy(&server_addr.sin_addr, hp->h_addr_list[0], sizeof(struct in_addr));
    8421042    }
    8431043
     
    8611061     * timeo is filled in after we know whether it'll be TCP or UDP. */
    8621062    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;
     1063    data.retrans  = 3;
     1064    data.acregmin = 3;
     1065    data.acregmax = 60;
     1066    data.acdirmin = 30;
     1067    data.acdirmax = 60;
     1068    data.namlen   = NAME_MAX;
     1069
    8711070    soft = 0;
    8721071    intr = 0;
     
    8751074    nolock = 0;
    8761075    noac = 0;
     1076    nordirplus = 0;
    8771077    retry = 10000;      /* 10000 minutes ~ 1 week */
    8781078    tcp = 0;
     
    8891089        char *opteq = strchr(opt, '=');
    8901090        if (opteq) {
     1091            int val, idx;
    8911092            static const char options[] ALIGN1 =
    8921093                /* 0 */ "rsize\0"
     
    9111112                /* 19 */ "namlen\0"
    9121113                /* 20 */ "addr\0";
    913             int val = xatoi_u(opteq + 1);
    914             *opteq = '\0';
    915             switch (index_in_strings(options, opt)) {
     1114
     1115            *opteq++ = '\0';
     1116            idx = index_in_strings(options, opt);
     1117            switch (idx) {
     1118            case 12: // "mounthost"
     1119                mounthost = xstrndup(opteq,
     1120                        strcspn(opteq, " \t\n\r,"));
     1121                continue;
     1122            case 18: // "proto"
     1123                if (!strncmp(opteq, "tcp", 3))
     1124                    tcp = 1;
     1125                else if (!strncmp(opteq, "udp", 3))
     1126                    tcp = 0;
     1127                else
     1128                    bb_error_msg("warning: unrecognized proto= option");
     1129                continue;
     1130            case 20: // "addr" - ignore
     1131                continue;
     1132            }
     1133
     1134            val = xatoi_positive(opteq);
     1135            switch (idx) {
    9161136            case 0: // "rsize"
    9171137                data.rsize = val;
    918                 break;
     1138                continue;
    9191139            case 1: // "wsize"
    9201140                data.wsize = val;
    921                 break;
     1141                continue;
    9221142            case 2: // "timeo"
    9231143                data.timeo = val;
    924                 break;
     1144                continue;
    9251145            case 3: // "retrans"
    9261146                data.retrans = val;
    927                 break;
     1147                continue;
    9281148            case 4: // "acregmin"
    9291149                data.acregmin = val;
    930                 break;
     1150                continue;
    9311151            case 5: // "acregmax"
    9321152                data.acregmax = val;
    933                 break;
     1153                continue;
    9341154            case 6: // "acdirmin"
    9351155                data.acdirmin = val;
    936                 break;
     1156                continue;
    9371157            case 7: // "acdirmax"
    9381158                data.acdirmax = val;
    939                 break;
     1159                continue;
    9401160            case 8: // "actimeo"
    9411161                data.acregmin = val;
     
    9431163                data.acdirmin = val;
    9441164                data.acdirmax = val;
    945                 break;
     1165                continue;
    9461166            case 9: // "retry"
    9471167                retry = val;
    948                 break;
     1168                continue;
    9491169            case 10: // "port"
    9501170                port = val;
    951                 break;
     1171                continue;
    9521172            case 11: // "mountport"
    9531173                mountport = val;
    954                 break;
    955             case 12: // "mounthost"
    956                 mounthost = xstrndup(opteq+1,
    957                         strcspn(opteq+1," \t\n\r,"));
    958                 break;
     1174                continue;
    9591175            case 13: // "mountprog"
    9601176                mountprog = val;
    961                 break;
     1177                continue;
    9621178            case 14: // "mountvers"
    9631179                mountvers = val;
    964                 break;
     1180                continue;
    9651181            case 15: // "nfsprog"
    9661182                nfsprog = val;
    967                 break;
     1183                continue;
    9681184            case 16: // "nfsvers"
    9691185            case 17: // "vers"
    9701186                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;
     1187                continue;
    9801188            case 19: // "namlen"
    981                 if (nfs_mount_version >= 2)
     1189                //if (nfs_mount_version >= 2)
    9821190                    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;
     1191                //else
     1192                //  bb_error_msg("warning: option namlen is not supported\n");
     1193                continue;
    9881194            default:
    9891195                bb_error_msg("unknown nfs mount parameter: %s=%d", opt, val);
     
    9911197            }
    9921198        }
    993         else {
     1199        else { /* not of the form opt=val */
    9941200            static const char options[] ALIGN1 =
    9951201                "bg\0"
     
    10031209                "tcp\0"
    10041210                "udp\0"
    1005                 "lock\0";
     1211                "lock\0"
     1212                "rdirplus\0";
    10061213            int val = 1;
    10071214            if (!strncmp(opt, "no", 2)) {
     
    10111218            switch (index_in_strings(options, opt)) {
    10121219            case 0: // "bg"
     1220#if BB_MMU
    10131221                bg = val;
     1222#endif
    10141223                break;
    10151224            case 1: // "fg"
     1225#if BB_MMU
    10161226                bg = !val;
     1227#endif
    10171228                break;
    10181229            case 2: // "soft"
     
    10461257                    bb_error_msg("warning: option nolock is not supported");
    10471258                break;
     1259            case 11: //rdirplus
     1260                nordirplus = !val;
     1261                break;
    10481262            default:
    10491263                bb_error_msg("unknown nfs mount option: %s%s", val ? "" : "no", opt);
     
    10581272        | (posix ? NFS_MOUNT_POSIX : 0)
    10591273        | (nocto ? NFS_MOUNT_NOCTO : 0)
    1060         | (noac ? NFS_MOUNT_NOAC : 0);
     1274        | (noac ? NFS_MOUNT_NOAC : 0)
     1275        | (nordirplus ? NFS_MOUNT_NORDIRPLUS : 0);
    10611276    if (nfs_mount_version >= 2)
    10621277        data.flags |= (tcp ? NFS_MOUNT_TCP : 0);
     
    10881303     */
    10891304    if (bg && we_saw_this_host_before(hostname)) {
    1090         daemonized = daemonize(); /* parent or error */
     1305        daemonized = daemonize();
    10911306        if (daemonized <= 0) { /* parent or error */
    10921307            retval = -daemonized;
     
    10951310    }
    10961311
    1097     /* create mount daemon client */
     1312    /* Create mount daemon client */
    10981313    /* See if the nfs host = mount host. */
    10991314    if (mounthost) {
     
    11061321                bb_herror_msg("%s", mounthost);
    11071322                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);
    11161323            }
     1324            if (hp->h_length != (int)sizeof(struct in_addr)) {
     1325                bb_error_msg_and_die("only IPv4 is supported");
     1326            }
     1327            mount_server_addr.sin_family = AF_INET;
     1328            memcpy(&mount_server_addr.sin_addr, hp->h_addr_list[0], sizeof(struct in_addr));
    11171329        }
    11181330    }
     
    11331345        struct timeval total_timeout;
    11341346        struct timeval retry_timeout;
    1135         struct pmap* pm_mnt;
     1347        struct pmap pm_mnt;
    11361348        time_t t;
    11371349        time_t prevt;
     
    11421354        total_timeout.tv_sec = 20;
    11431355        total_timeout.tv_usec = 0;
     1356/* FIXME: use monotonic()? */
    11441357        timeout = time(NULL) + 60 * retry;
    11451358        prevt = 0;
    11461359        t = 30;
    1147 retry:
    1148         /* be careful not to use too many CPU cycles */
     1360 retry:
     1361        /* Be careful not to use too many CPU cycles */
    11491362        if (t - prevt < 30)
    11501363            sleep(30);
    11511364
    1152         pm_mnt = get_mountport(&mount_server_addr,
     1365        get_mountport(&pm_mnt, &mount_server_addr,
    11531366                mountprog,
    11541367                mountvers,
    11551368                proto,
    11561369                mountport);
    1157         nfsvers = (pm_mnt->pm_vers < 2) ? 2 : pm_mnt->pm_vers;
     1370        nfsvers = (pm_mnt.pm_vers < 2) ? 2 : pm_mnt.pm_vers;
    11581371
    11591372        /* contact the mount daemon via TCP */
    1160         mount_server_addr.sin_port = htons(pm_mnt->pm_port);
     1373        mount_server_addr.sin_port = htons(pm_mnt.pm_port);
    11611374        msock = RPC_ANYSOCK;
    11621375
    1163         switch (pm_mnt->pm_prot) {
     1376        switch (pm_mnt.pm_prot) {
    11641377        case IPPROTO_UDP:
    11651378            mclient = clntudp_create(&mount_server_addr,
    1166                          pm_mnt->pm_prog,
    1167                          pm_mnt->pm_vers,
     1379                         pm_mnt.pm_prog,
     1380                         pm_mnt.pm_vers,
    11681381                         retry_timeout,
    11691382                         &msock);
    11701383            if (mclient)
    11711384                break;
    1172             mount_server_addr.sin_port = htons(pm_mnt->pm_port);
     1385            mount_server_addr.sin_port = htons(pm_mnt.pm_port);
    11731386            msock = RPC_ANYSOCK;
    11741387        case IPPROTO_TCP:
    11751388            mclient = clnttcp_create(&mount_server_addr,
    1176                          pm_mnt->pm_prog,
    1177                          pm_mnt->pm_vers,
     1389                         pm_mnt.pm_prog,
     1390                         pm_mnt.pm_vers,
    11781391                         &msock, 0, 0);
    11791392            break;
    11801393        default:
    1181             mclient = 0;
     1394            mclient = NULL;
    11821395        }
    11831396        if (!mclient) {
     
    11861399        } else {
    11871400            enum clnt_stat clnt_stat;
    1188             /* try to mount hostname:pathname */
     1401
     1402            /* Try to mount hostname:pathname */
    11891403            mclient->cl_auth = authunix_create_default();
    11901404
    1191             /* make pointers in xdr_mountres3 NULL so
     1405            /* Make pointers in xdr_mountres3 NULL so
    11921406             * that xdr_array allocates memory for us
    11931407             */
    11941408            memset(&status, 0, sizeof(status));
    11951409
    1196             if (pm_mnt->pm_vers == 3)
     1410            if (pm_mnt.pm_vers == 3)
    11971411                clnt_stat = clnt_call(mclient, MOUNTPROC3_MNT,
    11981412                          (xdrproc_t) xdr_dirpath,
     
    12201434            auth_destroy(mclient->cl_auth);
    12211435            clnt_destroy(mclient);
    1222             mclient = 0;
     1436            mclient = NULL;
    12231437            close(msock);
     1438            msock = -1;
    12241439        }
    12251440
    12261441        /* Timeout. We are going to retry... maybe */
    1227 
    12281442        if (!bg)
    12291443            goto fail;
     
    12441458    }
    12451459
    1246 prepare_kernel_data:
     1460 prepare_kernel_data:
    12471461
    12481462    if (nfsvers == 2) {
     
    12791493    }
    12801494
    1281     /* create nfs socket for kernel */
    1282 
     1495    /* Create nfs socket for kernel */
    12831496    if (tcp) {
    12841497        if (nfs_mount_version < 3) {
     
    13061519    server_addr.sin_port = htons(port);
    13071520
    1308     /* prepare data structure for kernel */
    1309 
     1521    /* Prepare data structure for kernel */
    13101522    data.fd = fsock;
    13111523    memcpy((char *) &data.addr, (char *) &server_addr, sizeof(data.addr));
    13121524    strncpy(data.hostname, hostname, sizeof(data.hostname));
    13131525
    1314     /* clean up */
    1315 
     1526    /* Clean up */
    13161527    auth_destroy(mclient->cl_auth);
    13171528    clnt_destroy(mclient);
    13181529    close(msock);
     1530    msock = -1;
    13191531
    13201532    if (bg) {
     
    13261538                daemonized = daemonize();
    13271539                if (daemonized <= 0) { /* parent or error */
     1540/* FIXME: parent doesn't close fsock - ??! */
    13281541                    retval = -daemonized;
    13291542                    goto ret;
     
    13371550    }
    13381551
    1339 do_mount: /* perform actual mount */
    1340 
     1552    /* Perform actual mount */
     1553 do_mount:
    13411554    mp->mnt_type = (char*)"nfs";
    13421555    retval = mount_it_now(mp, vfsflags, (char*)&data);
    13431556    goto ret;
    13441557
    1345 fail:   /* abort */
    1346 
    1347     if (msock != -1) {
     1558    /* Abort */
     1559 fail:
     1560    if (msock >= 0) {
    13481561        if (mclient) {
    13491562            auth_destroy(mclient->cl_auth);
     
    13521565        close(msock);
    13531566    }
    1354     if (fsock != -1)
     1567    if (fsock >= 0)
    13551568        close(fsock);
    13561569
    1357 ret:
     1570 ret:
    13581571    free(hostname);
    13591572    free(mounthost);
     
    13621575}
    13631576
    1364 #else /* !ENABLE_FEATURE_MOUNT_NFS */
    1365 
    1366 /* Never called. Call should be optimized out. */
    1367 int nfsmount(struct mntent *mp, int vfsflags, char *filteropts);
    1368 
    1369 #endif /* !ENABLE_FEATURE_MOUNT_NFS */
     1577#else // !ENABLE_FEATURE_MOUNT_NFS
     1578
     1579// Never called. Call should be optimized out.
     1580int nfsmount(struct mntent *mp, long vfsflags, char *filteropts);
     1581
     1582#endif // !ENABLE_FEATURE_MOUNT_NFS
    13701583
    13711584// Mount one directory.  Handles CIFS, NFS, loopback, autobind, and filesystem
     
    13741587static int singlemount(struct mntent *mp, int ignore_busy)
    13751588{
    1376     int rc = -1, vfsflags;
    1377     char *loopFile = 0, *filteropts = 0;
    1378     llist_t *fl = 0;
     1589    int rc = -1;
     1590    long vfsflags;
     1591    char *loopFile = NULL, *filteropts = NULL;
     1592    llist_t *fl = NULL;
    13791593    struct stat st;
    13801594
     1595    errno = 0;
     1596
    13811597    vfsflags = parse_mount_options(mp->mnt_opts, &filteropts);
    13821598
    1383     // Treat fstype "auto" as unspecified.
    1384 
    1385     if (mp->mnt_type && strcmp(mp->mnt_type,"auto") == 0)
    1386         mp->mnt_type = 0;
     1599    // Treat fstype "auto" as unspecified
     1600    if (mp->mnt_type && strcmp(mp->mnt_type, "auto") == 0)
     1601        mp->mnt_type = NULL;
     1602
     1603    // Might this be a virtual filesystem?
     1604    if (ENABLE_FEATURE_MOUNT_HELPERS && strchr(mp->mnt_fsname, '#')) {
     1605        char *args[35];
     1606        char *s;
     1607        int n;
     1608        // fsname: "cmd#arg1#arg2..."
     1609        // WARNING: allows execution of arbitrary commands!
     1610        // Try "mount 'sh#-c#sh' bogus_dir".
     1611        // It is safe ONLY because non-root
     1612        // cannot use two-argument mount command
     1613        // and using one-argument "mount 'sh#-c#sh'" doesn't work:
     1614        // "mount: can't find sh#-c#sh in /etc/fstab"
     1615        // (if /etc/fstab has it, it's ok: root sets up /etc/fstab).
     1616
     1617        s = mp->mnt_fsname;
     1618        n = 0;
     1619        args[n++] = s;
     1620        while (*s && n < 35 - 2) {
     1621            if (*s++ == '#' && *s != '#') {
     1622                s[-1] = '\0';
     1623                args[n++] = s;
     1624            }
     1625        }
     1626        args[n++] = mp->mnt_dir;
     1627        args[n] = NULL;
     1628        rc = spawn_and_wait(args);
     1629        goto report_error;
     1630    }
    13871631
    13881632    // Might this be an CIFS filesystem?
    1389 
    13901633    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]
     1634     && (!mp->mnt_type || strcmp(mp->mnt_type, "cifs") == 0)
     1635     && (mp->mnt_fsname[0] == '/' || mp->mnt_fsname[0] == '\\')
     1636     && mp->mnt_fsname[0] == mp->mnt_fsname[1]
    13941637    ) {
     1638        int len;
     1639        char c;
    13951640        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);
     1641        char *hostname, *dotted, *ip;
     1642
     1643        hostname = mp->mnt_fsname + 2;
     1644        len = strcspn(hostname, "/\\");
     1645        if (len == 0 || hostname[len] == '\0')
     1646            goto report_error;
     1647        c = hostname[len];
     1648        hostname[len] = '\0';
     1649        lsa = host2sockaddr(hostname, 0);
     1650        hostname[len] = c;
     1651        if (!lsa)
     1652            goto report_error;
     1653
     1654        // Insert "ip=..." option into options
     1655        dotted = xmalloc_sockaddr2dotted_noport(&lsa->u.sa);
     1656        if (ENABLE_FEATURE_CLEAN_UP) free(lsa);
    14171657        ip = xasprintf("ip=%s", dotted);
     1658        if (ENABLE_FEATURE_CLEAN_UP) free(dotted);
    14181659        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
     1660        if (ENABLE_FEATURE_CLEAN_UP) free(ip);
     1661
     1662        // "-o mand" is required [why?]
    14261663        vfsflags |= MS_MANDLOCK;
    1427 
    14281664        mp->mnt_type = (char*)"cifs";
    14291665        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         }
     1666
    14361667        goto report_error;
    14371668    }
    14381669
    14391670    // Might this be an NFS filesystem?
    1440 
    14411671    if (ENABLE_FEATURE_MOUNT_NFS
    1442      && (!mp->mnt_type || !strcmp(mp->mnt_type, "nfs"))
     1672     && (!mp->mnt_type || strcmp(mp->mnt_type, "nfs") == 0)
    14431673     && strchr(mp->mnt_fsname, ':') != NULL
    14441674    ) {
     
    14511681    // (We use stat, not lstat, in order to allow
    14521682    // mount symlink_to_file_or_blkdev dir)
    1453 
    14541683    if (!stat(mp->mnt_fsname, &st)
    14551684     && !(vfsflags & (MS_REMOUNT | MS_BIND | MS_MOVE))
    14561685    ) {
    14571686        // Do we need to allocate a loopback device for it?
    1458 
    14591687        if (ENABLE_FEATURE_MOUNT_LOOP && S_ISREG(st.st_mode)) {
    14601688            loopFile = bb_simplify_path(mp->mnt_fsname);
    1461             mp->mnt_fsname = NULL; /* will receive malloced loop dev name */
    1462             if (set_loop(&(mp->mnt_fsname), loopFile, 0) < 0) {
     1689            mp->mnt_fsname = NULL; // will receive malloced loop dev name
     1690            if (set_loop(&mp->mnt_fsname, loopFile, 0) < 0) {
    14631691                if (errno == EPERM || errno == EACCES)
    14641692                    bb_error_msg(bb_msg_perm_denied_are_you_root);
    14651693                else
    1466                     bb_perror_msg("cannot setup loop device");
     1694                    bb_perror_msg("can't setup loop device");
    14671695                return errno;
    14681696            }
    14691697
    14701698        // Autodetect bind mounts
    1471 
    14721699        } else if (S_ISDIR(st.st_mode) && !mp->mnt_type)
    14731700            vfsflags |= MS_BIND;
    14741701    }
    14751702
    1476     /* If we know the fstype (or don't need to), jump straight
    1477      * to the actual mount. */
    1478 
    1479     if (mp->mnt_type || (vfsflags & (MS_REMOUNT | MS_BIND | MS_MOVE)))
     1703    // If we know the fstype (or don't need to), jump straight
     1704    // to the actual mount.
     1705    if (mp->mnt_type || (vfsflags & (MS_REMOUNT | MS_BIND | MS_MOVE))) {
    14801706        rc = mount_it_now(mp, vfsflags, filteropts);
    1481     else {
     1707    } else {
    14821708        // Loop through filesystem types until mount succeeds
    14831709        // or we run out
    14841710
    1485         /* Initialize list of block backed filesystems.  This has to be
    1486          * done here so that during "mount -a", mounts after /proc shows up
    1487          * can autodetect. */
    1488 
     1711        // Initialize list of block backed filesystems.
     1712        // This has to be done here so that during "mount -a",
     1713        // mounts after /proc shows up can autodetect.
    14891714        if (!fslist) {
    14901715            fslist = get_block_backed_filesystems();
     
    14961721            mp->mnt_type = fl->data;
    14971722            rc = mount_it_now(mp, vfsflags, filteropts);
    1498             if (!rc) break;
     1723            if (!rc)
     1724                break;
    14991725        }
    15001726    }
    15011727
    15021728    // If mount failed, clean up loop file (if any).
    1503 
    15041729    if (ENABLE_FEATURE_MOUNT_LOOP && rc && loopFile) {
    15051730        del_loop(mp->mnt_fsname);
     
    15141739        free(filteropts);
    15151740
    1516     if (rc && errno == EBUSY && ignore_busy)
    1517         rc = 0;
    1518     if (rc < 0)
     1741    if (errno == EBUSY && ignore_busy)
     1742        return 0;
     1743    if (rc != 0)
    15191744        bb_perror_msg("mounting %s on %s failed", mp->mnt_fsname, mp->mnt_dir);
    1520 
    15211745    return rc;
     1746}
     1747
     1748// -O support
     1749//    -O interprets a list of filter options which select whether a mount
     1750// point will be mounted: only mounts with options matching *all* filtering
     1751// options will be selected.
     1752//    By default each -O filter option must be present in the list of mount
     1753// options, but if it is prefixed by "no" then it must be absent.
     1754// For example,
     1755//  -O a,nob,c  matches  -o a,c  but fails to match  -o a,b,c
     1756//              (and also fails to match  -o a  because  -o c  is absent).
     1757//
     1758// It is different from -t in that each option is matched exactly; a leading
     1759// "no" at the beginning of one option does not negate the rest.
     1760static int match_opt(const char *fs_opt_in, const char *O_opt)
     1761{
     1762    if (!O_opt)
     1763        return 1;
     1764
     1765    while (*O_opt) {
     1766        const char *fs_opt = fs_opt_in;
     1767        int O_len;
     1768        int match;
     1769
     1770        // If option begins with "no" then treat as an inverted match:
     1771        // matching is a failure
     1772        match = 0;
     1773        if (O_opt[0] == 'n' && O_opt[1] == 'o') {
     1774            match = 1;
     1775            O_opt += 2;
     1776        }
     1777        // Isolate the current O option
     1778        O_len = strchrnul(O_opt, ',') - O_opt;
     1779        // Check for a match against existing options
     1780        while (1) {
     1781            if (strncmp(fs_opt, O_opt, O_len) == 0
     1782             && (fs_opt[O_len] == '\0' || fs_opt[O_len] == ',')
     1783            ) {
     1784                if (match)
     1785                    return 0;  // "no" prefix, but option found
     1786                match = 1;  // current O option found, go check next one
     1787                break;
     1788            }
     1789            fs_opt = strchr(fs_opt, ',');
     1790            if (!fs_opt)
     1791                break;
     1792            fs_opt++;
     1793        }
     1794        if (match == 0)
     1795            return 0;     // match wanted but not found
     1796        if (O_opt[O_len] == '\0') // end?
     1797            break;
     1798        // Step to the next O option
     1799        O_opt += O_len + 1;
     1800    }
     1801    // If we get here then everything matched
     1802    return 1;
    15221803}
    15231804
    15241805// Parse options, if necessary parse fstab/mtab, and call singlemount for
    15251806// each directory to be mounted.
    1526 
    1527 static const char must_be_root[] ALIGN1 = "you must be root";
    1528 
    1529 int mount_main(int argc, char **argv);
    1530 int mount_main(int argc, char **argv)
    1531 {
    1532     enum { OPT_ALL = 0x10 };
    1533 
    1534     char *cmdopts = xstrdup(""), *fstype=0, *storage_path=0;
    1535     char *opt_o;
     1807int mount_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     1808int mount_main(int argc UNUSED_PARAM, char **argv)
     1809{
     1810    char *cmdopts = xzalloc(1);
     1811    char *fstype = NULL;
     1812    char *O_optmatch = NULL;
     1813    char *storage_path;
     1814    llist_t *lst_o = NULL;
    15361815    const char *fstabname;
    15371816    FILE *fstab;
    1538     int i, j, rc = 0;
     1817    int i, j;
     1818    int rc = EXIT_SUCCESS;
    15391819    unsigned opt;
    15401820    struct mntent mtpair[2], *mtcur = mtpair;
    1541     SKIP_DESKTOP(const int nonroot = 0;)
    1542     USE_DESKTOP( int nonroot = (getuid() != 0);)
    1543 
    1544     /* parse long options, like --bind and --move.  Note that -o option
    1545      * and --option are synonymous.  Yes, this means --remount,rw works. */
    1546 
    1547     for (i = j = 0; i < argc; i++) {
    1548         if (argv[i][0] == '-' && argv[i][1] == '-') {
    1549             append_mount_options(&cmdopts, argv[i]+2);
    1550         } else argv[j++] = argv[i];
    1551     }
    1552     argv[j] = 0;
    1553     argc = j;
     1821    IF_NOT_DESKTOP(const int nonroot = 0;)
     1822
     1823    IF_DESKTOP(int nonroot = ) sanitize_env_if_suid();
     1824
     1825    // Parse long options, like --bind and --move.  Note that -o option
     1826    // and --option are synonymous.  Yes, this means --remount,rw works.
     1827    for (i = j = 1; argv[i]; i++) {
     1828        if (argv[i][0] == '-' && argv[i][1] == '-')
     1829            append_mount_options(&cmdopts, argv[i] + 2);
     1830        else
     1831            argv[j++] = argv[i];
     1832    }
     1833    argv[j] = NULL;
    15541834
    15551835    // Parse remaining options
    1556 
    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)
     1836    // Max 2 params; -o is a list, -v is a counter
     1837    opt_complementary = "?2o::" IF_FEATURE_MOUNT_VERBOSE("vv");
     1838    opt = getopt32(argv, OPTION_STR, &lst_o, &fstype, &O_optmatch
     1839            IF_FEATURE_MOUNT_VERBOSE(, &verbose));
     1840    while (lst_o) append_mount_options(&cmdopts, llist_pop(&lst_o)); // -o
     1841    if (opt & OPT_r) append_mount_options(&cmdopts, "ro"); // -r
     1842    if (opt & OPT_w) append_mount_options(&cmdopts, "rw"); // -w
    15671843    argv += optind;
    1568     argc -= optind;
    1569 
    1570     // Three or more non-option arguments?  Die with a usage message.
    1571 
    1572     if (argc > 2) bb_show_usage();
    15731844
    15741845    // If we have no arguments, show currently mounted filesystems
    1575 
    1576     if (!argc) {
    1577         if (!(opt & OPT_ALL)) {
     1846    if (!argv[0]) {
     1847        if (!(opt & OPT_a)) {
    15781848            FILE *mountTable = setmntent(bb_path_mtab_file, "r");
    15791849
    1580             if (!mountTable) bb_error_msg_and_die("no %s", bb_path_mtab_file);
    1581 
    1582             while (getmntent_r(mountTable, mtpair, bb_common_bufsiz1,
    1583                                 sizeof(bb_common_bufsiz1)))
     1850            if (!mountTable)
     1851                bb_error_msg_and_die("no %s", bb_path_mtab_file);
     1852
     1853            while (getmntent_r(mountTable, &mtpair[0], getmntent_buf,
     1854                                GETMNTENT_BUFSIZE))
    15841855            {
    15851856                // Don't show rootfs. FIXME: why??
    15861857                // util-linux 2.12a happily shows rootfs...
    1587                 //if (!strcmp(mtpair->mnt_fsname, "rootfs")) continue;
    1588 
    1589                 if (!fstype || !strcmp(mtpair->mnt_type, fstype))
     1858                //if (strcmp(mtpair->mnt_fsname, "rootfs") == 0) continue;
     1859
     1860                if (!fstype || strcmp(mtpair->mnt_type, fstype) == 0)
    15901861                    printf("%s on %s type %s (%s)\n", mtpair->mnt_fsname,
    15911862                            mtpair->mnt_dir, mtpair->mnt_type,
    15921863                            mtpair->mnt_opts);
    15931864            }
    1594             if (ENABLE_FEATURE_CLEAN_UP) endmntent(mountTable);
     1865            if (ENABLE_FEATURE_CLEAN_UP)
     1866                endmntent(mountTable);
    15951867            return EXIT_SUCCESS;
    15961868        }
    1597     } else storage_path = bb_simplify_path(argv[0]);
    1598 
    1599     // When we have two arguments, the second is the directory and we can
    1600     // skip looking at fstab entirely.  We can always abspath() the directory
    1601     // argument when we get it.
    1602 
    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];
    1608         mtpair->mnt_type = fstype;
    1609         mtpair->mnt_opts = cmdopts;
    1610         rc = singlemount(mtpair, 0);
    1611         goto clean_up;
    1612     }
    1613 
    1614     i = parse_mount_options(cmdopts, 0);
     1869        storage_path = NULL;
     1870    } else {
     1871        // When we have two arguments, the second is the directory and we can
     1872        // skip looking at fstab entirely.  We can always abspath() the directory
     1873        // argument when we get it.
     1874        if (argv[1]) {
     1875            if (nonroot)
     1876                bb_error_msg_and_die(bb_msg_you_must_be_root);
     1877            mtpair->mnt_fsname = argv[0];
     1878            mtpair->mnt_dir = argv[1];
     1879            mtpair->mnt_type = fstype;
     1880            mtpair->mnt_opts = cmdopts;
     1881            resolve_mount_spec(&mtpair->mnt_fsname);
     1882            rc = singlemount(mtpair, /*ignore_busy:*/ 0);
     1883            return rc;
     1884        }
     1885        storage_path = bb_simplify_path(argv[0]); // malloced
     1886    }
     1887
     1888    // Past this point, we are handling either "mount -a [opts]"
     1889    // or "mount [opts] single_param"
     1890
     1891    i = parse_mount_options(cmdopts, NULL); // FIXME: should be "long", not "int"
    16151892    if (nonroot && (i & ~MS_SILENT)) // Non-root users cannot specify flags
    1616         bb_error_msg_and_die(must_be_root);
     1893        bb_error_msg_and_die(bb_msg_you_must_be_root);
    16171894
    16181895    // If we have a shared subtree flag, don't worry about fstab or mtab.
    1619 
    16201896    if (ENABLE_FEATURE_MOUNT_FLAGS
    16211897     && (i & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))
    16221898    ) {
    1623         rc = mount("", argv[0], "", i, "");
    1624         if (rc) bb_perror_msg_and_die("%s", argv[0]);
    1625         goto clean_up;
     1899        // verbose_mount(source, target, type, flags, data)
     1900        rc = verbose_mount("", argv[0], "", i, "");
     1901        if (rc)
     1902            bb_simple_perror_msg_and_die(argv[0]);
     1903        return rc;
    16261904    }
    16271905
    16281906    // Open either fstab or mtab
    1629 
    16301907    fstabname = "/etc/fstab";
    16311908    if (i & MS_REMOUNT) {
     1909        // WARNING. I am not sure this matches util-linux's
     1910        // behavior. It's possible util-linux does not
     1911        // take -o opts from mtab (takes only mount source).
    16321912        fstabname = bb_path_mtab_file;
    16331913    }
    16341914    fstab = setmntent(fstabname, "r");
    16351915    if (!fstab)
    1636         bb_perror_msg_and_die("cannot read %s", fstabname);
    1637 
    1638     // Loop through entries until we find what we're looking for.
    1639 
     1916        bb_perror_msg_and_die("can't read '%s'", fstabname);
     1917
     1918    // Loop through entries until we find what we're looking for
    16401919    memset(mtpair, 0, sizeof(mtpair));
    16411920    for (;;) {
    1642         struct mntent *mtnext = (mtcur==mtpair ? mtpair+1 : mtpair);
     1921        struct mntent *mtother = (mtcur==mtpair ? mtpair+1 : mtpair);
    16431922
    16441923        // Get next fstab entry
    1645 
    1646         if (!getmntent_r(fstab, mtcur, bb_common_bufsiz1
    1647                     + (mtcur==mtpair ? sizeof(bb_common_bufsiz1)/2 : 0),
    1648                 sizeof(bb_common_bufsiz1)/2))
    1649         {
    1650             // Were we looking for something specific?
    1651 
    1652             if (argc) {
    1653 
    1654                 // If we didn't find anything, complain.
    1655 
    1656                 if (!mtnext->mnt_fsname)
    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                 }
    1666 
    1667                 // Mount the last thing we found.
    1668 
    1669                 mtcur->mnt_opts = xstrdup(mtcur->mnt_opts);
    1670                 append_mount_options(&(mtcur->mnt_opts), cmdopts);
    1671                 rc = singlemount(mtcur, 0);
    1672                 free(mtcur->mnt_opts);
     1924        if (!getmntent_r(fstab, mtcur, getmntent_buf
     1925                    + (mtcur==mtpair ? GETMNTENT_BUFSIZE/2 : 0),
     1926                GETMNTENT_BUFSIZE/2)
     1927        ) { // End of fstab/mtab is reached
     1928            mtcur = mtother; // the thing we found last time
     1929            break;
     1930        }
     1931
     1932        // If we're trying to mount something specific and this isn't it,
     1933        // skip it.  Note we must match the exact text in fstab (ala
     1934        // "proc") or a full path from root
     1935        if (argv[0]) {
     1936
     1937            // Is this what we're looking for?
     1938            if (strcmp(argv[0], mtcur->mnt_fsname) != 0
     1939             && strcmp(storage_path, mtcur->mnt_fsname) != 0
     1940             && strcmp(argv[0], mtcur->mnt_dir) != 0
     1941             && strcmp(storage_path, mtcur->mnt_dir) != 0
     1942            ) {
     1943                continue; // no
    16731944            }
    1674             goto clean_up;
    1675         }
    1676 
    1677         /* If we're trying to mount something specific and this isn't it,
    1678          * skip it.  Note we must match both the exact text in fstab (ala
    1679          * "proc") or a full path from root */
    1680 
    1681         if (argc) {
    1682 
    1683             // Is this what we're looking for?
    1684 
    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;
    1689 
    1690             // Remember this entry.  Something later may have overmounted
    1691             // it, and we want the _last_ match.
    1692 
    1693             mtcur = mtnext;
    1694 
    1695         // If we're mounting all.
    1696 
     1945
     1946            // Remember this entry.  Something later may have
     1947            // overmounted it, and we want the _last_ match.
     1948            mtcur = mtother;
     1949
     1950        // If we're mounting all
    16971951        } else {
    1698             // Do we need to match a filesystem type?
    1699             if (fstype && match_fstype(mtcur, fstype)) continue;
    1700 
    1701             // Skip noauto and swap anyway.
    1702 
    1703             if (parse_mount_options(mtcur->mnt_opts, 0)
    1704                 & (MOUNT_NOAUTO | MOUNT_SWAP)) continue;
    1705 
     1952            struct mntent *mp;
    17061953            // No, mount -a won't mount anything,
    1707             // even user mounts, for mere humans.
    1708 
     1954            // even user mounts, for mere humans
    17091955            if (nonroot)
    1710                 bb_error_msg_and_die(must_be_root);
    1711 
    1712             // Mount this thing.
     1956                bb_error_msg_and_die(bb_msg_you_must_be_root);
     1957
     1958            // Does type match? (NULL matches always)
     1959            if (!match_fstype(mtcur, fstype))
     1960                continue;
     1961
     1962            // Skip noauto and swap anyway
     1963            if ((parse_mount_options(mtcur->mnt_opts, NULL) & (MOUNT_NOAUTO | MOUNT_SWAP))
     1964            // swap is bogus "fstype", parse_mount_options can't check fstypes
     1965             || strcasecmp(mtcur->mnt_type, "swap") == 0
     1966            ) {
     1967                continue;
     1968            }
     1969
     1970            // Does (at least one) option match?
     1971            // (NULL matches always)
     1972            if (!match_opt(mtcur->mnt_opts, O_optmatch))
     1973                continue;
     1974
     1975            resolve_mount_spec(&mtcur->mnt_fsname);
    17131976
    17141977            // NFS mounts want this to be xrealloc-able
    17151978            mtcur->mnt_opts = xstrdup(mtcur->mnt_opts);
    1716             if (singlemount(mtcur, 1)) {
    1717                 /* Count number of failed mounts */
    1718                 rc++;
     1979
     1980            // If nothing is mounted on this directory...
     1981            // (otherwise repeated "mount -a" mounts everything again)
     1982            mp = find_mount_point(mtcur->mnt_dir, /*subdir_too:*/ 0);
     1983            // We do not check fsname match of found mount point -
     1984            // "/" may have fsname of "/dev/root" while fstab
     1985            // says "/dev/something_else".
     1986            if (mp) {
     1987                if (verbose) {
     1988                    bb_error_msg("according to %s, "
     1989                        "%s is already mounted on %s",
     1990                        bb_path_mtab_file,
     1991                        mp->mnt_fsname, mp->mnt_dir);
     1992                }
     1993            } else {
     1994                // ...mount this thing
     1995                if (singlemount(mtcur, /*ignore_busy:*/ 1)) {
     1996                    // Count number of failed mounts
     1997                    rc++;
     1998                }
    17191999            }
    17202000            free(mtcur->mnt_opts);
    17212001        }
    17222002    }
    1723     if (ENABLE_FEATURE_CLEAN_UP) endmntent(fstab);
    1724 
    1725 clean_up:
    1726 
     2003
     2004    // End of fstab/mtab is reached.
     2005    // Were we looking for something specific?
     2006    if (argv[0]) { // yes
     2007        long l;
     2008
     2009        // If we didn't find anything, complain
     2010        if (!mtcur->mnt_fsname)
     2011            bb_error_msg_and_die("can't find %s in %s",
     2012                argv[0], fstabname);
     2013
     2014        // What happens when we try to "mount swap_partition"?
     2015        // (fstab containts "swap_partition swap swap defaults 0 0")
     2016        // util-linux-ng 2.13.1 does this:
     2017        // stat("/sbin/mount.swap", 0x7fff62a3a350) = -1 ENOENT (No such file or directory)
     2018        // mount("swap_partition", "swap", "swap", MS_MGC_VAL, NULL) = -1 ENOENT (No such file or directory)
     2019        // lstat("swap", 0x7fff62a3a640)           = -1 ENOENT (No such file or directory)
     2020        // write(2, "mount: mount point swap does not exist\n", 39) = 39
     2021        // exit_group(32)                          = ?
     2022#if 0
     2023        // In case we want to simply skip swap partitions:
     2024        l = parse_mount_options(mtcur->mnt_opts, NULL);
     2025        if ((l & MOUNT_SWAP)
     2026        // swap is bogus "fstype", parse_mount_options can't check fstypes
     2027         || strcasecmp(mtcur->mnt_type, "swap") == 0
     2028        ) {
     2029            goto ret;
     2030        }
     2031#endif
     2032        if (nonroot) {
     2033            // fstab must have "users" or "user"
     2034            l = parse_mount_options(mtcur->mnt_opts, NULL);
     2035            if (!(l & MOUNT_USERS))
     2036                bb_error_msg_and_die(bb_msg_you_must_be_root);
     2037        }
     2038
     2039        //util-linux-2.12 does not do this check.
     2040        //// If nothing is mounted on this directory...
     2041        //// (otherwise repeated "mount FOO" mounts FOO again)
     2042        //mp = find_mount_point(mtcur->mnt_dir, /*subdir_too:*/ 0);
     2043        //if (mp) {
     2044        //  bb_error_msg("according to %s, "
     2045        //      "%s is already mounted on %s",
     2046        //      bb_path_mtab_file,
     2047        //      mp->mnt_fsname, mp->mnt_dir);
     2048        //} else {
     2049            // ...mount the last thing we found
     2050            mtcur->mnt_opts = xstrdup(mtcur->mnt_opts);
     2051            append_mount_options(&(mtcur->mnt_opts), cmdopts);
     2052            resolve_mount_spec(&mtpair->mnt_fsname);
     2053            rc = singlemount(mtcur, /*ignore_busy:*/ 0);
     2054            if (ENABLE_FEATURE_CLEAN_UP)
     2055                free(mtcur->mnt_opts);
     2056        //}
     2057    }
     2058
     2059 //ret:
     2060    if (ENABLE_FEATURE_CLEAN_UP)
     2061        endmntent(fstab);
    17272062    if (ENABLE_FEATURE_CLEAN_UP) {
    17282063        free(storage_path);
     
    17302065    }
    17312066
     2067//TODO: exitcode should be ORed mask of (from "man mount"):
     2068// 0 success
     2069// 1 incorrect invocation or permissions
     2070// 2 system error (out of memory, cannot fork, no more loop devices)
     2071// 4 internal mount bug or missing nfs support in mount
     2072// 8 user interrupt
     2073//16 problems writing or locking /etc/mtab
     2074//32 mount failure
     2075//64 some mount succeeded
    17322076    return rc;
    17332077}
  • branches/2.2.9/mindi-busybox/util-linux/pivot_root.c

    r1765 r2725  
    77 *     regardless of the kernel being used.
    88 *
    9  * Licensed under GPL version 2, see file LICENSE in this tarball for details.
     9 * Licensed under GPLv2, see file LICENSE in this source tree.
    1010 */
    1111#include "libbb.h"
     
    1313extern int pivot_root(const char * new_root,const char * put_old);
    1414
    15 int pivot_root_main(int argc, char **argv);
     15int pivot_root_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
    1616int pivot_root_main(int argc, char **argv)
    1717{
  • branches/2.2.9/mindi-busybox/util-linux/rdate.c

    r1765 r2725  
    66 * by Sterling Huxley <sterling@europa.com>
    77 *
    8  * Licensed under GPL v2 or later, see file License for details.
     8 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    99*/
    1010
     
    1313enum { RFC_868_BIAS = 2208988800UL };
    1414
    15 static void socket_timeout(int sig)
     15static void socket_timeout(int sig UNUSED_PARAM)
    1616{
    1717    bb_error_msg_and_die("timeout connecting to time server");
     
    4343}
    4444
    45 int rdate_main(int argc, char **argv);
    46 int rdate_main(int argc, char **argv)
     45int rdate_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     46int rdate_main(int argc UNUSED_PARAM, char **argv)
    4747{
    4848    time_t remote_time;
     
    6262        else
    6363            if (stime(&remote_time) < 0)
    64                 bb_perror_msg_and_die("cannot set time of day");
     64                bb_perror_msg_and_die("can't set time of day");
    6565    }
    6666
  • branches/2.2.9/mindi-busybox/util-linux/readprofile.c

    r1765 r2725  
    55 *  Copyright (C) 1994,1996 Alessandro Rubini (rubini@ipvvis.unipv.it)
    66 *
    7  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    88 */
    99
    1010/*
    11  * 1999-02-22 Arkadiusz Mikiewicz <misiek@pld.ORG.PL>
     11 * 1999-02-22 Arkadiusz Mickiewicz <misiek@pld.ORG.PL>
    1212 * - added Native Language Support
    1313 * 1999-09-01 Stephane Eranian <eranian@cello.hpl.hp.com>
     
    4242static const char defaultpro[] ALIGN1 = "/proc/profile";
    4343
    44 int readprofile_main(int argc, char **argv);
    45 int readprofile_main(int argc, char **argv)
     44int readprofile_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     45int readprofile_main(int argc UNUSED_PARAM, char **argv)
    4646{
    4747    FILE *map;
    48     const char *mapFile, *proFile, *mult = 0;
     48    const char *mapFile, *proFile;
    4949    unsigned long indx = 1;
    5050    size_t len;
     
    5656    char mapline[S_LEN];
    5757    char mode[8];
    58     int optAll = 0, optInfo = 0, optReset = 0;
    59     int optVerbose = 0, optNative = 0;
    60     int optBins = 0, optSub = 0;
    6158    int maplineno = 1;
    6259    int header_printed;
     60    int multiplier = 0;
     61    unsigned opt;
     62    enum {
     63        OPT_M = (1 << 0),
     64        OPT_m = (1 << 1),
     65        OPT_p = (1 << 2),
     66        OPT_n = (1 << 3),
     67        OPT_a = (1 << 4),
     68        OPT_b = (1 << 5),
     69        OPT_s = (1 << 6),
     70        OPT_i = (1 << 7),
     71        OPT_r = (1 << 8),
     72        OPT_v = (1 << 9),
     73    };
     74#define optMult    (opt & OPT_M)
     75#define optNative  (opt & OPT_n)
     76#define optAll     (opt & OPT_a)
     77#define optBins    (opt & OPT_b)
     78#define optSub     (opt & OPT_s)
     79#define optInfo    (opt & OPT_i)
     80#define optReset   (opt & OPT_r)
     81#define optVerbose (opt & OPT_v)
    6382
    6483#define next (current^1)
     
    6786    mapFile = defaultmap;
    6887
    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);
    74 
    75     if (optReset || mult) {
    76         int multiplier, fd, to_write;
     88    opt_complementary = "M+"; /* -M N */
     89    opt = getopt32(argv, "M:m:p:nabsirv", &multiplier, &mapFile, &proFile);
     90
     91    if (opt & (OPT_M|OPT_r)) { /* mult or reset, or both */
     92        int fd, to_write;
    7793
    7894        /*
     
    8096         * not sizeof(int), the multiplier is not changed
    8197         */
    82         if (mult) {
    83             multiplier = xatoi_u(mult);
    84             to_write = sizeof(int);
    85         } else {
    86             multiplier = 0;
    87             to_write = 1;   /* sth different from sizeof(int) */
    88         }
     98        to_write = sizeof(int);
     99        if (!optMult)
     100            to_write = 1;  /* sth different from sizeof(int) */
    89101
    90102        fd = xopen(defaultpro, O_WRONLY);
    91 
    92         if (full_write(fd, &multiplier, to_write) != to_write)
    93             bb_perror_msg_and_die("error writing %s", defaultpro);
    94 
     103        xwrite(fd, &multiplier, to_write);
    95104        close(fd);
    96105        return EXIT_SUCCESS;
     
    101110     */
    102111    len = MAXINT(ssize_t);
    103     buf = xmalloc_open_read_close(proFile, &len);
     112    buf = xmalloc_xopen_read_close(proFile, &len);
    104113    if (!optNative) {
    105         int entries = len/sizeof(*buf);
     114        int entries = len / sizeof(*buf);
    106115        int big = 0, small = 0, i;
    107116        unsigned *p;
     
    136145    total = 0;
    137146
    138     map = xfopen(mapFile, "r");
     147    map = xfopen_for_read(mapFile);
    139148
    140149    while (fgets(mapline, S_LEN, map)) {
     
    168177           Absolute symbols */
    169178        if ((*mode == 'A' || *mode == '?') && total == 0) continue;
    170         if (*mode != 'T' && *mode != 't' &&
    171             *mode != 'W' && *mode != 'w')
    172             break;  /* only text is profiled */
     179        if (*mode != 'T' && *mode != 't'
     180         && *mode != 'W' && *mode != 'w'
     181        ) {
     182            break;  /* only text is profiled */
     183        }
    173184
    174185        if (indx >= len / sizeof(*buf))
     
    191202            if (optVerbose || this > 0)
    192203                printf("  total\t\t\t\t%u\n", this);
    193         } else if ((this || optAll) &&
    194                (fn_len = next_add-fn_add) != 0) {
     204        } else if ((this || optAll)
     205                && (fn_len = next_add-fn_add) != 0
     206        ) {
    195207            if (optVerbose)
    196208                printf("%016llx %-40s %6i %8.4f\n", fn_add,
  • branches/2.2.9/mindi-busybox/util-linux/setarch.c

    r1765 r2725  
    11/* vi: set sw=4 ts=4: */
    22/*
    3  * Linux32/linux64 allows for changing uname emulation.
     3 * linux32/linux64 allows for changing uname emulation.
    44 *
    55 * Copyright 2002 Andi Kleen, SuSE Labs.
    66 *
    7  * Licensed under GPL v2 or later, see file License for details.
     7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    88*/
    99
     
    1212#include "libbb.h"
    1313
    14 int setarch_main(int ATTRIBUTE_UNUSED argc, char **argv);
    15 int setarch_main(int ATTRIBUTE_UNUSED argc, char **argv)
     14int setarch_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     15int setarch_main(int argc UNUSED_PARAM, char **argv)
    1616{
    17     int pers = -1;
     17    int pers;
    1818
    1919    /* Figure out what personality we are supposed to switch to ...
    2020     * we can be invoked as either:
    21      * argv[0],argv[1] -> "setarch","personality"
    22      * argv[0]         -> "personality"
     21     * argv[0],argv[1] == "setarch","personality"
     22     * argv[0]         == "personality"
    2323     */
    24 retry:
    25     if (argv[0][5] == '6') /* linux64 */
     24    if (ENABLE_SETARCH && applet_name[0] == 's'
     25     && argv[1] && strncpy(argv[1], "linux", 5)
     26    ) {
     27        applet_name = argv[1];
     28        argv++;
     29    }
     30    if (applet_name[5] == '6') /* linux64 */
    2631        pers = PER_LINUX;
    27     else if (argv[0][5] == '3') /* linux32 */
     32    else if (applet_name[5] == '3') /* linux32 */
    2833        pers = PER_LINUX32;
    29     else if (pers == -1 && argv[1] != NULL) {
    30         pers = PER_LINUX32;
    31         ++argv;
    32         goto retry;
    33     }
     34    else
     35        bb_show_usage();
    3436
    35     /* make user actually gave us something to do */
    36     ++argv;
     37    argv++;
    3738    if (argv[0] == NULL)
    3839        bb_show_usage();
     
    4041    /* Try to set personality */
    4142    if (personality(pers) >= 0) {
    42 
    4343        /* Try to execute the program */
    4444        BB_EXECVP(argv[0], argv);
    4545    }
    4646
    47     bb_perror_msg_and_die("%s", argv[0]);
     47    bb_simple_perror_msg_and_die(argv[0]);
    4848}
  • branches/2.2.9/mindi-busybox/util-linux/swaponoff.c

    r1765 r2725  
    55 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
    66 *
    7  * Licensed under the GPL version 2, see the file LICENSE in this tarball.
     7 * Licensed under GPLv2, see file LICENSE in this source tree.
    88 */
    99
     
    1212#include <sys/swap.h>
    1313
     14#if ENABLE_FEATURE_MOUNT_LABEL
     15# include "volume_id.h"
     16#else
     17# define resolve_mount_spec(fsname) ((void)0)
     18#endif
     19
     20#if ENABLE_FEATURE_SWAPON_PRI
     21struct globals {
     22    int flags;
     23} FIX_ALIASING;
     24#define G (*(struct globals*)&bb_common_bufsiz1)
     25#define g_flags (G.flags)
     26#else
     27#define g_flags 0
     28#endif
     29
    1430static int swap_enable_disable(char *device)
    1531{
     
    1733    struct stat st;
    1834
     35    resolve_mount_spec(&device);
    1936    xstat(device, &st);
    2037
     
    2239    /* test for holes */
    2340    if (S_ISREG(st.st_mode))
    24         if (st.st_blocks * 512 < st.st_size)
     41        if (st.st_blocks * (off_t)512 < st.st_size)
    2542            bb_error_msg("warning: swap file has holes");
    2643#endif
    2744
    2845    if (applet_name[5] == 'n')
    29         status = swapon(device, 0);
     46        status = swapon(device, g_flags);
    3047    else
    3148        status = swapoff(device);
    3249
    3350    if (status != 0) {
    34         bb_perror_msg("%s", device);
     51        bb_simple_perror_msg(device);
    3552        return 1;
    3653    }
     
    5067
    5168    err = 0;
    52     while ((m = getmntent(f)) != NULL)
    53         if (strcmp(m->mnt_type, MNTTYPE_SWAP) == 0)
    54             err += swap_enable_disable(m->mnt_fsname);
     69    while ((m = getmntent(f)) != NULL) {
     70        if (strcmp(m->mnt_type, MNTTYPE_SWAP) == 0) {
     71            /* swapon -a should ignore entries with noauto,
     72             * but swapoff -a should process them */
     73            if (applet_name[5] != 'n'
     74             || hasmntopt(m, MNTOPT_NOAUTO) == NULL
     75            ) {
     76                err += swap_enable_disable(m->mnt_fsname);
     77            }
     78        }
     79    }
    5580
    56     endmntent(f);
     81    if (ENABLE_FEATURE_CLEAN_UP)
     82        endmntent(f);
    5783
    5884    return err;
    5985}
    6086
    61 int swap_on_off_main(int argc, char **argv);
    62 int swap_on_off_main(int argc, char **argv)
     87int swap_on_off_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     88int swap_on_off_main(int argc UNUSED_PARAM, char **argv)
    6389{
    6490    int ret;
    6591
    66     if (argc == 1)
     92#if !ENABLE_FEATURE_SWAPON_PRI
     93    ret = getopt32(argv, "a");
     94#else
     95    opt_complementary = "p+";
     96    ret = getopt32(argv, (applet_name[5] == 'n') ? "ap:" : "a", &g_flags);
     97
     98    if (ret & 2) { // -p
     99        g_flags = SWAP_FLAG_PREFER |
     100            ((g_flags & SWAP_FLAG_PRIO_MASK) << SWAP_FLAG_PRIO_SHIFT);
     101        ret &= 1;
     102    }
     103#endif
     104
     105    if (ret /* & 1: not needed */) // -a
     106        return do_em_all();
     107
     108    argv += optind;
     109    if (!*argv)
    67110        bb_show_usage();
    68111
    69     ret = getopt32(argv, "a");
    70     if (ret)
    71         return do_em_all();
     112    /* ret = 0; redundant */
     113    do {
     114        ret += swap_enable_disable(*argv);
     115    } while (*++argv);
    72116
    73     /* ret = 0; redundant */
    74     while (*++argv)
    75         ret += swap_enable_disable(*argv);
    76117    return ret;
    77118}
  • branches/2.2.9/mindi-busybox/util-linux/switch_root.c

    r1765 r2725  
    44 * Switch from rootfs to another filesystem as the root of the mount tree.
    55 *
    6  * Licensed under GPL version 2, see file LICENSE in this tarball for details.
     6 * Licensed under GPLv2, see file LICENSE in this source tree.
    77 */
    8 
     8#include <sys/vfs.h>
     9#include <sys/mount.h>
    910#include "libbb.h"
    10 #include <sys/vfs.h>
    11 
    12 
    13 // Make up for header deficiencies.
    14 
     11// Make up for header deficiencies
    1512#ifndef RAMFS_MAGIC
    16 #define RAMFS_MAGIC     0x858458f6
     13# define RAMFS_MAGIC ((unsigned)0x858458f6)
    1714#endif
    18 
    1915#ifndef TMPFS_MAGIC
    20 #define TMPFS_MAGIC     0x01021994
     16# define TMPFS_MAGIC ((unsigned)0x01021994)
    2117#endif
    22 
    2318#ifndef MS_MOVE
    24 #define MS_MOVE         8192
     19# define MS_MOVE     8192
    2520#endif
    2621
    27 static dev_t rootdev;
    28 
    29 // Recursively delete contents of rootfs.
    30 
    31 static void delete_contents(const char *directory)
     22// Recursively delete contents of rootfs
     23static void delete_contents(const char *directory, dev_t rootdev)
    3224{
    3325    DIR *dir;
     
    3628
    3729    // Don't descend into other filesystems
    38     if (lstat(directory, &st) || st.st_dev != rootdev) return;
    39 
    40     // Recursively delete the contents of directories.
     30    if (lstat(directory, &st) || st.st_dev != rootdev)
     31        return;
     32
     33    // Recursively delete the contents of directories
    4134    if (S_ISDIR(st.st_mode)) {
    4235        dir = opendir(directory);
     
    4639
    4740                // Skip . and ..
    48                 if (*newdir=='.' && (!newdir[1] || (newdir[1]=='.' && !newdir[2])))
     41                if (DOT_OR_DOTDOT(newdir))
    4942                    continue;
    5043
    5144                // Recurse to delete contents
    52                 newdir = alloca(strlen(directory) + strlen(d->d_name) + 2);
    53                 sprintf(newdir, "%s/%s", directory, d->d_name);
    54                 delete_contents(newdir);
     45                newdir = concat_path_file(directory, newdir);
     46                delete_contents(newdir, rootdev);
     47                free(newdir);
    5548            }
    5649            closedir(dir);
    5750
    58             // Directory should now be empty.  Zap it.
     51            // Directory should now be empty, zap it
    5952            rmdir(directory);
    6053        }
    61 
    62     // It wasn't a directory.  Zap it.
    63 
    64     } else unlink(directory);
     54    } else {
     55        // It wasn't a directory, zap it
     56        unlink(directory);
     57    }
    6558}
    6659
    67 int switch_root_main(int argc, char **argv);
    68 int switch_root_main(int argc, char **argv)
     60int switch_root_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     61int switch_root_main(int argc UNUSED_PARAM, char **argv)
    6962{
    7063    char *newroot, *console = NULL;
    71     struct stat st1, st2;
     64    struct stat st;
    7265    struct statfs stfs;
     66    dev_t rootdev;
    7367
    7468    // Parse args (-c console)
    75 
    76     opt_complementary = "-2";
    77     getopt32(argv, "c:", &console);
     69    opt_complementary = "-2"; // minimum 2 params
     70    getopt32(argv, "+c:", &console); // '+': stop at first non-option
    7871    argv += optind;
    79 
    80     // Change to new root directory and verify it's a different fs.
    81 
    8272    newroot = *argv++;
    8373
     74    // Change to new root directory and verify it's a different fs
    8475    xchdir(newroot);
    85     if (lstat(".", &st1) || lstat("/", &st2) || st1.st_dev == st2.st_dev) {
    86         bb_error_msg_and_die("bad newroot %s", newroot);
    87     }
    88     rootdev = st2.st_dev;
    89 
    90     // Additional sanity checks: we're about to rm -rf /,  so be REALLY SURE
    91     // we mean it.  (I could make this a CONFIG option, but I would get email
    92     // from all the people who WILL eat their filesystems.)
    93 
    94     if (lstat("/init", &st1) || !S_ISREG(st1.st_mode) || statfs("/", &stfs) ||
    95         (stfs.f_type != RAMFS_MAGIC && stfs.f_type != TMPFS_MAGIC) ||
    96         getpid() != 1)
    97     {
    98         bb_error_msg_and_die("not rootfs");
     76    xstat("/", &st);
     77    rootdev = st.st_dev;
     78    xstat(".", &st);
     79    if (st.st_dev == rootdev || getpid() != 1) {
     80        // Show usage, it says new root must be a mountpoint
     81        // and we must be PID 1
     82        bb_show_usage();
     83    }
     84
     85    // Additional sanity checks: we're about to rm -rf /, so be REALLY SURE
     86    // we mean it. I could make this a CONFIG option, but I would get email
     87    // from all the people who WILL destroy their filesystems.
     88    if (stat("/init", &st) != 0 || !S_ISREG(st.st_mode)) {
     89        bb_error_msg_and_die("/init is not a regular file");
     90    }
     91    statfs("/", &stfs); // this never fails
     92    if ((unsigned)stfs.f_type != RAMFS_MAGIC
     93     && (unsigned)stfs.f_type != TMPFS_MAGIC
     94    ) {
     95        bb_error_msg_and_die("root filesystem is not ramfs/tmpfs");
    9996    }
    10097
    10198    // Zap everything out of rootdev
    102 
    103     delete_contents("/");
    104 
    105     // Overmount / with newdir and chroot into it.  The chdir is needed to
    106     // recalculate "." and ".." links.
    107 
    108     if (mount(".", "/", NULL, MS_MOVE, NULL) || chroot("."))
    109         bb_error_msg_and_die("error moving root");
     99    delete_contents("/", rootdev);
     100
     101    // Overmount / with newdir and chroot into it
     102    if (mount(".", "/", NULL, MS_MOVE, NULL)) {
     103        // For example, fails when newroot is not a mountpoint
     104        bb_perror_msg_and_die("error moving root");
     105    }
     106    xchroot(".");
     107    // The chdir is needed to recalculate "." and ".." links
    110108    xchdir("/");
    111109
    112     // If a new console specified, redirect stdin/stdout/stderr to that.
    113 
     110    // If a new console specified, redirect stdin/stdout/stderr to it
    114111    if (console) {
    115112        close(0);
    116113        xopen(console, O_RDWR);
    117         dup2(0, 1);
    118         dup2(0, 2);
    119     }
    120 
    121     // Exec real init.  (This is why we must be pid 1.)
     114        xdup2(0, 1);
     115        xdup2(0, 2);
     116    }
     117
     118    // Exec real init
    122119    execv(argv[0], argv);
    123     bb_perror_msg_and_die("bad init %s", argv[0]);
     120    bb_perror_msg_and_die("can't execute '%s'", argv[0]);
    124121}
     122
     123/*
     124From: Rob Landley <rob@landley.net>
     125Date: Tue, Jun 16, 2009 at 7:47 PM
     126Subject: Re: switch_root...
     127
     128...
     129...
     130...
     131
     132If you're _not_ running out of init_ramfs (if for example you're using initrd
     133instead), you probably shouldn't use switch_root because it's the wrong tool.
     134
     135Basically what the sucker does is something like the following shell script:
     136
     137 find / -xdev | xargs rm -rf
     138 cd "$1"
     139 shift
     140 mount --move . /
     141 exec chroot . "$@"
     142
     143There are a couple reasons that won't work as a shell script:
     144
     1451) If you delete the commands out of your $PATH, your shell scripts can't run
     146more commands, but you can't start using dynamically linked _new_ commands
     147until after you do the chroot because the path to the dynamic linker is wrong.
     148So there's a step that needs to be sort of atomic but can't be as a shell
     149script.  (You can work around this with static linking or very carefully laid
     150out paths and sequencing, but it's brittle, ugly, and non-obvious.)
     151
     1522) The "find | rm" bit will acually delete everything because the mount points
     153still show up (even if their contents don't), and rm -rf will then happily zap
     154that.  So the first line is an oversimplification of what you need to do _not_
     155to descend into other filesystems and delete their contents.
     156
     157The reason we do this is to free up memory, by the way.  Since initramfs is a
     158ramfs, deleting its contents frees up the memory it uses.  (We leave it with
     159one remaining dentry for the new mount point, but that's ok.)
     160
     161Note that you cannot ever umount rootfs, for approximately the same reason you
     162can't kill PID 1.  The kernel tracks mount points as a doubly linked list, and
     163the pointer to the start/end of that list always points to an entry that's
     164known to be there (rootfs), so it never has to worry about moving that pointer
     165and it never has to worry about the list being empty.  (Back around 2.6.13
     166there _was_ a bug that let you umount rootfs, and the system locked hard the
     167instant you did so endlessly looping to find the end of the mount list and
     168never stopping.  They fixed it.)
     169
     170Oh, and the reason we mount --move _and_ do the chroot is due to the way "/"
     171works.  Each process has two special symlinks, ".", and "/".  Each of them
     172points to the dentry of a directory, and give you a location paths can start
     173from.  (Historically ".." was also special, because you could enter a
     174directory via a symlink so backing out to the directory you came from doesn't
     175necessarily mean the one physically above where "." points to.  These days I
     176think it's just handed off to the filesystem.)
     177
     178Anyway, path resolution starts with "." or "/" (although the "./" at the start
     179of the path may be implicit), meaning it's relative to one of those two
     180directories.  Your current directory, and your current root directory.  The
     181chdir() syscall changes where "." points to, and the chroot() syscall changes
     182where "/" points to.  (Again, both are per-process which is why chroot only
     183affects your current process and its child processes.)
     184
     185Note that chroot() does _not_ change where "." points to, and back before they
     186put crazy security checks into the kernel your current directory could be
     187somewhere you could no longer access after the chroot.  (The command line
     188chroot does a cd as well, the chroot _syscall_ is what I'm talking about.)
     189
     190The reason mounting something new over / has no obvious effect is the same
     191reason mounting something over your current directory has no obvious effect:
     192the . and / links aren't recalculated after a mount, so they still point to
     193the same dentry they did before, even if that dentry is no longer accessible
     194by other means.  Note that "cd ." is a NOP, and "chroot /" is a nop; both look
     195up the cached dentry and set it right back.  They don't re-parse any paths,
     196because they're what all paths your process uses would be relative to.
     197
     198That's why the careful sequencing above: we cd into the new mount point before
     199we do the mount --move.  Moving the mount point would otherwise make it
     200totally inaccessible to is because cd-ing to the old path wouldn't give it to
     201us anymore, and cd "/" just gives us the cached dentry from when the process
     202was created (in this case the old initramfs one).  But the "." symlink gives
     203us the dentry of the filesystem we just moved, so we can then "chroot ." to
     204copy that dentry to "/" and get the new filesystem.  If we _didn't_ save that
     205dentry in "." we couldn't get it back after the mount --move.
     206
     207(Yes, this is all screwy and I had to email questions to Linus Torvalds to get
     208it straight myself.  I keep meaning to write up a "how mount actually works"
     209document someday...)
     210*/
  • branches/2.2.9/mindi-busybox/util-linux/umount.c

    r1765 r2725  
    66 * Copyright (C) 2005 by Rob Landley <rob@landley.net>
    77 *
    8  * Licensed under GPL version 2, see file LICENSE in this tarball for details.
     8 * Licensed under GPLv2, see file LICENSE in this source tree.
    99 */
    10 
    1110#include <mntent.h>
    12 #include <getopt.h>
     11#include <sys/mount.h>
    1312#include "libbb.h"
    1413
    15 #define OPTION_STRING       "flDnravdt:"
    16 #define OPT_FORCE           1
    17 #define OPT_LAZY            2
    18 #define OPT_DONTFREELOOP    4
    19 #define OPT_NO_MTAB         8
    20 #define OPT_REMOUNT         16
    21 #define OPT_ALL             (ENABLE_FEATURE_UMOUNT_ALL ? 32 : 0)
     14#if defined(__dietlibc__)
     15// TODO: This does not belong here.
     16/* 16.12.2006, Sampo Kellomaki (sampo@iki.fi)
     17 * dietlibc-0.30 does not have implementation of getmntent_r() */
     18static struct mntent *getmntent_r(FILE* stream, struct mntent* result,
     19        char* buffer UNUSED_PARAM, int bufsize UNUSED_PARAM)
     20{
     21    struct mntent* ment = getmntent(stream);
     22    return memcpy(result, ment, sizeof(*ment));
     23}
     24#endif
    2225
    23 int umount_main(int argc, char **argv);
    24 int umount_main(int argc, char **argv)
     26/* ignored: -v -d -t -i */
     27#define OPTION_STRING           "fldnra" "vdt:i"
     28#define OPT_FORCE               (1 << 0) // Same as MNT_FORCE
     29#define OPT_LAZY                (1 << 1) // Same as MNT_DETACH
     30#define OPT_FREELOOP            (1 << 2)
     31#define OPT_NO_MTAB             (1 << 3)
     32#define OPT_REMOUNT             (1 << 4)
     33#define OPT_ALL                 (ENABLE_FEATURE_UMOUNT_ALL ? (1 << 5) : 0)
     34
     35int umount_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     36int umount_main(int argc UNUSED_PARAM, char **argv)
    2537{
    2638    int doForce;
    27     char path[2*PATH_MAX];
    2839    struct mntent me;
    2940    FILE *fp;
    30     char *fstype = 0;
     41    char *fstype = NULL;
    3142    int status = EXIT_SUCCESS;
    3243    unsigned opt;
     
    3748    } *mtl, *m;
    3849
    39     /* Parse any options */
    40 
    4150    opt = getopt32(argv, OPTION_STRING, &fstype);
    42 
    43     argc -= optind;
     51    //argc -= optind;
    4452    argv += optind;
    4553
     54    // MNT_FORCE and MNT_DETACH (from linux/fs.h) must match
     55    // OPT_FORCE and OPT_LAZY, otherwise this trick won't work:
    4656    doForce = MAX((opt & OPT_FORCE), (opt & OPT_LAZY));
    4757
     
    5161     * entry.  Notice that this also naturally reverses the list so that -a
    5262     * umounts the most recent entries first. */
     63    m = mtl = NULL;
    5364
    54     m = mtl = 0;
    55 
    56     /* If we're umounting all, then m points to the start of the list and
    57      * the argument list should be empty (which will match all). */
    58 
     65    // If we're umounting all, then m points to the start of the list and
     66    // the argument list should be empty (which will match all).
    5967    fp = setmntent(bb_path_mtab_file, "r");
    6068    if (!fp) {
    6169        if (opt & OPT_ALL)
    62             bb_error_msg_and_die("cannot open %s", bb_path_mtab_file);
     70            bb_error_msg_and_die("can't open '%s'", bb_path_mtab_file);
    6371    } else {
    64         while (getmntent_r(fp, &me, path, sizeof(path))) {
     72        while (getmntent_r(fp, &me, bb_common_bufsiz1, sizeof(bb_common_bufsiz1))) {
    6573            /* Match fstype if passed */
    66             if (fstype && match_fstype(&me, fstype))
     74            if (!match_fstype(&me, fstype))
    6775                continue;
    68             m = xmalloc(sizeof(struct mtab_list));
     76            m = xzalloc(sizeof(*m));
    6977            m->next = mtl;
    7078            m->device = xstrdup(me.mnt_fsname);
     
    7583    }
    7684
    77     /* If we're not umounting all, we need at least one argument. */
     85    // If we're not umounting all, we need at least one argument.
    7886    if (!(opt & OPT_ALL) && !fstype) {
    79         m = 0;
    80         if (!argc) bb_show_usage();
     87        if (!argv[0])
     88            bb_show_usage();
     89        m = NULL;
    8190    }
    8291
     
    8594        int curstat;
    8695        char *zapit = *argv;
     96        char *path;
    8797
    8898        // Do we already know what to umount this time through the loop?
    89         if (m) safe_strncpy(path, m->dir, PATH_MAX);
     99        if (m)
     100            path = xstrdup(m->dir);
    90101        // For umount -a, end of mtab means time to exit.
    91         else if (opt & OPT_ALL) break;
    92         // Get next command line argument (and look it up in mtab list)
    93         else if (!argc--) break;
     102        else if (opt & OPT_ALL)
     103            break;
     104        // Use command line argument (and look it up in mtab list)
    94105        else {
     106            if (!zapit)
     107                break;
    95108            argv++;
    96             realpath(zapit, path);
    97             for (m = mtl; m; m = m->next)
    98                 if (!strcmp(path, m->dir) || !strcmp(path, m->device))
    99                     break;
     109            path = xmalloc_realpath(zapit);
     110            if (path) {
     111                for (m = mtl; m; m = m->next)
     112                    if (strcmp(path, m->dir) == 0 || strcmp(path, m->device) == 0)
     113                        break;
     114            }
    100115        }
    101116        // If we couldn't find this sucker in /etc/mtab, punt by passing our
     
    108123
    109124        // Force the unmount, if necessary.
    110         if (curstat && doForce) {
     125        if (curstat && doForce)
    111126            curstat = umount2(zapit, doForce);
    112             if (curstat)
    113                 bb_error_msg("forced umount of %s failed!", zapit);
    114         }
    115127
    116128        // If still can't umount, maybe remount read-only?
    117         if (curstat && (opt & OPT_REMOUNT) && errno == EBUSY && m) {
    118             curstat = mount(m->device, zapit, NULL, MS_REMOUNT|MS_RDONLY, NULL);
    119             bb_error_msg(curstat ? "cannot remount %s read-only" :
    120                          "%s busy - remounted read-only", m->device);
    121         }
    122 
    123129        if (curstat) {
    124             status = EXIT_FAILURE;
    125             bb_perror_msg("cannot umount %s", zapit);
     130            if ((opt & OPT_REMOUNT) && errno == EBUSY && m) {
     131                // Note! Even if we succeed here, later we should not
     132                // free loop device or erase mtab entry!
     133                const char *msg = "%s busy - remounted read-only";
     134                curstat = mount(m->device, zapit, NULL, MS_REMOUNT|MS_RDONLY, NULL);
     135                if (curstat) {
     136                    msg = "can't remount %s read-only";
     137                    status = EXIT_FAILURE;
     138                }
     139                bb_error_msg(msg, m->device);
     140            } else {
     141                status = EXIT_FAILURE;
     142                bb_perror_msg("can't %sumount %s", (doForce ? "forcibly " : ""), zapit);
     143            }
    126144        } else {
    127             /* De-allocate the loop device.  This ioctl should be ignored on
    128              * any non-loop block devices. */
    129             if (ENABLE_FEATURE_MOUNT_LOOP && !(opt & OPT_DONTFREELOOP) && m)
     145            // De-allocate the loop device.  This ioctl should be ignored on
     146            // any non-loop block devices.
     147            if (ENABLE_FEATURE_MOUNT_LOOP && (opt & OPT_FREELOOP) && m)
    130148                del_loop(m->device);
    131149            if (ENABLE_FEATURE_MTAB_SUPPORT && !(opt & OPT_NO_MTAB) && m)
     
    136154        // Note this means that "umount /dev/blah" will unmount all instances
    137155        // of /dev/blah, not just the most recent.
    138         while (m && (m = m->next))
    139             if ((opt & OPT_ALL) || !strcmp(path, m->device))
    140                 break;
     156        if (m) {
     157            while ((m = m->next) != NULL)
     158                // NB: if m is non-NULL, path is non-NULL as well
     159                if ((opt & OPT_ALL) || strcmp(path, m->device) == 0)
     160                    break;
     161        }
     162        free(path);
    141163    }
    142164
    143165    // Free mtab list if necessary
    144 
    145166    if (ENABLE_FEATURE_CLEAN_UP) {
    146167        while (mtl) {
Note: See TracChangeset for help on using the changeset viewer.