2

How i can get fat32 attributes (like archived, hidden...) in linux without spawning a new process with fatattr utility call ? May be there is python binding for it or for linux/fs functions (fat_ioctl_get_attributes, http://www.cs.fsu.edu/~baker/devices/lxr/http/source/linux/fs/fat/file.c). Or maybe it can be done with python-xattr ?

therg
  • 465
  • 5
  • 11

1 Answers1

4

As you can see in the function name, the kernel function fat_ioctl_get_attributes is called from userspace via an ioctl, and I'm not aware of any other binding. Therefore, you can simply read the attributes by calling ioctl yourself, like this:

import array
import fcntl
import os

FAT_IOCTL_GET_ATTRIBUTES = 0x80047210
FATATTR_BITS = 'rhsvda67'

def get_fat_attrs(fn):
    fd = os.open(fn, os.O_RDONLY)
    try:
        buf = array.array('L', [0])
        try:
            fcntl.ioctl(fd, FAT_IOCTL_GET_ATTRIBUTES, buf, True)
        except IOError as ioe:
            if ioe.errno == 25: # Not a FAT volume
                return None
            else:
                raise

        return buf[0]
    finally:
        os.close(fd)

if __name__ == '__main__':
    import sys
    for fn in sys.argv[1:]:
        attrv = get_fat_attrs(fn)
        if attrv is None:
            print(fn + ': Not on a FAT volume')
            continue
        s = ''.join((fb if (1 << idx) & attrv else ' ')
                    for idx,fb in enumerate(FATATTR_BITS))
        print(fn + ': ' + s)
phihag
  • 278,196
  • 72
  • 453
  • 469
  • Why `import sys` after you know its the main? – Serdalis Apr 09 '13 at 08:09
  • 1
    @Serdalis Because in the next line, this demo program iterates over all [command-line arguments](http://docs.python.org/3/library/sys.html#sys.argv) of the program, and `sys` isn't needed if this demo program is used as a library. – phihag Apr 09 '13 at 08:14
  • I was thinking about this solution, but how did you get function address (FAT_IOCTL_GET_ATTRIBUTES = 0x80047210)? On my distr i got error "Function not implemented". – therg Apr 09 '13 at 08:24
  • @user2260486 That's a strange error, since ioctl numbers are part of the kernel interface and therefore should not change. What output do you get for `strace -e ioctl -e raw=ioctl fatattr /` after installing strace and fatattr? – phihag Apr 09 '13 at 08:43
  • `$ uname --a` `Linux deb7 3.2.0-4-amd64 #1 SMP Debian 3.2.35-2 x86_64 GNU/Linux` `$ strace -e ioctl -e raw=ioctl fatattr /` `ioctl(0x3, 0x80047210, 0x7fff9d8d1edc) = -1 (errno 25)` `/: Inappropriate ioctl for device` – therg Apr 09 '13 at 09:08
  • That looks like everything is fine. If fatattr works, this Python program should as well. If this Python program doesn't work on a FAT file, can you upload the file `log.strace` you get with `strace -o log.strace python demo.py /some/file/on/a/fat/device` and `strace -o log.strace fatattr /some/file/on/a/fat/device` somewhere? – phihag Apr 09 '13 at 09:17
  • Thanks you very much, everything works fine, i just tried it on wrong image. – therg Apr 09 '13 at 09:26