Linux 下读写 FAT 属性信息
March 22nd, 2009
Comments off
FAT 是 Windows 下的文件系统格式。每个 FAT 下的文件都包含 ARHIVE,SYSTEM,HIDDEN,READ-ONLY 等属性。而 Linux 下面缺乏读写 FAT 属性信息的命令,难以读出,或者设置这些 FAT 属性。
而实际上 Linux 内核的 vfat 模块包含相应的 ioctl 命令,可以修改文件的属性。在 <linux/msdos_fs.h> 定义如下:
#define FAT_IOCTL_GET_ATTRIBUTES _IOR('r', 0x10, __u32) #define FAT_IOCTL_SET_ATTRIBUTES _IOW('r', 0x11, __u32)
上述两个 ioctl 命令接受一个 int 类型,该 int 值的不同 bit 位,按照下面的定义表示不同的文件属性:
#define ATTR_RO 1 /* read-only */ #define ATTR_HIDDEN 2 /* hidden */ #define ATTR_SYS 4 /* system */ #define ATTR_VOLUME 8 /* volume label */ #define ATTR_DIR 16 /* directory */ #define ATTR_ARCH 32 /* archived */
由于没有发现有命令可以利用上述 ioctl 接口,操作 FAT 文件的属性,我自己写了一个 attrib.py 文件,代码在最后。该命令接收两个参数,说明如下
Usage: ./attrib.py dir_or_file dump|load
下面的命令将 /mnt/fat 目录下所有子目录和文件的属性输出到文件 attributes.dump 文件中
./attrib.py /mnt/fat dump > attributes.dump
./attrib.py dump 输出的部分内容如下:
A..SHR ./ntldr A..SHR ./NTDETECT.COM A..SHR ./boot.ini A..SHR ./IO.SYS A..SHR ./MSDOS.SYS .D..H. ./WINDOWS/inf .D.S.R ./WINDOWS/Fonts .D.SH. ./WINDOWS/Installer .D.S.. ./WINDOWS/Tasks .D.S.. ./WINDOWS/Downloaded Program Files ...SH. ./WINDOWS/winnt.bmp ...SH. ./WINDOWS/winnt256.bmp A...HR ./WINDOWS/WindowsShell.Manifest A..S.. ./WINDOWS/bootstat.dat
下面的命令将根据 attributes.dump 文件中包含的属性信息,给 /mnt/fat 目录下所有子目录和文件设置相应的属性
./attrib.py /mnt/fat load < attributes.dump
下面是 attrib.py 的源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | #!/usr/bin/python import os import sys import fcntl import posixpath ATTR_ARCH = 0x20 ATTR_DIR = 0x10 ATTR_VOLUME = 0x08 ATTR_SYSTEM = 0x04 ATTR_HIDDEN = 0x02 ATTR_RO = 0x01 AttrBitName = { ATTR_ARCH: 'A', ATTR_DIR: 'D', ATTR_VOLUME: 'V', ATTR_SYSTEM: 'S', ATTR_HIDDEN: 'H', ATTR_RO: 'R', } AttrBits = AttrBitName.keys() AttrBits.sort() AttrBits.reverse() FAT_GETATTR_IOCTL = 0x80047210 FAT_SETATTR_IOCTL = 0x40047211 def fat_getattr(filename): fd = os.open(filename, os.O_RDONLY) try: word = fcntl.ioctl(fd, FAT_GETATTR_IOCTL, ' ') except: os.close(fd) raise os.close(fd) return ord(word[0]) def fat_setattr(filename, attr): fd = os.open(filename, os.O_RDONLY) word = '%s\0\0\0' % chr(attr) try: fcntl.ioctl(fd, FAT_SETATTR_IOCTL, word) except: os.close(fd) raise os.close(fd) def fat_attrstr(attr): bit_to_name = lambda bit: bit & attr and AttrBitName[bit] or '.' return ''.join(map(bit_to_name, AttrBits)) def fat_strattr(str): str_to_bin = lambda x: x[0] == x[1] and '1' or '0' bin = ''.join(map(str_to_bin, zip('ADVSHR', str))) return int(bin, 2) def fat_dumpattr(): for cur, dirs, files in os.walk('.'): items = dirs + files for item in items: try: filename = '%s/%s' % (cur, item) attr = fat_getattr(filename) str = fat_attrstr(attr) print '%s %s' % (str, filename) except Exception, e: print e def fat_loadattr(): for line in sys.stdin.readlines(): str = line[:6] file = line[6:].strip() if posixpath.exists(file): newattr = fat_strattr(str) oldattr = fat_getattr(file) if newattr == oldattr: print 'ignore same attribute %s[0x%02x]: %s' % (str, newattr, file) else: oldstr = fat_attrstr(oldattr) fat_setattr(file, newattr) print '-%s[0x%02X] +%s[0x%02X] %s' % (oldstr, oldattr, str, newattr, file) else: print 'ignore not existing file: %s' % file def usage(): print 'Usage: %s dir_or_file dump|load' % sys.argv[0] exit(1) if len(sys.argv) != 3: usage() target_dir = sys.argv[1] old_dir = os.getcwd() try: os.chdir(target_dir) except: print 'Bad directory: %s' % target_dir usage() op = sys.argv[2] if op == 'dump': fat_dumpattr() elif op == 'load': fat_loadattr() else: print 'Bad option: %s' % op usage() os.chdir(old_dir) |
Recent Comments