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