Issue40644
This issue tracker has been migrated to GitHub,
and is currently read-only.
For more information,
see the GitHub FAQs in the Python's Developer Guide.
Created on 2020-05-16 11:44 by scrool, last changed 2022-04-11 14:59 by admin.
Messages (4) | |||
---|---|---|---|
msg369041 - (view) | Author: Pavol Babinčák (scrool) * | Date: 2020-05-16 11:44 | |
I'm using Windows and lets' say I have this directory structure listed with cmd: > dir /A ... 16.05.20 11:15 <DIR> directory 16.05.20 10:47 0 hidden 16.05.20 11:25 <SYMLINK> link [regular] 16.05.20 10:47 0 readonly 16.05.20 11:15 0 regular 16.05.20 10:48 0 system ... or PowerShell: PS > dir -Force Mode LastWriteTime Length Name ---- ------------- ------ ---- d----- 16.5.20 11:15 directory -a-h-- 16.5.20 10:47 0 hidden -a---l 16.5.20 11:25 0 link -ar--- 16.5.20 10:47 0 readonly -a---- 16.5.20 11:15 0 regular -a--s- 16.5.20 10:48 0 system or attrib: > attrib A H hidden A link A R readonly A regular A S system I'd like to print file attributes in a text form. If I use stat.filemode(): >>> import os, stat >>> print("\n".join(["{} {}".format(stat.filemode(os.stat(n).st_mode), n) for n in os.listdir('.')])) drwxrwxrwx directory -rw-rw-rw- hidden -rw-rw-rw- link -r--r--r-- readonly -rw-rw-rw- regular -rw-rw-rw- system >>> not surprisingly I miss all windows attributes. On the top of that I get only values of stat.S_IWRITE and stat.S_IREAD as documented in os.chmod(). I'd like to have a new function, let's say fileattributes() which would behave like this: >>> print("\n".join(["{} {}".format(stat.fileattributes(os.stat(n).st_file_attributes), n) for n in os.listdir('.')])) d----- directory -a-h-- hidden -a---l link -ar--- readonly -a---- regular -a--s- system >>> In this example I have used same format of attributes as in PowerShell because it is most similar to filemode(). I guess link cannot be currently identified with contants in stat module. |
|||
msg369071 - (view) | Author: Eryk Sun (eryksun) * ![]() |
Date: 2020-05-16 22:09 | |
There's no reason this can't be generalized to file attributes/flags on other platforms such as st_flags on BSD/macOS and st_attributes on Linux (depending on bpo-39533 -- but statx only returns a small subset of attributes that are available via chattr and lsattr). Here's a table of approximately corresponding file attributes in BSD, Linux, and Windows: BSD [1] Linux Windows ------------------------------------------------------------------------ UF_NODUMP STATX_ATTR_NODUMP -d UF_APPEND STATX_ATTR_APPEND -a STATX_ATTR_ENCRYPTED -E FILE_ATTRIBUTE_ENCRYPTED -E UF_COMPRESSED STATX_ATTR_COMPRESSED -c FILE_ATTRIBUTE_COMPRESSED -C UF_IMMUTABLE STATX_ATTR_IMMUTABLE -i FILE_ATTRIBUTE_READONLY -R [2] UF_NOUNLINK FILE_ATTRIBUTE_READONLY -R [2] UF_READONLY FILE_ATTRIBUTE_READONLY -R UF_HIDDEN FILE_ATTRIBUTE_HIDDEN -H UF_SYSTEM FILE_ATTRIBUTE_SYSTEM -S UF_ARCHIVE FILE_ATTRIBUTE_ARCHIVE -A UF_SPARSE FILE_ATTRIBUTE_SPARSE_FILE -P UF_REPARSE FILE_ATTRIBUTE_REPARSE_POINT -L UF_OFFLINE FILE_ATTRIBUTE_OFFLINE -O [1] Not supported on all BSD platforms, including macOS. [2] Readonly applies to regular file data, not metadata or directory contents (index data). Also, it disallows unlink but allows rename. > not surprisingly I miss all windows attributes. On the top of that I > get only values of stat.S_IWRITE and stat.S_IREAD as documented in > os.chmod(). Windows doesn't implement a direct equivalent of the Unix file mode. But Windows file attributes partially overlap the Unix file mode for the S_IFMT filetype bits. In particular, WinAPI GetFileType classifies an open file based on the device type as one of FILE_TYPE_CHAR (S_IFCHR), FILE_TYPE_PIPE (S_IFIFO, S_IFSOCK), or FILE_TYPE_DISK (S_IFBLK, S_IFREG, S_IFDIR, S_IFLNK). For the latter, FILE_ATTRIBUTE_DIRECTORY and FILE_ATTRIBUTE_REPARSE_POINT distinguish S_IFDIR and reparse points, including S_IFLNK, depending on the reparse tag. The lack of either attribute indicates S_IFREG, and no support for file attributes indicates S_IFBLK. For example: >>> stat.filemode(os.stat('//./nul').st_mode) # S_IFCHR 'c---------' >>> stat.filemode(os.stat('//./pipe').st_mode) # S_IFIFO 'p---------' >>> stat.filemode(os.stat('//./C:').st_mode) # S_IFBLK 'b---------' (Apparently, we aren't fabricating any bogus permissions for the above cases.) Free of charge, you also get a hack that sets the execute bit on directories, and also on files that have a file extension in the set {".COM", ".EXE", ".BAT", ".CMD"}. Caveat emptor: this has nothing to do with whether the file or directory actually grants the caller execute access. >>> stat.filemode(os.stat('C:/').st_mode) # S_IFDIR 'drwxrwxrwx' >>> os.stat('C:/Temp/spam.bat').st_file_attributes & stat.FILE_ATTRIBUTE_READONLY 1 >>> os.readlink('C:/Temp/symlink.bat') 'spam.bat' >>> stat.filemode(os.lstat('C:/Temp/symlink.bat').st_mode) # S_IFLNK 'lrwxrwxrwx' >>> stat.filemode(os.stat('C:/Temp/symlink.bat').st_mode) # S_IFREG '-r-xr-xr-x' Regarding the permission mode bits, many environments (including Python) misuse FILE_ATTRIBUTE_READONLY as a write permission, i.e. readonly removes the S_IWUSR | S_IWGRP | S_IWOTH bits. Certainly readonly should be a factor in os.access(), but it is not a permission; no one can be granted permission to write to a readonly file. Using it as such is inconsistent with UF_IMMUTABLE in BSD and STATX_ATTR_IMMUTABLE in Linux. It's also inconsistent with how write permission works in Unix, since readonly disallows deleting the file, which has nothing to do with write permission on a file in Unix. |
|||
msg369108 - (view) | Author: Pavol Babinčák (scrool) * | Date: 2020-05-17 09:33 | |
Thanks for exhaustive response! The way how I understand this is it might be beneficial to extend request to get text representation of file attributes on other architectures. I didn't know about statx() syscall. From what I can tell there is no binary, similar to 'stat', that would print attributes of a file in a text form. I guess there is no common way to print those attributes from statx()? --- I see that filemode() works consistently across platforms even on Windows. I guess I could use this everywhere: stat.filemode(stat.S_IFMT(os.lstat(n).st_mode) --- And finally modes on Windows won't be ever complete in filemode() because of lack of file modes. I still have some approximation with users' mode (rwx): format(stat.filemode(stat.S_IMODE(os.lstat(n).st_mode))[1:4] To get: r - as readable file or link w - as not readonly x - executable by file extension --- Is that accurate summary? I'm wondering if it would make sense to rename this issue to leave out Windows? |
|||
msg369109 - (view) | Author: Pavol Babinčák (scrool) * | Date: 2020-05-17 09:34 | |
In a second example I meant: stat.filemode(stat.S_IMODE(os.lstat(n).st_mode))[1:4] |
History | |||
---|---|---|---|
Date | User | Action | Args |
2022-04-11 14:59:31 | admin | set | github: 84824 |
2020-05-17 09:34:38 | scrool | set | messages: + msg369109 |
2020-05-17 09:33:17 | scrool | set | messages: + msg369108 |
2020-05-16 22:09:58 | eryksun | set | nosy:
+ eryksun messages: + msg369071 |
2020-05-16 11:44:47 | scrool | create |