/src/cpython/Modules/_stat.c
Line | Count | Source (jump to first uncovered line) |
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 | | // Need limited C API version 3.13 for PyModule_Add() on Windows |
15 | | #include "pyconfig.h" // Py_GIL_DISABLED |
16 | | #ifndef Py_GIL_DISABLED |
17 | | # define Py_LIMITED_API 0x030d0000 |
18 | | #endif |
19 | | |
20 | | #include "Python.h" |
21 | | |
22 | | #ifdef HAVE_SYS_TYPES_H |
23 | | #include <sys/types.h> |
24 | | #endif /* HAVE_SYS_TYPES_H */ |
25 | | |
26 | | #ifdef HAVE_SYS_STAT_H |
27 | | #include <sys/stat.h> |
28 | | #endif /* HAVE_SYS_STAT_H */ |
29 | | |
30 | | #ifdef MS_WINDOWS |
31 | | #include <windows.h> |
32 | | typedef unsigned short mode_t; |
33 | | |
34 | | /* FILE_ATTRIBUTE_INTEGRITY_STREAM and FILE_ATTRIBUTE_NO_SCRUB_DATA |
35 | | are not present in VC2010, so define them manually */ |
36 | | #ifndef FILE_ATTRIBUTE_INTEGRITY_STREAM |
37 | | # define FILE_ATTRIBUTE_INTEGRITY_STREAM 0x8000 |
38 | | #endif |
39 | | |
40 | | #ifndef FILE_ATTRIBUTE_NO_SCRUB_DATA |
41 | | # define FILE_ATTRIBUTE_NO_SCRUB_DATA 0x20000 |
42 | | #endif |
43 | | |
44 | | #ifndef IO_REPARSE_TAG_APPEXECLINK |
45 | | # define IO_REPARSE_TAG_APPEXECLINK 0x8000001BL |
46 | | #endif |
47 | | |
48 | | #endif /* MS_WINDOWS */ |
49 | | |
50 | | /* From Python's stat.py */ |
51 | | #ifndef S_IMODE |
52 | 0 | # define S_IMODE 07777 |
53 | | #endif |
54 | | |
55 | | /* S_IFXXX constants (file types) |
56 | | * |
57 | | * Only the names are defined by POSIX but not their value. All common file |
58 | | * types seems to have the same numeric value on all platforms, though. |
59 | | * |
60 | | * fileutils.h guarantees S_IFMT, S_IFDIR, S_IFCHR, S_IFREG and S_IFLNK |
61 | | */ |
62 | | |
63 | | #ifndef S_IFBLK |
64 | | # define S_IFBLK 0060000 |
65 | | #endif |
66 | | |
67 | | #ifndef S_IFIFO |
68 | | # define S_IFIFO 0010000 |
69 | | #endif |
70 | | |
71 | | #ifndef S_IFSOCK |
72 | | # define S_IFSOCK 0140000 |
73 | | #endif |
74 | | |
75 | | #ifndef S_IFDOOR |
76 | | # define S_IFDOOR 0 |
77 | | #endif |
78 | | |
79 | | #ifndef S_IFPORT |
80 | | # define S_IFPORT 0 |
81 | | #endif |
82 | | |
83 | | #ifndef S_IFWHT |
84 | | # define S_IFWHT 0 |
85 | | #endif |
86 | | |
87 | | |
88 | | /* S_ISXXX() |
89 | | * fileutils.h defines S_ISDIR(), S_ISREG() and S_ISCHR() |
90 | | */ |
91 | | |
92 | | #ifndef S_ISBLK |
93 | | # define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK) |
94 | | #endif |
95 | | |
96 | | #ifndef S_ISFIFO |
97 | | # define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO) |
98 | | #endif |
99 | | |
100 | | #ifndef S_ISLNK |
101 | | # define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK) |
102 | | #endif |
103 | | |
104 | | #ifndef S_ISSOCK |
105 | | # define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK) |
106 | | #endif |
107 | | |
108 | | #ifndef S_ISDOOR |
109 | 0 | # define S_ISDOOR(mode) 0 |
110 | | #endif |
111 | | |
112 | | #ifndef S_ISPORT |
113 | 0 | # define S_ISPORT(mode) 0 |
114 | | #endif |
115 | | |
116 | | #ifndef S_ISWHT |
117 | 0 | # define S_ISWHT(mode) 0 |
118 | | #endif |
119 | | |
120 | | |
121 | | /* S_I* file permission |
122 | | * |
123 | | * The permission bit value are defined by POSIX standards. |
124 | | */ |
125 | | #ifndef S_ISUID |
126 | | # define S_ISUID 04000 |
127 | | #endif |
128 | | |
129 | | #ifndef S_ISGID |
130 | | # define S_ISGID 02000 |
131 | | #endif |
132 | | |
133 | | /* what is S_ENFMT? */ |
134 | | #ifndef S_ENFMT |
135 | | # define S_ENFMT S_ISGID |
136 | | #endif |
137 | | |
138 | | #ifndef S_ISVTX |
139 | | # define S_ISVTX 01000 |
140 | | #endif |
141 | | |
142 | | #ifndef S_IREAD |
143 | | # define S_IREAD 00400 |
144 | | #endif |
145 | | |
146 | | #ifndef S_IWRITE |
147 | | # define S_IWRITE 00200 |
148 | | #endif |
149 | | |
150 | | #ifndef S_IEXEC |
151 | | # define S_IEXEC 00100 |
152 | | #endif |
153 | | |
154 | | #ifndef S_IRWXU |
155 | | # define S_IRWXU 00700 |
156 | | #endif |
157 | | |
158 | | #ifndef S_IRUSR |
159 | | # define S_IRUSR 00400 |
160 | | #endif |
161 | | |
162 | | #ifndef S_IWUSR |
163 | | # define S_IWUSR 00200 |
164 | | #endif |
165 | | |
166 | | #ifndef S_IXUSR |
167 | | # define S_IXUSR 00100 |
168 | | #endif |
169 | | |
170 | | #ifndef S_IRWXG |
171 | | # define S_IRWXG 00070 |
172 | | #endif |
173 | | |
174 | | #ifndef S_IRGRP |
175 | | # define S_IRGRP 00040 |
176 | | #endif |
177 | | |
178 | | #ifndef S_IWGRP |
179 | | # define S_IWGRP 00020 |
180 | | #endif |
181 | | |
182 | | #ifndef S_IXGRP |
183 | | # define S_IXGRP 00010 |
184 | | #endif |
185 | | |
186 | | #ifndef S_IRWXO |
187 | | # define S_IRWXO 00007 |
188 | | #endif |
189 | | |
190 | | #ifndef S_IROTH |
191 | | # define S_IROTH 00004 |
192 | | #endif |
193 | | |
194 | | #ifndef S_IWOTH |
195 | | # define S_IWOTH 00002 |
196 | | #endif |
197 | | |
198 | | #ifndef S_IXOTH |
199 | | # define S_IXOTH 00001 |
200 | | #endif |
201 | | |
202 | | |
203 | | /* Names for file flags */ |
204 | | #ifndef UF_SETTABLE |
205 | | # define UF_SETTABLE 0x0000ffff |
206 | | #endif |
207 | | |
208 | | #ifndef UF_NODUMP |
209 | | # define UF_NODUMP 0x00000001 |
210 | | #endif |
211 | | |
212 | | #ifndef UF_IMMUTABLE |
213 | | # define UF_IMMUTABLE 0x00000002 |
214 | | #endif |
215 | | |
216 | | #ifndef UF_APPEND |
217 | | # define UF_APPEND 0x00000004 |
218 | | #endif |
219 | | |
220 | | #ifndef UF_OPAQUE |
221 | | # define UF_OPAQUE 0x00000008 |
222 | | #endif |
223 | | |
224 | | #ifndef UF_NOUNLINK |
225 | | # define UF_NOUNLINK 0x00000010 |
226 | | #endif |
227 | | |
228 | | #ifndef UF_COMPRESSED |
229 | | # define UF_COMPRESSED 0x00000020 |
230 | | #endif |
231 | | |
232 | | #ifndef UF_TRACKED |
233 | | # define UF_TRACKED 0x00000040 |
234 | | #endif |
235 | | |
236 | | #ifndef UF_DATAVAULT |
237 | | # define UF_DATAVAULT 0x00000080 |
238 | | #endif |
239 | | |
240 | | #ifndef UF_HIDDEN |
241 | | # define UF_HIDDEN 0x00008000 |
242 | | #endif |
243 | | |
244 | | #ifndef SF_SETTABLE |
245 | | # define SF_SETTABLE 0xffff0000 |
246 | | #endif |
247 | | |
248 | | #ifndef SF_ARCHIVED |
249 | | # define SF_ARCHIVED 0x00010000 |
250 | | #endif |
251 | | |
252 | | #ifndef SF_IMMUTABLE |
253 | | # define SF_IMMUTABLE 0x00020000 |
254 | | #endif |
255 | | |
256 | | #ifndef SF_APPEND |
257 | | # define SF_APPEND 0x00040000 |
258 | | #endif |
259 | | |
260 | | #ifndef SF_NOUNLINK |
261 | | # define SF_NOUNLINK 0x00100000 |
262 | | #endif |
263 | | |
264 | | #ifndef SF_SNAPSHOT |
265 | | # define SF_SNAPSHOT 0x00200000 |
266 | | #endif |
267 | | |
268 | | #ifndef SF_FIRMLINK |
269 | | # define SF_FIRMLINK 0x00800000 |
270 | | #endif |
271 | | |
272 | | #ifndef SF_DATALESS |
273 | | # define SF_DATALESS 0x40000000 |
274 | | #endif |
275 | | |
276 | | #if defined(__APPLE__) && !defined(SF_SUPPORTED) |
277 | | /* On older macOS versions the definition of SF_SUPPORTED is different |
278 | | * from that on newer versions. |
279 | | * |
280 | | * Provide a consistent experience by redefining. |
281 | | * |
282 | | * None of bit bits set in the actual SF_SUPPORTED but not in this |
283 | | * definition are defined on these versions of macOS. |
284 | | */ |
285 | | # undef SF_SETTABLE |
286 | | # define SF_SUPPORTED 0x009f0000 |
287 | | # define SF_SETTABLE 0x3fff0000 |
288 | | # define SF_SYNTHETIC 0xc0000000 |
289 | | #endif |
290 | | |
291 | | |
292 | | static mode_t |
293 | | _PyLong_AsMode_t(PyObject *op) |
294 | 16 | { |
295 | 16 | unsigned long value; |
296 | 16 | mode_t mode; |
297 | | |
298 | 16 | if (PyLong_Check(op)) { |
299 | 16 | value = PyLong_AsUnsignedLong(op); |
300 | 16 | } |
301 | 0 | else { |
302 | 0 | op = PyNumber_Index(op); |
303 | 0 | if (op == NULL) { |
304 | 0 | return (mode_t)-1; |
305 | 0 | } |
306 | 0 | value = PyLong_AsUnsignedLong(op); |
307 | 0 | Py_DECREF(op); |
308 | 0 | } |
309 | | |
310 | 16 | if ((value == (unsigned long)-1) && PyErr_Occurred()) { |
311 | 0 | return (mode_t)-1; |
312 | 0 | } |
313 | | |
314 | 16 | mode = (mode_t)value; |
315 | 16 | if ((unsigned long)mode != value) { |
316 | 0 | PyErr_SetString(PyExc_OverflowError, "mode out of range"); |
317 | 0 | return (mode_t)-1; |
318 | 0 | } |
319 | 16 | return mode; |
320 | 16 | } |
321 | | |
322 | | |
323 | | #define stat_S_ISFUNC(isfunc, doc) \ |
324 | | static PyObject * \ |
325 | | stat_ ##isfunc (PyObject *self, PyObject *omode) \ |
326 | 16 | { \ |
327 | 16 | mode_t mode = _PyLong_AsMode_t(omode); \ |
328 | 16 | if ((mode == (mode_t)-1) && PyErr_Occurred()) \ |
329 | 16 | return NULL; \ |
330 | 16 | return PyBool_FromLong(isfunc(mode)); \ |
331 | 16 | } \ Line | Count | Source | 326 | 16 | { \ | 327 | 16 | mode_t mode = _PyLong_AsMode_t(omode); \ | 328 | 16 | if ((mode == (mode_t)-1) && PyErr_Occurred()) \ | 329 | 16 | return NULL; \ | 330 | 16 | return PyBool_FromLong(isfunc(mode)); \ | 331 | 16 | } \ |
Unexecuted instantiation: _stat.c:stat_S_ISCHR Unexecuted instantiation: _stat.c:stat_S_ISBLK Unexecuted instantiation: _stat.c:stat_S_ISREG Unexecuted instantiation: _stat.c:stat_S_ISFIFO Unexecuted instantiation: _stat.c:stat_S_ISLNK Unexecuted instantiation: _stat.c:stat_S_ISSOCK Unexecuted instantiation: _stat.c:stat_S_ISDOOR Unexecuted instantiation: _stat.c:stat_S_ISPORT Unexecuted instantiation: _stat.c:stat_S_ISWHT |
332 | | PyDoc_STRVAR(stat_ ## isfunc ## _doc, doc) |
333 | | |
334 | 16 | stat_S_ISFUNC(S_ISDIR, |
335 | | "S_ISDIR(mode) -> bool\n\n" |
336 | | "Return True if mode is from a directory."); |
337 | | |
338 | 0 | stat_S_ISFUNC(S_ISCHR, |
339 | | "S_ISCHR(mode) -> bool\n\n" |
340 | | "Return True if mode is from a character special device file."); |
341 | | |
342 | 0 | stat_S_ISFUNC(S_ISBLK, |
343 | | "S_ISBLK(mode) -> bool\n\n" |
344 | | "Return True if mode is from a block special device file."); |
345 | | |
346 | 0 | stat_S_ISFUNC(S_ISREG, |
347 | | "S_ISREG(mode) -> bool\n\n" |
348 | | "Return True if mode is from a regular file."); |
349 | | |
350 | 0 | stat_S_ISFUNC(S_ISFIFO, |
351 | | "S_ISFIFO(mode) -> bool\n\n" |
352 | | "Return True if mode is from a FIFO (named pipe)."); |
353 | | |
354 | 0 | stat_S_ISFUNC(S_ISLNK, |
355 | | "S_ISLNK(mode) -> bool\n\n" |
356 | | "Return True if mode is from a symbolic link."); |
357 | | |
358 | 0 | stat_S_ISFUNC(S_ISSOCK, |
359 | | "S_ISSOCK(mode) -> bool\n\n" |
360 | | "Return True if mode is from a socket."); |
361 | | |
362 | 0 | stat_S_ISFUNC(S_ISDOOR, |
363 | | "S_ISDOOR(mode) -> bool\n\n" |
364 | | "Return True if mode is from a door."); |
365 | | |
366 | 0 | stat_S_ISFUNC(S_ISPORT, |
367 | | "S_ISPORT(mode) -> bool\n\n" |
368 | | "Return True if mode is from an event port."); |
369 | | |
370 | 0 | stat_S_ISFUNC(S_ISWHT, |
371 | | "S_ISWHT(mode) -> bool\n\n" |
372 | | "Return True if mode is from a whiteout."); |
373 | | |
374 | | |
375 | | PyDoc_STRVAR(stat_S_IMODE_doc, |
376 | | "Return the portion of the file's mode that can be set by os.chmod()."); |
377 | | |
378 | | static PyObject * |
379 | | stat_S_IMODE(PyObject *self, PyObject *omode) |
380 | 0 | { |
381 | 0 | mode_t mode = _PyLong_AsMode_t(omode); |
382 | 0 | if ((mode == (mode_t)-1) && PyErr_Occurred()) |
383 | 0 | return NULL; |
384 | 0 | return PyLong_FromUnsignedLong(mode & S_IMODE); |
385 | 0 | } |
386 | | |
387 | | |
388 | | PyDoc_STRVAR(stat_S_IFMT_doc, |
389 | | "Return the portion of the file's mode that describes the file type."); |
390 | | |
391 | | static PyObject * |
392 | | stat_S_IFMT(PyObject *self, PyObject *omode) |
393 | 0 | { |
394 | 0 | mode_t mode = _PyLong_AsMode_t(omode); |
395 | 0 | if ((mode == (mode_t)-1) && PyErr_Occurred()) |
396 | 0 | return NULL; |
397 | 0 | return PyLong_FromUnsignedLong(mode & S_IFMT); |
398 | 0 | } |
399 | | |
400 | | /* file type chars according to |
401 | | http://en.wikibooks.org/wiki/C_Programming/POSIX_Reference/sys/stat.h */ |
402 | | |
403 | | static char |
404 | | filetype(mode_t mode) |
405 | 0 | { |
406 | | /* common cases first */ |
407 | 0 | if (S_ISREG(mode)) return '-'; |
408 | 0 | if (S_ISDIR(mode)) return 'd'; |
409 | 0 | if (S_ISLNK(mode)) return 'l'; |
410 | | /* special files */ |
411 | 0 | if (S_ISBLK(mode)) return 'b'; |
412 | 0 | if (S_ISCHR(mode)) return 'c'; |
413 | 0 | if (S_ISFIFO(mode)) return 'p'; |
414 | 0 | if (S_ISSOCK(mode)) return 's'; |
415 | | /* non-standard types */ |
416 | 0 | if (S_ISDOOR(mode)) return 'D'; |
417 | 0 | if (S_ISPORT(mode)) return 'P'; |
418 | 0 | if (S_ISWHT(mode)) return 'w'; |
419 | | /* unknown */ |
420 | 0 | return '?'; |
421 | 0 | } |
422 | | |
423 | | static void |
424 | | fileperm(mode_t mode, char *buf) |
425 | 0 | { |
426 | 0 | buf[0] = mode & S_IRUSR ? 'r' : '-'; |
427 | 0 | buf[1] = mode & S_IWUSR ? 'w' : '-'; |
428 | 0 | if (mode & S_ISUID) { |
429 | 0 | buf[2] = mode & S_IXUSR ? 's' : 'S'; |
430 | 0 | } else { |
431 | 0 | buf[2] = mode & S_IXUSR ? 'x' : '-'; |
432 | 0 | } |
433 | 0 | buf[3] = mode & S_IRGRP ? 'r' : '-'; |
434 | 0 | buf[4] = mode & S_IWGRP ? 'w' : '-'; |
435 | 0 | if (mode & S_ISGID) { |
436 | 0 | buf[5] = mode & S_IXGRP ? 's' : 'S'; |
437 | 0 | } else { |
438 | 0 | buf[5] = mode & S_IXGRP ? 'x' : '-'; |
439 | 0 | } |
440 | 0 | buf[6] = mode & S_IROTH ? 'r' : '-'; |
441 | 0 | buf[7] = mode & S_IWOTH ? 'w' : '-'; |
442 | 0 | if (mode & S_ISVTX) { |
443 | 0 | buf[8] = mode & S_IXOTH ? 't' : 'T'; |
444 | 0 | } else { |
445 | 0 | buf[8] = mode & S_IXOTH ? 'x' : '-'; |
446 | 0 | } |
447 | 0 | } |
448 | | |
449 | | PyDoc_STRVAR(stat_filemode_doc, |
450 | | "Convert a file's mode to a string of the form '-rwxrwxrwx'"); |
451 | | |
452 | | static PyObject * |
453 | | stat_filemode(PyObject *self, PyObject *omode) |
454 | 0 | { |
455 | 0 | char buf[10]; |
456 | 0 | mode_t mode; |
457 | |
|
458 | 0 | mode = _PyLong_AsMode_t(omode); |
459 | 0 | if ((mode == (mode_t)-1) && PyErr_Occurred()) |
460 | 0 | return NULL; |
461 | | |
462 | 0 | buf[0] = filetype(mode); |
463 | 0 | fileperm(mode, &buf[1]); |
464 | 0 | return PyUnicode_FromStringAndSize(buf, 10); |
465 | 0 | } |
466 | | |
467 | | |
468 | | static PyMethodDef stat_methods[] = { |
469 | | {"S_ISDIR", stat_S_ISDIR, METH_O, stat_S_ISDIR_doc}, |
470 | | {"S_ISCHR", stat_S_ISCHR, METH_O, stat_S_ISCHR_doc}, |
471 | | {"S_ISBLK", stat_S_ISBLK, METH_O, stat_S_ISBLK_doc}, |
472 | | {"S_ISREG", stat_S_ISREG, METH_O, stat_S_ISREG_doc}, |
473 | | {"S_ISFIFO", stat_S_ISFIFO, METH_O, stat_S_ISFIFO_doc}, |
474 | | {"S_ISLNK", stat_S_ISLNK, METH_O, stat_S_ISLNK_doc}, |
475 | | {"S_ISSOCK", stat_S_ISSOCK, METH_O, stat_S_ISSOCK_doc}, |
476 | | {"S_ISDOOR", stat_S_ISDOOR, METH_O, stat_S_ISDOOR_doc}, |
477 | | {"S_ISPORT", stat_S_ISPORT, METH_O, stat_S_ISPORT_doc}, |
478 | | {"S_ISWHT", stat_S_ISWHT, METH_O, stat_S_ISWHT_doc}, |
479 | | {"S_IMODE", stat_S_IMODE, METH_O, stat_S_IMODE_doc}, |
480 | | {"S_IFMT", stat_S_IFMT, METH_O, stat_S_IFMT_doc}, |
481 | | {"filemode", stat_filemode, METH_O, stat_filemode_doc}, |
482 | | {NULL, NULL} /* sentinel */ |
483 | | }; |
484 | | |
485 | | |
486 | | PyDoc_STRVAR(module_doc, |
487 | | "S_IFMT_: file type bits\n\ |
488 | | S_IFDIR: directory\n\ |
489 | | S_IFCHR: character device\n\ |
490 | | S_IFBLK: block device\n\ |
491 | | S_IFREG: regular file\n\ |
492 | | S_IFIFO: fifo (named pipe)\n\ |
493 | | S_IFLNK: symbolic link\n\ |
494 | | S_IFSOCK: socket file\n\ |
495 | | S_IFDOOR: door\n\ |
496 | | S_IFPORT: event port\n\ |
497 | | S_IFWHT: whiteout\n\ |
498 | | \n" |
499 | | |
500 | | "S_ISUID: set UID bit\n\ |
501 | | S_ISGID: set GID bit\n\ |
502 | | S_ENFMT: file locking enforcement\n\ |
503 | | S_ISVTX: sticky bit\n\ |
504 | | S_IREAD: Unix V7 synonym for S_IRUSR\n\ |
505 | | S_IWRITE: Unix V7 synonym for S_IWUSR\n\ |
506 | | S_IEXEC: Unix V7 synonym for S_IXUSR\n\ |
507 | | S_IRWXU: mask for owner permissions\n\ |
508 | | S_IRUSR: read by owner\n\ |
509 | | S_IWUSR: write by owner\n\ |
510 | | S_IXUSR: execute by owner\n\ |
511 | | S_IRWXG: mask for group permissions\n\ |
512 | | S_IRGRP: read by group\n\ |
513 | | S_IWGRP: write by group\n\ |
514 | | S_IXGRP: execute by group\n\ |
515 | | S_IRWXO: mask for others (not in group) permissions\n\ |
516 | | S_IROTH: read by others\n\ |
517 | | S_IWOTH: write by others\n\ |
518 | | S_IXOTH: execute by others\n\ |
519 | | \n" |
520 | | |
521 | | "UF_SETTABLE: mask of owner changeable flags\n\ |
522 | | UF_NODUMP: do not dump file\n\ |
523 | | UF_IMMUTABLE: file may not be changed\n\ |
524 | | UF_APPEND: file may only be appended to\n\ |
525 | | UF_OPAQUE: directory is opaque when viewed through a union stack\n\ |
526 | | UF_NOUNLINK: file may not be renamed or deleted\n\ |
527 | | UF_COMPRESSED: macOS: file is hfs-compressed\n\ |
528 | | UF_TRACKED: used for dealing with document IDs\n\ |
529 | | UF_DATAVAULT: entitlement required for reading and writing\n\ |
530 | | UF_HIDDEN: macOS: file should not be displayed\n\ |
531 | | SF_SETTABLE: mask of super user changeable flags\n\ |
532 | | SF_ARCHIVED: file may be archived\n\ |
533 | | SF_IMMUTABLE: file may not be changed\n\ |
534 | | SF_APPEND: file may only be appended to\n\ |
535 | | SF_RESTRICTED: entitlement required for writing\n\ |
536 | | SF_NOUNLINK: file may not be renamed or deleted\n\ |
537 | | SF_SNAPSHOT: file is a snapshot file\n\ |
538 | | SF_FIRMLINK: file is a firmlink\n\ |
539 | | SF_DATALESS: file is a dataless object\n\ |
540 | | \n\ |
541 | | On macOS:\n\ |
542 | | SF_SUPPORTED: mask of super user supported flags\n\ |
543 | | SF_SYNTHETIC: mask of read-only synthetic flags\n\ |
544 | | \n" |
545 | | |
546 | | "ST_MODE\n\ |
547 | | ST_INO\n\ |
548 | | ST_DEV\n\ |
549 | | ST_NLINK\n\ |
550 | | ST_UID\n\ |
551 | | ST_GID\n\ |
552 | | ST_SIZE\n\ |
553 | | ST_ATIME\n\ |
554 | | ST_MTIME\n\ |
555 | | ST_CTIME\n\ |
556 | | \n" |
557 | | |
558 | | "FILE_ATTRIBUTE_*: Windows file attribute constants\n\ |
559 | | (only present on Windows)\n\ |
560 | | "); |
561 | | |
562 | | |
563 | | static int |
564 | | stat_exec(PyObject *module) |
565 | 16 | { |
566 | 16 | #define ADD_INT_MACRO(module, macro) \ |
567 | 752 | do { \ |
568 | 752 | if (PyModule_AddIntConstant(module, #macro, macro) < 0) { \ |
569 | 0 | return -1; \ |
570 | 0 | } \ |
571 | 752 | } while (0) |
572 | | |
573 | 16 | ADD_INT_MACRO(module, S_IFDIR); |
574 | 16 | ADD_INT_MACRO(module, S_IFCHR); |
575 | 16 | ADD_INT_MACRO(module, S_IFBLK); |
576 | 16 | ADD_INT_MACRO(module, S_IFREG); |
577 | 16 | ADD_INT_MACRO(module, S_IFIFO); |
578 | 16 | ADD_INT_MACRO(module, S_IFLNK); |
579 | 16 | ADD_INT_MACRO(module, S_IFSOCK); |
580 | 16 | ADD_INT_MACRO(module, S_IFDOOR); |
581 | 16 | ADD_INT_MACRO(module, S_IFPORT); |
582 | 16 | ADD_INT_MACRO(module, S_IFWHT); |
583 | | |
584 | 16 | ADD_INT_MACRO(module, S_ISUID); |
585 | 16 | ADD_INT_MACRO(module, S_ISGID); |
586 | 16 | ADD_INT_MACRO(module, S_ISVTX); |
587 | 16 | ADD_INT_MACRO(module, S_ENFMT); |
588 | | |
589 | 16 | ADD_INT_MACRO(module, S_IREAD); |
590 | 16 | ADD_INT_MACRO(module, S_IWRITE); |
591 | 16 | ADD_INT_MACRO(module, S_IEXEC); |
592 | | |
593 | 16 | ADD_INT_MACRO(module, S_IRWXU); |
594 | 16 | ADD_INT_MACRO(module, S_IRUSR); |
595 | 16 | ADD_INT_MACRO(module, S_IWUSR); |
596 | 16 | ADD_INT_MACRO(module, S_IXUSR); |
597 | | |
598 | 16 | ADD_INT_MACRO(module, S_IRWXG); |
599 | 16 | ADD_INT_MACRO(module, S_IRGRP); |
600 | 16 | ADD_INT_MACRO(module, S_IWGRP); |
601 | 16 | ADD_INT_MACRO(module, S_IXGRP); |
602 | | |
603 | 16 | ADD_INT_MACRO(module, S_IRWXO); |
604 | 16 | ADD_INT_MACRO(module, S_IROTH); |
605 | 16 | ADD_INT_MACRO(module, S_IWOTH); |
606 | 16 | ADD_INT_MACRO(module, S_IXOTH); |
607 | | |
608 | 16 | ADD_INT_MACRO(module, UF_SETTABLE); |
609 | 16 | ADD_INT_MACRO(module, UF_NODUMP); |
610 | 16 | ADD_INT_MACRO(module, UF_IMMUTABLE); |
611 | 16 | ADD_INT_MACRO(module, UF_APPEND); |
612 | 16 | ADD_INT_MACRO(module, UF_OPAQUE); |
613 | 16 | ADD_INT_MACRO(module, UF_NOUNLINK); |
614 | 16 | ADD_INT_MACRO(module, UF_COMPRESSED); |
615 | 16 | ADD_INT_MACRO(module, UF_TRACKED); |
616 | 16 | ADD_INT_MACRO(module, UF_DATAVAULT); |
617 | 16 | ADD_INT_MACRO(module, UF_HIDDEN); |
618 | 16 | ADD_INT_MACRO(module, SF_SETTABLE); |
619 | 16 | ADD_INT_MACRO(module, SF_ARCHIVED); |
620 | 16 | ADD_INT_MACRO(module, SF_IMMUTABLE); |
621 | 16 | ADD_INT_MACRO(module, SF_APPEND); |
622 | 16 | ADD_INT_MACRO(module, SF_NOUNLINK); |
623 | 16 | ADD_INT_MACRO(module, SF_SNAPSHOT); |
624 | 16 | ADD_INT_MACRO(module, SF_FIRMLINK); |
625 | 16 | ADD_INT_MACRO(module, SF_DATALESS); |
626 | | |
627 | | #ifdef SF_SUPPORTED |
628 | | ADD_INT_MACRO(module, SF_SUPPORTED); |
629 | | #endif |
630 | | #ifdef SF_SYNTHETIC |
631 | | ADD_INT_MACRO(module, SF_SYNTHETIC); |
632 | | #endif |
633 | | |
634 | | |
635 | 16 | const char* st_constants[] = { |
636 | 16 | "ST_MODE", |
637 | 16 | "ST_INO", |
638 | 16 | "ST_DEV", |
639 | 16 | "ST_NLINK", |
640 | 16 | "ST_UID", |
641 | 16 | "ST_GID", |
642 | 16 | "ST_SIZE", |
643 | 16 | "ST_ATIME", |
644 | 16 | "ST_MTIME", |
645 | 16 | "ST_CTIME" |
646 | 16 | }; |
647 | | |
648 | 176 | for (int i = 0; i < (int)Py_ARRAY_LENGTH(st_constants); i++) { |
649 | 160 | if (PyModule_AddIntConstant(module, st_constants[i], i) < 0) { |
650 | 0 | return -1; |
651 | 0 | } |
652 | 160 | } |
653 | | |
654 | | #ifdef MS_WINDOWS |
655 | | ADD_INT_MACRO(module, FILE_ATTRIBUTE_ARCHIVE); |
656 | | ADD_INT_MACRO(module, FILE_ATTRIBUTE_COMPRESSED); |
657 | | ADD_INT_MACRO(module, FILE_ATTRIBUTE_DEVICE); |
658 | | ADD_INT_MACRO(module, FILE_ATTRIBUTE_DIRECTORY); |
659 | | ADD_INT_MACRO(module, FILE_ATTRIBUTE_ENCRYPTED); |
660 | | ADD_INT_MACRO(module, FILE_ATTRIBUTE_HIDDEN); |
661 | | ADD_INT_MACRO(module, FILE_ATTRIBUTE_INTEGRITY_STREAM); |
662 | | ADD_INT_MACRO(module, FILE_ATTRIBUTE_NORMAL); |
663 | | ADD_INT_MACRO(module, FILE_ATTRIBUTE_NOT_CONTENT_INDEXED); |
664 | | ADD_INT_MACRO(module, FILE_ATTRIBUTE_NO_SCRUB_DATA); |
665 | | ADD_INT_MACRO(module, FILE_ATTRIBUTE_OFFLINE); |
666 | | ADD_INT_MACRO(module, FILE_ATTRIBUTE_READONLY); |
667 | | ADD_INT_MACRO(module, FILE_ATTRIBUTE_REPARSE_POINT); |
668 | | ADD_INT_MACRO(module, FILE_ATTRIBUTE_SPARSE_FILE); |
669 | | ADD_INT_MACRO(module, FILE_ATTRIBUTE_SYSTEM); |
670 | | ADD_INT_MACRO(module, FILE_ATTRIBUTE_TEMPORARY); |
671 | | ADD_INT_MACRO(module, FILE_ATTRIBUTE_VIRTUAL); |
672 | | |
673 | | if (PyModule_Add(module, "IO_REPARSE_TAG_SYMLINK", |
674 | | PyLong_FromUnsignedLong(IO_REPARSE_TAG_SYMLINK)) < 0) { |
675 | | return -1; |
676 | | } |
677 | | if (PyModule_Add(module, "IO_REPARSE_TAG_MOUNT_POINT", |
678 | | PyLong_FromUnsignedLong(IO_REPARSE_TAG_MOUNT_POINT)) < 0) { |
679 | | return -1; |
680 | | } |
681 | | if (PyModule_Add(module, "IO_REPARSE_TAG_APPEXECLINK", |
682 | | PyLong_FromUnsignedLong(IO_REPARSE_TAG_APPEXECLINK)) < 0) { |
683 | | return -1; |
684 | | } |
685 | | #endif |
686 | | |
687 | 16 | return 0; |
688 | 16 | } |
689 | | |
690 | | |
691 | | static PyModuleDef_Slot stat_slots[] = { |
692 | | {Py_mod_exec, stat_exec}, |
693 | | {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, |
694 | | {Py_mod_gil, Py_MOD_GIL_NOT_USED}, |
695 | | {0, NULL} |
696 | | }; |
697 | | |
698 | | |
699 | | static struct PyModuleDef statmodule = { |
700 | | PyModuleDef_HEAD_INIT, |
701 | | .m_name = "_stat", |
702 | | .m_doc = module_doc, |
703 | | .m_size = 0, |
704 | | .m_methods = stat_methods, |
705 | | .m_slots = stat_slots, |
706 | | }; |
707 | | |
708 | | |
709 | | PyMODINIT_FUNC |
710 | | PyInit__stat(void) |
711 | 16 | { |
712 | 16 | return PyModuleDef_Init(&statmodule); |
713 | 16 | } |