Home | History | Annotate | Download | only in Modules
      1 /* stat.h interface
      2  *
      3  * The module defines all S_IF*, S_I*, UF_*, SF_* and ST_* constants to
      4  * sensible default values as well as defines S_IS*() macros in order to keep
      5  * backward compatibility with the old stat.py module.
      6  *
      7  * New constants and macros such as S_IFDOOR / S_ISDOOR() are always defined
      8  * as int 0.
      9  *
     10  * NOTE: POSIX only defines the values of the S_I* permission bits.
     11  *
     12  */
     13 
     14 #define PY_SSIZE_T_CLEAN
     15 #include "Python.h"
     16 
     17 #ifdef __cplusplus
     18 extern "C" {
     19 #endif
     20 
     21 #ifdef HAVE_SYS_TYPES_H
     22 #include <sys/types.h>
     23 #endif /* HAVE_SYS_TYPES_H */
     24 
     25 #ifdef HAVE_SYS_STAT_H
     26 #include <sys/stat.h>
     27 #endif /* HAVE_SYS_STAT_H */
     28 
     29 #ifdef MS_WINDOWS
     30 #include <windows.h>
     31 typedef unsigned short mode_t;
     32 
     33 /* FILE_ATTRIBUTE_INTEGRITY_STREAM and FILE_ATTRIBUTE_NO_SCRUB_DATA
     34    are not present in VC2010, so define them manually */
     35 #ifndef FILE_ATTRIBUTE_INTEGRITY_STREAM
     36 #  define FILE_ATTRIBUTE_INTEGRITY_STREAM 0x8000
     37 #endif
     38 
     39 #ifndef FILE_ATTRIBUTE_NO_SCRUB_DATA
     40 #  define FILE_ATTRIBUTE_NO_SCRUB_DATA 0x20000
     41 #endif
     42 
     43 #endif /* MS_WINDOWS */
     44 
     45 /* From Python's stat.py */
     46 #ifndef S_IMODE
     47 #  define S_IMODE 07777
     48 #endif
     49 
     50 /* S_IFXXX constants (file types)
     51  *
     52  * Only the names are defined by POSIX but not their value. All common file
     53  * types seems to have the same numeric value on all platforms, though.
     54  *
     55  * pyport.h guarantees S_IFMT, S_IFDIR, S_IFCHR, S_IFREG and S_IFLNK
     56  */
     57 
     58 #ifndef S_IFBLK
     59 #  define S_IFBLK 0060000
     60 #endif
     61 
     62 #ifndef S_IFIFO
     63 #  define S_IFIFO 0010000
     64 #endif
     65 
     66 #ifndef S_IFSOCK
     67 #  define S_IFSOCK 0140000
     68 #endif
     69 
     70 #ifndef S_IFDOOR
     71 #  define S_IFDOOR 0
     72 #endif
     73 
     74 #ifndef S_IFPORT
     75 #  define S_IFPORT 0
     76 #endif
     77 
     78 #ifndef S_IFWHT
     79 #  define S_IFWHT 0
     80 #endif
     81 
     82 
     83 /* S_ISXXX()
     84  * pyport.h defines S_ISDIR(), S_ISREG() and S_ISCHR()
     85  */
     86 
     87 #ifndef S_ISBLK
     88 #  define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)
     89 #endif
     90 
     91 #ifndef S_ISFIFO
     92 #  define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
     93 #endif
     94 
     95 #ifndef S_ISLNK
     96 #  define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
     97 #endif
     98 
     99 #ifndef S_ISSOCK
    100 #  define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
    101 #endif
    102 
    103 #ifndef S_ISDOOR
    104 #  define S_ISDOOR(mode) 0
    105 #endif
    106 
    107 #ifndef S_ISPORT
    108 #  define S_ISPORT(mode) 0
    109 #endif
    110 
    111 #ifndef S_ISWHT
    112 #  define S_ISWHT(mode) 0
    113 #endif
    114 
    115 
    116 /* S_I* file permission
    117  *
    118  * The permission bit value are defined by POSIX standards.
    119  */
    120 #ifndef S_ISUID
    121 #  define S_ISUID 04000
    122 #endif
    123 
    124 #ifndef S_ISGID
    125 #  define S_ISGID 02000
    126 #endif
    127 
    128 /* what is S_ENFMT? */
    129 #ifndef S_ENFMT
    130 #  define S_ENFMT S_ISGID
    131 #endif
    132 
    133 #ifndef S_ISVTX
    134 #  define S_ISVTX 01000
    135 #endif
    136 
    137 #ifndef S_IREAD
    138 #  define S_IREAD 00400
    139 #endif
    140 
    141 #ifndef S_IWRITE
    142 #  define S_IWRITE 00200
    143 #endif
    144 
    145 #ifndef S_IEXEC
    146 #  define S_IEXEC 00100
    147 #endif
    148 
    149 #ifndef S_IRWXU
    150 #  define S_IRWXU 00700
    151 #endif
    152 
    153 #ifndef S_IRUSR
    154 #  define S_IRUSR 00400
    155 #endif
    156 
    157 #ifndef S_IWUSR
    158 #  define S_IWUSR 00200
    159 #endif
    160 
    161 #ifndef S_IXUSR
    162 #  define S_IXUSR 00100
    163 #endif
    164 
    165 #ifndef S_IRWXG
    166 #  define S_IRWXG 00070
    167 #endif
    168 
    169 #ifndef S_IRGRP
    170 #  define S_IRGRP 00040
    171 #endif
    172 
    173 #ifndef S_IWGRP
    174 #  define S_IWGRP 00020
    175 #endif
    176 
    177 #ifndef S_IXGRP
    178 #  define S_IXGRP 00010
    179 #endif
    180 
    181 #ifndef S_IRWXO
    182 #  define S_IRWXO 00007
    183 #endif
    184 
    185 #ifndef S_IROTH
    186 #  define S_IROTH 00004
    187 #endif
    188 
    189 #ifndef S_IWOTH
    190 #  define S_IWOTH 00002
    191 #endif
    192 
    193 #ifndef S_IXOTH
    194 #  define S_IXOTH 00001
    195 #endif
    196 
    197 
    198 /* Names for file flags */
    199 #ifndef UF_NODUMP
    200 #  define UF_NODUMP 0x00000001
    201 #endif
    202 
    203 #ifndef UF_IMMUTABLE
    204 #  define UF_IMMUTABLE 0x00000002
    205 #endif
    206 
    207 #ifndef UF_APPEND
    208 #  define UF_APPEND 0x00000004
    209 #endif
    210 
    211 #ifndef UF_OPAQUE
    212 #  define UF_OPAQUE 0x00000008
    213 #endif
    214 
    215 #ifndef UF_NOUNLINK
    216 #  define UF_NOUNLINK 0x00000010
    217 #endif
    218 
    219 #ifndef UF_COMPRESSED
    220 #  define UF_COMPRESSED 0x00000020
    221 #endif
    222 
    223 #ifndef UF_HIDDEN
    224 #  define UF_HIDDEN 0x00008000
    225 #endif
    226 
    227 #ifndef SF_ARCHIVED
    228 #  define SF_ARCHIVED 0x00010000
    229 #endif
    230 
    231 #ifndef SF_IMMUTABLE
    232 #  define SF_IMMUTABLE 0x00020000
    233 #endif
    234 
    235 #ifndef SF_APPEND
    236 #  define SF_APPEND 0x00040000
    237 #endif
    238 
    239 #ifndef SF_NOUNLINK
    240 #  define SF_NOUNLINK 0x00100000
    241 #endif
    242 
    243 #ifndef SF_SNAPSHOT
    244 #  define SF_SNAPSHOT 0x00200000
    245 #endif
    246 
    247 static mode_t
    248 _PyLong_AsMode_t(PyObject *op)
    249 {
    250     unsigned long value;
    251     mode_t mode;
    252 
    253     value = PyLong_AsUnsignedLong(op);
    254     if ((value == (unsigned long)-1) && PyErr_Occurred())
    255         return (mode_t)-1;
    256 
    257     mode = (mode_t)value;
    258     if ((unsigned long)mode != value) {
    259         PyErr_SetString(PyExc_OverflowError, "mode out of range");
    260         return (mode_t)-1;
    261     }
    262     return mode;
    263 }
    264 
    265 
    266 #define stat_S_ISFUNC(isfunc, doc)                             \
    267     static PyObject *                                          \
    268     stat_ ##isfunc (PyObject *self, PyObject *omode)           \
    269     {                                                          \
    270        mode_t mode = _PyLong_AsMode_t(omode);                   \
    271        if ((mode == (mode_t)-1) && PyErr_Occurred())           \
    272            return NULL;                                        \
    273        return PyBool_FromLong(isfunc(mode));                   \
    274     }                                                          \
    275     PyDoc_STRVAR(stat_ ## isfunc ## _doc, doc)
    276 
    277 stat_S_ISFUNC(S_ISDIR,
    278     "S_ISDIR(mode) -> bool\n\n"
    279     "Return True if mode is from a directory.");
    280 
    281 stat_S_ISFUNC(S_ISCHR,
    282     "S_ISCHR(mode) -> bool\n\n"
    283     "Return True if mode is from a character special device file.");
    284 
    285 stat_S_ISFUNC(S_ISBLK,
    286     "S_ISBLK(mode) -> bool\n\n"
    287     "Return True if mode is from a block special device file.");
    288 
    289 stat_S_ISFUNC(S_ISREG,
    290     "S_ISREG(mode) -> bool\n\n"
    291     "Return True if mode is from a regular file.");
    292 
    293 stat_S_ISFUNC(S_ISFIFO,
    294     "S_ISFIFO(mode) -> bool\n\n"
    295     "Return True if mode is from a FIFO (named pipe).");
    296 
    297 stat_S_ISFUNC(S_ISLNK,
    298     "S_ISLNK(mode) -> bool\n\n"
    299     "Return True if mode is from a symbolic link.");
    300 
    301 stat_S_ISFUNC(S_ISSOCK,
    302     "S_ISSOCK(mode) -> bool\n\n"
    303     "Return True if mode is from a socket.");
    304 
    305 stat_S_ISFUNC(S_ISDOOR,
    306     "S_ISDOOR(mode) -> bool\n\n"
    307     "Return True if mode is from a door.");
    308 
    309 stat_S_ISFUNC(S_ISPORT,
    310     "S_ISPORT(mode) -> bool\n\n"
    311     "Return True if mode is from an event port.");
    312 
    313 stat_S_ISFUNC(S_ISWHT,
    314     "S_ISWHT(mode) -> bool\n\n"
    315     "Return True if mode is from a whiteout.");
    316 
    317 
    318 PyDoc_STRVAR(stat_S_IMODE_doc,
    319 "Return the portion of the file's mode that can be set by os.chmod().");
    320 
    321 static PyObject *
    322 stat_S_IMODE(PyObject *self, PyObject *omode)
    323 {
    324     mode_t mode = _PyLong_AsMode_t(omode);
    325     if ((mode == (mode_t)-1) && PyErr_Occurred())
    326         return NULL;
    327     return PyLong_FromUnsignedLong(mode & S_IMODE);
    328 }
    329 
    330 
    331 PyDoc_STRVAR(stat_S_IFMT_doc,
    332 "Return the portion of the file's mode that describes the file type.");
    333 
    334 static PyObject *
    335 stat_S_IFMT(PyObject *self, PyObject *omode)
    336 {
    337     mode_t mode = _PyLong_AsMode_t(omode);
    338     if ((mode == (mode_t)-1) && PyErr_Occurred())
    339         return NULL;
    340     return PyLong_FromUnsignedLong(mode & S_IFMT);
    341 }
    342 
    343 /* file type chars according to
    344    http://en.wikibooks.org/wiki/C_Programming/POSIX_Reference/sys/stat.h */
    345 
    346 static char
    347 filetype(mode_t mode)
    348 {
    349     /* common cases first */
    350     if (S_ISREG(mode))  return '-';
    351     if (S_ISDIR(mode))  return 'd';
    352     if (S_ISLNK(mode))  return 'l';
    353     /* special files */
    354     if (S_ISBLK(mode))  return 'b';
    355     if (S_ISCHR(mode))  return 'c';
    356     if (S_ISFIFO(mode)) return 'p';
    357     if (S_ISSOCK(mode)) return 's';
    358     /* non-standard types */
    359     if (S_ISDOOR(mode)) return 'D';
    360     if (S_ISPORT(mode)) return 'P';
    361     if (S_ISWHT(mode))  return 'w';
    362     /* unknown */
    363     return '?';
    364 }
    365 
    366 static void
    367 fileperm(mode_t mode, char *buf)
    368 {
    369     buf[0] = mode & S_IRUSR ? 'r' : '-';
    370     buf[1] = mode & S_IWUSR ? 'w' : '-';
    371     if (mode & S_ISUID) {
    372         buf[2] = mode & S_IXUSR ? 's' : 'S';
    373     } else {
    374         buf[2] = mode & S_IXUSR ? 'x' : '-';
    375     }
    376     buf[3] = mode & S_IRGRP ? 'r' : '-';
    377     buf[4] = mode & S_IWGRP ? 'w' : '-';
    378     if (mode & S_ISGID) {
    379         buf[5] = mode & S_IXGRP ? 's' : 'S';
    380     } else {
    381         buf[5] = mode & S_IXGRP ? 'x' : '-';
    382     }
    383     buf[6] = mode & S_IROTH ? 'r' : '-';
    384     buf[7] = mode & S_IWOTH ? 'w' : '-';
    385     if (mode & S_ISVTX) {
    386         buf[8] = mode & S_IXOTH ? 't' : 'T';
    387     } else {
    388         buf[8] = mode & S_IXOTH ? 'x' : '-';
    389     }
    390 }
    391 
    392 PyDoc_STRVAR(stat_filemode_doc,
    393 "Convert a file's mode to a string of the form '-rwxrwxrwx'");
    394 
    395 static PyObject *
    396 stat_filemode(PyObject *self, PyObject *omode)
    397 {
    398     char buf[10];
    399     mode_t mode;
    400 
    401     mode = _PyLong_AsMode_t(omode);
    402     if ((mode == (mode_t)-1) && PyErr_Occurred())
    403         return NULL;
    404 
    405     buf[0] = filetype(mode);
    406     fileperm(mode, &buf[1]);
    407     return PyUnicode_FromStringAndSize(buf, 10);
    408 }
    409 
    410 
    411 static PyMethodDef stat_methods[] = {
    412     {"S_ISDIR",         stat_S_ISDIR,  METH_O, stat_S_ISDIR_doc},
    413     {"S_ISCHR",         stat_S_ISCHR,  METH_O, stat_S_ISCHR_doc},
    414     {"S_ISBLK",         stat_S_ISBLK,  METH_O, stat_S_ISBLK_doc},
    415     {"S_ISREG",         stat_S_ISREG,  METH_O, stat_S_ISREG_doc},
    416     {"S_ISFIFO",        stat_S_ISFIFO, METH_O, stat_S_ISFIFO_doc},
    417     {"S_ISLNK",         stat_S_ISLNK,  METH_O, stat_S_ISLNK_doc},
    418     {"S_ISSOCK",        stat_S_ISSOCK, METH_O, stat_S_ISSOCK_doc},
    419     {"S_ISDOOR",        stat_S_ISDOOR, METH_O, stat_S_ISDOOR_doc},
    420     {"S_ISPORT",        stat_S_ISPORT, METH_O, stat_S_ISPORT_doc},
    421     {"S_ISWHT",         stat_S_ISWHT,  METH_O, stat_S_ISWHT_doc},
    422     {"S_IMODE",         stat_S_IMODE,  METH_O, stat_S_IMODE_doc},
    423     {"S_IFMT",          stat_S_IFMT,   METH_O, stat_S_IFMT_doc},
    424     {"filemode",        stat_filemode, METH_O, stat_filemode_doc},
    425     {NULL,              NULL}           /* sentinel */
    426 };
    427 
    428 
    429 PyDoc_STRVAR(module_doc,
    430 "S_IFMT_: file type bits\n\
    431 S_IFDIR: directory\n\
    432 S_IFCHR: character device\n\
    433 S_IFBLK: block device\n\
    434 S_IFREG: regular file\n\
    435 S_IFIFO: fifo (named pipe)\n\
    436 S_IFLNK: symbolic link\n\
    437 S_IFSOCK: socket file\n\
    438 S_IFDOOR: door\n\
    439 S_IFPORT: event port\n\
    440 S_IFWHT: whiteout\n\
    441 \n"
    442 
    443 "S_ISUID: set UID bit\n\
    444 S_ISGID: set GID bit\n\
    445 S_ENFMT: file locking enforcement\n\
    446 S_ISVTX: sticky bit\n\
    447 S_IREAD: Unix V7 synonym for S_IRUSR\n\
    448 S_IWRITE: Unix V7 synonym for S_IWUSR\n\
    449 S_IEXEC: Unix V7 synonym for S_IXUSR\n\
    450 S_IRWXU: mask for owner permissions\n\
    451 S_IRUSR: read by owner\n\
    452 S_IWUSR: write by owner\n\
    453 S_IXUSR: execute by owner\n\
    454 S_IRWXG: mask for group permissions\n\
    455 S_IRGRP: read by group\n\
    456 S_IWGRP: write by group\n\
    457 S_IXGRP: execute by group\n\
    458 S_IRWXO: mask for others (not in group) permissions\n\
    459 S_IROTH: read by others\n\
    460 S_IWOTH: write by others\n\
    461 S_IXOTH: execute by others\n\
    462 \n"
    463 
    464 "UF_NODUMP: do not dump file\n\
    465 UF_IMMUTABLE: file may not be changed\n\
    466 UF_APPEND: file may only be appended to\n\
    467 UF_OPAQUE: directory is opaque when viewed through a union stack\n\
    468 UF_NOUNLINK: file may not be renamed or deleted\n\
    469 UF_COMPRESSED: OS X: file is hfs-compressed\n\
    470 UF_HIDDEN: OS X: file should not be displayed\n\
    471 SF_ARCHIVED: file may be archived\n\
    472 SF_IMMUTABLE: file may not be changed\n\
    473 SF_APPEND: file may only be appended to\n\
    474 SF_NOUNLINK: file may not be renamed or deleted\n\
    475 SF_SNAPSHOT: file is a snapshot file\n\
    476 \n"
    477 
    478 "ST_MODE\n\
    479 ST_INO\n\
    480 ST_DEV\n\
    481 ST_NLINK\n\
    482 ST_UID\n\
    483 ST_GID\n\
    484 ST_SIZE\n\
    485 ST_ATIME\n\
    486 ST_MTIME\n\
    487 ST_CTIME\n\
    488 \n"
    489 
    490 "FILE_ATTRIBUTE_*: Windows file attribute constants\n\
    491                    (only present on Windows)\n\
    492 ");
    493 
    494 
    495 static struct PyModuleDef statmodule = {
    496     PyModuleDef_HEAD_INIT,
    497     "_stat",
    498     module_doc,
    499     -1,
    500     stat_methods,
    501     NULL,
    502     NULL,
    503     NULL,
    504     NULL
    505 };
    506 
    507 PyMODINIT_FUNC
    508 PyInit__stat(void)
    509 {
    510     PyObject *m;
    511     m = PyModule_Create(&statmodule);
    512     if (m == NULL)
    513         return NULL;
    514 
    515     if (PyModule_AddIntMacro(m, S_IFDIR)) return NULL;
    516     if (PyModule_AddIntMacro(m, S_IFCHR)) return NULL;
    517     if (PyModule_AddIntMacro(m, S_IFBLK)) return NULL;
    518     if (PyModule_AddIntMacro(m, S_IFREG)) return NULL;
    519     if (PyModule_AddIntMacro(m, S_IFIFO)) return NULL;
    520     if (PyModule_AddIntMacro(m, S_IFLNK)) return NULL;
    521     if (PyModule_AddIntMacro(m, S_IFSOCK)) return NULL;
    522     if (PyModule_AddIntMacro(m, S_IFDOOR)) return NULL;
    523     if (PyModule_AddIntMacro(m, S_IFPORT)) return NULL;
    524     if (PyModule_AddIntMacro(m, S_IFWHT)) return NULL;
    525 
    526     if (PyModule_AddIntMacro(m, S_ISUID)) return NULL;
    527     if (PyModule_AddIntMacro(m, S_ISGID)) return NULL;
    528     if (PyModule_AddIntMacro(m, S_ISVTX)) return NULL;
    529     if (PyModule_AddIntMacro(m, S_ENFMT)) return NULL;
    530 
    531     if (PyModule_AddIntMacro(m, S_IREAD)) return NULL;
    532     if (PyModule_AddIntMacro(m, S_IWRITE)) return NULL;
    533     if (PyModule_AddIntMacro(m, S_IEXEC)) return NULL;
    534 
    535     if (PyModule_AddIntMacro(m, S_IRWXU)) return NULL;
    536     if (PyModule_AddIntMacro(m, S_IRUSR)) return NULL;
    537     if (PyModule_AddIntMacro(m, S_IWUSR)) return NULL;
    538     if (PyModule_AddIntMacro(m, S_IXUSR)) return NULL;
    539 
    540     if (PyModule_AddIntMacro(m, S_IRWXG)) return NULL;
    541     if (PyModule_AddIntMacro(m, S_IRGRP)) return NULL;
    542     if (PyModule_AddIntMacro(m, S_IWGRP)) return NULL;
    543     if (PyModule_AddIntMacro(m, S_IXGRP)) return NULL;
    544 
    545     if (PyModule_AddIntMacro(m, S_IRWXO)) return NULL;
    546     if (PyModule_AddIntMacro(m, S_IROTH)) return NULL;
    547     if (PyModule_AddIntMacro(m, S_IWOTH)) return NULL;
    548     if (PyModule_AddIntMacro(m, S_IXOTH)) return NULL;
    549 
    550     if (PyModule_AddIntMacro(m, UF_NODUMP)) return NULL;
    551     if (PyModule_AddIntMacro(m, UF_IMMUTABLE)) return NULL;
    552     if (PyModule_AddIntMacro(m, UF_APPEND)) return NULL;
    553     if (PyModule_AddIntMacro(m, UF_OPAQUE)) return NULL;
    554     if (PyModule_AddIntMacro(m, UF_NOUNLINK)) return NULL;
    555     if (PyModule_AddIntMacro(m, UF_COMPRESSED)) return NULL;
    556     if (PyModule_AddIntMacro(m, UF_HIDDEN)) return NULL;
    557     if (PyModule_AddIntMacro(m, SF_ARCHIVED)) return NULL;
    558     if (PyModule_AddIntMacro(m, SF_IMMUTABLE)) return NULL;
    559     if (PyModule_AddIntMacro(m, SF_APPEND)) return NULL;
    560     if (PyModule_AddIntMacro(m, SF_NOUNLINK)) return NULL;
    561     if (PyModule_AddIntMacro(m, SF_SNAPSHOT)) return NULL;
    562 
    563     if (PyModule_AddIntConstant(m, "ST_MODE", 0)) return NULL;
    564     if (PyModule_AddIntConstant(m, "ST_INO", 1)) return NULL;
    565     if (PyModule_AddIntConstant(m, "ST_DEV", 2)) return NULL;
    566     if (PyModule_AddIntConstant(m, "ST_NLINK", 3)) return NULL;
    567     if (PyModule_AddIntConstant(m, "ST_UID", 4)) return NULL;
    568     if (PyModule_AddIntConstant(m, "ST_GID", 5)) return NULL;
    569     if (PyModule_AddIntConstant(m, "ST_SIZE", 6)) return NULL;
    570     if (PyModule_AddIntConstant(m, "ST_ATIME", 7)) return NULL;
    571     if (PyModule_AddIntConstant(m, "ST_MTIME", 8)) return NULL;
    572     if (PyModule_AddIntConstant(m, "ST_CTIME", 9)) return NULL;
    573 
    574 #ifdef MS_WINDOWS
    575     if (PyModule_AddIntMacro(m, FILE_ATTRIBUTE_ARCHIVE)) return NULL;
    576     if (PyModule_AddIntMacro(m, FILE_ATTRIBUTE_COMPRESSED)) return NULL;
    577     if (PyModule_AddIntMacro(m, FILE_ATTRIBUTE_DEVICE)) return NULL;
    578     if (PyModule_AddIntMacro(m, FILE_ATTRIBUTE_DIRECTORY)) return NULL;
    579     if (PyModule_AddIntMacro(m, FILE_ATTRIBUTE_ENCRYPTED)) return NULL;
    580     if (PyModule_AddIntMacro(m, FILE_ATTRIBUTE_HIDDEN)) return NULL;
    581     if (PyModule_AddIntMacro(m, FILE_ATTRIBUTE_INTEGRITY_STREAM)) return NULL;
    582     if (PyModule_AddIntMacro(m, FILE_ATTRIBUTE_NORMAL)) return NULL;
    583     if (PyModule_AddIntMacro(m, FILE_ATTRIBUTE_NOT_CONTENT_INDEXED)) return NULL;
    584     if (PyModule_AddIntMacro(m, FILE_ATTRIBUTE_NO_SCRUB_DATA)) return NULL;
    585     if (PyModule_AddIntMacro(m, FILE_ATTRIBUTE_OFFLINE)) return NULL;
    586     if (PyModule_AddIntMacro(m, FILE_ATTRIBUTE_READONLY)) return NULL;
    587     if (PyModule_AddIntMacro(m, FILE_ATTRIBUTE_REPARSE_POINT)) return NULL;
    588     if (PyModule_AddIntMacro(m, FILE_ATTRIBUTE_SPARSE_FILE)) return NULL;
    589     if (PyModule_AddIntMacro(m, FILE_ATTRIBUTE_SYSTEM)) return NULL;
    590     if (PyModule_AddIntMacro(m, FILE_ATTRIBUTE_TEMPORARY)) return NULL;
    591     if (PyModule_AddIntMacro(m, FILE_ATTRIBUTE_VIRTUAL)) return NULL;
    592 #endif
    593 
    594     return m;
    595 }
    596 
    597 #ifdef __cplusplus
    598 }
    599 #endif
    600