busybox/util-linux/fatattr.c
<<
>>
Prefs
   1/* vi: set sw=4 ts=4: */
   2/*
   3 * Display or change file attributes on a fat file system
   4 *
   5 * Copyright 2005 H. Peter Anvin
   6 * Busybox'ed (2014) by Pascal Bellard <pascal.bellard@ads-lu.com>
   7 *
   8 * This file can be redistributed under the terms of the GNU General
   9 * Public License
  10 */
  11//config:config FATATTR
  12//config:       bool "fatattr (1.9 kb)"
  13//config:       default y
  14//config:       help
  15//config:       fatattr lists or changes the file attributes on a fat file system.
  16
  17//applet:IF_FATATTR(APPLET_NOEXEC(fatattr, fatattr, BB_DIR_BIN, BB_SUID_DROP, fatattr))
  18
  19//kbuild:lib-$(CONFIG_FATATTR) += fatattr.o
  20
  21//usage:#define fatattr_trivial_usage
  22//usage:       "[-+rhsvda] FILE..."
  23//usage:#define fatattr_full_usage "\n\n"
  24//usage:       "Change file attributes on FAT filesystem\n"
  25//usage:     "\n        -       Clear attributes"
  26//usage:     "\n        +       Set attributes"
  27//usage:     "\n        r       Read only"
  28//usage:     "\n        h       Hidden"
  29//usage:     "\n        s       System"
  30//usage:     "\n        v       Volume label"
  31//usage:     "\n        d       Directory"
  32//usage:     "\n        a       Archive"
  33
  34#include "libbb.h"
  35/* linux/msdos_fs.h says: */
  36#ifndef FAT_IOCTL_GET_ATTRIBUTES
  37# define FAT_IOCTL_GET_ATTRIBUTES        _IOR('r', 0x10, uint32_t)
  38# define FAT_IOCTL_SET_ATTRIBUTES        _IOW('r', 0x11, uint32_t)
  39#endif
  40
  41/* Currently supports only the FAT flags, not the NTFS ones.
  42 * Extra space at the end is a hack to print space separator in file listing.
  43 * Let's hope no one ever passes space as an option char :)
  44 */
  45static const char bit_to_char[] ALIGN1 = "rhsvda67 ";
  46
  47static inline unsigned long get_flag(char c)
  48{
  49        const char *fp = strchr(bit_to_char, c);
  50        if (!fp)
  51                bb_error_msg_and_die("invalid character '%c'", c);
  52        return 1 << (fp - bit_to_char);
  53}
  54
  55static unsigned decode_arg(const char *arg)
  56{
  57        unsigned fl = 0;
  58        while (*++arg)
  59                fl |= get_flag(*arg);
  60        return fl;
  61}
  62
  63int fatattr_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  64int fatattr_main(int argc UNUSED_PARAM, char **argv)
  65{
  66        unsigned set_mask = 0;
  67        unsigned clear_mask = 0;
  68
  69        for (;;) {
  70                unsigned fl;
  71                char *arg = *++argv;
  72
  73                if (!arg)
  74                        bb_show_usage();
  75                if (arg[0] != '-' && arg[0] != '+')
  76                        break;
  77                fl = decode_arg(arg);
  78                if (arg[0] == '+')
  79                        set_mask |= fl;
  80                else
  81                        clear_mask |= fl;
  82        }
  83
  84        do {
  85                int fd, i;
  86                uint32_t attr;
  87
  88                fd = xopen(*argv, O_RDONLY);
  89                xioctl(fd, FAT_IOCTL_GET_ATTRIBUTES, &attr);
  90                attr = (attr | set_mask) & ~clear_mask;
  91                if (set_mask | clear_mask)
  92                        xioctl(fd, FAT_IOCTL_SET_ATTRIBUTES, &attr);
  93                else {
  94                        for (i = 0; bit_to_char[i]; i++) {
  95                                bb_putchar((attr & 1) ? bit_to_char[i] : ' ');
  96                                attr >>= 1;
  97                        }
  98                        puts(*argv);
  99                }
 100                close(fd);
 101        } while (*++argv);
 102
 103        return EXIT_SUCCESS;
 104}
 105