diff --git a/Lib/stat.py b/Lib/stat.py --- a/Lib/stat.py +++ b/Lib/stat.py @@ -1,6 +1,11 @@ """Constants/functions for interpreting results of os.stat() and os.lstat(). Suggested usage: from stat import * + +*** DEPRECATED *** +The stat.py module has been superseded by a C implementation in +Modules/statmodule.c. The Python implementation is left for alternative +Python interpreters like Jython. """ # Indices for stat struct members in the tuple returned by os.stat() @@ -108,15 +113,17 @@ SF_NOUNLINK = 0x00100000 # file may not be renamed or deleted SF_SNAPSHOT = 0x00200000 # file is a snapshot file +_filetype_table = { + S_IFDIR: 'd', + S_IFCHR: 'c', + S_IFBLK: 'b', + S_IFREG: '-', + S_IFIFO: 'p', + S_IFLNK: 'l', + S_IFSOCK: 's', +} _filemode_table = ( - ((S_IFLNK, "l"), - (S_IFREG, "-"), - (S_IFBLK, "b"), - (S_IFDIR, "d"), - (S_IFCHR, "c"), - (S_IFIFO, "p")), - ((S_IRUSR, "r"),), ((S_IWUSR, "w"),), ((S_IXUSR|S_ISUID, "s"), @@ -139,6 +146,7 @@ def filemode(mode): """Convert a file's mode to a string of the form '-rwxrwxrwx'.""" perm = [] + perm.append(_filetype_table.get(S_IFMT(mode), '?')) for table in _filemode_table: for bit, char in table: if mode & bit == bit: diff --git a/Lib/test/test_stat.py b/Lib/test/test_stat.py --- a/Lib/test/test_stat.py +++ b/Lib/test/test_stat.py @@ -2,13 +2,63 @@ import os import stat from test.support import TESTFN, run_unittest +from importlib.machinery import SourceFileLoader +def getstatpy(): + # stat.py module is next to os.py + libdir = os.path.abspath(os.path.dirname(os.__file__)) + statpy = os.path.join(libdir, "stat.py") + modname = "statpy" + return SourceFileLoader(modname, statpy).load_module(modname) -def get_mode(fname=TESTFN): - return stat.filemode(os.lstat(fname).st_mode) - +statpy = getstatpy() class TestFilemode(unittest.TestCase): + statmod = None + + file_flags = {'SF_APPEND', 'SF_ARCHIVED', 'SF_IMMUTABLE', 'SF_NOUNLINK', + 'SF_SNAPSHOT', 'UF_APPEND', 'UF_COMPRESSED', 'UF_HIDDEN', + 'UF_IMMUTABLE', 'UF_NODUMP', 'UF_NOUNLINK', 'UF_OPAQUE'} + + formats = {'S_IFBLK', 'S_IFCHR', 'S_IFDIR', 'S_IFIFO', 'S_IFLNK', + 'S_IFREG', 'S_IFSOCK'} + + format_funcs = {'S_ISBLK', 'S_ISCHR', 'S_ISDIR', 'S_ISFIFO', 'S_ISLNK', + 'S_ISREG', 'S_ISSOCK'} + + stat_struct = dict( + ST_MODE = 0, + ST_INO = 1, + ST_DEV = 2, + ST_NLINK = 3, + ST_UID = 4, + ST_GID = 5, + ST_SIZE = 6, + ST_ATIME = 7, + ST_MTIME = 8, + ST_CTIME = 9) + + # permission bit value are defined by POSIX + permission_bits = { + 'S_ISUID': 0o4000, + 'S_ISGID': 0o2000, + 'S_ENFMT': 0o2000, + 'S_ISVTX': 0o1000, + 'S_IRWXU': 0o700, + 'S_IRUSR': 0o400, + 'S_IREAD': 0o400, + 'S_IWUSR': 0o200, + 'S_IWRITE': 0o200, + 'S_IXUSR': 0o100, + 'S_IEXEC': 0o100, + 'S_IRWXG': 0o070, + 'S_IRGRP': 0o040, + 'S_IWGRP': 0o020, + 'S_IXGRP': 0o010, + 'S_IRWXO': 0o007, + 'S_IROTH': 0o004, + 'S_IWOTH': 0o002, + 'S_IXOTH': 0o001} def setUp(self): try: @@ -20,29 +70,84 @@ pass tearDown = setUp + def get_mode(self, fname=TESTFN): + st_mode = os.lstat(fname).st_mode + modestr = self.statmod.filemode(st_mode) + return st_mode, modestr + + def getmembers(self, prefix): + result = [] + for key in dir(self.statmod): + if not key.startswith(prefix): + continue + value = getattr(self.statmod, key) + result.append((key, value)) + return result + + def assertS_IS(self, name, mode): + # test format, lstrip for S_IFIFO + fmt = getattr(self.statmod, "S_IF" + name.lstrip("F")) + self.assertEqual(self.statmod.S_IFMT(mode), fmt) + # test that just one function returns true + testname = "S_IS" + name + for funcname in self.format_funcs: + func = getattr(self.statmod, funcname, None) + if func is None: + if funcname == testname: + raise ValueError(funcname) + continue + if funcname == testname: + self.assertTrue(func(mode)) + else: + self.assertFalse(func(mode)) + def test_mode(self): with open(TESTFN, 'w'): pass if os.name == 'posix': os.chmod(TESTFN, 0o700) - self.assertEqual(get_mode(), '-rwx------') + st_mode, modestr = self.get_mode() + self.assertEqual(modestr, '-rwx------') + self.assertS_IS("REG", st_mode) + self.assertEqual(self.statmod.S_IMODE(st_mode), + self.statmod.S_IRWXU) + os.chmod(TESTFN, 0o070) - self.assertEqual(get_mode(), '----rwx---') + st_mode, modestr = self.get_mode() + self.assertEqual(modestr, '----rwx---') + self.assertS_IS("REG", st_mode) + self.assertEqual(self.statmod.S_IMODE(st_mode), + self.statmod.S_IRWXG) + os.chmod(TESTFN, 0o007) - self.assertEqual(get_mode(), '-------rwx') + st_mode, modestr = self.get_mode() + self.assertEqual(modestr, '-------rwx') + self.assertS_IS("REG", st_mode) + self.assertEqual(self.statmod.S_IMODE(st_mode), + self.statmod.S_IRWXO) + os.chmod(TESTFN, 0o444) - self.assertEqual(get_mode(), '-r--r--r--') + st_mode, modestr = self.get_mode() + self.assertS_IS("REG", st_mode) + self.assertEqual(modestr, '-r--r--r--') + self.assertEqual(self.statmod.S_IMODE(st_mode), 0o444) else: os.chmod(TESTFN, 0o700) - self.assertEqual(get_mode()[:3], '-rw') + st_mode, modestr = self.get_mode() + self.assertEqual(modestr[:3], '-rw') + self.assertS_IS("REG", st_mode) + self.assertEqual(self.statmod.S_IFMT(st_mode), + self.statmod.S_IFREG) def test_directory(self): os.mkdir(TESTFN) os.chmod(TESTFN, 0o700) + st_mode, modestr = self.get_mode() + self.assertS_IS("DIR", st_mode) if os.name == 'posix': - self.assertEqual(get_mode(), 'drwx------') + self.assertEqual(modestr, 'drwx------') else: - self.assertEqual(get_mode()[0], 'd') + self.assertEqual(modestr[0], 'd') @unittest.skipUnless(hasattr(os, 'symlink'), 'os.symlink not available') def test_link(self): @@ -51,16 +156,51 @@ except (OSError, NotImplementedError) as err: raise unittest.SkipTest(str(err)) else: - self.assertEqual(get_mode()[0], 'l') + st_mode, modestr = self.get_mode() + self.assertEqual(modestr[0], 'l') + self.assertS_IS("LNK", st_mode) @unittest.skipUnless(hasattr(os, 'mkfifo'), 'os.mkfifo not available') def test_fifo(self): os.mkfifo(TESTFN, 0o700) - self.assertEqual(get_mode(), 'prwx------') + st_mode, modestr = self.get_mode() + self.assertEqual(modestr, 'prwx------') + self.assertS_IS("FIFO", st_mode) + + def test_module_attributes(self): + for key, value in self.stat_struct.items(): + modvalue = getattr(self.statmod, key) + self.assertEqual(value, modvalue, key) + for key, value in self.permission_bits.items(): + modvalue = getattr(self.statmod, key) + self.assertEqual(value, modvalue, key) + for key in self.file_flags: + modvalue = getattr(self.statmod, key) + self.assertIsInstance(modvalue, int) + for key in self.formats: + modvalue = getattr(self.statmod, key) + self.assertIsInstance(modvalue, int) + for key in self.format_funcs: + func = getattr(self.statmod, key) + self.assertTrue(callable(func)) + + +class TestFilemodeStatC(TestFilemode): + statmod = stat + # C stat module has more formats + formats = TestFilemode.formats | {'S_IFDOOR', 'S_IFPORT', 'S_IFWHT'} + + format_funcs = TestFilemode.format_funcs | {'S_ISDOOR', + 'S_ISPORT', 'S_ISWHT'} + + +class TestFilemodeStatPy(TestFilemode): + statmod = statpy def test_main(): - run_unittest(TestFilemode) + run_unittest(TestFilemodeStatC) + run_unittest(TestFilemodeStatPy) if __name__ == '__main__': test_main() diff --git a/Modules/Setup.dist b/Modules/Setup.dist --- a/Modules/Setup.dist +++ b/Modules/Setup.dist @@ -117,6 +117,7 @@ _collections _collectionsmodule.c # Container types itertools itertoolsmodule.c # Functions creating iterators for efficient looping atexit atexitmodule.c # Register functions to be run at interpreter-shutdown +stat statmodule.c # stat.h interface # access to ISO C locale support _locale _localemodule.c # -lintl diff --git a/Modules/statmodule.c b/Modules/statmodule.c new file mode 100644 --- /dev/null +++ b/Modules/statmodule.c @@ -0,0 +1,552 @@ + +/* stat.h interface */ + +#define PY_SSIZE_T_CLEAN +#include "Python.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef HAVE_SYS_TYPES_H +#include +#endif /* HAVE_SYS_TYPES_H */ + +#ifdef HAVE_SYS_STAT_H +#include +#endif /* HAVE_SYS_STAT_H */ + +/* From Python's stat.py */ +#ifndef S_IMODE +# define S_IMODE 07777 +#endif + +/* S_IFXXX constants */ +#ifndef S_IFMT +# define S_IFMT 0170000 +#endif + +#ifndef S_IFDIR +# define S_IFDIR 0040000 +#endif + +#ifndef S_IFCHR +# define S_IFCHR 0020000 +#endif + +#ifndef S_IFBLK +# define S_IFBLK 0060000 +#endif + +#ifndef S_IFREG +# define S_IFREG 0100000 +#endif + +#ifndef S_IFIFO +# define S_IFIFO 0010000 +#endif + +#ifndef S_IFLNK +# define S_IFLNK 0120000 +#endif + +#ifndef S_IFSOCK +# define S_IFSOCK 0140000 +#endif + +#ifndef S_IFDOOR +# define S_IFDOOR 0 +#endif + +#ifndef S_IFPORT +# define S_IFPORT 0 +#endif + +#ifndef S_IFWHT +# define S_IFWHT 0 +#endif + + +/* S_ISXXX() */ +#ifndef S_ISDIR +# define S_ISDIR(mode) ((mode) & S_IFMT) == S_IDIR +#endif + +#ifndef S_ISCHR +# define S_ISCHR(mode) ((mode) & S_IFMT) == S_ICHR +#endif + +#ifndef S_ISBLK +# define S_ISBLK(mode) ((mode) & S_IFMT) == S_IBLK +#endif + +#ifndef S_ISREG +# define S_ISREG(mode) ((mode) & S_IFMT) == S_IREG +#endif + +#ifndef S_ISFIFO +# define S_ISFIFO(mode) ((mode) & S_IFMT) == S_IFIFO +#endif + +#ifndef S_ISLNK +# define S_ISLNK(mode) ((mode) & S_IFMT) == S_IFLNK +#endif + +#ifndef S_ISSOCK +# define S_ISSOCK(mode) ((mode) & S_IFMT) == S_IFSOCK +#endif + +#ifndef S_ISDOOR +# define S_ISDOOR(mode) 0 +#endif + +#ifndef S_ISPORT +# define S_ISPORT(mode) 0 +#endif + +#ifndef S_ISWHT +# define S_ISWHT(mode) 0 +#endif + + +/* for OS without stat.h */ +#ifndef S_ISUID +# define S_ISUID 04000 +#endif + +#ifndef S_ISGID +# define S_ISGID 02000 +#endif + +/* what is S_ENFMT? */ +#ifndef S_ENFMT +# define S_ENFMT S_ISGID +#endif + +#ifndef S_ISVTX +# define S_ISVTX 01000 +#endif + +#ifndef S_IREAD +# define S_IREAD 00400 +#endif + +#ifndef S_IWRITE +# define S_IWRITE 00200 +#endif + +#ifndef S_IEXEC +# define S_IEXEC 00100 +#endif + +#ifndef S_IRWXU +# define S_IRWXU 00700 +#endif + +#ifndef S_IRUSR +# define S_IRUSR 00400 +#endif + +#ifndef S_IWUSR +# define S_IWUSR 00200 +#endif + +#ifndef S_IXUSR +# define S_IXUSR 00100 +#endif + +#ifndef S_IRWXG +# define S_IRWXG 00070 +#endif + +#ifndef S_IRGRP +# define S_IRGRP 00040 +#endif + +#ifndef S_IWGRP +# define S_IWGRP 00020 +#endif + +#ifndef S_IXGRP +# define S_IXGRP 00010 +#endif + +#ifndef S_IRWXO +# define S_IRWXO 00007 +#endif + +#ifndef S_IROTH +# define S_IROTH 00004 +#endif + +#ifndef S_IWOTH +# define S_IWOTH 00002 +#endif + +#ifndef S_IXOTH +# define S_IXOTH 00001 +#endif + + +/* Names for file flags */ +#ifndef UF_NODUMP +# define UF_NODUMP 0x00000001 +#endif + +#ifndef UF_IMMUTABLE +# define UF_IMMUTABLE 0x00000002 +#endif + +#ifndef UF_APPEND +# define UF_APPEND 0x00000004 +#endif + +#ifndef UF_OPAQUE +# define UF_OPAQUE 0x00000008 +#endif + +#ifndef UF_NOUNLINK +# define UF_NOUNLINK 0x00000010 +#endif + +#ifndef UF_COMPRESSED +# define UF_COMPRESSED 0x00000020 +#endif + +#ifndef UF_HIDDEN +# define UF_HIDDEN 0x00008000 +#endif + +#ifndef SF_ARCHIVED +# define SF_ARCHIVED 0x00010000 +#endif + +#ifndef SF_IMMUTABLE +# define SF_IMMUTABLE 0x00020000 +#endif + +#ifndef SF_APPEND +# define SF_APPEND 0x00040000 +#endif + +#ifndef SF_NOUNLINK +# define SF_NOUNLINK 0x00100000 +#endif + +#ifndef SF_SNAPSHOT +# define SF_SNAPSHOT 0x00200000 +#endif + + +#define stat_S_ISFUNC(isfunc, doc) \ + static PyObject * \ + stat_ ##isfunc (PyObject *self, PyObject *omode) \ + { \ + unsigned long mode = PyLong_AsUnsignedLong(omode); \ + if ((mode == (unsigned long)-1) && PyErr_Occurred()) { \ + return NULL; \ + } \ + return PyBool_FromLong(isfunc(mode)); \ + } \ + PyDoc_STRVAR(stat_ ## isfunc ## _doc, doc) + +stat_S_ISFUNC(S_ISDIR, + "S_ISDIR(mode) -> bool\n\n" + "Return True if mode is from a directory."); + +stat_S_ISFUNC(S_ISCHR, + "S_ISCHR(mode) -> bool\n\n" + "Return True if mode is from a character special device file."); + +stat_S_ISFUNC(S_ISBLK, + "S_ISBLK(mode) -> bool\n\n" + "Return True if mode is from a block special device file."); + +stat_S_ISFUNC(S_ISREG, + "S_ISREG(mode) -> bool\n\n" + "Return True if mode is from a regular file."); + +stat_S_ISFUNC(S_ISFIFO, + "S_ISFIFO(mode) -> bool\n\n" + "Return True if mode is from a FIFO (named pipe)."); + +stat_S_ISFUNC(S_ISLNK, + "S_ISLNK(mode) -> bool\n\n" + "Return True if mode is from a symbolic link."); + +stat_S_ISFUNC(S_ISSOCK, + "S_ISSOCK(mode) -> bool\n\n" + "Return True if mode is from a socket."); + +stat_S_ISFUNC(S_ISDOOR, + "S_ISDOOR(mode) -> bool\n\n" + "Return True if mode is from a door."); + +stat_S_ISFUNC(S_ISPORT, + "S_ISPORT(mode) -> bool\n\n" + "Return True if mode is from a port."); + +stat_S_ISFUNC(S_ISWHT, + "S_ISWHT(mode) -> bool\n\n" + "Return True if mode is from a whiteout."); + + +PyDoc_STRVAR(stat_S_IMODE_doc, +"Return the portion of the file's mode that can be set by os.chmod()."); + +static PyObject * +stat_S_IMODE(PyObject *self, PyObject *omode) +{ + unsigned long mode = PyLong_AsUnsignedLong(omode); + if ((mode == (unsigned long)-1) && PyErr_Occurred()) { + return NULL; + } + return PyLong_FromUnsignedLong(mode & S_IMODE); +} + + +PyDoc_STRVAR(stat_S_IFMT_doc, +"Return the portion of the file's mode that describes the file type."); + +static PyObject * +stat_S_IFMT(PyObject *self, PyObject *omode) +{ + unsigned long mode = PyLong_AsUnsignedLong(omode); + if ((mode == (unsigned long)-1) && PyErr_Occurred()) { + return NULL; + } + return PyLong_FromUnsignedLong(mode & S_IFMT); +} + + +static char +filetype(mode_t mode) +{ + /* common cases first */ + if (S_ISREG(mode)) return '-'; + if (S_ISDIR(mode)) return 'd'; + if (S_ISLNK(mode)) return 'l'; + /* special files */ + if (S_ISBLK(mode)) return 'b'; + if (S_ISCHR(mode)) return 'c'; + if (S_ISFIFO(mode)) return 'p'; + if (S_ISSOCK(mode)) return 's'; + /* non-standard types */ + if (S_ISDOOR(mode)) return 'D'; + if (S_ISPORT(mode)) return 'P'; + if (S_ISWHT(mode)) return 'w'; + /* unknown */ + return '?'; +} + +static void +fileperm(mode_t mode, char *buf) +{ + buf[0] = mode & S_IRUSR ? 'r' : '-'; + buf[1] = mode & S_IWUSR ? 'w' : '-'; + if (mode & S_ISUID) { + buf[2] = mode & S_IXUSR ? 's' : 'S'; + } else { + buf[2] = mode & S_IXUSR ? 'x' : '-'; + } + buf[3] = mode & S_IRGRP ? 'r' : '-'; + buf[4] = mode & S_IWGRP ? 'w' : '-'; + if (mode & S_ISGID) { + buf[5] = mode & S_IXGRP ? 's' : 'S'; + } else { + buf[5] = mode & S_IXGRP ? 'x' : '-'; + } + buf[6] = mode & S_IROTH ? 'r' : '-'; + buf[7] = mode & S_IWOTH ? 'w' : '-'; + if (mode & S_ISVTX) { + buf[8] = mode & S_IXOTH ? 't' : 'T'; + } else { + buf[8] = mode & S_IXOTH ? 'x' : '-'; + } +} + +PyDoc_STRVAR(stat_filemode_doc, +"Convert a file's mode to a string of the form '-rwxrwxrwx'"); + +static PyObject * +stat_filemode(PyObject *self, PyObject *omode) +{ + char buf[10]; + unsigned long mode; + + mode = PyLong_AsUnsignedLong(omode); + if ((mode == (unsigned long)-1) && PyErr_Occurred()) { + return NULL; + } + + buf[0] = filetype(mode); + fileperm(mode, &buf[1]); + return PyUnicode_FromStringAndSize(buf, 10); +} + + +static PyMethodDef stat_methods[] = { + {"S_ISDIR", stat_S_ISDIR, METH_O, stat_S_ISDIR_doc}, + {"S_ISCHR", stat_S_ISCHR, METH_O, stat_S_ISCHR_doc}, + {"S_ISBLK", stat_S_ISBLK, METH_O, stat_S_ISBLK_doc}, + {"S_ISREG", stat_S_ISREG, METH_O, stat_S_ISREG_doc}, + {"S_ISFIFO", stat_S_ISFIFO, METH_O, stat_S_ISFIFO_doc}, + {"S_ISLNK", stat_S_ISLNK, METH_O, stat_S_ISLNK_doc}, + {"S_ISSOCK", stat_S_ISSOCK, METH_O, stat_S_ISSOCK_doc}, + {"S_ISDOOR", stat_S_ISDOOR, METH_O, stat_S_ISDOOR_doc}, + {"S_ISPORT", stat_S_ISPORT, METH_O, stat_S_ISPORT_doc}, + {"S_ISWHT", stat_S_ISWHT, METH_O, stat_S_ISWHT_doc}, + {"S_IMODE", stat_S_IMODE, METH_O, stat_S_IMODE_doc}, + {"S_IFMT", stat_S_IFMT, METH_O, stat_S_IFMT_doc}, + {"filemode", stat_filemode, METH_O, stat_filemode_doc}, + {NULL, NULL} /* sentinel */ +}; + + +PyDoc_STRVAR(module_doc, +"S_IFMT_: file type bits\n\ +S_IFDIR: directory\n\ +S_IFCHR: character device\n\ +S_IFBLK: block device\n\ +S_IFREG: regular file\n\ +S_IFIFO: fifo (named pipe)\n\ +S_IFLNK: symbolic link\n\ +S_IFSOCK: socket file\n\ +S_IFDOOR: door\n\ +S_IFPORT: port\n\ +S_IFWHT: whiteout\n\ +\n" + +"S_ISUID: set UID bit\n\ +S_ISGID: set GID bit\n\ +S_ENFMT: file locking enforcement\n\ +S_ISVTX: sticky bit\n\ +S_IREAD: Unix V7 synonym for S_IRUSR\n\ +S_IWRITE: Unix V7 synonym for S_IWUSR\n\ +S_IEXEC: Unix V7 synonym for S_IXUSR\n\ +S_IRWXU: mask for owner permissions\n\ +S_IRUSR: read by owner\n\ +S_IWUSR: write by owner\n\ +S_IXUSR: execute by owner\n\ +S_IRWXG: mask for group permissions\n\ +S_IRGRP: read by group\n\ +S_IWGRP: write by group\n\ +S_IXGRP: execute by group\n\ +S_IRWXO: mask for others (not in group) permissions\n\ +S_IROTH: read by others\n\ +S_IWOTH: write by others\n\ +S_IXOTH: execute by others\n\ +\n" + +"UF_NODUMP: do not dump file\n\ +UF_IMMUTABLE: file may not be changed\n\ +UF_APPEND: file may only be appended to\n\ +UF_OPAQUE: directory is opaque when viewed through a union stack\n\ +UF_NOUNLINK: file may not be renamed or deleted\n\ +UF_COMPRESSED: OS X: file is hfs-compressed\n\ +UF_HIDDEN: OS X: file should not be displayed\n\ +SF_ARCHIVED: file may be archived\n\ +SF_IMMUTABLE: file may not be changed\n\ +SF_APPEND: file may only be appended to\n\ +SF_NOUNLINK: file may not be renamed or deleted\n\ +SF_SNAPSHOT: file is a snapshot file\n\ +\n" + +"ST_MODE\n\ +ST_INO\n\ +ST_DEV\n\ +ST_NLINK\n\ +ST_UID\n\ +ST_GID\n\ +ST_SIZE\n\ +ST_ATIME\n\ +ST_MTIME\n\ +ST_CTIME\n\ +"); + + +static struct PyModuleDef statmodule = { + PyModuleDef_HEAD_INIT, + "stat", + module_doc, + -1, + stat_methods, + NULL, + NULL, + NULL, + NULL +}; + +PyMODINIT_FUNC +PyInit_stat(void) +{ + PyObject *m; + m = PyModule_Create(&statmodule); + if (m == NULL) + return NULL; + + if (PyModule_AddIntMacro(m, S_IFDIR)) return NULL; + if (PyModule_AddIntMacro(m, S_IFCHR)) return NULL; + if (PyModule_AddIntMacro(m, S_IFBLK)) return NULL; + if (PyModule_AddIntMacro(m, S_IFREG)) return NULL; + if (PyModule_AddIntMacro(m, S_IFIFO)) return NULL; + if (PyModule_AddIntMacro(m, S_IFLNK)) return NULL; + if (PyModule_AddIntMacro(m, S_IFSOCK)) return NULL; + if (PyModule_AddIntMacro(m, S_IFDOOR)) return NULL; + if (PyModule_AddIntMacro(m, S_IFPORT)) return NULL; + if (PyModule_AddIntMacro(m, S_IFWHT)) return NULL; + + if (PyModule_AddIntMacro(m, S_ISUID)) return NULL; + if (PyModule_AddIntMacro(m, S_ISGID)) return NULL; + if (PyModule_AddIntMacro(m, S_ISVTX)) return NULL; + if (PyModule_AddIntMacro(m, S_ENFMT)) return NULL; + + if (PyModule_AddIntMacro(m, S_IREAD)) return NULL; + if (PyModule_AddIntMacro(m, S_IWRITE)) return NULL; + if (PyModule_AddIntMacro(m, S_IEXEC)) return NULL; + + if (PyModule_AddIntMacro(m, S_IRWXU)) return NULL; + if (PyModule_AddIntMacro(m, S_IRUSR)) return NULL; + if (PyModule_AddIntMacro(m, S_IWUSR)) return NULL; + if (PyModule_AddIntMacro(m, S_IXUSR)) return NULL; + + if (PyModule_AddIntMacro(m, S_IRWXG)) return NULL; + if (PyModule_AddIntMacro(m, S_IRGRP)) return NULL; + if (PyModule_AddIntMacro(m, S_IWGRP)) return NULL; + if (PyModule_AddIntMacro(m, S_IXGRP)) return NULL; + + if (PyModule_AddIntMacro(m, S_IRWXO)) return NULL; + if (PyModule_AddIntMacro(m, S_IROTH)) return NULL; + if (PyModule_AddIntMacro(m, S_IWOTH)) return NULL; + if (PyModule_AddIntMacro(m, S_IXOTH)) return NULL; + + if (PyModule_AddIntMacro(m, UF_NODUMP)) return NULL; + if (PyModule_AddIntMacro(m, UF_IMMUTABLE)) return NULL; + if (PyModule_AddIntMacro(m, UF_APPEND)) return NULL; + if (PyModule_AddIntMacro(m, UF_OPAQUE)) return NULL; + if (PyModule_AddIntMacro(m, UF_NOUNLINK)) return NULL; + if (PyModule_AddIntMacro(m, UF_COMPRESSED)) return NULL; + if (PyModule_AddIntMacro(m, UF_HIDDEN)) return NULL; + if (PyModule_AddIntMacro(m, SF_ARCHIVED)) return NULL; + if (PyModule_AddIntMacro(m, SF_IMMUTABLE)) return NULL; + if (PyModule_AddIntMacro(m, SF_APPEND)) return NULL; + if (PyModule_AddIntMacro(m, SF_NOUNLINK)) return NULL; + if (PyModule_AddIntMacro(m, SF_SNAPSHOT)) return NULL; + + if (PyModule_AddIntConstant(m, "ST_MODE", 0)) return NULL; + if (PyModule_AddIntConstant(m, "ST_INO", 1)) return NULL; + if (PyModule_AddIntConstant(m, "ST_DEV", 2)) return NULL; + if (PyModule_AddIntConstant(m, "ST_NLINK", 3)) return NULL; + if (PyModule_AddIntConstant(m, "ST_UID", 4)) return NULL; + if (PyModule_AddIntConstant(m, "ST_GID", 5)) return NULL; + if (PyModule_AddIntConstant(m, "ST_SIZE", 6)) return NULL; + if (PyModule_AddIntConstant(m, "ST_ATIME", 7)) return NULL; + if (PyModule_AddIntConstant(m, "ST_MTIME", 8)) return NULL; + if (PyModule_AddIntConstant(m, "ST_CTIME", 9)) return NULL; + + return m; +} + +#ifdef __cplusplus +} +#endif diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -525,6 +525,7 @@ + @@ -678,4 +679,4 @@ - \ No newline at end of file +