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