Archive

Posts Tagged ‘fat’

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 &amp; 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)
Categories: 开源软件 Tags: ,