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