posixmodule.c revision 6b8f0c892a075488fb6799bf5dbb9ed6743d31e2
1 2/* POSIX module implementation */ 3 4/* This file is also used for Windows NT/MS-Win. In that case the 5 module actually calls itself 'nt', not 'posix', and a few 6 functions are either unimplemented or implemented differently. The source 7 assumes that for Windows NT, the macro 'MS_WINDOWS' is defined independent 8 of the compiler used. Different compilers define their own feature 9 test macro, e.g. '_MSC_VER'. */ 10 11 12 13#ifdef __APPLE__ 14 /* 15 * Step 1 of support for weak-linking a number of symbols existing on 16 * OSX 10.4 and later, see the comment in the #ifdef __APPLE__ block 17 * at the end of this file for more information. 18 */ 19# pragma weak lchown 20# pragma weak statvfs 21# pragma weak fstatvfs 22 23#endif /* __APPLE__ */ 24 25#define PY_SSIZE_T_CLEAN 26 27#include "Python.h" 28#include "structmember.h" 29#ifndef MS_WINDOWS 30#include "posixmodule.h" 31#else 32#include "winreparse.h" 33#endif 34 35#ifdef __cplusplus 36extern "C" { 37#endif 38 39PyDoc_STRVAR(posix__doc__, 40"This module provides access to operating system functionality that is\n\ 41standardized by the C Standard and the POSIX standard (a thinly\n\ 42disguised Unix interface). Refer to the library manual and\n\ 43corresponding Unix manual entries for more information on calls."); 44 45 46#ifdef HAVE_SYS_UIO_H 47#include <sys/uio.h> 48#endif 49 50#ifdef HAVE_SYS_TYPES_H 51#include <sys/types.h> 52#endif /* HAVE_SYS_TYPES_H */ 53 54#ifdef HAVE_SYS_STAT_H 55#include <sys/stat.h> 56#endif /* HAVE_SYS_STAT_H */ 57 58#ifdef HAVE_SYS_WAIT_H 59#include <sys/wait.h> /* For WNOHANG */ 60#endif 61 62#ifdef HAVE_SIGNAL_H 63#include <signal.h> 64#endif 65 66#ifdef HAVE_FCNTL_H 67#include <fcntl.h> 68#endif /* HAVE_FCNTL_H */ 69 70#ifdef HAVE_GRP_H 71#include <grp.h> 72#endif 73 74#ifdef HAVE_SYSEXITS_H 75#include <sysexits.h> 76#endif /* HAVE_SYSEXITS_H */ 77 78#ifdef HAVE_SYS_LOADAVG_H 79#include <sys/loadavg.h> 80#endif 81 82#ifdef HAVE_LANGINFO_H 83#include <langinfo.h> 84#endif 85 86#ifdef HAVE_SYS_SENDFILE_H 87#include <sys/sendfile.h> 88#endif 89 90#ifdef HAVE_SCHED_H 91#include <sched.h> 92#endif 93 94#if !defined(CPU_ALLOC) && defined(HAVE_SCHED_SETAFFINITY) 95#undef HAVE_SCHED_SETAFFINITY 96#endif 97 98#if defined(HAVE_SYS_XATTR_H) && defined(__GLIBC__) && !defined(__FreeBSD_kernel__) && !defined(__GNU__) 99#define USE_XATTRS 100#endif 101 102#ifdef USE_XATTRS 103#include <sys/xattr.h> 104#endif 105 106#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__) 107#ifdef HAVE_SYS_SOCKET_H 108#include <sys/socket.h> 109#endif 110#endif 111 112#ifdef HAVE_DLFCN_H 113#include <dlfcn.h> 114#endif 115 116#ifdef __hpux 117#include <sys/mpctl.h> 118#endif 119 120#if defined(__DragonFly__) || \ 121 defined(__OpenBSD__) || \ 122 defined(__FreeBSD__) || \ 123 defined(__NetBSD__) || \ 124 defined(__APPLE__) 125#include <sys/sysctl.h> 126#endif 127 128#if defined(MS_WINDOWS) 129# define TERMSIZE_USE_CONIO 130#elif defined(HAVE_SYS_IOCTL_H) 131# include <sys/ioctl.h> 132# if defined(HAVE_TERMIOS_H) 133# include <termios.h> 134# endif 135# if defined(TIOCGWINSZ) 136# define TERMSIZE_USE_IOCTL 137# endif 138#endif /* MS_WINDOWS */ 139 140/* Various compilers have only certain posix functions */ 141/* XXX Gosh I wish these were all moved into pyconfig.h */ 142#if defined(__WATCOMC__) && !defined(__QNX__) /* Watcom compiler */ 143#define HAVE_OPENDIR 1 144#define HAVE_SYSTEM 1 145#include <process.h> 146#else 147#ifdef _MSC_VER /* Microsoft compiler */ 148#define HAVE_GETPPID 1 149#define HAVE_GETLOGIN 1 150#define HAVE_SPAWNV 1 151#define HAVE_EXECV 1 152#define HAVE_PIPE 1 153#define HAVE_SYSTEM 1 154#define HAVE_CWAIT 1 155#define HAVE_FSYNC 1 156#define fsync _commit 157#else 158/* Unix functions that the configure script doesn't check for */ 159#define HAVE_EXECV 1 160#define HAVE_FORK 1 161#if defined(__USLC__) && defined(__SCO_VERSION__) /* SCO UDK Compiler */ 162#define HAVE_FORK1 1 163#endif 164#define HAVE_GETEGID 1 165#define HAVE_GETEUID 1 166#define HAVE_GETGID 1 167#define HAVE_GETPPID 1 168#define HAVE_GETUID 1 169#define HAVE_KILL 1 170#define HAVE_OPENDIR 1 171#define HAVE_PIPE 1 172#define HAVE_SYSTEM 1 173#define HAVE_WAIT 1 174#define HAVE_TTYNAME 1 175#endif /* _MSC_VER */ 176#endif /* ! __WATCOMC__ || __QNX__ */ 177 178 179/*[clinic input] 180# one of the few times we lie about this name! 181module os 182[clinic start generated code]*/ 183/*[clinic end generated code: output=da39a3ee5e6b4b0d input=94a0f0f978acae17]*/ 184 185#ifndef _MSC_VER 186 187#if defined(__sgi)&&_COMPILER_VERSION>=700 188/* declare ctermid_r if compiling with MIPSPro 7.x in ANSI C mode 189 (default) */ 190extern char *ctermid_r(char *); 191#endif 192 193#ifndef HAVE_UNISTD_H 194#if defined(PYCC_VACPP) 195extern int mkdir(char *); 196#else 197#if ( defined(__WATCOMC__) || defined(_MSC_VER) ) && !defined(__QNX__) 198extern int mkdir(const char *); 199#else 200extern int mkdir(const char *, mode_t); 201#endif 202#endif 203#if defined(__IBMC__) || defined(__IBMCPP__) 204extern int chdir(char *); 205extern int rmdir(char *); 206#else 207extern int chdir(const char *); 208extern int rmdir(const char *); 209#endif 210extern int chmod(const char *, mode_t); 211/*#ifdef HAVE_FCHMOD 212extern int fchmod(int, mode_t); 213#endif*/ 214/*#ifdef HAVE_LCHMOD 215extern int lchmod(const char *, mode_t); 216#endif*/ 217extern int chown(const char *, uid_t, gid_t); 218extern char *getcwd(char *, int); 219extern char *strerror(int); 220extern int link(const char *, const char *); 221extern int rename(const char *, const char *); 222extern int stat(const char *, struct stat *); 223extern int unlink(const char *); 224#ifdef HAVE_SYMLINK 225extern int symlink(const char *, const char *); 226#endif /* HAVE_SYMLINK */ 227#ifdef HAVE_LSTAT 228extern int lstat(const char *, struct stat *); 229#endif /* HAVE_LSTAT */ 230#endif /* !HAVE_UNISTD_H */ 231 232#endif /* !_MSC_VER */ 233 234#ifdef HAVE_UTIME_H 235#include <utime.h> 236#endif /* HAVE_UTIME_H */ 237 238#ifdef HAVE_SYS_UTIME_H 239#include <sys/utime.h> 240#define HAVE_UTIME_H /* pretend we do for the rest of this file */ 241#endif /* HAVE_SYS_UTIME_H */ 242 243#ifdef HAVE_SYS_TIMES_H 244#include <sys/times.h> 245#endif /* HAVE_SYS_TIMES_H */ 246 247#ifdef HAVE_SYS_PARAM_H 248#include <sys/param.h> 249#endif /* HAVE_SYS_PARAM_H */ 250 251#ifdef HAVE_SYS_UTSNAME_H 252#include <sys/utsname.h> 253#endif /* HAVE_SYS_UTSNAME_H */ 254 255#ifdef HAVE_DIRENT_H 256#include <dirent.h> 257#define NAMLEN(dirent) strlen((dirent)->d_name) 258#else 259#if defined(__WATCOMC__) && !defined(__QNX__) 260#include <direct.h> 261#define NAMLEN(dirent) strlen((dirent)->d_name) 262#else 263#define dirent direct 264#define NAMLEN(dirent) (dirent)->d_namlen 265#endif 266#ifdef HAVE_SYS_NDIR_H 267#include <sys/ndir.h> 268#endif 269#ifdef HAVE_SYS_DIR_H 270#include <sys/dir.h> 271#endif 272#ifdef HAVE_NDIR_H 273#include <ndir.h> 274#endif 275#endif 276 277#ifdef _MSC_VER 278#ifdef HAVE_DIRECT_H 279#include <direct.h> 280#endif 281#ifdef HAVE_IO_H 282#include <io.h> 283#endif 284#ifdef HAVE_PROCESS_H 285#include <process.h> 286#endif 287#ifndef VOLUME_NAME_DOS 288#define VOLUME_NAME_DOS 0x0 289#endif 290#ifndef VOLUME_NAME_NT 291#define VOLUME_NAME_NT 0x2 292#endif 293#ifndef IO_REPARSE_TAG_SYMLINK 294#define IO_REPARSE_TAG_SYMLINK (0xA000000CL) 295#endif 296#ifndef IO_REPARSE_TAG_MOUNT_POINT 297#define IO_REPARSE_TAG_MOUNT_POINT (0xA0000003L) 298#endif 299#include "osdefs.h" 300#include <malloc.h> 301#include <windows.h> 302#include <shellapi.h> /* for ShellExecute() */ 303#include <lmcons.h> /* for UNLEN */ 304#ifdef SE_CREATE_SYMBOLIC_LINK_NAME /* Available starting with Vista */ 305#define HAVE_SYMLINK 306static int win32_can_symlink = 0; 307#endif 308#endif /* _MSC_VER */ 309 310#ifndef MAXPATHLEN 311#if defined(PATH_MAX) && PATH_MAX > 1024 312#define MAXPATHLEN PATH_MAX 313#else 314#define MAXPATHLEN 1024 315#endif 316#endif /* MAXPATHLEN */ 317 318#ifdef UNION_WAIT 319/* Emulate some macros on systems that have a union instead of macros */ 320 321#ifndef WIFEXITED 322#define WIFEXITED(u_wait) (!(u_wait).w_termsig && !(u_wait).w_coredump) 323#endif 324 325#ifndef WEXITSTATUS 326#define WEXITSTATUS(u_wait) (WIFEXITED(u_wait)?((u_wait).w_retcode):-1) 327#endif 328 329#ifndef WTERMSIG 330#define WTERMSIG(u_wait) ((u_wait).w_termsig) 331#endif 332 333#define WAIT_TYPE union wait 334#define WAIT_STATUS_INT(s) (s.w_status) 335 336#else /* !UNION_WAIT */ 337#define WAIT_TYPE int 338#define WAIT_STATUS_INT(s) (s) 339#endif /* UNION_WAIT */ 340 341/* Don't use the "_r" form if we don't need it (also, won't have a 342 prototype for it, at least on Solaris -- maybe others as well?). */ 343#if defined(HAVE_CTERMID_R) && defined(WITH_THREAD) 344#define USE_CTERMID_R 345#endif 346 347/* choose the appropriate stat and fstat functions and return structs */ 348#undef STAT 349#undef FSTAT 350#undef STRUCT_STAT 351#ifdef MS_WINDOWS 352# define STAT win32_stat 353# define LSTAT win32_lstat 354# define FSTAT _Py_fstat_noraise 355# define STRUCT_STAT struct _Py_stat_struct 356#else 357# define STAT stat 358# define LSTAT lstat 359# define FSTAT fstat 360# define STRUCT_STAT struct stat 361#endif 362 363#if defined(MAJOR_IN_MKDEV) 364#include <sys/mkdev.h> 365#else 366#if defined(MAJOR_IN_SYSMACROS) 367#include <sys/sysmacros.h> 368#endif 369#if defined(HAVE_MKNOD) && defined(HAVE_SYS_MKDEV_H) 370#include <sys/mkdev.h> 371#endif 372#endif 373 374#define DWORD_MAX 4294967295U 375 376#ifdef MS_WINDOWS 377#define INITFUNC PyInit_nt 378#define MODNAME "nt" 379#else 380#define INITFUNC PyInit_posix 381#define MODNAME "posix" 382#endif 383 384#ifdef MS_WINDOWS 385/* defined in fileutils.c */ 386PyAPI_FUNC(void) _Py_time_t_to_FILE_TIME(time_t, int, FILETIME *); 387PyAPI_FUNC(void) _Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *, 388 ULONG, struct _Py_stat_struct *); 389#endif 390 391#ifdef MS_WINDOWS 392static int 393win32_warn_bytes_api() 394{ 395 return PyErr_WarnEx(PyExc_DeprecationWarning, 396 "The Windows bytes API has been deprecated, " 397 "use Unicode filenames instead", 398 1); 399} 400#endif 401 402 403#ifndef MS_WINDOWS 404PyObject * 405_PyLong_FromUid(uid_t uid) 406{ 407 if (uid == (uid_t)-1) 408 return PyLong_FromLong(-1); 409 return PyLong_FromUnsignedLong(uid); 410} 411 412PyObject * 413_PyLong_FromGid(gid_t gid) 414{ 415 if (gid == (gid_t)-1) 416 return PyLong_FromLong(-1); 417 return PyLong_FromUnsignedLong(gid); 418} 419 420int 421_Py_Uid_Converter(PyObject *obj, void *p) 422{ 423 uid_t uid; 424 PyObject *index; 425 int overflow; 426 long result; 427 unsigned long uresult; 428 429 index = PyNumber_Index(obj); 430 if (index == NULL) { 431 PyErr_Format(PyExc_TypeError, 432 "uid should be integer, not %.200s", 433 Py_TYPE(obj)->tp_name); 434 return 0; 435 } 436 437 /* 438 * Handling uid_t is complicated for two reasons: 439 * * Although uid_t is (always?) unsigned, it still 440 * accepts -1. 441 * * We don't know its size in advance--it may be 442 * bigger than an int, or it may be smaller than 443 * a long. 444 * 445 * So a bit of defensive programming is in order. 446 * Start with interpreting the value passed 447 * in as a signed long and see if it works. 448 */ 449 450 result = PyLong_AsLongAndOverflow(index, &overflow); 451 452 if (!overflow) { 453 uid = (uid_t)result; 454 455 if (result == -1) { 456 if (PyErr_Occurred()) 457 goto fail; 458 /* It's a legitimate -1, we're done. */ 459 goto success; 460 } 461 462 /* Any other negative number is disallowed. */ 463 if (result < 0) 464 goto underflow; 465 466 /* Ensure the value wasn't truncated. */ 467 if (sizeof(uid_t) < sizeof(long) && 468 (long)uid != result) 469 goto underflow; 470 goto success; 471 } 472 473 if (overflow < 0) 474 goto underflow; 475 476 /* 477 * Okay, the value overflowed a signed long. If it 478 * fits in an *unsigned* long, it may still be okay, 479 * as uid_t may be unsigned long on this platform. 480 */ 481 uresult = PyLong_AsUnsignedLong(index); 482 if (PyErr_Occurred()) { 483 if (PyErr_ExceptionMatches(PyExc_OverflowError)) 484 goto overflow; 485 goto fail; 486 } 487 488 uid = (uid_t)uresult; 489 490 /* 491 * If uid == (uid_t)-1, the user actually passed in ULONG_MAX, 492 * but this value would get interpreted as (uid_t)-1 by chown 493 * and its siblings. That's not what the user meant! So we 494 * throw an overflow exception instead. (We already 495 * handled a real -1 with PyLong_AsLongAndOverflow() above.) 496 */ 497 if (uid == (uid_t)-1) 498 goto overflow; 499 500 /* Ensure the value wasn't truncated. */ 501 if (sizeof(uid_t) < sizeof(long) && 502 (unsigned long)uid != uresult) 503 goto overflow; 504 /* fallthrough */ 505 506success: 507 Py_DECREF(index); 508 *(uid_t *)p = uid; 509 return 1; 510 511underflow: 512 PyErr_SetString(PyExc_OverflowError, 513 "uid is less than minimum"); 514 goto fail; 515 516overflow: 517 PyErr_SetString(PyExc_OverflowError, 518 "uid is greater than maximum"); 519 /* fallthrough */ 520 521fail: 522 Py_DECREF(index); 523 return 0; 524} 525 526int 527_Py_Gid_Converter(PyObject *obj, void *p) 528{ 529 gid_t gid; 530 PyObject *index; 531 int overflow; 532 long result; 533 unsigned long uresult; 534 535 index = PyNumber_Index(obj); 536 if (index == NULL) { 537 PyErr_Format(PyExc_TypeError, 538 "gid should be integer, not %.200s", 539 Py_TYPE(obj)->tp_name); 540 return 0; 541 } 542 543 /* 544 * Handling gid_t is complicated for two reasons: 545 * * Although gid_t is (always?) unsigned, it still 546 * accepts -1. 547 * * We don't know its size in advance--it may be 548 * bigger than an int, or it may be smaller than 549 * a long. 550 * 551 * So a bit of defensive programming is in order. 552 * Start with interpreting the value passed 553 * in as a signed long and see if it works. 554 */ 555 556 result = PyLong_AsLongAndOverflow(index, &overflow); 557 558 if (!overflow) { 559 gid = (gid_t)result; 560 561 if (result == -1) { 562 if (PyErr_Occurred()) 563 goto fail; 564 /* It's a legitimate -1, we're done. */ 565 goto success; 566 } 567 568 /* Any other negative number is disallowed. */ 569 if (result < 0) { 570 goto underflow; 571 } 572 573 /* Ensure the value wasn't truncated. */ 574 if (sizeof(gid_t) < sizeof(long) && 575 (long)gid != result) 576 goto underflow; 577 goto success; 578 } 579 580 if (overflow < 0) 581 goto underflow; 582 583 /* 584 * Okay, the value overflowed a signed long. If it 585 * fits in an *unsigned* long, it may still be okay, 586 * as gid_t may be unsigned long on this platform. 587 */ 588 uresult = PyLong_AsUnsignedLong(index); 589 if (PyErr_Occurred()) { 590 if (PyErr_ExceptionMatches(PyExc_OverflowError)) 591 goto overflow; 592 goto fail; 593 } 594 595 gid = (gid_t)uresult; 596 597 /* 598 * If gid == (gid_t)-1, the user actually passed in ULONG_MAX, 599 * but this value would get interpreted as (gid_t)-1 by chown 600 * and its siblings. That's not what the user meant! So we 601 * throw an overflow exception instead. (We already 602 * handled a real -1 with PyLong_AsLongAndOverflow() above.) 603 */ 604 if (gid == (gid_t)-1) 605 goto overflow; 606 607 /* Ensure the value wasn't truncated. */ 608 if (sizeof(gid_t) < sizeof(long) && 609 (unsigned long)gid != uresult) 610 goto overflow; 611 /* fallthrough */ 612 613success: 614 Py_DECREF(index); 615 *(gid_t *)p = gid; 616 return 1; 617 618underflow: 619 PyErr_SetString(PyExc_OverflowError, 620 "gid is less than minimum"); 621 goto fail; 622 623overflow: 624 PyErr_SetString(PyExc_OverflowError, 625 "gid is greater than maximum"); 626 /* fallthrough */ 627 628fail: 629 Py_DECREF(index); 630 return 0; 631} 632#endif /* MS_WINDOWS */ 633 634 635#ifdef HAVE_LONG_LONG 636# define _PyLong_FromDev PyLong_FromLongLong 637#else 638# define _PyLong_FromDev PyLong_FromLong 639#endif 640 641 642#if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) 643static int 644_Py_Dev_Converter(PyObject *obj, void *p) 645{ 646#ifdef HAVE_LONG_LONG 647 *((dev_t *)p) = PyLong_AsUnsignedLongLong(obj); 648#else 649 *((dev_t *)p) = PyLong_AsUnsignedLong(obj); 650#endif 651 if (PyErr_Occurred()) 652 return 0; 653 return 1; 654} 655#endif /* HAVE_MKNOD && HAVE_MAKEDEV */ 656 657 658#ifdef AT_FDCWD 659/* 660 * Why the (int) cast? Solaris 10 defines AT_FDCWD as 0xffd19553 (-3041965); 661 * without the int cast, the value gets interpreted as uint (4291925331), 662 * which doesn't play nicely with all the initializer lines in this file that 663 * look like this: 664 * int dir_fd = DEFAULT_DIR_FD; 665 */ 666#define DEFAULT_DIR_FD (int)AT_FDCWD 667#else 668#define DEFAULT_DIR_FD (-100) 669#endif 670 671static int 672_fd_converter(PyObject *o, int *p, const char *allowed) 673{ 674 int overflow; 675 long long_value; 676 677 PyObject *index = PyNumber_Index(o); 678 if (index == NULL) { 679 PyErr_Format(PyExc_TypeError, 680 "argument should be %s, not %.200s", 681 allowed, Py_TYPE(o)->tp_name); 682 return 0; 683 } 684 685 long_value = PyLong_AsLongAndOverflow(index, &overflow); 686 Py_DECREF(index); 687 if (overflow > 0 || long_value > INT_MAX) { 688 PyErr_SetString(PyExc_OverflowError, 689 "fd is greater than maximum"); 690 return 0; 691 } 692 if (overflow < 0 || long_value < INT_MIN) { 693 PyErr_SetString(PyExc_OverflowError, 694 "fd is less than minimum"); 695 return 0; 696 } 697 698 *p = (int)long_value; 699 return 1; 700} 701 702static int 703dir_fd_converter(PyObject *o, void *p) 704{ 705 if (o == Py_None) { 706 *(int *)p = DEFAULT_DIR_FD; 707 return 1; 708 } 709 return _fd_converter(o, (int *)p, "integer"); 710} 711 712 713/* 714 * A PyArg_ParseTuple "converter" function 715 * that handles filesystem paths in the manner 716 * preferred by the os module. 717 * 718 * path_converter accepts (Unicode) strings and their 719 * subclasses, and bytes and their subclasses. What 720 * it does with the argument depends on the platform: 721 * 722 * * On Windows, if we get a (Unicode) string we 723 * extract the wchar_t * and return it; if we get 724 * bytes we extract the char * and return that. 725 * 726 * * On all other platforms, strings are encoded 727 * to bytes using PyUnicode_FSConverter, then we 728 * extract the char * from the bytes object and 729 * return that. 730 * 731 * path_converter also optionally accepts signed 732 * integers (representing open file descriptors) instead 733 * of path strings. 734 * 735 * Input fields: 736 * path.nullable 737 * If nonzero, the path is permitted to be None. 738 * path.allow_fd 739 * If nonzero, the path is permitted to be a file handle 740 * (a signed int) instead of a string. 741 * path.function_name 742 * If non-NULL, path_converter will use that as the name 743 * of the function in error messages. 744 * (If path.function_name is NULL it omits the function name.) 745 * path.argument_name 746 * If non-NULL, path_converter will use that as the name 747 * of the parameter in error messages. 748 * (If path.argument_name is NULL it uses "path".) 749 * 750 * Output fields: 751 * path.wide 752 * Points to the path if it was expressed as Unicode 753 * and was not encoded. (Only used on Windows.) 754 * path.narrow 755 * Points to the path if it was expressed as bytes, 756 * or it was Unicode and was encoded to bytes. 757 * path.fd 758 * Contains a file descriptor if path.accept_fd was true 759 * and the caller provided a signed integer instead of any 760 * sort of string. 761 * 762 * WARNING: if your "path" parameter is optional, and is 763 * unspecified, path_converter will never get called. 764 * So if you set allow_fd, you *MUST* initialize path.fd = -1 765 * yourself! 766 * path.length 767 * The length of the path in characters, if specified as 768 * a string. 769 * path.object 770 * The original object passed in. 771 * path.cleanup 772 * For internal use only. May point to a temporary object. 773 * (Pay no attention to the man behind the curtain.) 774 * 775 * At most one of path.wide or path.narrow will be non-NULL. 776 * If path was None and path.nullable was set, 777 * or if path was an integer and path.allow_fd was set, 778 * both path.wide and path.narrow will be NULL 779 * and path.length will be 0. 780 * 781 * path_converter takes care to not write to the path_t 782 * unless it's successful. However it must reset the 783 * "cleanup" field each time it's called. 784 * 785 * Use as follows: 786 * path_t path; 787 * memset(&path, 0, sizeof(path)); 788 * PyArg_ParseTuple(args, "O&", path_converter, &path); 789 * // ... use values from path ... 790 * path_cleanup(&path); 791 * 792 * (Note that if PyArg_Parse fails you don't need to call 793 * path_cleanup(). However it is safe to do so.) 794 */ 795typedef struct { 796 const char *function_name; 797 const char *argument_name; 798 int nullable; 799 int allow_fd; 800 wchar_t *wide; 801 char *narrow; 802 int fd; 803 Py_ssize_t length; 804 PyObject *object; 805 PyObject *cleanup; 806} path_t; 807 808#define PATH_T_INITIALIZE(function_name, argument_name, nullable, allow_fd) \ 809 {function_name, argument_name, nullable, allow_fd, NULL, NULL, -1, 0, NULL, NULL} 810 811static void 812path_cleanup(path_t *path) { 813 if (path->cleanup) { 814 Py_CLEAR(path->cleanup); 815 } 816} 817 818static int 819path_converter(PyObject *o, void *p) { 820 path_t *path = (path_t *)p; 821 PyObject *unicode, *bytes; 822 Py_ssize_t length; 823 char *narrow; 824 825#define FORMAT_EXCEPTION(exc, fmt) \ 826 PyErr_Format(exc, "%s%s" fmt, \ 827 path->function_name ? path->function_name : "", \ 828 path->function_name ? ": " : "", \ 829 path->argument_name ? path->argument_name : "path") 830 831 /* Py_CLEANUP_SUPPORTED support */ 832 if (o == NULL) { 833 path_cleanup(path); 834 return 1; 835 } 836 837 /* ensure it's always safe to call path_cleanup() */ 838 path->cleanup = NULL; 839 840 if (o == Py_None) { 841 if (!path->nullable) { 842 FORMAT_EXCEPTION(PyExc_TypeError, 843 "can't specify None for %s argument"); 844 return 0; 845 } 846 path->wide = NULL; 847 path->narrow = NULL; 848 path->length = 0; 849 path->object = o; 850 path->fd = -1; 851 return 1; 852 } 853 854 unicode = PyUnicode_FromObject(o); 855 if (unicode) { 856#ifdef MS_WINDOWS 857 wchar_t *wide; 858 859 wide = PyUnicode_AsUnicodeAndSize(unicode, &length); 860 if (!wide) { 861 Py_DECREF(unicode); 862 return 0; 863 } 864 if (length > 32767) { 865 FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows"); 866 Py_DECREF(unicode); 867 return 0; 868 } 869 if (wcslen(wide) != length) { 870 FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character"); 871 Py_DECREF(unicode); 872 return 0; 873 } 874 875 path->wide = wide; 876 path->narrow = NULL; 877 path->length = length; 878 path->object = o; 879 path->fd = -1; 880 path->cleanup = unicode; 881 return Py_CLEANUP_SUPPORTED; 882#else 883 int converted = PyUnicode_FSConverter(unicode, &bytes); 884 Py_DECREF(unicode); 885 if (!converted) 886 bytes = NULL; 887#endif 888 } 889 else { 890 PyErr_Clear(); 891 if (PyObject_CheckBuffer(o)) 892 bytes = PyBytes_FromObject(o); 893 else 894 bytes = NULL; 895 if (!bytes) { 896 PyErr_Clear(); 897 if (path->allow_fd) { 898 int fd; 899 int result = _fd_converter(o, &fd, 900 "string, bytes or integer"); 901 if (result) { 902 path->wide = NULL; 903 path->narrow = NULL; 904 path->length = 0; 905 path->object = o; 906 path->fd = fd; 907 return result; 908 } 909 } 910 } 911 } 912 913 if (!bytes) { 914 if (!PyErr_Occurred()) 915 FORMAT_EXCEPTION(PyExc_TypeError, "illegal type for %s parameter"); 916 return 0; 917 } 918 919#ifdef MS_WINDOWS 920 if (win32_warn_bytes_api()) { 921 Py_DECREF(bytes); 922 return 0; 923 } 924#endif 925 926 length = PyBytes_GET_SIZE(bytes); 927#ifdef MS_WINDOWS 928 if (length > MAX_PATH-1) { 929 FORMAT_EXCEPTION(PyExc_ValueError, "%s too long for Windows"); 930 Py_DECREF(bytes); 931 return 0; 932 } 933#endif 934 935 narrow = PyBytes_AS_STRING(bytes); 936 if ((size_t)length != strlen(narrow)) { 937 FORMAT_EXCEPTION(PyExc_ValueError, "embedded null character in %s"); 938 Py_DECREF(bytes); 939 return 0; 940 } 941 942 path->wide = NULL; 943 path->narrow = narrow; 944 path->length = length; 945 path->object = o; 946 path->fd = -1; 947 path->cleanup = bytes; 948 return Py_CLEANUP_SUPPORTED; 949} 950 951static void 952argument_unavailable_error(char *function_name, char *argument_name) { 953 PyErr_Format(PyExc_NotImplementedError, 954 "%s%s%s unavailable on this platform", 955 (function_name != NULL) ? function_name : "", 956 (function_name != NULL) ? ": ": "", 957 argument_name); 958} 959 960static int 961dir_fd_unavailable(PyObject *o, void *p) 962{ 963 int dir_fd; 964 if (!dir_fd_converter(o, &dir_fd)) 965 return 0; 966 if (dir_fd != DEFAULT_DIR_FD) { 967 argument_unavailable_error(NULL, "dir_fd"); 968 return 0; 969 } 970 *(int *)p = dir_fd; 971 return 1; 972} 973 974static int 975fd_specified(char *function_name, int fd) { 976 if (fd == -1) 977 return 0; 978 979 argument_unavailable_error(function_name, "fd"); 980 return 1; 981} 982 983static int 984follow_symlinks_specified(char *function_name, int follow_symlinks) { 985 if (follow_symlinks) 986 return 0; 987 988 argument_unavailable_error(function_name, "follow_symlinks"); 989 return 1; 990} 991 992static int 993path_and_dir_fd_invalid(char *function_name, path_t *path, int dir_fd) { 994 if (!path->narrow && !path->wide && (dir_fd != DEFAULT_DIR_FD)) { 995 PyErr_Format(PyExc_ValueError, 996 "%s: can't specify dir_fd without matching path", 997 function_name); 998 return 1; 999 } 1000 return 0; 1001} 1002 1003static int 1004dir_fd_and_fd_invalid(char *function_name, int dir_fd, int fd) { 1005 if ((dir_fd != DEFAULT_DIR_FD) && (fd != -1)) { 1006 PyErr_Format(PyExc_ValueError, 1007 "%s: can't specify both dir_fd and fd", 1008 function_name); 1009 return 1; 1010 } 1011 return 0; 1012} 1013 1014static int 1015fd_and_follow_symlinks_invalid(char *function_name, int fd, 1016 int follow_symlinks) { 1017 if ((fd > 0) && (!follow_symlinks)) { 1018 PyErr_Format(PyExc_ValueError, 1019 "%s: cannot use fd and follow_symlinks together", 1020 function_name); 1021 return 1; 1022 } 1023 return 0; 1024} 1025 1026static int 1027dir_fd_and_follow_symlinks_invalid(char *function_name, int dir_fd, 1028 int follow_symlinks) { 1029 if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) { 1030 PyErr_Format(PyExc_ValueError, 1031 "%s: cannot use dir_fd and follow_symlinks together", 1032 function_name); 1033 return 1; 1034 } 1035 return 0; 1036} 1037 1038#ifdef MS_WINDOWS 1039 typedef PY_LONG_LONG Py_off_t; 1040#else 1041 typedef off_t Py_off_t; 1042#endif 1043 1044static int 1045Py_off_t_converter(PyObject *arg, void *addr) 1046{ 1047#ifdef HAVE_LARGEFILE_SUPPORT 1048 *((Py_off_t *)addr) = PyLong_AsLongLong(arg); 1049#else 1050 *((Py_off_t *)addr) = PyLong_AsLong(arg); 1051#endif 1052 if (PyErr_Occurred()) 1053 return 0; 1054 return 1; 1055} 1056 1057static PyObject * 1058PyLong_FromPy_off_t(Py_off_t offset) 1059{ 1060#ifdef HAVE_LARGEFILE_SUPPORT 1061 return PyLong_FromLongLong(offset); 1062#else 1063 return PyLong_FromLong(offset); 1064#endif 1065} 1066 1067 1068#if defined _MSC_VER && _MSC_VER >= 1400 && _MSC_VER < 1900 1069/* Legacy implementation of _PyVerify_fd_dup2 while transitioning to 1070 * MSVC 14.0. This should eventually be removed. (issue23524) 1071 */ 1072#define IOINFO_L2E 5 1073#define IOINFO_ARRAYS 64 1074#define IOINFO_ARRAY_ELTS (1 << IOINFO_L2E) 1075#define _NHANDLE_ (IOINFO_ARRAYS * IOINFO_ARRAY_ELTS) 1076#define _NO_CONSOLE_FILENO (intptr_t)-2 1077 1078/* the special case of checking dup2. The target fd must be in a sensible range */ 1079static int 1080_PyVerify_fd_dup2(int fd1, int fd2) 1081{ 1082 if (!_PyVerify_fd(fd1)) 1083 return 0; 1084 if (fd2 == _NO_CONSOLE_FILENO) 1085 return 0; 1086 if ((unsigned)fd2 < _NHANDLE_) 1087 return 1; 1088 else 1089 return 0; 1090} 1091#else 1092#define _PyVerify_fd_dup2(fd1, fd2) (_PyVerify_fd(fd1) && (fd2) >= 0) 1093#endif 1094 1095#ifdef MS_WINDOWS 1096 1097static int 1098win32_get_reparse_tag(HANDLE reparse_point_handle, ULONG *reparse_tag) 1099{ 1100 char target_buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; 1101 REPARSE_DATA_BUFFER *rdb = (REPARSE_DATA_BUFFER *)target_buffer; 1102 DWORD n_bytes_returned; 1103 1104 if (0 == DeviceIoControl( 1105 reparse_point_handle, 1106 FSCTL_GET_REPARSE_POINT, 1107 NULL, 0, /* in buffer */ 1108 target_buffer, sizeof(target_buffer), 1109 &n_bytes_returned, 1110 NULL)) /* we're not using OVERLAPPED_IO */ 1111 return FALSE; 1112 1113 if (reparse_tag) 1114 *reparse_tag = rdb->ReparseTag; 1115 1116 return TRUE; 1117} 1118 1119#endif /* MS_WINDOWS */ 1120 1121/* Return a dictionary corresponding to the POSIX environment table */ 1122#if defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED)) 1123/* On Darwin/MacOSX a shared library or framework has no access to 1124** environ directly, we must obtain it with _NSGetEnviron(). See also 1125** man environ(7). 1126*/ 1127#include <crt_externs.h> 1128static char **environ; 1129#elif !defined(_MSC_VER) && ( !defined(__WATCOMC__) || defined(__QNX__) ) 1130extern char **environ; 1131#endif /* !_MSC_VER */ 1132 1133static PyObject * 1134convertenviron(void) 1135{ 1136 PyObject *d; 1137#ifdef MS_WINDOWS 1138 wchar_t **e; 1139#else 1140 char **e; 1141#endif 1142 1143 d = PyDict_New(); 1144 if (d == NULL) 1145 return NULL; 1146#if defined(WITH_NEXT_FRAMEWORK) || (defined(__APPLE__) && defined(Py_ENABLE_SHARED)) 1147 if (environ == NULL) 1148 environ = *_NSGetEnviron(); 1149#endif 1150#ifdef MS_WINDOWS 1151 /* _wenviron must be initialized in this way if the program is started 1152 through main() instead of wmain(). */ 1153 _wgetenv(L""); 1154 if (_wenviron == NULL) 1155 return d; 1156 /* This part ignores errors */ 1157 for (e = _wenviron; *e != NULL; e++) { 1158 PyObject *k; 1159 PyObject *v; 1160 wchar_t *p = wcschr(*e, L'='); 1161 if (p == NULL) 1162 continue; 1163 k = PyUnicode_FromWideChar(*e, (Py_ssize_t)(p-*e)); 1164 if (k == NULL) { 1165 PyErr_Clear(); 1166 continue; 1167 } 1168 v = PyUnicode_FromWideChar(p+1, wcslen(p+1)); 1169 if (v == NULL) { 1170 PyErr_Clear(); 1171 Py_DECREF(k); 1172 continue; 1173 } 1174 if (PyDict_GetItem(d, k) == NULL) { 1175 if (PyDict_SetItem(d, k, v) != 0) 1176 PyErr_Clear(); 1177 } 1178 Py_DECREF(k); 1179 Py_DECREF(v); 1180 } 1181#else 1182 if (environ == NULL) 1183 return d; 1184 /* This part ignores errors */ 1185 for (e = environ; *e != NULL; e++) { 1186 PyObject *k; 1187 PyObject *v; 1188 char *p = strchr(*e, '='); 1189 if (p == NULL) 1190 continue; 1191 k = PyBytes_FromStringAndSize(*e, (int)(p-*e)); 1192 if (k == NULL) { 1193 PyErr_Clear(); 1194 continue; 1195 } 1196 v = PyBytes_FromStringAndSize(p+1, strlen(p+1)); 1197 if (v == NULL) { 1198 PyErr_Clear(); 1199 Py_DECREF(k); 1200 continue; 1201 } 1202 if (PyDict_GetItem(d, k) == NULL) { 1203 if (PyDict_SetItem(d, k, v) != 0) 1204 PyErr_Clear(); 1205 } 1206 Py_DECREF(k); 1207 Py_DECREF(v); 1208 } 1209#endif 1210 return d; 1211} 1212 1213/* Set a POSIX-specific error from errno, and return NULL */ 1214 1215static PyObject * 1216posix_error(void) 1217{ 1218 return PyErr_SetFromErrno(PyExc_OSError); 1219} 1220 1221#ifdef MS_WINDOWS 1222static PyObject * 1223win32_error(char* function, const char* filename) 1224{ 1225 /* XXX We should pass the function name along in the future. 1226 (winreg.c also wants to pass the function name.) 1227 This would however require an additional param to the 1228 Windows error object, which is non-trivial. 1229 */ 1230 errno = GetLastError(); 1231 if (filename) 1232 return PyErr_SetFromWindowsErrWithFilename(errno, filename); 1233 else 1234 return PyErr_SetFromWindowsErr(errno); 1235} 1236 1237static PyObject * 1238win32_error_object(char* function, PyObject* filename) 1239{ 1240 /* XXX - see win32_error for comments on 'function' */ 1241 errno = GetLastError(); 1242 if (filename) 1243 return PyErr_SetExcFromWindowsErrWithFilenameObject( 1244 PyExc_OSError, 1245 errno, 1246 filename); 1247 else 1248 return PyErr_SetFromWindowsErr(errno); 1249} 1250 1251#endif /* MS_WINDOWS */ 1252 1253static PyObject * 1254path_error(path_t *path) 1255{ 1256#ifdef MS_WINDOWS 1257 return PyErr_SetExcFromWindowsErrWithFilenameObject(PyExc_OSError, 1258 0, path->object); 1259#else 1260 return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object); 1261#endif 1262} 1263 1264 1265static PyObject * 1266path_error2(path_t *path, path_t *path2) 1267{ 1268#ifdef MS_WINDOWS 1269 return PyErr_SetExcFromWindowsErrWithFilenameObjects(PyExc_OSError, 1270 0, path->object, path2->object); 1271#else 1272 return PyErr_SetFromErrnoWithFilenameObjects(PyExc_OSError, 1273 path->object, path2->object); 1274#endif 1275} 1276 1277 1278/* POSIX generic methods */ 1279 1280static int 1281fildes_converter(PyObject *o, void *p) 1282{ 1283 int fd; 1284 int *pointer = (int *)p; 1285 fd = PyObject_AsFileDescriptor(o); 1286 if (fd < 0) 1287 return 0; 1288 *pointer = fd; 1289 return 1; 1290} 1291 1292static PyObject * 1293posix_fildes_fd(int fd, int (*func)(int)) 1294{ 1295 int res; 1296 int async_err = 0; 1297 1298 if (!_PyVerify_fd(fd)) 1299 return posix_error(); 1300 1301 do { 1302 Py_BEGIN_ALLOW_THREADS 1303 _Py_BEGIN_SUPPRESS_IPH 1304 res = (*func)(fd); 1305 _Py_END_SUPPRESS_IPH 1306 Py_END_ALLOW_THREADS 1307 } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); 1308 if (res != 0) 1309 return (!async_err) ? posix_error() : NULL; 1310 Py_RETURN_NONE; 1311} 1312 1313 1314#ifdef MS_WINDOWS 1315/* This is a reimplementation of the C library's chdir function, 1316 but one that produces Win32 errors instead of DOS error codes. 1317 chdir is essentially a wrapper around SetCurrentDirectory; however, 1318 it also needs to set "magic" environment variables indicating 1319 the per-drive current directory, which are of the form =<drive>: */ 1320static BOOL __stdcall 1321win32_chdir(LPCSTR path) 1322{ 1323 char new_path[MAX_PATH]; 1324 int result; 1325 char env[4] = "=x:"; 1326 1327 if(!SetCurrentDirectoryA(path)) 1328 return FALSE; 1329 result = GetCurrentDirectoryA(Py_ARRAY_LENGTH(new_path), new_path); 1330 if (!result) 1331 return FALSE; 1332 /* In the ANSI API, there should not be any paths longer 1333 than MAX_PATH-1 (not including the final null character). */ 1334 assert(result < Py_ARRAY_LENGTH(new_path)); 1335 if (strncmp(new_path, "\\\\", 2) == 0 || 1336 strncmp(new_path, "//", 2) == 0) 1337 /* UNC path, nothing to do. */ 1338 return TRUE; 1339 env[1] = new_path[0]; 1340 return SetEnvironmentVariableA(env, new_path); 1341} 1342 1343/* The Unicode version differs from the ANSI version 1344 since the current directory might exceed MAX_PATH characters */ 1345static BOOL __stdcall 1346win32_wchdir(LPCWSTR path) 1347{ 1348 wchar_t path_buf[MAX_PATH], *new_path = path_buf; 1349 int result; 1350 wchar_t env[4] = L"=x:"; 1351 1352 if(!SetCurrentDirectoryW(path)) 1353 return FALSE; 1354 result = GetCurrentDirectoryW(Py_ARRAY_LENGTH(path_buf), new_path); 1355 if (!result) 1356 return FALSE; 1357 if (result > Py_ARRAY_LENGTH(new_path)) { 1358 new_path = PyMem_RawMalloc(result * sizeof(wchar_t)); 1359 if (!new_path) { 1360 SetLastError(ERROR_OUTOFMEMORY); 1361 return FALSE; 1362 } 1363 result = GetCurrentDirectoryW(result, new_path); 1364 if (!result) { 1365 PyMem_RawFree(new_path); 1366 return FALSE; 1367 } 1368 } 1369 if (wcsncmp(new_path, L"\\\\", 2) == 0 || 1370 wcsncmp(new_path, L"//", 2) == 0) 1371 /* UNC path, nothing to do. */ 1372 return TRUE; 1373 env[1] = new_path[0]; 1374 result = SetEnvironmentVariableW(env, new_path); 1375 if (new_path != path_buf) 1376 PyMem_RawFree(new_path); 1377 return result; 1378} 1379#endif 1380 1381#ifdef MS_WINDOWS 1382/* The CRT of Windows has a number of flaws wrt. its stat() implementation: 1383 - time stamps are restricted to second resolution 1384 - file modification times suffer from forth-and-back conversions between 1385 UTC and local time 1386 Therefore, we implement our own stat, based on the Win32 API directly. 1387*/ 1388#define HAVE_STAT_NSEC 1 1389#define HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES 1 1390 1391static BOOL 1392attributes_from_dir(LPCSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag) 1393{ 1394 HANDLE hFindFile; 1395 WIN32_FIND_DATAA FileData; 1396 hFindFile = FindFirstFileA(pszFile, &FileData); 1397 if (hFindFile == INVALID_HANDLE_VALUE) 1398 return FALSE; 1399 FindClose(hFindFile); 1400 memset(info, 0, sizeof(*info)); 1401 *reparse_tag = 0; 1402 info->dwFileAttributes = FileData.dwFileAttributes; 1403 info->ftCreationTime = FileData.ftCreationTime; 1404 info->ftLastAccessTime = FileData.ftLastAccessTime; 1405 info->ftLastWriteTime = FileData.ftLastWriteTime; 1406 info->nFileSizeHigh = FileData.nFileSizeHigh; 1407 info->nFileSizeLow = FileData.nFileSizeLow; 1408/* info->nNumberOfLinks = 1; */ 1409 if (FileData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) 1410 *reparse_tag = FileData.dwReserved0; 1411 return TRUE; 1412} 1413 1414static void 1415find_data_to_file_info_w(WIN32_FIND_DATAW *pFileData, 1416 BY_HANDLE_FILE_INFORMATION *info, 1417 ULONG *reparse_tag) 1418{ 1419 memset(info, 0, sizeof(*info)); 1420 info->dwFileAttributes = pFileData->dwFileAttributes; 1421 info->ftCreationTime = pFileData->ftCreationTime; 1422 info->ftLastAccessTime = pFileData->ftLastAccessTime; 1423 info->ftLastWriteTime = pFileData->ftLastWriteTime; 1424 info->nFileSizeHigh = pFileData->nFileSizeHigh; 1425 info->nFileSizeLow = pFileData->nFileSizeLow; 1426/* info->nNumberOfLinks = 1; */ 1427 if (pFileData->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) 1428 *reparse_tag = pFileData->dwReserved0; 1429 else 1430 *reparse_tag = 0; 1431} 1432 1433static BOOL 1434attributes_from_dir_w(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag) 1435{ 1436 HANDLE hFindFile; 1437 WIN32_FIND_DATAW FileData; 1438 hFindFile = FindFirstFileW(pszFile, &FileData); 1439 if (hFindFile == INVALID_HANDLE_VALUE) 1440 return FALSE; 1441 FindClose(hFindFile); 1442 find_data_to_file_info_w(&FileData, info, reparse_tag); 1443 return TRUE; 1444} 1445 1446static BOOL 1447get_target_path(HANDLE hdl, wchar_t **target_path) 1448{ 1449 int buf_size, result_length; 1450 wchar_t *buf; 1451 1452 /* We have a good handle to the target, use it to determine 1453 the target path name (then we'll call lstat on it). */ 1454 buf_size = GetFinalPathNameByHandleW(hdl, 0, 0, 1455 VOLUME_NAME_DOS); 1456 if(!buf_size) 1457 return FALSE; 1458 1459 buf = PyMem_New(wchar_t, buf_size+1); 1460 if (!buf) { 1461 SetLastError(ERROR_OUTOFMEMORY); 1462 return FALSE; 1463 } 1464 1465 result_length = GetFinalPathNameByHandleW(hdl, 1466 buf, buf_size, VOLUME_NAME_DOS); 1467 1468 if(!result_length) { 1469 PyMem_Free(buf); 1470 return FALSE; 1471 } 1472 1473 if(!CloseHandle(hdl)) { 1474 PyMem_Free(buf); 1475 return FALSE; 1476 } 1477 1478 buf[result_length] = 0; 1479 1480 *target_path = buf; 1481 return TRUE; 1482} 1483 1484static int 1485win32_xstat_impl_w(const wchar_t *path, struct _Py_stat_struct *result, 1486 BOOL traverse); 1487static int 1488win32_xstat_impl(const char *path, struct _Py_stat_struct *result, 1489 BOOL traverse) 1490{ 1491 int code; 1492 HANDLE hFile, hFile2; 1493 BY_HANDLE_FILE_INFORMATION info; 1494 ULONG reparse_tag = 0; 1495 wchar_t *target_path; 1496 const char *dot; 1497 1498 hFile = CreateFileA( 1499 path, 1500 FILE_READ_ATTRIBUTES, /* desired access */ 1501 0, /* share mode */ 1502 NULL, /* security attributes */ 1503 OPEN_EXISTING, 1504 /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */ 1505 /* FILE_FLAG_OPEN_REPARSE_POINT does not follow the symlink. 1506 Because of this, calls like GetFinalPathNameByHandle will return 1507 the symlink path again and not the actual final path. */ 1508 FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS| 1509 FILE_FLAG_OPEN_REPARSE_POINT, 1510 NULL); 1511 1512 if (hFile == INVALID_HANDLE_VALUE) { 1513 /* Either the target doesn't exist, or we don't have access to 1514 get a handle to it. If the former, we need to return an error. 1515 If the latter, we can use attributes_from_dir. */ 1516 if (GetLastError() != ERROR_SHARING_VIOLATION) 1517 return -1; 1518 /* Could not get attributes on open file. Fall back to 1519 reading the directory. */ 1520 if (!attributes_from_dir(path, &info, &reparse_tag)) 1521 /* Very strange. This should not fail now */ 1522 return -1; 1523 if (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { 1524 if (traverse) { 1525 /* Should traverse, but could not open reparse point handle */ 1526 SetLastError(ERROR_SHARING_VIOLATION); 1527 return -1; 1528 } 1529 } 1530 } else { 1531 if (!GetFileInformationByHandle(hFile, &info)) { 1532 CloseHandle(hFile); 1533 return -1; 1534 } 1535 if (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { 1536 if (!win32_get_reparse_tag(hFile, &reparse_tag)) 1537 return -1; 1538 1539 /* Close the outer open file handle now that we're about to 1540 reopen it with different flags. */ 1541 if (!CloseHandle(hFile)) 1542 return -1; 1543 1544 if (traverse) { 1545 /* In order to call GetFinalPathNameByHandle we need to open 1546 the file without the reparse handling flag set. */ 1547 hFile2 = CreateFileA( 1548 path, FILE_READ_ATTRIBUTES, FILE_SHARE_READ, 1549 NULL, OPEN_EXISTING, 1550 FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS, 1551 NULL); 1552 if (hFile2 == INVALID_HANDLE_VALUE) 1553 return -1; 1554 1555 if (!get_target_path(hFile2, &target_path)) 1556 return -1; 1557 1558 code = win32_xstat_impl_w(target_path, result, FALSE); 1559 PyMem_Free(target_path); 1560 return code; 1561 } 1562 } else 1563 CloseHandle(hFile); 1564 } 1565 _Py_attribute_data_to_stat(&info, reparse_tag, result); 1566 1567 /* Set S_IEXEC if it is an .exe, .bat, ... */ 1568 dot = strrchr(path, '.'); 1569 if (dot) { 1570 if (stricmp(dot, ".bat") == 0 || stricmp(dot, ".cmd") == 0 || 1571 stricmp(dot, ".exe") == 0 || stricmp(dot, ".com") == 0) 1572 result->st_mode |= 0111; 1573 } 1574 return 0; 1575} 1576 1577static int 1578win32_xstat_impl_w(const wchar_t *path, struct _Py_stat_struct *result, 1579 BOOL traverse) 1580{ 1581 int code; 1582 HANDLE hFile, hFile2; 1583 BY_HANDLE_FILE_INFORMATION info; 1584 ULONG reparse_tag = 0; 1585 wchar_t *target_path; 1586 const wchar_t *dot; 1587 1588 hFile = CreateFileW( 1589 path, 1590 FILE_READ_ATTRIBUTES, /* desired access */ 1591 0, /* share mode */ 1592 NULL, /* security attributes */ 1593 OPEN_EXISTING, 1594 /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */ 1595 /* FILE_FLAG_OPEN_REPARSE_POINT does not follow the symlink. 1596 Because of this, calls like GetFinalPathNameByHandle will return 1597 the symlink path again and not the actual final path. */ 1598 FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS| 1599 FILE_FLAG_OPEN_REPARSE_POINT, 1600 NULL); 1601 1602 if (hFile == INVALID_HANDLE_VALUE) { 1603 /* Either the target doesn't exist, or we don't have access to 1604 get a handle to it. If the former, we need to return an error. 1605 If the latter, we can use attributes_from_dir. */ 1606 if (GetLastError() != ERROR_SHARING_VIOLATION) 1607 return -1; 1608 /* Could not get attributes on open file. Fall back to 1609 reading the directory. */ 1610 if (!attributes_from_dir_w(path, &info, &reparse_tag)) 1611 /* Very strange. This should not fail now */ 1612 return -1; 1613 if (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { 1614 if (traverse) { 1615 /* Should traverse, but could not open reparse point handle */ 1616 SetLastError(ERROR_SHARING_VIOLATION); 1617 return -1; 1618 } 1619 } 1620 } else { 1621 if (!GetFileInformationByHandle(hFile, &info)) { 1622 CloseHandle(hFile); 1623 return -1; 1624 } 1625 if (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { 1626 if (!win32_get_reparse_tag(hFile, &reparse_tag)) 1627 return -1; 1628 1629 /* Close the outer open file handle now that we're about to 1630 reopen it with different flags. */ 1631 if (!CloseHandle(hFile)) 1632 return -1; 1633 1634 if (traverse) { 1635 /* In order to call GetFinalPathNameByHandle we need to open 1636 the file without the reparse handling flag set. */ 1637 hFile2 = CreateFileW( 1638 path, FILE_READ_ATTRIBUTES, FILE_SHARE_READ, 1639 NULL, OPEN_EXISTING, 1640 FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS, 1641 NULL); 1642 if (hFile2 == INVALID_HANDLE_VALUE) 1643 return -1; 1644 1645 if (!get_target_path(hFile2, &target_path)) 1646 return -1; 1647 1648 code = win32_xstat_impl_w(target_path, result, FALSE); 1649 PyMem_Free(target_path); 1650 return code; 1651 } 1652 } else 1653 CloseHandle(hFile); 1654 } 1655 _Py_attribute_data_to_stat(&info, reparse_tag, result); 1656 1657 /* Set S_IEXEC if it is an .exe, .bat, ... */ 1658 dot = wcsrchr(path, '.'); 1659 if (dot) { 1660 if (_wcsicmp(dot, L".bat") == 0 || _wcsicmp(dot, L".cmd") == 0 || 1661 _wcsicmp(dot, L".exe") == 0 || _wcsicmp(dot, L".com") == 0) 1662 result->st_mode |= 0111; 1663 } 1664 return 0; 1665} 1666 1667static int 1668win32_xstat(const char *path, struct _Py_stat_struct *result, BOOL traverse) 1669{ 1670 /* Protocol violation: we explicitly clear errno, instead of 1671 setting it to a POSIX error. Callers should use GetLastError. */ 1672 int code = win32_xstat_impl(path, result, traverse); 1673 errno = 0; 1674 return code; 1675} 1676 1677static int 1678win32_xstat_w(const wchar_t *path, struct _Py_stat_struct *result, BOOL traverse) 1679{ 1680 /* Protocol violation: we explicitly clear errno, instead of 1681 setting it to a POSIX error. Callers should use GetLastError. */ 1682 int code = win32_xstat_impl_w(path, result, traverse); 1683 errno = 0; 1684 return code; 1685} 1686/* About the following functions: win32_lstat_w, win32_stat, win32_stat_w 1687 1688 In Posix, stat automatically traverses symlinks and returns the stat 1689 structure for the target. In Windows, the equivalent GetFileAttributes by 1690 default does not traverse symlinks and instead returns attributes for 1691 the symlink. 1692 1693 Therefore, win32_lstat will get the attributes traditionally, and 1694 win32_stat will first explicitly resolve the symlink target and then will 1695 call win32_lstat on that result. 1696 1697 The _w represent Unicode equivalents of the aforementioned ANSI functions. */ 1698 1699static int 1700win32_lstat(const char* path, struct _Py_stat_struct *result) 1701{ 1702 return win32_xstat(path, result, FALSE); 1703} 1704 1705static int 1706win32_lstat_w(const wchar_t* path, struct _Py_stat_struct *result) 1707{ 1708 return win32_xstat_w(path, result, FALSE); 1709} 1710 1711static int 1712win32_stat(const char* path, struct _Py_stat_struct *result) 1713{ 1714 return win32_xstat(path, result, TRUE); 1715} 1716 1717static int 1718win32_stat_w(const wchar_t* path, struct _Py_stat_struct *result) 1719{ 1720 return win32_xstat_w(path, result, TRUE); 1721} 1722 1723#endif /* MS_WINDOWS */ 1724 1725PyDoc_STRVAR(stat_result__doc__, 1726"stat_result: Result from stat, fstat, or lstat.\n\n\ 1727This object may be accessed either as a tuple of\n\ 1728 (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\ 1729or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\ 1730\n\ 1731Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\ 1732or st_flags, they are available as attributes only.\n\ 1733\n\ 1734See os.stat for more information."); 1735 1736static PyStructSequence_Field stat_result_fields[] = { 1737 {"st_mode", "protection bits"}, 1738 {"st_ino", "inode"}, 1739 {"st_dev", "device"}, 1740 {"st_nlink", "number of hard links"}, 1741 {"st_uid", "user ID of owner"}, 1742 {"st_gid", "group ID of owner"}, 1743 {"st_size", "total size, in bytes"}, 1744 /* The NULL is replaced with PyStructSequence_UnnamedField later. */ 1745 {NULL, "integer time of last access"}, 1746 {NULL, "integer time of last modification"}, 1747 {NULL, "integer time of last change"}, 1748 {"st_atime", "time of last access"}, 1749 {"st_mtime", "time of last modification"}, 1750 {"st_ctime", "time of last change"}, 1751 {"st_atime_ns", "time of last access in nanoseconds"}, 1752 {"st_mtime_ns", "time of last modification in nanoseconds"}, 1753 {"st_ctime_ns", "time of last change in nanoseconds"}, 1754#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE 1755 {"st_blksize", "blocksize for filesystem I/O"}, 1756#endif 1757#ifdef HAVE_STRUCT_STAT_ST_BLOCKS 1758 {"st_blocks", "number of blocks allocated"}, 1759#endif 1760#ifdef HAVE_STRUCT_STAT_ST_RDEV 1761 {"st_rdev", "device type (if inode device)"}, 1762#endif 1763#ifdef HAVE_STRUCT_STAT_ST_FLAGS 1764 {"st_flags", "user defined flags for file"}, 1765#endif 1766#ifdef HAVE_STRUCT_STAT_ST_GEN 1767 {"st_gen", "generation number"}, 1768#endif 1769#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME 1770 {"st_birthtime", "time of creation"}, 1771#endif 1772#ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES 1773 {"st_file_attributes", "Windows file attribute bits"}, 1774#endif 1775 {0} 1776}; 1777 1778#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE 1779#define ST_BLKSIZE_IDX 16 1780#else 1781#define ST_BLKSIZE_IDX 15 1782#endif 1783 1784#ifdef HAVE_STRUCT_STAT_ST_BLOCKS 1785#define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1) 1786#else 1787#define ST_BLOCKS_IDX ST_BLKSIZE_IDX 1788#endif 1789 1790#ifdef HAVE_STRUCT_STAT_ST_RDEV 1791#define ST_RDEV_IDX (ST_BLOCKS_IDX+1) 1792#else 1793#define ST_RDEV_IDX ST_BLOCKS_IDX 1794#endif 1795 1796#ifdef HAVE_STRUCT_STAT_ST_FLAGS 1797#define ST_FLAGS_IDX (ST_RDEV_IDX+1) 1798#else 1799#define ST_FLAGS_IDX ST_RDEV_IDX 1800#endif 1801 1802#ifdef HAVE_STRUCT_STAT_ST_GEN 1803#define ST_GEN_IDX (ST_FLAGS_IDX+1) 1804#else 1805#define ST_GEN_IDX ST_FLAGS_IDX 1806#endif 1807 1808#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME 1809#define ST_BIRTHTIME_IDX (ST_GEN_IDX+1) 1810#else 1811#define ST_BIRTHTIME_IDX ST_GEN_IDX 1812#endif 1813 1814#ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES 1815#define ST_FILE_ATTRIBUTES_IDX (ST_BIRTHTIME_IDX+1) 1816#else 1817#define ST_FILE_ATTRIBUTES_IDX ST_BIRTHTIME_IDX 1818#endif 1819 1820static PyStructSequence_Desc stat_result_desc = { 1821 "stat_result", /* name */ 1822 stat_result__doc__, /* doc */ 1823 stat_result_fields, 1824 10 1825}; 1826 1827PyDoc_STRVAR(statvfs_result__doc__, 1828"statvfs_result: Result from statvfs or fstatvfs.\n\n\ 1829This object may be accessed either as a tuple of\n\ 1830 (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\ 1831or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\ 1832\n\ 1833See os.statvfs for more information."); 1834 1835static PyStructSequence_Field statvfs_result_fields[] = { 1836 {"f_bsize", }, 1837 {"f_frsize", }, 1838 {"f_blocks", }, 1839 {"f_bfree", }, 1840 {"f_bavail", }, 1841 {"f_files", }, 1842 {"f_ffree", }, 1843 {"f_favail", }, 1844 {"f_flag", }, 1845 {"f_namemax",}, 1846 {0} 1847}; 1848 1849static PyStructSequence_Desc statvfs_result_desc = { 1850 "statvfs_result", /* name */ 1851 statvfs_result__doc__, /* doc */ 1852 statvfs_result_fields, 1853 10 1854}; 1855 1856#if defined(HAVE_WAITID) && !defined(__APPLE__) 1857PyDoc_STRVAR(waitid_result__doc__, 1858"waitid_result: Result from waitid.\n\n\ 1859This object may be accessed either as a tuple of\n\ 1860 (si_pid, si_uid, si_signo, si_status, si_code),\n\ 1861or via the attributes si_pid, si_uid, and so on.\n\ 1862\n\ 1863See os.waitid for more information."); 1864 1865static PyStructSequence_Field waitid_result_fields[] = { 1866 {"si_pid", }, 1867 {"si_uid", }, 1868 {"si_signo", }, 1869 {"si_status", }, 1870 {"si_code", }, 1871 {0} 1872}; 1873 1874static PyStructSequence_Desc waitid_result_desc = { 1875 "waitid_result", /* name */ 1876 waitid_result__doc__, /* doc */ 1877 waitid_result_fields, 1878 5 1879}; 1880static PyTypeObject WaitidResultType; 1881#endif 1882 1883static int initialized; 1884static PyTypeObject StatResultType; 1885static PyTypeObject StatVFSResultType; 1886#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) 1887static PyTypeObject SchedParamType; 1888#endif 1889static newfunc structseq_new; 1890 1891static PyObject * 1892statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds) 1893{ 1894 PyStructSequence *result; 1895 int i; 1896 1897 result = (PyStructSequence*)structseq_new(type, args, kwds); 1898 if (!result) 1899 return NULL; 1900 /* If we have been initialized from a tuple, 1901 st_?time might be set to None. Initialize it 1902 from the int slots. */ 1903 for (i = 7; i <= 9; i++) { 1904 if (result->ob_item[i+3] == Py_None) { 1905 Py_DECREF(Py_None); 1906 Py_INCREF(result->ob_item[i]); 1907 result->ob_item[i+3] = result->ob_item[i]; 1908 } 1909 } 1910 return (PyObject*)result; 1911} 1912 1913 1914 1915/* If true, st_?time is float. */ 1916static int _stat_float_times = 1; 1917 1918PyDoc_STRVAR(stat_float_times__doc__, 1919"stat_float_times([newval]) -> oldval\n\n\ 1920Determine whether os.[lf]stat represents time stamps as float objects.\n\ 1921\n\ 1922If value is True, future calls to stat() return floats; if it is False,\n\ 1923future calls return ints.\n\ 1924If value is omitted, return the current setting.\n"); 1925 1926/* AC 3.5: the public default value should be None, not ready for that yet */ 1927static PyObject* 1928stat_float_times(PyObject* self, PyObject *args) 1929{ 1930 int newval = -1; 1931 if (!PyArg_ParseTuple(args, "|i:stat_float_times", &newval)) 1932 return NULL; 1933 if (PyErr_WarnEx(PyExc_DeprecationWarning, 1934 "stat_float_times() is deprecated", 1935 1)) 1936 return NULL; 1937 if (newval == -1) 1938 /* Return old value */ 1939 return PyBool_FromLong(_stat_float_times); 1940 _stat_float_times = newval; 1941 Py_INCREF(Py_None); 1942 return Py_None; 1943} 1944 1945static PyObject *billion = NULL; 1946 1947static void 1948fill_time(PyObject *v, int index, time_t sec, unsigned long nsec) 1949{ 1950 PyObject *s = _PyLong_FromTime_t(sec); 1951 PyObject *ns_fractional = PyLong_FromUnsignedLong(nsec); 1952 PyObject *s_in_ns = NULL; 1953 PyObject *ns_total = NULL; 1954 PyObject *float_s = NULL; 1955 1956 if (!(s && ns_fractional)) 1957 goto exit; 1958 1959 s_in_ns = PyNumber_Multiply(s, billion); 1960 if (!s_in_ns) 1961 goto exit; 1962 1963 ns_total = PyNumber_Add(s_in_ns, ns_fractional); 1964 if (!ns_total) 1965 goto exit; 1966 1967 if (_stat_float_times) { 1968 float_s = PyFloat_FromDouble(sec + 1e-9*nsec); 1969 if (!float_s) 1970 goto exit; 1971 } 1972 else { 1973 float_s = s; 1974 Py_INCREF(float_s); 1975 } 1976 1977 PyStructSequence_SET_ITEM(v, index, s); 1978 PyStructSequence_SET_ITEM(v, index+3, float_s); 1979 PyStructSequence_SET_ITEM(v, index+6, ns_total); 1980 s = NULL; 1981 float_s = NULL; 1982 ns_total = NULL; 1983exit: 1984 Py_XDECREF(s); 1985 Py_XDECREF(ns_fractional); 1986 Py_XDECREF(s_in_ns); 1987 Py_XDECREF(ns_total); 1988 Py_XDECREF(float_s); 1989} 1990 1991/* pack a system stat C structure into the Python stat tuple 1992 (used by posix_stat() and posix_fstat()) */ 1993static PyObject* 1994_pystat_fromstructstat(STRUCT_STAT *st) 1995{ 1996 unsigned long ansec, mnsec, cnsec; 1997 PyObject *v = PyStructSequence_New(&StatResultType); 1998 if (v == NULL) 1999 return NULL; 2000 2001 PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long)st->st_mode)); 2002#ifdef HAVE_LARGEFILE_SUPPORT 2003 PyStructSequence_SET_ITEM(v, 1, 2004 PyLong_FromLongLong((PY_LONG_LONG)st->st_ino)); 2005#else 2006 PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long)st->st_ino)); 2007#endif 2008#ifdef MS_WINDOWS 2009 PyStructSequence_SET_ITEM(v, 2, PyLong_FromUnsignedLong(st->st_dev)); 2010#else 2011 PyStructSequence_SET_ITEM(v, 2, _PyLong_FromDev(st->st_dev)); 2012#endif 2013 PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long)st->st_nlink)); 2014#if defined(MS_WINDOWS) 2015 PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong(0)); 2016 PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong(0)); 2017#else 2018 PyStructSequence_SET_ITEM(v, 4, _PyLong_FromUid(st->st_uid)); 2019 PyStructSequence_SET_ITEM(v, 5, _PyLong_FromGid(st->st_gid)); 2020#endif 2021#ifdef HAVE_LARGEFILE_SUPPORT 2022 PyStructSequence_SET_ITEM(v, 6, 2023 PyLong_FromLongLong((PY_LONG_LONG)st->st_size)); 2024#else 2025 PyStructSequence_SET_ITEM(v, 6, PyLong_FromLong(st->st_size)); 2026#endif 2027 2028#if defined(HAVE_STAT_TV_NSEC) 2029 ansec = st->st_atim.tv_nsec; 2030 mnsec = st->st_mtim.tv_nsec; 2031 cnsec = st->st_ctim.tv_nsec; 2032#elif defined(HAVE_STAT_TV_NSEC2) 2033 ansec = st->st_atimespec.tv_nsec; 2034 mnsec = st->st_mtimespec.tv_nsec; 2035 cnsec = st->st_ctimespec.tv_nsec; 2036#elif defined(HAVE_STAT_NSEC) 2037 ansec = st->st_atime_nsec; 2038 mnsec = st->st_mtime_nsec; 2039 cnsec = st->st_ctime_nsec; 2040#else 2041 ansec = mnsec = cnsec = 0; 2042#endif 2043 fill_time(v, 7, st->st_atime, ansec); 2044 fill_time(v, 8, st->st_mtime, mnsec); 2045 fill_time(v, 9, st->st_ctime, cnsec); 2046 2047#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE 2048 PyStructSequence_SET_ITEM(v, ST_BLKSIZE_IDX, 2049 PyLong_FromLong((long)st->st_blksize)); 2050#endif 2051#ifdef HAVE_STRUCT_STAT_ST_BLOCKS 2052 PyStructSequence_SET_ITEM(v, ST_BLOCKS_IDX, 2053 PyLong_FromLong((long)st->st_blocks)); 2054#endif 2055#ifdef HAVE_STRUCT_STAT_ST_RDEV 2056 PyStructSequence_SET_ITEM(v, ST_RDEV_IDX, 2057 PyLong_FromLong((long)st->st_rdev)); 2058#endif 2059#ifdef HAVE_STRUCT_STAT_ST_GEN 2060 PyStructSequence_SET_ITEM(v, ST_GEN_IDX, 2061 PyLong_FromLong((long)st->st_gen)); 2062#endif 2063#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME 2064 { 2065 PyObject *val; 2066 unsigned long bsec,bnsec; 2067 bsec = (long)st->st_birthtime; 2068#ifdef HAVE_STAT_TV_NSEC2 2069 bnsec = st->st_birthtimespec.tv_nsec; 2070#else 2071 bnsec = 0; 2072#endif 2073 if (_stat_float_times) { 2074 val = PyFloat_FromDouble(bsec + 1e-9*bnsec); 2075 } else { 2076 val = PyLong_FromLong((long)bsec); 2077 } 2078 PyStructSequence_SET_ITEM(v, ST_BIRTHTIME_IDX, 2079 val); 2080 } 2081#endif 2082#ifdef HAVE_STRUCT_STAT_ST_FLAGS 2083 PyStructSequence_SET_ITEM(v, ST_FLAGS_IDX, 2084 PyLong_FromLong((long)st->st_flags)); 2085#endif 2086#ifdef HAVE_STRUCT_STAT_ST_FILE_ATTRIBUTES 2087 PyStructSequence_SET_ITEM(v, ST_FILE_ATTRIBUTES_IDX, 2088 PyLong_FromUnsignedLong(st->st_file_attributes)); 2089#endif 2090 2091 if (PyErr_Occurred()) { 2092 Py_DECREF(v); 2093 return NULL; 2094 } 2095 2096 return v; 2097} 2098 2099/* POSIX methods */ 2100 2101 2102static PyObject * 2103posix_do_stat(char *function_name, path_t *path, 2104 int dir_fd, int follow_symlinks) 2105{ 2106 STRUCT_STAT st; 2107 int result; 2108 2109#if !defined(MS_WINDOWS) && !defined(HAVE_FSTATAT) && !defined(HAVE_LSTAT) 2110 if (follow_symlinks_specified(function_name, follow_symlinks)) 2111 return NULL; 2112#endif 2113 2114 if (path_and_dir_fd_invalid("stat", path, dir_fd) || 2115 dir_fd_and_fd_invalid("stat", dir_fd, path->fd) || 2116 fd_and_follow_symlinks_invalid("stat", path->fd, follow_symlinks)) 2117 return NULL; 2118 2119 Py_BEGIN_ALLOW_THREADS 2120 if (path->fd != -1) 2121 result = FSTAT(path->fd, &st); 2122 else 2123#ifdef MS_WINDOWS 2124 if (path->wide) { 2125 if (follow_symlinks) 2126 result = win32_stat_w(path->wide, &st); 2127 else 2128 result = win32_lstat_w(path->wide, &st); 2129 } 2130 else 2131#endif 2132#if defined(HAVE_LSTAT) || defined(MS_WINDOWS) 2133 if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD)) 2134 result = LSTAT(path->narrow, &st); 2135 else 2136#endif 2137#ifdef HAVE_FSTATAT 2138 if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) 2139 result = fstatat(dir_fd, path->narrow, &st, 2140 follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW); 2141 else 2142#endif 2143 result = STAT(path->narrow, &st); 2144 Py_END_ALLOW_THREADS 2145 2146 if (result != 0) { 2147 return path_error(path); 2148 } 2149 2150 return _pystat_fromstructstat(&st); 2151} 2152 2153/*[python input] 2154 2155for s in """ 2156 2157FACCESSAT 2158FCHMODAT 2159FCHOWNAT 2160FSTATAT 2161LINKAT 2162MKDIRAT 2163MKFIFOAT 2164MKNODAT 2165OPENAT 2166READLINKAT 2167SYMLINKAT 2168UNLINKAT 2169 2170""".strip().split(): 2171 s = s.strip() 2172 print(""" 2173#ifdef HAVE_{s} 2174 #define {s}_DIR_FD_CONVERTER dir_fd_converter 2175#else 2176 #define {s}_DIR_FD_CONVERTER dir_fd_unavailable 2177#endif 2178""".rstrip().format(s=s)) 2179 2180for s in """ 2181 2182FCHDIR 2183FCHMOD 2184FCHOWN 2185FDOPENDIR 2186FEXECVE 2187FPATHCONF 2188FSTATVFS 2189FTRUNCATE 2190 2191""".strip().split(): 2192 s = s.strip() 2193 print(""" 2194#ifdef HAVE_{s} 2195 #define PATH_HAVE_{s} 1 2196#else 2197 #define PATH_HAVE_{s} 0 2198#endif 2199 2200""".rstrip().format(s=s)) 2201[python start generated code]*/ 2202 2203#ifdef HAVE_FACCESSAT 2204 #define FACCESSAT_DIR_FD_CONVERTER dir_fd_converter 2205#else 2206 #define FACCESSAT_DIR_FD_CONVERTER dir_fd_unavailable 2207#endif 2208 2209#ifdef HAVE_FCHMODAT 2210 #define FCHMODAT_DIR_FD_CONVERTER dir_fd_converter 2211#else 2212 #define FCHMODAT_DIR_FD_CONVERTER dir_fd_unavailable 2213#endif 2214 2215#ifdef HAVE_FCHOWNAT 2216 #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_converter 2217#else 2218 #define FCHOWNAT_DIR_FD_CONVERTER dir_fd_unavailable 2219#endif 2220 2221#ifdef HAVE_FSTATAT 2222 #define FSTATAT_DIR_FD_CONVERTER dir_fd_converter 2223#else 2224 #define FSTATAT_DIR_FD_CONVERTER dir_fd_unavailable 2225#endif 2226 2227#ifdef HAVE_LINKAT 2228 #define LINKAT_DIR_FD_CONVERTER dir_fd_converter 2229#else 2230 #define LINKAT_DIR_FD_CONVERTER dir_fd_unavailable 2231#endif 2232 2233#ifdef HAVE_MKDIRAT 2234 #define MKDIRAT_DIR_FD_CONVERTER dir_fd_converter 2235#else 2236 #define MKDIRAT_DIR_FD_CONVERTER dir_fd_unavailable 2237#endif 2238 2239#ifdef HAVE_MKFIFOAT 2240 #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_converter 2241#else 2242 #define MKFIFOAT_DIR_FD_CONVERTER dir_fd_unavailable 2243#endif 2244 2245#ifdef HAVE_MKNODAT 2246 #define MKNODAT_DIR_FD_CONVERTER dir_fd_converter 2247#else 2248 #define MKNODAT_DIR_FD_CONVERTER dir_fd_unavailable 2249#endif 2250 2251#ifdef HAVE_OPENAT 2252 #define OPENAT_DIR_FD_CONVERTER dir_fd_converter 2253#else 2254 #define OPENAT_DIR_FD_CONVERTER dir_fd_unavailable 2255#endif 2256 2257#ifdef HAVE_READLINKAT 2258 #define READLINKAT_DIR_FD_CONVERTER dir_fd_converter 2259#else 2260 #define READLINKAT_DIR_FD_CONVERTER dir_fd_unavailable 2261#endif 2262 2263#ifdef HAVE_SYMLINKAT 2264 #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_converter 2265#else 2266 #define SYMLINKAT_DIR_FD_CONVERTER dir_fd_unavailable 2267#endif 2268 2269#ifdef HAVE_UNLINKAT 2270 #define UNLINKAT_DIR_FD_CONVERTER dir_fd_converter 2271#else 2272 #define UNLINKAT_DIR_FD_CONVERTER dir_fd_unavailable 2273#endif 2274 2275#ifdef HAVE_FCHDIR 2276 #define PATH_HAVE_FCHDIR 1 2277#else 2278 #define PATH_HAVE_FCHDIR 0 2279#endif 2280 2281#ifdef HAVE_FCHMOD 2282 #define PATH_HAVE_FCHMOD 1 2283#else 2284 #define PATH_HAVE_FCHMOD 0 2285#endif 2286 2287#ifdef HAVE_FCHOWN 2288 #define PATH_HAVE_FCHOWN 1 2289#else 2290 #define PATH_HAVE_FCHOWN 0 2291#endif 2292 2293#ifdef HAVE_FDOPENDIR 2294 #define PATH_HAVE_FDOPENDIR 1 2295#else 2296 #define PATH_HAVE_FDOPENDIR 0 2297#endif 2298 2299#ifdef HAVE_FEXECVE 2300 #define PATH_HAVE_FEXECVE 1 2301#else 2302 #define PATH_HAVE_FEXECVE 0 2303#endif 2304 2305#ifdef HAVE_FPATHCONF 2306 #define PATH_HAVE_FPATHCONF 1 2307#else 2308 #define PATH_HAVE_FPATHCONF 0 2309#endif 2310 2311#ifdef HAVE_FSTATVFS 2312 #define PATH_HAVE_FSTATVFS 1 2313#else 2314 #define PATH_HAVE_FSTATVFS 0 2315#endif 2316 2317#ifdef HAVE_FTRUNCATE 2318 #define PATH_HAVE_FTRUNCATE 1 2319#else 2320 #define PATH_HAVE_FTRUNCATE 0 2321#endif 2322/*[python end generated code: output=4bd4f6f7d41267f1 input=80b4c890b6774ea5]*/ 2323 2324#ifdef MS_WINDOWS 2325 #undef PATH_HAVE_FTRUNCATE 2326 #define PATH_HAVE_FTRUNCATE 1 2327#endif 2328 2329/*[python input] 2330 2331class path_t_converter(CConverter): 2332 2333 type = "path_t" 2334 impl_by_reference = True 2335 parse_by_reference = True 2336 2337 converter = 'path_converter' 2338 2339 def converter_init(self, *, allow_fd=False, nullable=False): 2340 # right now path_t doesn't support default values. 2341 # to support a default value, you'll need to override initialize(). 2342 if self.default not in (unspecified, None): 2343 fail("Can't specify a default to the path_t converter!") 2344 2345 if self.c_default not in (None, 'Py_None'): 2346 raise RuntimeError("Can't specify a c_default to the path_t converter!") 2347 2348 self.nullable = nullable 2349 self.allow_fd = allow_fd 2350 2351 def pre_render(self): 2352 def strify(value): 2353 if isinstance(value, str): 2354 return value 2355 return str(int(bool(value))) 2356 2357 # add self.py_name here when merging with posixmodule conversion 2358 self.c_default = 'PATH_T_INITIALIZE("{}", "{}", {}, {})'.format( 2359 self.function.name, 2360 self.name, 2361 strify(self.nullable), 2362 strify(self.allow_fd), 2363 ) 2364 2365 def cleanup(self): 2366 return "path_cleanup(&" + self.name + ");\n" 2367 2368 2369class dir_fd_converter(CConverter): 2370 type = 'int' 2371 2372 def converter_init(self, requires=None): 2373 if self.default in (unspecified, None): 2374 self.c_default = 'DEFAULT_DIR_FD' 2375 if isinstance(requires, str): 2376 self.converter = requires.upper() + '_DIR_FD_CONVERTER' 2377 else: 2378 self.converter = 'dir_fd_converter' 2379 2380class fildes_converter(CConverter): 2381 type = 'int' 2382 converter = 'fildes_converter' 2383 2384class uid_t_converter(CConverter): 2385 type = "uid_t" 2386 converter = '_Py_Uid_Converter' 2387 2388class gid_t_converter(CConverter): 2389 type = "gid_t" 2390 converter = '_Py_Gid_Converter' 2391 2392class dev_t_converter(CConverter): 2393 type = 'dev_t' 2394 converter = '_Py_Dev_Converter' 2395 2396class dev_t_return_converter(unsigned_long_return_converter): 2397 type = 'dev_t' 2398 conversion_fn = '_PyLong_FromDev' 2399 unsigned_cast = '(dev_t)' 2400 2401class FSConverter_converter(CConverter): 2402 type = 'PyObject *' 2403 converter = 'PyUnicode_FSConverter' 2404 def converter_init(self): 2405 if self.default is not unspecified: 2406 fail("FSConverter_converter does not support default values") 2407 self.c_default = 'NULL' 2408 2409 def cleanup(self): 2410 return "Py_XDECREF(" + self.name + ");\n" 2411 2412class pid_t_converter(CConverter): 2413 type = 'pid_t' 2414 format_unit = '" _Py_PARSE_PID "' 2415 2416class idtype_t_converter(int_converter): 2417 type = 'idtype_t' 2418 2419class id_t_converter(CConverter): 2420 type = 'id_t' 2421 format_unit = '" _Py_PARSE_PID "' 2422 2423class Py_intptr_t_converter(CConverter): 2424 type = 'Py_intptr_t' 2425 format_unit = '" _Py_PARSE_INTPTR "' 2426 2427class Py_off_t_converter(CConverter): 2428 type = 'Py_off_t' 2429 converter = 'Py_off_t_converter' 2430 2431class Py_off_t_return_converter(long_return_converter): 2432 type = 'Py_off_t' 2433 conversion_fn = 'PyLong_FromPy_off_t' 2434 2435class path_confname_converter(CConverter): 2436 type="int" 2437 converter="conv_path_confname" 2438 2439class confstr_confname_converter(path_confname_converter): 2440 converter='conv_confstr_confname' 2441 2442class sysconf_confname_converter(path_confname_converter): 2443 converter="conv_sysconf_confname" 2444 2445class sched_param_converter(CConverter): 2446 type = 'struct sched_param' 2447 converter = 'convert_sched_param' 2448 impl_by_reference = True; 2449 2450[python start generated code]*/ 2451/*[python end generated code: output=da39a3ee5e6b4b0d input=affe68316f160401]*/ 2452 2453/*[clinic input] 2454 2455os.stat 2456 2457 path : path_t(allow_fd=True) 2458 Path to be examined; can be string, bytes, or open-file-descriptor int. 2459 2460 * 2461 2462 dir_fd : dir_fd(requires='fstatat') = None 2463 If not None, it should be a file descriptor open to a directory, 2464 and path should be a relative string; path will then be relative to 2465 that directory. 2466 2467 follow_symlinks: bool = True 2468 If False, and the last element of the path is a symbolic link, 2469 stat will examine the symbolic link itself instead of the file 2470 the link points to. 2471 2472Perform a stat system call on the given path. 2473 2474dir_fd and follow_symlinks may not be implemented 2475 on your platform. If they are unavailable, using them will raise a 2476 NotImplementedError. 2477 2478It's an error to use dir_fd or follow_symlinks when specifying path as 2479 an open file descriptor. 2480 2481[clinic start generated code]*/ 2482 2483static PyObject * 2484os_stat_impl(PyModuleDef *module, path_t *path, int dir_fd, 2485 int follow_symlinks) 2486/*[clinic end generated code: output=e4f7569f95d523ca input=099d356c306fa24a]*/ 2487{ 2488 return posix_do_stat("stat", path, dir_fd, follow_symlinks); 2489} 2490 2491 2492/*[clinic input] 2493os.lstat 2494 2495 path : path_t 2496 2497 * 2498 2499 dir_fd : dir_fd(requires='fstatat') = None 2500 2501Perform a stat system call on the given path, without following symbolic links. 2502 2503Like stat(), but do not follow symbolic links. 2504Equivalent to stat(path, follow_symlinks=False). 2505[clinic start generated code]*/ 2506 2507static PyObject * 2508os_lstat_impl(PyModuleDef *module, path_t *path, int dir_fd) 2509/*[clinic end generated code: output=7a748e333fcb39bd input=0b7474765927b925]*/ 2510{ 2511 int follow_symlinks = 0; 2512 return posix_do_stat("lstat", path, dir_fd, follow_symlinks); 2513} 2514 2515 2516/*[clinic input] 2517os.access -> bool 2518 2519 path: path_t(allow_fd=True) 2520 Path to be tested; can be string, bytes, or open-file-descriptor int. 2521 2522 mode: int 2523 Operating-system mode bitfield. Can be F_OK to test existence, 2524 or the inclusive-OR of R_OK, W_OK, and X_OK. 2525 2526 * 2527 2528 dir_fd : dir_fd(requires='faccessat') = None 2529 If not None, it should be a file descriptor open to a directory, 2530 and path should be relative; path will then be relative to that 2531 directory. 2532 2533 effective_ids: bool = False 2534 If True, access will use the effective uid/gid instead of 2535 the real uid/gid. 2536 2537 follow_symlinks: bool = True 2538 If False, and the last element of the path is a symbolic link, 2539 access will examine the symbolic link itself instead of the file 2540 the link points to. 2541 2542Use the real uid/gid to test for access to a path. 2543 2544{parameters} 2545dir_fd, effective_ids, and follow_symlinks may not be implemented 2546 on your platform. If they are unavailable, using them will raise a 2547 NotImplementedError. 2548 2549Note that most operations will use the effective uid/gid, therefore this 2550 routine can be used in a suid/sgid environment to test if the invoking user 2551 has the specified access to the path. 2552 2553[clinic start generated code]*/ 2554 2555static int 2556os_access_impl(PyModuleDef *module, path_t *path, int mode, int dir_fd, 2557 int effective_ids, int follow_symlinks) 2558/*[clinic end generated code: output=abaa53340210088d input=b75a756797af45ec]*/ 2559{ 2560 int return_value; 2561 2562#ifdef MS_WINDOWS 2563 DWORD attr; 2564#else 2565 int result; 2566#endif 2567 2568#ifndef HAVE_FACCESSAT 2569 if (follow_symlinks_specified("access", follow_symlinks)) 2570 return -1; 2571 2572 if (effective_ids) { 2573 argument_unavailable_error("access", "effective_ids"); 2574 return -1; 2575 } 2576#endif 2577 2578#ifdef MS_WINDOWS 2579 Py_BEGIN_ALLOW_THREADS 2580 if (path->wide != NULL) 2581 attr = GetFileAttributesW(path->wide); 2582 else 2583 attr = GetFileAttributesA(path->narrow); 2584 Py_END_ALLOW_THREADS 2585 2586 /* 2587 * Access is possible if 2588 * * we didn't get a -1, and 2589 * * write access wasn't requested, 2590 * * or the file isn't read-only, 2591 * * or it's a directory. 2592 * (Directories cannot be read-only on Windows.) 2593 */ 2594 return_value = (attr != INVALID_FILE_ATTRIBUTES) && 2595 (!(mode & 2) || 2596 !(attr & FILE_ATTRIBUTE_READONLY) || 2597 (attr & FILE_ATTRIBUTE_DIRECTORY)); 2598#else 2599 2600 Py_BEGIN_ALLOW_THREADS 2601#ifdef HAVE_FACCESSAT 2602 if ((dir_fd != DEFAULT_DIR_FD) || 2603 effective_ids || 2604 !follow_symlinks) { 2605 int flags = 0; 2606 if (!follow_symlinks) 2607 flags |= AT_SYMLINK_NOFOLLOW; 2608 if (effective_ids) 2609 flags |= AT_EACCESS; 2610 result = faccessat(dir_fd, path->narrow, mode, flags); 2611 } 2612 else 2613#endif 2614 result = access(path->narrow, mode); 2615 Py_END_ALLOW_THREADS 2616 return_value = !result; 2617#endif 2618 2619 return return_value; 2620} 2621 2622#ifndef F_OK 2623#define F_OK 0 2624#endif 2625#ifndef R_OK 2626#define R_OK 4 2627#endif 2628#ifndef W_OK 2629#define W_OK 2 2630#endif 2631#ifndef X_OK 2632#define X_OK 1 2633#endif 2634 2635 2636#ifdef HAVE_TTYNAME 2637/*[clinic input] 2638os.ttyname -> DecodeFSDefault 2639 2640 fd: int 2641 Integer file descriptor handle. 2642 2643 / 2644 2645Return the name of the terminal device connected to 'fd'. 2646[clinic start generated code]*/ 2647 2648static char * 2649os_ttyname_impl(PyModuleDef *module, int fd) 2650/*[clinic end generated code: output=03ad3d5ccaef75c3 input=5f72ca83e76b3b45]*/ 2651{ 2652 char *ret; 2653 2654 ret = ttyname(fd); 2655 if (ret == NULL) 2656 posix_error(); 2657 return ret; 2658} 2659#endif 2660 2661#ifdef HAVE_CTERMID 2662/*[clinic input] 2663os.ctermid 2664 2665Return the name of the controlling terminal for this process. 2666[clinic start generated code]*/ 2667 2668static PyObject * 2669os_ctermid_impl(PyModuleDef *module) 2670/*[clinic end generated code: output=1b73788201e0aebd input=3b87fdd52556382d]*/ 2671{ 2672 char *ret; 2673 char buffer[L_ctermid]; 2674 2675#ifdef USE_CTERMID_R 2676 ret = ctermid_r(buffer); 2677#else 2678 ret = ctermid(buffer); 2679#endif 2680 if (ret == NULL) 2681 return posix_error(); 2682 return PyUnicode_DecodeFSDefault(buffer); 2683} 2684#endif /* HAVE_CTERMID */ 2685 2686 2687/*[clinic input] 2688os.chdir 2689 2690 path: path_t(allow_fd='PATH_HAVE_FCHDIR') 2691 2692Change the current working directory to the specified path. 2693 2694path may always be specified as a string. 2695On some platforms, path may also be specified as an open file descriptor. 2696 If this functionality is unavailable, using it raises an exception. 2697[clinic start generated code]*/ 2698 2699static PyObject * 2700os_chdir_impl(PyModuleDef *module, path_t *path) 2701/*[clinic end generated code: output=7358e3a20fb5aa93 input=1a4a15b4d12cb15d]*/ 2702{ 2703 int result; 2704 2705 Py_BEGIN_ALLOW_THREADS 2706#ifdef MS_WINDOWS 2707 if (path->wide) 2708 result = win32_wchdir(path->wide); 2709 else 2710 result = win32_chdir(path->narrow); 2711 result = !result; /* on unix, success = 0, on windows, success = !0 */ 2712#else 2713#ifdef HAVE_FCHDIR 2714 if (path->fd != -1) 2715 result = fchdir(path->fd); 2716 else 2717#endif 2718 result = chdir(path->narrow); 2719#endif 2720 Py_END_ALLOW_THREADS 2721 2722 if (result) { 2723 return path_error(path); 2724 } 2725 2726 Py_RETURN_NONE; 2727} 2728 2729 2730#ifdef HAVE_FCHDIR 2731/*[clinic input] 2732os.fchdir 2733 2734 fd: fildes 2735 2736Change to the directory of the given file descriptor. 2737 2738fd must be opened on a directory, not a file. 2739Equivalent to os.chdir(fd). 2740 2741[clinic start generated code]*/ 2742 2743static PyObject * 2744os_fchdir_impl(PyModuleDef *module, int fd) 2745/*[clinic end generated code: output=361d30df6b2d3418 input=18e816479a2fa985]*/ 2746{ 2747 return posix_fildes_fd(fd, fchdir); 2748} 2749#endif /* HAVE_FCHDIR */ 2750 2751 2752/*[clinic input] 2753os.chmod 2754 2755 path: path_t(allow_fd='PATH_HAVE_FCHMOD') 2756 Path to be modified. May always be specified as a str or bytes. 2757 On some platforms, path may also be specified as an open file descriptor. 2758 If this functionality is unavailable, using it raises an exception. 2759 2760 mode: int 2761 Operating-system mode bitfield. 2762 2763 * 2764 2765 dir_fd : dir_fd(requires='fchmodat') = None 2766 If not None, it should be a file descriptor open to a directory, 2767 and path should be relative; path will then be relative to that 2768 directory. 2769 2770 follow_symlinks: bool = True 2771 If False, and the last element of the path is a symbolic link, 2772 chmod will modify the symbolic link itself instead of the file 2773 the link points to. 2774 2775Change the access permissions of a file. 2776 2777It is an error to use dir_fd or follow_symlinks when specifying path as 2778 an open file descriptor. 2779dir_fd and follow_symlinks may not be implemented on your platform. 2780 If they are unavailable, using them will raise a NotImplementedError. 2781 2782[clinic start generated code]*/ 2783 2784static PyObject * 2785os_chmod_impl(PyModuleDef *module, path_t *path, int mode, int dir_fd, 2786 int follow_symlinks) 2787/*[clinic end generated code: output=05e7f73b1a843ba2 input=7f1618e5e15cc196]*/ 2788{ 2789 int result; 2790 2791#ifdef MS_WINDOWS 2792 DWORD attr; 2793#endif 2794 2795#ifdef HAVE_FCHMODAT 2796 int fchmodat_nofollow_unsupported = 0; 2797#endif 2798 2799#if !(defined(HAVE_FCHMODAT) || defined(HAVE_LCHMOD)) 2800 if (follow_symlinks_specified("chmod", follow_symlinks)) 2801 return NULL; 2802#endif 2803 2804#ifdef MS_WINDOWS 2805 Py_BEGIN_ALLOW_THREADS 2806 if (path->wide) 2807 attr = GetFileAttributesW(path->wide); 2808 else 2809 attr = GetFileAttributesA(path->narrow); 2810 if (attr == INVALID_FILE_ATTRIBUTES) 2811 result = 0; 2812 else { 2813 if (mode & _S_IWRITE) 2814 attr &= ~FILE_ATTRIBUTE_READONLY; 2815 else 2816 attr |= FILE_ATTRIBUTE_READONLY; 2817 if (path->wide) 2818 result = SetFileAttributesW(path->wide, attr); 2819 else 2820 result = SetFileAttributesA(path->narrow, attr); 2821 } 2822 Py_END_ALLOW_THREADS 2823 2824 if (!result) { 2825 return path_error(path); 2826 } 2827#else /* MS_WINDOWS */ 2828 Py_BEGIN_ALLOW_THREADS 2829#ifdef HAVE_FCHMOD 2830 if (path->fd != -1) 2831 result = fchmod(path->fd, mode); 2832 else 2833#endif 2834#ifdef HAVE_LCHMOD 2835 if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD)) 2836 result = lchmod(path->narrow, mode); 2837 else 2838#endif 2839#ifdef HAVE_FCHMODAT 2840 if ((dir_fd != DEFAULT_DIR_FD) || !follow_symlinks) { 2841 /* 2842 * fchmodat() doesn't currently support AT_SYMLINK_NOFOLLOW! 2843 * The documentation specifically shows how to use it, 2844 * and then says it isn't implemented yet. 2845 * (true on linux with glibc 2.15, and openindiana 3.x) 2846 * 2847 * Once it is supported, os.chmod will automatically 2848 * support dir_fd and follow_symlinks=False. (Hopefully.) 2849 * Until then, we need to be careful what exception we raise. 2850 */ 2851 result = fchmodat(dir_fd, path->narrow, mode, 2852 follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW); 2853 /* 2854 * But wait! We can't throw the exception without allowing threads, 2855 * and we can't do that in this nested scope. (Macro trickery, sigh.) 2856 */ 2857 fchmodat_nofollow_unsupported = 2858 result && 2859 ((errno == ENOTSUP) || (errno == EOPNOTSUPP)) && 2860 !follow_symlinks; 2861 } 2862 else 2863#endif 2864 result = chmod(path->narrow, mode); 2865 Py_END_ALLOW_THREADS 2866 2867 if (result) { 2868#ifdef HAVE_FCHMODAT 2869 if (fchmodat_nofollow_unsupported) { 2870 if (dir_fd != DEFAULT_DIR_FD) 2871 dir_fd_and_follow_symlinks_invalid("chmod", 2872 dir_fd, follow_symlinks); 2873 else 2874 follow_symlinks_specified("chmod", follow_symlinks); 2875 } 2876 else 2877#endif 2878 return path_error(path); 2879 } 2880#endif 2881 2882 Py_RETURN_NONE; 2883} 2884 2885 2886#ifdef HAVE_FCHMOD 2887/*[clinic input] 2888os.fchmod 2889 2890 fd: int 2891 mode: int 2892 2893Change the access permissions of the file given by file descriptor fd. 2894 2895Equivalent to os.chmod(fd, mode). 2896[clinic start generated code]*/ 2897 2898static PyObject * 2899os_fchmod_impl(PyModuleDef *module, int fd, int mode) 2900/*[clinic end generated code: output=2ee31ca226d1ed33 input=8ab11975ca01ee5b]*/ 2901{ 2902 int res; 2903 int async_err = 0; 2904 2905 do { 2906 Py_BEGIN_ALLOW_THREADS 2907 res = fchmod(fd, mode); 2908 Py_END_ALLOW_THREADS 2909 } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); 2910 if (res != 0) 2911 return (!async_err) ? posix_error() : NULL; 2912 2913 Py_RETURN_NONE; 2914} 2915#endif /* HAVE_FCHMOD */ 2916 2917 2918#ifdef HAVE_LCHMOD 2919/*[clinic input] 2920os.lchmod 2921 2922 path: path_t 2923 mode: int 2924 2925Change the access permissions of a file, without following symbolic links. 2926 2927If path is a symlink, this affects the link itself rather than the target. 2928Equivalent to chmod(path, mode, follow_symlinks=False)." 2929[clinic start generated code]*/ 2930 2931static PyObject * 2932os_lchmod_impl(PyModuleDef *module, path_t *path, int mode) 2933/*[clinic end generated code: output=7c0cc46588d89e46 input=90c5663c7465d24f]*/ 2934{ 2935 int res; 2936 Py_BEGIN_ALLOW_THREADS 2937 res = lchmod(path->narrow, mode); 2938 Py_END_ALLOW_THREADS 2939 if (res < 0) { 2940 path_error(path); 2941 return NULL; 2942 } 2943 Py_RETURN_NONE; 2944} 2945#endif /* HAVE_LCHMOD */ 2946 2947 2948#ifdef HAVE_CHFLAGS 2949/*[clinic input] 2950os.chflags 2951 2952 path: path_t 2953 flags: unsigned_long(bitwise=True) 2954 follow_symlinks: bool=True 2955 2956Set file flags. 2957 2958If follow_symlinks is False, and the last element of the path is a symbolic 2959 link, chflags will change flags on the symbolic link itself instead of the 2960 file the link points to. 2961follow_symlinks may not be implemented on your platform. If it is 2962unavailable, using it will raise a NotImplementedError. 2963 2964[clinic start generated code]*/ 2965 2966static PyObject * 2967os_chflags_impl(PyModuleDef *module, path_t *path, unsigned long flags, 2968 int follow_symlinks) 2969/*[clinic end generated code: output=ff2d6e73534a95b9 input=0327e29feb876236]*/ 2970{ 2971 int result; 2972 2973#ifndef HAVE_LCHFLAGS 2974 if (follow_symlinks_specified("chflags", follow_symlinks)) 2975 return NULL; 2976#endif 2977 2978 Py_BEGIN_ALLOW_THREADS 2979#ifdef HAVE_LCHFLAGS 2980 if (!follow_symlinks) 2981 result = lchflags(path->narrow, flags); 2982 else 2983#endif 2984 result = chflags(path->narrow, flags); 2985 Py_END_ALLOW_THREADS 2986 2987 if (result) 2988 return path_error(path); 2989 2990 Py_RETURN_NONE; 2991} 2992#endif /* HAVE_CHFLAGS */ 2993 2994 2995#ifdef HAVE_LCHFLAGS 2996/*[clinic input] 2997os.lchflags 2998 2999 path: path_t 3000 flags: unsigned_long(bitwise=True) 3001 3002Set file flags. 3003 3004This function will not follow symbolic links. 3005Equivalent to chflags(path, flags, follow_symlinks=False). 3006[clinic start generated code]*/ 3007 3008static PyObject * 3009os_lchflags_impl(PyModuleDef *module, path_t *path, unsigned long flags) 3010/*[clinic end generated code: output=6741322fb949661b input=f9f82ea8b585ca9d]*/ 3011{ 3012 int res; 3013 Py_BEGIN_ALLOW_THREADS 3014 res = lchflags(path->narrow, flags); 3015 Py_END_ALLOW_THREADS 3016 if (res < 0) { 3017 return path_error(path); 3018 } 3019 Py_RETURN_NONE; 3020} 3021#endif /* HAVE_LCHFLAGS */ 3022 3023 3024#ifdef HAVE_CHROOT 3025/*[clinic input] 3026os.chroot 3027 path: path_t 3028 3029Change root directory to path. 3030 3031[clinic start generated code]*/ 3032 3033static PyObject * 3034os_chroot_impl(PyModuleDef *module, path_t *path) 3035/*[clinic end generated code: output=b6dbfabe74ecaa9d input=14822965652c3dc3]*/ 3036{ 3037 int res; 3038 Py_BEGIN_ALLOW_THREADS 3039 res = chroot(path->narrow); 3040 Py_END_ALLOW_THREADS 3041 if (res < 0) 3042 return path_error(path); 3043 Py_RETURN_NONE; 3044} 3045#endif /* HAVE_CHROOT */ 3046 3047 3048#ifdef HAVE_FSYNC 3049/*[clinic input] 3050os.fsync 3051 3052 fd: fildes 3053 3054Force write of fd to disk. 3055[clinic start generated code]*/ 3056 3057static PyObject * 3058os_fsync_impl(PyModuleDef *module, int fd) 3059/*[clinic end generated code: output=83a350851064aea7 input=21c3645c056967f2]*/ 3060{ 3061 return posix_fildes_fd(fd, fsync); 3062} 3063#endif /* HAVE_FSYNC */ 3064 3065 3066#ifdef HAVE_SYNC 3067/*[clinic input] 3068os.sync 3069 3070Force write of everything to disk. 3071[clinic start generated code]*/ 3072 3073static PyObject * 3074os_sync_impl(PyModuleDef *module) 3075/*[clinic end generated code: output=ba524f656c201c40 input=84749fe5e9b404ff]*/ 3076{ 3077 Py_BEGIN_ALLOW_THREADS 3078 sync(); 3079 Py_END_ALLOW_THREADS 3080 Py_RETURN_NONE; 3081} 3082#endif /* HAVE_SYNC */ 3083 3084 3085#ifdef HAVE_FDATASYNC 3086#ifdef __hpux 3087extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */ 3088#endif 3089 3090/*[clinic input] 3091os.fdatasync 3092 3093 fd: fildes 3094 3095Force write of fd to disk without forcing update of metadata. 3096[clinic start generated code]*/ 3097 3098static PyObject * 3099os_fdatasync_impl(PyModuleDef *module, int fd) 3100/*[clinic end generated code: output=e0f04a3aff515b75 input=bc74791ee54dd291]*/ 3101{ 3102 return posix_fildes_fd(fd, fdatasync); 3103} 3104#endif /* HAVE_FDATASYNC */ 3105 3106 3107#ifdef HAVE_CHOWN 3108/*[clinic input] 3109os.chown 3110 3111 path : path_t(allow_fd='PATH_HAVE_FCHOWN') 3112 Path to be examined; can be string, bytes, or open-file-descriptor int. 3113 3114 uid: uid_t 3115 3116 gid: gid_t 3117 3118 * 3119 3120 dir_fd : dir_fd(requires='fchownat') = None 3121 If not None, it should be a file descriptor open to a directory, 3122 and path should be relative; path will then be relative to that 3123 directory. 3124 3125 follow_symlinks: bool = True 3126 If False, and the last element of the path is a symbolic link, 3127 stat will examine the symbolic link itself instead of the file 3128 the link points to. 3129 3130Change the owner and group id of path to the numeric uid and gid.\ 3131 3132path may always be specified as a string. 3133On some platforms, path may also be specified as an open file descriptor. 3134 If this functionality is unavailable, using it raises an exception. 3135If dir_fd is not None, it should be a file descriptor open to a directory, 3136 and path should be relative; path will then be relative to that directory. 3137If follow_symlinks is False, and the last element of the path is a symbolic 3138 link, chown will modify the symbolic link itself instead of the file the 3139 link points to. 3140It is an error to use dir_fd or follow_symlinks when specifying path as 3141 an open file descriptor. 3142dir_fd and follow_symlinks may not be implemented on your platform. 3143 If they are unavailable, using them will raise a NotImplementedError. 3144 3145[clinic start generated code]*/ 3146 3147static PyObject * 3148os_chown_impl(PyModuleDef *module, path_t *path, uid_t uid, gid_t gid, 3149 int dir_fd, int follow_symlinks) 3150/*[clinic end generated code: output=e0a4559f394dbd91 input=a61cc35574814d5d]*/ 3151{ 3152 int result; 3153 3154#if !(defined(HAVE_LCHOWN) || defined(HAVE_FCHOWNAT)) 3155 if (follow_symlinks_specified("chown", follow_symlinks)) 3156 return NULL; 3157#endif 3158 if (dir_fd_and_fd_invalid("chown", dir_fd, path->fd) || 3159 fd_and_follow_symlinks_invalid("chown", path->fd, follow_symlinks)) 3160 return NULL; 3161 3162#ifdef __APPLE__ 3163 /* 3164 * This is for Mac OS X 10.3, which doesn't have lchown. 3165 * (But we still have an lchown symbol because of weak-linking.) 3166 * It doesn't have fchownat either. So there's no possibility 3167 * of a graceful failover. 3168 */ 3169 if ((!follow_symlinks) && (lchown == NULL)) { 3170 follow_symlinks_specified("chown", follow_symlinks); 3171 return NULL; 3172 } 3173#endif 3174 3175 Py_BEGIN_ALLOW_THREADS 3176#ifdef HAVE_FCHOWN 3177 if (path->fd != -1) 3178 result = fchown(path->fd, uid, gid); 3179 else 3180#endif 3181#ifdef HAVE_LCHOWN 3182 if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD)) 3183 result = lchown(path->narrow, uid, gid); 3184 else 3185#endif 3186#ifdef HAVE_FCHOWNAT 3187 if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) 3188 result = fchownat(dir_fd, path->narrow, uid, gid, 3189 follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW); 3190 else 3191#endif 3192 result = chown(path->narrow, uid, gid); 3193 Py_END_ALLOW_THREADS 3194 3195 if (result) 3196 return path_error(path); 3197 3198 Py_RETURN_NONE; 3199} 3200#endif /* HAVE_CHOWN */ 3201 3202 3203#ifdef HAVE_FCHOWN 3204/*[clinic input] 3205os.fchown 3206 3207 fd: int 3208 uid: uid_t 3209 gid: gid_t 3210 3211Change the owner and group id of the file specified by file descriptor. 3212 3213Equivalent to os.chown(fd, uid, gid). 3214 3215[clinic start generated code]*/ 3216 3217static PyObject * 3218os_fchown_impl(PyModuleDef *module, int fd, uid_t uid, gid_t gid) 3219/*[clinic end generated code: output=7545abf8f6086d76 input=3af544ba1b13a0d7]*/ 3220{ 3221 int res; 3222 int async_err = 0; 3223 3224 do { 3225 Py_BEGIN_ALLOW_THREADS 3226 res = fchown(fd, uid, gid); 3227 Py_END_ALLOW_THREADS 3228 } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); 3229 if (res != 0) 3230 return (!async_err) ? posix_error() : NULL; 3231 3232 Py_RETURN_NONE; 3233} 3234#endif /* HAVE_FCHOWN */ 3235 3236 3237#ifdef HAVE_LCHOWN 3238/*[clinic input] 3239os.lchown 3240 3241 path : path_t 3242 uid: uid_t 3243 gid: gid_t 3244 3245Change the owner and group id of path to the numeric uid and gid. 3246 3247This function will not follow symbolic links. 3248Equivalent to os.chown(path, uid, gid, follow_symlinks=False). 3249[clinic start generated code]*/ 3250 3251static PyObject * 3252os_lchown_impl(PyModuleDef *module, path_t *path, uid_t uid, gid_t gid) 3253/*[clinic end generated code: output=bb0d2da1579ac275 input=b1c6014d563a7161]*/ 3254{ 3255 int res; 3256 Py_BEGIN_ALLOW_THREADS 3257 res = lchown(path->narrow, uid, gid); 3258 Py_END_ALLOW_THREADS 3259 if (res < 0) { 3260 return path_error(path); 3261 } 3262 Py_RETURN_NONE; 3263} 3264#endif /* HAVE_LCHOWN */ 3265 3266 3267static PyObject * 3268posix_getcwd(int use_bytes) 3269{ 3270 char *buf, *tmpbuf; 3271 char *cwd; 3272 const size_t chunk = 1024; 3273 size_t buflen = 0; 3274 PyObject *obj; 3275 3276#ifdef MS_WINDOWS 3277 if (!use_bytes) { 3278 wchar_t wbuf[MAXPATHLEN]; 3279 wchar_t *wbuf2 = wbuf; 3280 PyObject *resobj; 3281 DWORD len; 3282 Py_BEGIN_ALLOW_THREADS 3283 len = GetCurrentDirectoryW(Py_ARRAY_LENGTH(wbuf), wbuf); 3284 /* If the buffer is large enough, len does not include the 3285 terminating \0. If the buffer is too small, len includes 3286 the space needed for the terminator. */ 3287 if (len >= Py_ARRAY_LENGTH(wbuf)) { 3288 wbuf2 = PyMem_RawMalloc(len * sizeof(wchar_t)); 3289 if (wbuf2) 3290 len = GetCurrentDirectoryW(len, wbuf2); 3291 } 3292 Py_END_ALLOW_THREADS 3293 if (!wbuf2) { 3294 PyErr_NoMemory(); 3295 return NULL; 3296 } 3297 if (!len) { 3298 if (wbuf2 != wbuf) 3299 PyMem_RawFree(wbuf2); 3300 return PyErr_SetFromWindowsErr(0); 3301 } 3302 resobj = PyUnicode_FromWideChar(wbuf2, len); 3303 if (wbuf2 != wbuf) 3304 PyMem_RawFree(wbuf2); 3305 return resobj; 3306 } 3307 3308 if (win32_warn_bytes_api()) 3309 return NULL; 3310#endif 3311 3312 buf = cwd = NULL; 3313 Py_BEGIN_ALLOW_THREADS 3314 do { 3315 buflen += chunk; 3316 tmpbuf = PyMem_RawRealloc(buf, buflen); 3317 if (tmpbuf == NULL) 3318 break; 3319 3320 buf = tmpbuf; 3321 cwd = getcwd(buf, buflen); 3322 } while (cwd == NULL && errno == ERANGE); 3323 Py_END_ALLOW_THREADS 3324 3325 if (cwd == NULL) { 3326 PyMem_RawFree(buf); 3327 return posix_error(); 3328 } 3329 3330 if (use_bytes) 3331 obj = PyBytes_FromStringAndSize(buf, strlen(buf)); 3332 else 3333 obj = PyUnicode_DecodeFSDefault(buf); 3334 PyMem_RawFree(buf); 3335 3336 return obj; 3337} 3338 3339 3340/*[clinic input] 3341os.getcwd 3342 3343Return a unicode string representing the current working directory. 3344[clinic start generated code]*/ 3345 3346static PyObject * 3347os_getcwd_impl(PyModuleDef *module) 3348/*[clinic end generated code: output=efe3a8c0121525ea input=f069211bb70e3d39]*/ 3349{ 3350 return posix_getcwd(0); 3351} 3352 3353 3354/*[clinic input] 3355os.getcwdb 3356 3357Return a bytes string representing the current working directory. 3358[clinic start generated code]*/ 3359 3360static PyObject * 3361os_getcwdb_impl(PyModuleDef *module) 3362/*[clinic end generated code: output=7fce42ee4b2a296a input=f6f6a378dad3d9cb]*/ 3363{ 3364 return posix_getcwd(1); 3365} 3366 3367 3368#if ((!defined(HAVE_LINK)) && defined(MS_WINDOWS)) 3369#define HAVE_LINK 1 3370#endif 3371 3372#ifdef HAVE_LINK 3373/*[clinic input] 3374 3375os.link 3376 3377 src : path_t 3378 dst : path_t 3379 * 3380 src_dir_fd : dir_fd = None 3381 dst_dir_fd : dir_fd = None 3382 follow_symlinks: bool = True 3383 3384Create a hard link to a file. 3385 3386If either src_dir_fd or dst_dir_fd is not None, it should be a file 3387 descriptor open to a directory, and the respective path string (src or dst) 3388 should be relative; the path will then be relative to that directory. 3389If follow_symlinks is False, and the last element of src is a symbolic 3390 link, link will create a link to the symbolic link itself instead of the 3391 file the link points to. 3392src_dir_fd, dst_dir_fd, and follow_symlinks may not be implemented on your 3393 platform. If they are unavailable, using them will raise a 3394 NotImplementedError. 3395[clinic start generated code]*/ 3396 3397static PyObject * 3398os_link_impl(PyModuleDef *module, path_t *src, path_t *dst, int src_dir_fd, 3399 int dst_dir_fd, int follow_symlinks) 3400/*[clinic end generated code: output=f47a7e88f7b391b6 input=b0095ebbcbaa7e04]*/ 3401{ 3402#ifdef MS_WINDOWS 3403 BOOL result; 3404#else 3405 int result; 3406#endif 3407 3408#ifndef HAVE_LINKAT 3409 if ((src_dir_fd != DEFAULT_DIR_FD) || (dst_dir_fd != DEFAULT_DIR_FD)) { 3410 argument_unavailable_error("link", "src_dir_fd and dst_dir_fd"); 3411 return NULL; 3412 } 3413#endif 3414 3415 if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) { 3416 PyErr_SetString(PyExc_NotImplementedError, 3417 "link: src and dst must be the same type"); 3418 return NULL; 3419 } 3420 3421#ifdef MS_WINDOWS 3422 Py_BEGIN_ALLOW_THREADS 3423 if (src->wide) 3424 result = CreateHardLinkW(dst->wide, src->wide, NULL); 3425 else 3426 result = CreateHardLinkA(dst->narrow, src->narrow, NULL); 3427 Py_END_ALLOW_THREADS 3428 3429 if (!result) 3430 return path_error2(src, dst); 3431#else 3432 Py_BEGIN_ALLOW_THREADS 3433#ifdef HAVE_LINKAT 3434 if ((src_dir_fd != DEFAULT_DIR_FD) || 3435 (dst_dir_fd != DEFAULT_DIR_FD) || 3436 (!follow_symlinks)) 3437 result = linkat(src_dir_fd, src->narrow, 3438 dst_dir_fd, dst->narrow, 3439 follow_symlinks ? AT_SYMLINK_FOLLOW : 0); 3440 else 3441#endif 3442 result = link(src->narrow, dst->narrow); 3443 Py_END_ALLOW_THREADS 3444 3445 if (result) 3446 return path_error2(src, dst); 3447#endif 3448 3449 Py_RETURN_NONE; 3450} 3451#endif 3452 3453 3454#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR) 3455static PyObject * 3456_listdir_windows_no_opendir(path_t *path, PyObject *list) 3457{ 3458 PyObject *v; 3459 HANDLE hFindFile = INVALID_HANDLE_VALUE; 3460 BOOL result; 3461 WIN32_FIND_DATA FileData; 3462 char namebuf[MAX_PATH+4]; /* Overallocate for "\*.*" */ 3463 char *bufptr = namebuf; 3464 /* only claim to have space for MAX_PATH */ 3465 Py_ssize_t len = Py_ARRAY_LENGTH(namebuf)-4; 3466 PyObject *po = NULL; 3467 wchar_t *wnamebuf = NULL; 3468 3469 if (!path->narrow) { 3470 WIN32_FIND_DATAW wFileData; 3471 wchar_t *po_wchars; 3472 3473 if (!path->wide) { /* Default arg: "." */ 3474 po_wchars = L"."; 3475 len = 1; 3476 } else { 3477 po_wchars = path->wide; 3478 len = wcslen(path->wide); 3479 } 3480 /* The +5 is so we can append "\\*.*\0" */ 3481 wnamebuf = PyMem_New(wchar_t, len + 5); 3482 if (!wnamebuf) { 3483 PyErr_NoMemory(); 3484 goto exit; 3485 } 3486 wcscpy(wnamebuf, po_wchars); 3487 if (len > 0) { 3488 wchar_t wch = wnamebuf[len-1]; 3489 if (wch != SEP && wch != ALTSEP && wch != L':') 3490 wnamebuf[len++] = SEP; 3491 wcscpy(wnamebuf + len, L"*.*"); 3492 } 3493 if ((list = PyList_New(0)) == NULL) { 3494 goto exit; 3495 } 3496 Py_BEGIN_ALLOW_THREADS 3497 hFindFile = FindFirstFileW(wnamebuf, &wFileData); 3498 Py_END_ALLOW_THREADS 3499 if (hFindFile == INVALID_HANDLE_VALUE) { 3500 int error = GetLastError(); 3501 if (error == ERROR_FILE_NOT_FOUND) 3502 goto exit; 3503 Py_DECREF(list); 3504 list = path_error(path); 3505 goto exit; 3506 } 3507 do { 3508 /* Skip over . and .. */ 3509 if (wcscmp(wFileData.cFileName, L".") != 0 && 3510 wcscmp(wFileData.cFileName, L"..") != 0) { 3511 v = PyUnicode_FromWideChar(wFileData.cFileName, 3512 wcslen(wFileData.cFileName)); 3513 if (v == NULL) { 3514 Py_DECREF(list); 3515 list = NULL; 3516 break; 3517 } 3518 if (PyList_Append(list, v) != 0) { 3519 Py_DECREF(v); 3520 Py_DECREF(list); 3521 list = NULL; 3522 break; 3523 } 3524 Py_DECREF(v); 3525 } 3526 Py_BEGIN_ALLOW_THREADS 3527 result = FindNextFileW(hFindFile, &wFileData); 3528 Py_END_ALLOW_THREADS 3529 /* FindNextFile sets error to ERROR_NO_MORE_FILES if 3530 it got to the end of the directory. */ 3531 if (!result && GetLastError() != ERROR_NO_MORE_FILES) { 3532 Py_DECREF(list); 3533 list = path_error(path); 3534 goto exit; 3535 } 3536 } while (result == TRUE); 3537 3538 goto exit; 3539 } 3540 strcpy(namebuf, path->narrow); 3541 len = path->length; 3542 if (len > 0) { 3543 char ch = namebuf[len-1]; 3544 if (ch != '\\' && ch != '/' && ch != ':') 3545 namebuf[len++] = '\\'; 3546 strcpy(namebuf + len, "*.*"); 3547 } 3548 3549 if ((list = PyList_New(0)) == NULL) 3550 return NULL; 3551 3552 Py_BEGIN_ALLOW_THREADS 3553 hFindFile = FindFirstFile(namebuf, &FileData); 3554 Py_END_ALLOW_THREADS 3555 if (hFindFile == INVALID_HANDLE_VALUE) { 3556 int error = GetLastError(); 3557 if (error == ERROR_FILE_NOT_FOUND) 3558 goto exit; 3559 Py_DECREF(list); 3560 list = path_error(path); 3561 goto exit; 3562 } 3563 do { 3564 /* Skip over . and .. */ 3565 if (strcmp(FileData.cFileName, ".") != 0 && 3566 strcmp(FileData.cFileName, "..") != 0) { 3567 v = PyBytes_FromString(FileData.cFileName); 3568 if (v == NULL) { 3569 Py_DECREF(list); 3570 list = NULL; 3571 break; 3572 } 3573 if (PyList_Append(list, v) != 0) { 3574 Py_DECREF(v); 3575 Py_DECREF(list); 3576 list = NULL; 3577 break; 3578 } 3579 Py_DECREF(v); 3580 } 3581 Py_BEGIN_ALLOW_THREADS 3582 result = FindNextFile(hFindFile, &FileData); 3583 Py_END_ALLOW_THREADS 3584 /* FindNextFile sets error to ERROR_NO_MORE_FILES if 3585 it got to the end of the directory. */ 3586 if (!result && GetLastError() != ERROR_NO_MORE_FILES) { 3587 Py_DECREF(list); 3588 list = path_error(path); 3589 goto exit; 3590 } 3591 } while (result == TRUE); 3592 3593exit: 3594 if (hFindFile != INVALID_HANDLE_VALUE) { 3595 if (FindClose(hFindFile) == FALSE) { 3596 if (list != NULL) { 3597 Py_DECREF(list); 3598 list = path_error(path); 3599 } 3600 } 3601 } 3602 PyMem_Free(wnamebuf); 3603 3604 return list; 3605} /* end of _listdir_windows_no_opendir */ 3606 3607#else /* thus POSIX, ie: not (MS_WINDOWS and not HAVE_OPENDIR) */ 3608 3609static PyObject * 3610_posix_listdir(path_t *path, PyObject *list) 3611{ 3612 PyObject *v; 3613 DIR *dirp = NULL; 3614 struct dirent *ep; 3615 int return_str; /* if false, return bytes */ 3616#ifdef HAVE_FDOPENDIR 3617 int fd = -1; 3618#endif 3619 3620 errno = 0; 3621#ifdef HAVE_FDOPENDIR 3622 if (path->fd != -1) { 3623 /* closedir() closes the FD, so we duplicate it */ 3624 fd = _Py_dup(path->fd); 3625 if (fd == -1) 3626 return NULL; 3627 3628 return_str = 1; 3629 3630 Py_BEGIN_ALLOW_THREADS 3631 dirp = fdopendir(fd); 3632 Py_END_ALLOW_THREADS 3633 } 3634 else 3635#endif 3636 { 3637 char *name; 3638 if (path->narrow) { 3639 name = path->narrow; 3640 /* only return bytes if they specified a bytes object */ 3641 return_str = !(PyBytes_Check(path->object)); 3642 } 3643 else { 3644 name = "."; 3645 return_str = 1; 3646 } 3647 3648 Py_BEGIN_ALLOW_THREADS 3649 dirp = opendir(name); 3650 Py_END_ALLOW_THREADS 3651 } 3652 3653 if (dirp == NULL) { 3654 list = path_error(path); 3655#ifdef HAVE_FDOPENDIR 3656 if (fd != -1) { 3657 Py_BEGIN_ALLOW_THREADS 3658 close(fd); 3659 Py_END_ALLOW_THREADS 3660 } 3661#endif 3662 goto exit; 3663 } 3664 if ((list = PyList_New(0)) == NULL) { 3665 goto exit; 3666 } 3667 for (;;) { 3668 errno = 0; 3669 Py_BEGIN_ALLOW_THREADS 3670 ep = readdir(dirp); 3671 Py_END_ALLOW_THREADS 3672 if (ep == NULL) { 3673 if (errno == 0) { 3674 break; 3675 } else { 3676 Py_DECREF(list); 3677 list = path_error(path); 3678 goto exit; 3679 } 3680 } 3681 if (ep->d_name[0] == '.' && 3682 (NAMLEN(ep) == 1 || 3683 (ep->d_name[1] == '.' && NAMLEN(ep) == 2))) 3684 continue; 3685 if (return_str) 3686 v = PyUnicode_DecodeFSDefaultAndSize(ep->d_name, NAMLEN(ep)); 3687 else 3688 v = PyBytes_FromStringAndSize(ep->d_name, NAMLEN(ep)); 3689 if (v == NULL) { 3690 Py_CLEAR(list); 3691 break; 3692 } 3693 if (PyList_Append(list, v) != 0) { 3694 Py_DECREF(v); 3695 Py_CLEAR(list); 3696 break; 3697 } 3698 Py_DECREF(v); 3699 } 3700 3701exit: 3702 if (dirp != NULL) { 3703 Py_BEGIN_ALLOW_THREADS 3704#ifdef HAVE_FDOPENDIR 3705 if (fd > -1) 3706 rewinddir(dirp); 3707#endif 3708 closedir(dirp); 3709 Py_END_ALLOW_THREADS 3710 } 3711 3712 return list; 3713} /* end of _posix_listdir */ 3714#endif /* which OS */ 3715 3716 3717/*[clinic input] 3718os.listdir 3719 3720 path : path_t(nullable=True, allow_fd='PATH_HAVE_FDOPENDIR') = None 3721 3722Return a list containing the names of the files in the directory. 3723 3724path can be specified as either str or bytes. If path is bytes, 3725 the filenames returned will also be bytes; in all other circumstances 3726 the filenames returned will be str. 3727If path is None, uses the path='.'. 3728On some platforms, path may also be specified as an open file descriptor;\ 3729 the file descriptor must refer to a directory. 3730 If this functionality is unavailable, using it raises NotImplementedError. 3731 3732The list is in arbitrary order. It does not include the special 3733entries '.' and '..' even if they are present in the directory. 3734 3735 3736[clinic start generated code]*/ 3737 3738static PyObject * 3739os_listdir_impl(PyModuleDef *module, path_t *path) 3740/*[clinic end generated code: output=1fbe67c1f780c8b7 input=09e300416e3cd729]*/ 3741{ 3742#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR) 3743 return _listdir_windows_no_opendir(path, NULL); 3744#else 3745 return _posix_listdir(path, NULL); 3746#endif 3747} 3748 3749#ifdef MS_WINDOWS 3750/* A helper function for abspath on win32 */ 3751/*[clinic input] 3752os._getfullpathname 3753 3754 path: path_t 3755 / 3756 3757[clinic start generated code]*/ 3758 3759static PyObject * 3760os__getfullpathname_impl(PyModuleDef *module, path_t *path) 3761/*[clinic end generated code: output=b90b1f103b08773f input=332ed537c29d0a3e]*/ 3762{ 3763 if (!path->narrow) 3764 { 3765 wchar_t woutbuf[MAX_PATH], *woutbufp = woutbuf; 3766 wchar_t *wtemp; 3767 DWORD result; 3768 PyObject *v; 3769 3770 result = GetFullPathNameW(path->wide, 3771 Py_ARRAY_LENGTH(woutbuf), 3772 woutbuf, &wtemp); 3773 if (result > Py_ARRAY_LENGTH(woutbuf)) { 3774 woutbufp = PyMem_New(wchar_t, result); 3775 if (!woutbufp) 3776 return PyErr_NoMemory(); 3777 result = GetFullPathNameW(path->wide, result, woutbufp, &wtemp); 3778 } 3779 if (result) 3780 v = PyUnicode_FromWideChar(woutbufp, wcslen(woutbufp)); 3781 else 3782 v = win32_error_object("GetFullPathNameW", path->object); 3783 if (woutbufp != woutbuf) 3784 PyMem_Free(woutbufp); 3785 return v; 3786 } 3787 else { 3788 char outbuf[MAX_PATH]; 3789 char *temp; 3790 3791 if (!GetFullPathName(path->narrow, Py_ARRAY_LENGTH(outbuf), 3792 outbuf, &temp)) { 3793 win32_error_object("GetFullPathName", path->object); 3794 return NULL; 3795 } 3796 return PyBytes_FromString(outbuf); 3797 } 3798} 3799 3800 3801/*[clinic input] 3802os._getfinalpathname 3803 3804 path: unicode 3805 / 3806 3807A helper function for samepath on windows. 3808[clinic start generated code]*/ 3809 3810static PyObject * 3811os__getfinalpathname_impl(PyModuleDef *module, PyObject *path) 3812/*[clinic end generated code: output=8be81a5f51a34bcf input=71d5e89334891bf4]*/ 3813{ 3814 HANDLE hFile; 3815 int buf_size; 3816 wchar_t *target_path; 3817 int result_length; 3818 PyObject *result; 3819 wchar_t *path_wchar; 3820 3821 path_wchar = PyUnicode_AsUnicode(path); 3822 if (path_wchar == NULL) 3823 return NULL; 3824 3825 hFile = CreateFileW( 3826 path_wchar, 3827 0, /* desired access */ 3828 0, /* share mode */ 3829 NULL, /* security attributes */ 3830 OPEN_EXISTING, 3831 /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */ 3832 FILE_FLAG_BACKUP_SEMANTICS, 3833 NULL); 3834 3835 if(hFile == INVALID_HANDLE_VALUE) 3836 return win32_error_object("CreateFileW", path); 3837 3838 /* We have a good handle to the target, use it to determine the 3839 target path name. */ 3840 buf_size = GetFinalPathNameByHandleW(hFile, 0, 0, VOLUME_NAME_NT); 3841 3842 if(!buf_size) 3843 return win32_error_object("GetFinalPathNameByHandle", path); 3844 3845 target_path = PyMem_New(wchar_t, buf_size+1); 3846 if(!target_path) 3847 return PyErr_NoMemory(); 3848 3849 result_length = GetFinalPathNameByHandleW(hFile, target_path, 3850 buf_size, VOLUME_NAME_DOS); 3851 if(!result_length) 3852 return win32_error_object("GetFinalPathNamyByHandle", path); 3853 3854 if(!CloseHandle(hFile)) 3855 return win32_error_object("CloseHandle", path); 3856 3857 target_path[result_length] = 0; 3858 result = PyUnicode_FromWideChar(target_path, result_length); 3859 PyMem_Free(target_path); 3860 return result; 3861} 3862 3863PyDoc_STRVAR(posix__isdir__doc__, 3864"Return true if the pathname refers to an existing directory."); 3865 3866/*[clinic input] 3867os._isdir 3868 3869 path: path_t 3870 / 3871 3872[clinic start generated code]*/ 3873 3874static PyObject * 3875os__isdir_impl(PyModuleDef *module, path_t *path) 3876/*[clinic end generated code: output=f17b2d4e1994b0ff input=e794f12faab62a2a]*/ 3877{ 3878 DWORD attributes; 3879 3880 if (!path->narrow) 3881 attributes = GetFileAttributesW(path->wide); 3882 else 3883 attributes = GetFileAttributesA(path->narrow); 3884 3885 if (attributes == INVALID_FILE_ATTRIBUTES) 3886 Py_RETURN_FALSE; 3887 3888 if (attributes & FILE_ATTRIBUTE_DIRECTORY) 3889 Py_RETURN_TRUE; 3890 else 3891 Py_RETURN_FALSE; 3892} 3893 3894 3895/*[clinic input] 3896os._getvolumepathname 3897 3898 path: unicode 3899 3900A helper function for ismount on Win32. 3901[clinic start generated code]*/ 3902 3903static PyObject * 3904os__getvolumepathname_impl(PyModuleDef *module, PyObject *path) 3905/*[clinic end generated code: output=79a0ba729f956dbe input=7eacadc40acbda6b]*/ 3906{ 3907 PyObject *result; 3908 wchar_t *path_wchar, *mountpath=NULL; 3909 size_t buflen; 3910 BOOL ret; 3911 3912 path_wchar = PyUnicode_AsUnicodeAndSize(path, &buflen); 3913 if (path_wchar == NULL) 3914 return NULL; 3915 buflen += 1; 3916 3917 /* Volume path should be shorter than entire path */ 3918 buflen = Py_MAX(buflen, MAX_PATH); 3919 3920 if (buflen > DWORD_MAX) { 3921 PyErr_SetString(PyExc_OverflowError, "path too long"); 3922 return NULL; 3923 } 3924 3925 mountpath = PyMem_New(wchar_t, buflen); 3926 if (mountpath == NULL) 3927 return PyErr_NoMemory(); 3928 3929 Py_BEGIN_ALLOW_THREADS 3930 ret = GetVolumePathNameW(path_wchar, mountpath, 3931 Py_SAFE_DOWNCAST(buflen, size_t, DWORD)); 3932 Py_END_ALLOW_THREADS 3933 3934 if (!ret) { 3935 result = win32_error_object("_getvolumepathname", path); 3936 goto exit; 3937 } 3938 result = PyUnicode_FromWideChar(mountpath, wcslen(mountpath)); 3939 3940exit: 3941 PyMem_Free(mountpath); 3942 return result; 3943} 3944 3945#endif /* MS_WINDOWS */ 3946 3947 3948/*[clinic input] 3949os.mkdir 3950 3951 path : path_t 3952 3953 mode: int = 0o777 3954 3955 * 3956 3957 dir_fd : dir_fd(requires='mkdirat') = None 3958 3959# "mkdir(path, mode=0o777, *, dir_fd=None)\n\n\ 3960 3961Create a directory. 3962 3963If dir_fd is not None, it should be a file descriptor open to a directory, 3964 and path should be relative; path will then be relative to that directory. 3965dir_fd may not be implemented on your platform. 3966 If it is unavailable, using it will raise a NotImplementedError. 3967 3968The mode argument is ignored on Windows. 3969[clinic start generated code]*/ 3970 3971static PyObject * 3972os_mkdir_impl(PyModuleDef *module, path_t *path, int mode, int dir_fd) 3973/*[clinic end generated code: output=8bf1f738873ef2c5 input=e965f68377e9b1ce]*/ 3974{ 3975 int result; 3976 3977#ifdef MS_WINDOWS 3978 Py_BEGIN_ALLOW_THREADS 3979 if (path->wide) 3980 result = CreateDirectoryW(path->wide, NULL); 3981 else 3982 result = CreateDirectoryA(path->narrow, NULL); 3983 Py_END_ALLOW_THREADS 3984 3985 if (!result) 3986 return path_error(path); 3987#else 3988 Py_BEGIN_ALLOW_THREADS 3989#if HAVE_MKDIRAT 3990 if (dir_fd != DEFAULT_DIR_FD) 3991 result = mkdirat(dir_fd, path->narrow, mode); 3992 else 3993#endif 3994#if ( defined(__WATCOMC__) || defined(PYCC_VACPP) ) && !defined(__QNX__) 3995 result = mkdir(path->narrow); 3996#else 3997 result = mkdir(path->narrow, mode); 3998#endif 3999 Py_END_ALLOW_THREADS 4000 if (result < 0) 4001 return path_error(path); 4002#endif 4003 Py_RETURN_NONE; 4004} 4005 4006 4007/* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */ 4008#if defined(HAVE_SYS_RESOURCE_H) 4009#include <sys/resource.h> 4010#endif 4011 4012 4013#ifdef HAVE_NICE 4014/*[clinic input] 4015os.nice 4016 4017 increment: int 4018 / 4019 4020Add increment to the priority of process and return the new priority. 4021[clinic start generated code]*/ 4022 4023static PyObject * 4024os_nice_impl(PyModuleDef *module, int increment) 4025/*[clinic end generated code: output=8870418a3fc07b51 input=864be2d402a21da2]*/ 4026{ 4027 int value; 4028 4029 /* There are two flavours of 'nice': one that returns the new 4030 priority (as required by almost all standards out there) and the 4031 Linux/FreeBSD/BSDI one, which returns '0' on success and advices 4032 the use of getpriority() to get the new priority. 4033 4034 If we are of the nice family that returns the new priority, we 4035 need to clear errno before the call, and check if errno is filled 4036 before calling posix_error() on a returnvalue of -1, because the 4037 -1 may be the actual new priority! */ 4038 4039 errno = 0; 4040 value = nice(increment); 4041#if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY) 4042 if (value == 0) 4043 value = getpriority(PRIO_PROCESS, 0); 4044#endif 4045 if (value == -1 && errno != 0) 4046 /* either nice() or getpriority() returned an error */ 4047 return posix_error(); 4048 return PyLong_FromLong((long) value); 4049} 4050#endif /* HAVE_NICE */ 4051 4052 4053#ifdef HAVE_GETPRIORITY 4054/*[clinic input] 4055os.getpriority 4056 4057 which: int 4058 who: int 4059 4060Return program scheduling priority. 4061[clinic start generated code]*/ 4062 4063static PyObject * 4064os_getpriority_impl(PyModuleDef *module, int which, int who) 4065/*[clinic end generated code: output=4759937aa5b67ed6 input=9be615d40e2544ef]*/ 4066{ 4067 int retval; 4068 4069 errno = 0; 4070 retval = getpriority(which, who); 4071 if (errno != 0) 4072 return posix_error(); 4073 return PyLong_FromLong((long)retval); 4074} 4075#endif /* HAVE_GETPRIORITY */ 4076 4077 4078#ifdef HAVE_SETPRIORITY 4079/*[clinic input] 4080os.setpriority 4081 4082 which: int 4083 who: int 4084 priority: int 4085 4086Set program scheduling priority. 4087[clinic start generated code]*/ 4088 4089static PyObject * 4090os_setpriority_impl(PyModuleDef *module, int which, int who, int priority) 4091/*[clinic end generated code: output=6497d3301547e7d5 input=710ccbf65b9dc513]*/ 4092{ 4093 int retval; 4094 4095 retval = setpriority(which, who, priority); 4096 if (retval == -1) 4097 return posix_error(); 4098 Py_RETURN_NONE; 4099} 4100#endif /* HAVE_SETPRIORITY */ 4101 4102 4103static PyObject * 4104internal_rename(path_t *src, path_t *dst, int src_dir_fd, int dst_dir_fd, int is_replace) 4105{ 4106 char *function_name = is_replace ? "replace" : "rename"; 4107 int dir_fd_specified; 4108 4109#ifdef MS_WINDOWS 4110 BOOL result; 4111 int flags = is_replace ? MOVEFILE_REPLACE_EXISTING : 0; 4112#else 4113 int result; 4114#endif 4115 4116 dir_fd_specified = (src_dir_fd != DEFAULT_DIR_FD) || 4117 (dst_dir_fd != DEFAULT_DIR_FD); 4118#ifndef HAVE_RENAMEAT 4119 if (dir_fd_specified) { 4120 argument_unavailable_error(function_name, "src_dir_fd and dst_dir_fd"); 4121 return NULL; 4122 } 4123#endif 4124 4125 if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) { 4126 PyErr_Format(PyExc_ValueError, 4127 "%s: src and dst must be the same type", function_name); 4128 return NULL; 4129 } 4130 4131#ifdef MS_WINDOWS 4132 Py_BEGIN_ALLOW_THREADS 4133 if (src->wide) 4134 result = MoveFileExW(src->wide, dst->wide, flags); 4135 else 4136 result = MoveFileExA(src->narrow, dst->narrow, flags); 4137 Py_END_ALLOW_THREADS 4138 4139 if (!result) 4140 return path_error2(src, dst); 4141 4142#else 4143 Py_BEGIN_ALLOW_THREADS 4144#ifdef HAVE_RENAMEAT 4145 if (dir_fd_specified) 4146 result = renameat(src_dir_fd, src->narrow, dst_dir_fd, dst->narrow); 4147 else 4148#endif 4149 result = rename(src->narrow, dst->narrow); 4150 Py_END_ALLOW_THREADS 4151 4152 if (result) 4153 return path_error2(src, dst); 4154#endif 4155 Py_RETURN_NONE; 4156} 4157 4158 4159/*[clinic input] 4160os.rename 4161 4162 src : path_t 4163 dst : path_t 4164 * 4165 src_dir_fd : dir_fd = None 4166 dst_dir_fd : dir_fd = None 4167 4168Rename a file or directory. 4169 4170If either src_dir_fd or dst_dir_fd is not None, it should be a file 4171 descriptor open to a directory, and the respective path string (src or dst) 4172 should be relative; the path will then be relative to that directory. 4173src_dir_fd and dst_dir_fd, may not be implemented on your platform. 4174 If they are unavailable, using them will raise a NotImplementedError. 4175[clinic start generated code]*/ 4176 4177static PyObject * 4178os_rename_impl(PyModuleDef *module, path_t *src, path_t *dst, int src_dir_fd, 4179 int dst_dir_fd) 4180/*[clinic end generated code: output=08033bb2ec27fb5f input=faa61c847912c850]*/ 4181{ 4182 return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 0); 4183} 4184 4185 4186/*[clinic input] 4187os.replace = os.rename 4188 4189Rename a file or directory, overwriting the destination. 4190 4191If either src_dir_fd or dst_dir_fd is not None, it should be a file 4192 descriptor open to a directory, and the respective path string (src or dst) 4193 should be relative; the path will then be relative to that directory. 4194src_dir_fd and dst_dir_fd, may not be implemented on your platform. 4195 If they are unavailable, using them will raise a NotImplementedError." 4196[clinic start generated code]*/ 4197 4198static PyObject * 4199os_replace_impl(PyModuleDef *module, path_t *src, path_t *dst, 4200 int src_dir_fd, int dst_dir_fd) 4201/*[clinic end generated code: output=131d012eed8d3b8b input=25515dfb107c8421]*/ 4202{ 4203 return internal_rename(src, dst, src_dir_fd, dst_dir_fd, 1); 4204} 4205 4206 4207/*[clinic input] 4208os.rmdir 4209 4210 path: path_t 4211 * 4212 dir_fd: dir_fd(requires='unlinkat') = None 4213 4214Remove a directory. 4215 4216If dir_fd is not None, it should be a file descriptor open to a directory, 4217 and path should be relative; path will then be relative to that directory. 4218dir_fd may not be implemented on your platform. 4219 If it is unavailable, using it will raise a NotImplementedError. 4220[clinic start generated code]*/ 4221 4222static PyObject * 4223os_rmdir_impl(PyModuleDef *module, path_t *path, int dir_fd) 4224/*[clinic end generated code: output=cabadec80d5a77c7 input=38c8b375ca34a7e2]*/ 4225{ 4226 int result; 4227 4228 Py_BEGIN_ALLOW_THREADS 4229#ifdef MS_WINDOWS 4230 if (path->wide) 4231 result = RemoveDirectoryW(path->wide); 4232 else 4233 result = RemoveDirectoryA(path->narrow); 4234 result = !result; /* Windows, success=1, UNIX, success=0 */ 4235#else 4236#ifdef HAVE_UNLINKAT 4237 if (dir_fd != DEFAULT_DIR_FD) 4238 result = unlinkat(dir_fd, path->narrow, AT_REMOVEDIR); 4239 else 4240#endif 4241 result = rmdir(path->narrow); 4242#endif 4243 Py_END_ALLOW_THREADS 4244 4245 if (result) 4246 return path_error(path); 4247 4248 Py_RETURN_NONE; 4249} 4250 4251 4252#ifdef HAVE_SYSTEM 4253#ifdef MS_WINDOWS 4254/*[clinic input] 4255os.system -> long 4256 4257 command: Py_UNICODE 4258 4259Execute the command in a subshell. 4260[clinic start generated code]*/ 4261 4262static long 4263os_system_impl(PyModuleDef *module, Py_UNICODE *command) 4264/*[clinic end generated code: output=4c3bd5abcd9c29e7 input=303f5ce97df606b0]*/ 4265{ 4266 long result; 4267 Py_BEGIN_ALLOW_THREADS 4268 result = _wsystem(command); 4269 Py_END_ALLOW_THREADS 4270 return result; 4271} 4272#else /* MS_WINDOWS */ 4273/*[clinic input] 4274os.system -> long 4275 4276 command: FSConverter 4277 4278Execute the command in a subshell. 4279[clinic start generated code]*/ 4280 4281static long 4282os_system_impl(PyModuleDef *module, PyObject *command) 4283/*[clinic end generated code: output=800f775e10b7be55 input=86a58554ba6094af]*/ 4284{ 4285 long result; 4286 char *bytes = PyBytes_AsString(command); 4287 Py_BEGIN_ALLOW_THREADS 4288 result = system(bytes); 4289 Py_END_ALLOW_THREADS 4290 return result; 4291} 4292#endif 4293#endif /* HAVE_SYSTEM */ 4294 4295 4296/*[clinic input] 4297os.umask 4298 4299 mask: int 4300 / 4301 4302Set the current numeric umask and return the previous umask. 4303[clinic start generated code]*/ 4304 4305static PyObject * 4306os_umask_impl(PyModuleDef *module, int mask) 4307/*[clinic end generated code: output=9e1fe3c9f14d6a05 input=ab6bfd9b24d8a7e8]*/ 4308{ 4309 int i = (int)umask(mask); 4310 if (i < 0) 4311 return posix_error(); 4312 return PyLong_FromLong((long)i); 4313} 4314 4315#ifdef MS_WINDOWS 4316 4317/* override the default DeleteFileW behavior so that directory 4318symlinks can be removed with this function, the same as with 4319Unix symlinks */ 4320BOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName) 4321{ 4322 WIN32_FILE_ATTRIBUTE_DATA info; 4323 WIN32_FIND_DATAW find_data; 4324 HANDLE find_data_handle; 4325 int is_directory = 0; 4326 int is_link = 0; 4327 4328 if (GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &info)) { 4329 is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY; 4330 4331 /* Get WIN32_FIND_DATA structure for the path to determine if 4332 it is a symlink */ 4333 if(is_directory && 4334 info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { 4335 find_data_handle = FindFirstFileW(lpFileName, &find_data); 4336 4337 if(find_data_handle != INVALID_HANDLE_VALUE) { 4338 /* IO_REPARSE_TAG_SYMLINK if it is a symlink and 4339 IO_REPARSE_TAG_MOUNT_POINT if it is a junction point. */ 4340 is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK || 4341 find_data.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT; 4342 FindClose(find_data_handle); 4343 } 4344 } 4345 } 4346 4347 if (is_directory && is_link) 4348 return RemoveDirectoryW(lpFileName); 4349 4350 return DeleteFileW(lpFileName); 4351} 4352#endif /* MS_WINDOWS */ 4353 4354 4355/*[clinic input] 4356os.unlink 4357 4358 path: path_t 4359 * 4360 dir_fd: dir_fd(requires='unlinkat')=None 4361 4362Remove a file (same as remove()). 4363 4364If dir_fd is not None, it should be a file descriptor open to a directory, 4365 and path should be relative; path will then be relative to that directory. 4366dir_fd may not be implemented on your platform. 4367 If it is unavailable, using it will raise a NotImplementedError. 4368 4369[clinic start generated code]*/ 4370 4371static PyObject * 4372os_unlink_impl(PyModuleDef *module, path_t *path, int dir_fd) 4373/*[clinic end generated code: output=474afd5cd09b237e input=d7bcde2b1b2a2552]*/ 4374{ 4375 int result; 4376 4377 Py_BEGIN_ALLOW_THREADS 4378 _Py_BEGIN_SUPPRESS_IPH 4379#ifdef MS_WINDOWS 4380 if (path->wide) 4381 result = Py_DeleteFileW(path->wide); 4382 else 4383 result = DeleteFileA(path->narrow); 4384 result = !result; /* Windows, success=1, UNIX, success=0 */ 4385#else 4386#ifdef HAVE_UNLINKAT 4387 if (dir_fd != DEFAULT_DIR_FD) 4388 result = unlinkat(dir_fd, path->narrow, 0); 4389 else 4390#endif /* HAVE_UNLINKAT */ 4391 result = unlink(path->narrow); 4392#endif 4393 _Py_END_SUPPRESS_IPH 4394 Py_END_ALLOW_THREADS 4395 4396 if (result) 4397 return path_error(path); 4398 4399 Py_RETURN_NONE; 4400} 4401 4402 4403/*[clinic input] 4404os.remove = os.unlink 4405 4406Remove a file (same as unlink()). 4407 4408If dir_fd is not None, it should be a file descriptor open to a directory, 4409 and path should be relative; path will then be relative to that directory. 4410dir_fd may not be implemented on your platform. 4411 If it is unavailable, using it will raise a NotImplementedError. 4412[clinic start generated code]*/ 4413 4414static PyObject * 4415os_remove_impl(PyModuleDef *module, path_t *path, int dir_fd) 4416/*[clinic end generated code: output=d0d5149e64832b9e input=e05c5ab55cd30983]*/ 4417{ 4418 return os_unlink_impl(module, path, dir_fd); 4419} 4420 4421 4422static PyStructSequence_Field uname_result_fields[] = { 4423 {"sysname", "operating system name"}, 4424 {"nodename", "name of machine on network (implementation-defined)"}, 4425 {"release", "operating system release"}, 4426 {"version", "operating system version"}, 4427 {"machine", "hardware identifier"}, 4428 {NULL} 4429}; 4430 4431PyDoc_STRVAR(uname_result__doc__, 4432"uname_result: Result from os.uname().\n\n\ 4433This object may be accessed either as a tuple of\n\ 4434 (sysname, nodename, release, version, machine),\n\ 4435or via the attributes sysname, nodename, release, version, and machine.\n\ 4436\n\ 4437See os.uname for more information."); 4438 4439static PyStructSequence_Desc uname_result_desc = { 4440 "uname_result", /* name */ 4441 uname_result__doc__, /* doc */ 4442 uname_result_fields, 4443 5 4444}; 4445 4446static PyTypeObject UnameResultType; 4447 4448 4449#ifdef HAVE_UNAME 4450/*[clinic input] 4451os.uname 4452 4453Return an object identifying the current operating system. 4454 4455The object behaves like a named tuple with the following fields: 4456 (sysname, nodename, release, version, machine) 4457 4458[clinic start generated code]*/ 4459 4460static PyObject * 4461os_uname_impl(PyModuleDef *module) 4462/*[clinic end generated code: output=01e1421b757e753f input=e68bd246db3043ed]*/ 4463{ 4464 struct utsname u; 4465 int res; 4466 PyObject *value; 4467 4468 Py_BEGIN_ALLOW_THREADS 4469 res = uname(&u); 4470 Py_END_ALLOW_THREADS 4471 if (res < 0) 4472 return posix_error(); 4473 4474 value = PyStructSequence_New(&UnameResultType); 4475 if (value == NULL) 4476 return NULL; 4477 4478#define SET(i, field) \ 4479 { \ 4480 PyObject *o = PyUnicode_DecodeFSDefault(field); \ 4481 if (!o) { \ 4482 Py_DECREF(value); \ 4483 return NULL; \ 4484 } \ 4485 PyStructSequence_SET_ITEM(value, i, o); \ 4486 } \ 4487 4488 SET(0, u.sysname); 4489 SET(1, u.nodename); 4490 SET(2, u.release); 4491 SET(3, u.version); 4492 SET(4, u.machine); 4493 4494#undef SET 4495 4496 return value; 4497} 4498#endif /* HAVE_UNAME */ 4499 4500 4501 4502typedef struct { 4503 int now; 4504 time_t atime_s; 4505 long atime_ns; 4506 time_t mtime_s; 4507 long mtime_ns; 4508} utime_t; 4509 4510/* 4511 * these macros assume that "ut" is a pointer to a utime_t 4512 * they also intentionally leak the declaration of a pointer named "time" 4513 */ 4514#define UTIME_TO_TIMESPEC \ 4515 struct timespec ts[2]; \ 4516 struct timespec *time; \ 4517 if (ut->now) \ 4518 time = NULL; \ 4519 else { \ 4520 ts[0].tv_sec = ut->atime_s; \ 4521 ts[0].tv_nsec = ut->atime_ns; \ 4522 ts[1].tv_sec = ut->mtime_s; \ 4523 ts[1].tv_nsec = ut->mtime_ns; \ 4524 time = ts; \ 4525 } \ 4526 4527#define UTIME_TO_TIMEVAL \ 4528 struct timeval tv[2]; \ 4529 struct timeval *time; \ 4530 if (ut->now) \ 4531 time = NULL; \ 4532 else { \ 4533 tv[0].tv_sec = ut->atime_s; \ 4534 tv[0].tv_usec = ut->atime_ns / 1000; \ 4535 tv[1].tv_sec = ut->mtime_s; \ 4536 tv[1].tv_usec = ut->mtime_ns / 1000; \ 4537 time = tv; \ 4538 } \ 4539 4540#define UTIME_TO_UTIMBUF \ 4541 struct utimbuf u; \ 4542 struct utimbuf *time; \ 4543 if (ut->now) \ 4544 time = NULL; \ 4545 else { \ 4546 u.actime = ut->atime_s; \ 4547 u.modtime = ut->mtime_s; \ 4548 time = &u; \ 4549 } 4550 4551#define UTIME_TO_TIME_T \ 4552 time_t timet[2]; \ 4553 time_t *time; \ 4554 if (ut->now) \ 4555 time = NULL; \ 4556 else { \ 4557 timet[0] = ut->atime_s; \ 4558 timet[1] = ut->mtime_s; \ 4559 time = timet; \ 4560 } \ 4561 4562 4563#if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT) 4564 4565static int 4566utime_dir_fd(utime_t *ut, int dir_fd, char *path, int follow_symlinks) 4567{ 4568#ifdef HAVE_UTIMENSAT 4569 int flags = follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW; 4570 UTIME_TO_TIMESPEC; 4571 return utimensat(dir_fd, path, time, flags); 4572#elif defined(HAVE_FUTIMESAT) 4573 UTIME_TO_TIMEVAL; 4574 /* 4575 * follow_symlinks will never be false here; 4576 * we only allow !follow_symlinks and dir_fd together 4577 * if we have utimensat() 4578 */ 4579 assert(follow_symlinks); 4580 return futimesat(dir_fd, path, time); 4581#endif 4582} 4583 4584 #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_converter 4585#else 4586 #define FUTIMENSAT_DIR_FD_CONVERTER dir_fd_unavailable 4587#endif 4588 4589#if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS) 4590 4591static int 4592utime_fd(utime_t *ut, int fd) 4593{ 4594#ifdef HAVE_FUTIMENS 4595 UTIME_TO_TIMESPEC; 4596 return futimens(fd, time); 4597#else 4598 UTIME_TO_TIMEVAL; 4599 return futimes(fd, time); 4600#endif 4601} 4602 4603 #define PATH_UTIME_HAVE_FD 1 4604#else 4605 #define PATH_UTIME_HAVE_FD 0 4606#endif 4607 4608#if defined(HAVE_UTIMENSAT) || defined(HAVE_LUTIMES) 4609# define UTIME_HAVE_NOFOLLOW_SYMLINKS 4610#endif 4611 4612#ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS 4613 4614static int 4615utime_nofollow_symlinks(utime_t *ut, char *path) 4616{ 4617#ifdef HAVE_UTIMENSAT 4618 UTIME_TO_TIMESPEC; 4619 return utimensat(DEFAULT_DIR_FD, path, time, AT_SYMLINK_NOFOLLOW); 4620#else 4621 UTIME_TO_TIMEVAL; 4622 return lutimes(path, time); 4623#endif 4624} 4625 4626#endif 4627 4628#ifndef MS_WINDOWS 4629 4630static int 4631utime_default(utime_t *ut, char *path) 4632{ 4633#ifdef HAVE_UTIMENSAT 4634 UTIME_TO_TIMESPEC; 4635 return utimensat(DEFAULT_DIR_FD, path, time, 0); 4636#elif defined(HAVE_UTIMES) 4637 UTIME_TO_TIMEVAL; 4638 return utimes(path, time); 4639#elif defined(HAVE_UTIME_H) 4640 UTIME_TO_UTIMBUF; 4641 return utime(path, time); 4642#else 4643 UTIME_TO_TIME_T; 4644 return utime(path, time); 4645#endif 4646} 4647 4648#endif 4649 4650static int 4651split_py_long_to_s_and_ns(PyObject *py_long, time_t *s, long *ns) 4652{ 4653 int result = 0; 4654 PyObject *divmod; 4655 divmod = PyNumber_Divmod(py_long, billion); 4656 if (!divmod) 4657 goto exit; 4658 *s = _PyLong_AsTime_t(PyTuple_GET_ITEM(divmod, 0)); 4659 if ((*s == -1) && PyErr_Occurred()) 4660 goto exit; 4661 *ns = PyLong_AsLong(PyTuple_GET_ITEM(divmod, 1)); 4662 if ((*ns == -1) && PyErr_Occurred()) 4663 goto exit; 4664 4665 result = 1; 4666exit: 4667 Py_XDECREF(divmod); 4668 return result; 4669} 4670 4671 4672/*[clinic input] 4673os.utime 4674 4675 path: path_t(allow_fd='PATH_UTIME_HAVE_FD') 4676 times: object = NULL 4677 * 4678 ns: object = NULL 4679 dir_fd: dir_fd(requires='futimensat') = None 4680 follow_symlinks: bool=True 4681 4682# "utime(path, times=None, *[, ns], dir_fd=None, follow_symlinks=True)\n\ 4683 4684Set the access and modified time of path. 4685 4686path may always be specified as a string. 4687On some platforms, path may also be specified as an open file descriptor. 4688 If this functionality is unavailable, using it raises an exception. 4689 4690If times is not None, it must be a tuple (atime, mtime); 4691 atime and mtime should be expressed as float seconds since the epoch. 4692If ns is specified, it must be a tuple (atime_ns, mtime_ns); 4693 atime_ns and mtime_ns should be expressed as integer nanoseconds 4694 since the epoch. 4695If times is None and ns is unspecified, utime uses the current time. 4696Specifying tuples for both times and ns is an error. 4697 4698If dir_fd is not None, it should be a file descriptor open to a directory, 4699 and path should be relative; path will then be relative to that directory. 4700If follow_symlinks is False, and the last element of the path is a symbolic 4701 link, utime will modify the symbolic link itself instead of the file the 4702 link points to. 4703It is an error to use dir_fd or follow_symlinks when specifying path 4704 as an open file descriptor. 4705dir_fd and follow_symlinks may not be available on your platform. 4706 If they are unavailable, using them will raise a NotImplementedError. 4707 4708[clinic start generated code]*/ 4709 4710static PyObject * 4711os_utime_impl(PyModuleDef *module, path_t *path, PyObject *times, 4712 PyObject *ns, int dir_fd, int follow_symlinks) 4713/*[clinic end generated code: output=31f3434e560ba2f0 input=081cdc54ca685385]*/ 4714{ 4715#ifdef MS_WINDOWS 4716 HANDLE hFile; 4717 FILETIME atime, mtime; 4718#else 4719 int result; 4720#endif 4721 4722 PyObject *return_value = NULL; 4723 utime_t utime; 4724 4725 memset(&utime, 0, sizeof(utime_t)); 4726 4727 if (times && (times != Py_None) && ns) { 4728 PyErr_SetString(PyExc_ValueError, 4729 "utime: you may specify either 'times'" 4730 " or 'ns' but not both"); 4731 goto exit; 4732 } 4733 4734 if (times && (times != Py_None)) { 4735 time_t a_sec, m_sec; 4736 long a_nsec, m_nsec; 4737 if (!PyTuple_CheckExact(times) || (PyTuple_Size(times) != 2)) { 4738 PyErr_SetString(PyExc_TypeError, 4739 "utime: 'times' must be either" 4740 " a tuple of two ints or None"); 4741 goto exit; 4742 } 4743 utime.now = 0; 4744 if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 0), 4745 &a_sec, &a_nsec, _PyTime_ROUND_FLOOR) == -1 || 4746 _PyTime_ObjectToTimespec(PyTuple_GET_ITEM(times, 1), 4747 &m_sec, &m_nsec, _PyTime_ROUND_FLOOR) == -1) { 4748 goto exit; 4749 } 4750 utime.atime_s = a_sec; 4751 utime.atime_ns = a_nsec; 4752 utime.mtime_s = m_sec; 4753 utime.mtime_ns = m_nsec; 4754 } 4755 else if (ns) { 4756 if (!PyTuple_CheckExact(ns) || (PyTuple_Size(ns) != 2)) { 4757 PyErr_SetString(PyExc_TypeError, 4758 "utime: 'ns' must be a tuple of two ints"); 4759 goto exit; 4760 } 4761 utime.now = 0; 4762 if (!split_py_long_to_s_and_ns(PyTuple_GET_ITEM(ns, 0), 4763 &utime.atime_s, &utime.atime_ns) || 4764 !split_py_long_to_s_and_ns(PyTuple_GET_ITEM(ns, 1), 4765 &utime.mtime_s, &utime.mtime_ns)) { 4766 goto exit; 4767 } 4768 } 4769 else { 4770 /* times and ns are both None/unspecified. use "now". */ 4771 utime.now = 1; 4772 } 4773 4774#if !defined(UTIME_HAVE_NOFOLLOW_SYMLINKS) 4775 if (follow_symlinks_specified("utime", follow_symlinks)) 4776 goto exit; 4777#endif 4778 4779 if (path_and_dir_fd_invalid("utime", path, dir_fd) || 4780 dir_fd_and_fd_invalid("utime", dir_fd, path->fd) || 4781 fd_and_follow_symlinks_invalid("utime", path->fd, follow_symlinks)) 4782 goto exit; 4783 4784#if !defined(HAVE_UTIMENSAT) 4785 if ((dir_fd != DEFAULT_DIR_FD) && (!follow_symlinks)) { 4786 PyErr_SetString(PyExc_ValueError, 4787 "utime: cannot use dir_fd and follow_symlinks " 4788 "together on this platform"); 4789 goto exit; 4790 } 4791#endif 4792 4793#ifdef MS_WINDOWS 4794 Py_BEGIN_ALLOW_THREADS 4795 if (path->wide) 4796 hFile = CreateFileW(path->wide, FILE_WRITE_ATTRIBUTES, 0, 4797 NULL, OPEN_EXISTING, 4798 FILE_FLAG_BACKUP_SEMANTICS, NULL); 4799 else 4800 hFile = CreateFileA(path->narrow, FILE_WRITE_ATTRIBUTES, 0, 4801 NULL, OPEN_EXISTING, 4802 FILE_FLAG_BACKUP_SEMANTICS, NULL); 4803 Py_END_ALLOW_THREADS 4804 if (hFile == INVALID_HANDLE_VALUE) { 4805 path_error(path); 4806 goto exit; 4807 } 4808 4809 if (utime.now) { 4810 GetSystemTimeAsFileTime(&mtime); 4811 atime = mtime; 4812 } 4813 else { 4814 _Py_time_t_to_FILE_TIME(utime.atime_s, utime.atime_ns, &atime); 4815 _Py_time_t_to_FILE_TIME(utime.mtime_s, utime.mtime_ns, &mtime); 4816 } 4817 if (!SetFileTime(hFile, NULL, &atime, &mtime)) { 4818 /* Avoid putting the file name into the error here, 4819 as that may confuse the user into believing that 4820 something is wrong with the file, when it also 4821 could be the time stamp that gives a problem. */ 4822 PyErr_SetFromWindowsErr(0); 4823 goto exit; 4824 } 4825#else /* MS_WINDOWS */ 4826 Py_BEGIN_ALLOW_THREADS 4827 4828#ifdef UTIME_HAVE_NOFOLLOW_SYMLINKS 4829 if ((!follow_symlinks) && (dir_fd == DEFAULT_DIR_FD)) 4830 result = utime_nofollow_symlinks(&utime, path->narrow); 4831 else 4832#endif 4833 4834#if defined(HAVE_FUTIMESAT) || defined(HAVE_UTIMENSAT) 4835 if ((dir_fd != DEFAULT_DIR_FD) || (!follow_symlinks)) 4836 result = utime_dir_fd(&utime, dir_fd, path->narrow, follow_symlinks); 4837 else 4838#endif 4839 4840#if defined(HAVE_FUTIMES) || defined(HAVE_FUTIMENS) 4841 if (path->fd != -1) 4842 result = utime_fd(&utime, path->fd); 4843 else 4844#endif 4845 4846 result = utime_default(&utime, path->narrow); 4847 4848 Py_END_ALLOW_THREADS 4849 4850 if (result < 0) { 4851 /* see previous comment about not putting filename in error here */ 4852 return_value = posix_error(); 4853 goto exit; 4854 } 4855 4856#endif /* MS_WINDOWS */ 4857 4858 Py_INCREF(Py_None); 4859 return_value = Py_None; 4860 4861exit: 4862#ifdef MS_WINDOWS 4863 if (hFile != INVALID_HANDLE_VALUE) 4864 CloseHandle(hFile); 4865#endif 4866 return return_value; 4867} 4868 4869/* Process operations */ 4870 4871 4872/*[clinic input] 4873os._exit 4874 4875 status: int 4876 4877Exit to the system with specified status, without normal exit processing. 4878[clinic start generated code]*/ 4879 4880static PyObject * 4881os__exit_impl(PyModuleDef *module, int status) 4882/*[clinic end generated code: output=472a3cbaf68f3621 input=5e6d57556b0c4a62]*/ 4883{ 4884 _exit(status); 4885 return NULL; /* Make gcc -Wall happy */ 4886} 4887 4888#if defined(HAVE_EXECV) || defined(HAVE_SPAWNV) 4889static void 4890free_string_array(char **array, Py_ssize_t count) 4891{ 4892 Py_ssize_t i; 4893 for (i = 0; i < count; i++) 4894 PyMem_Free(array[i]); 4895 PyMem_DEL(array); 4896} 4897 4898static 4899int fsconvert_strdup(PyObject *o, char**out) 4900{ 4901 PyObject *bytes; 4902 Py_ssize_t size; 4903 if (!PyUnicode_FSConverter(o, &bytes)) 4904 return 0; 4905 size = PyBytes_GET_SIZE(bytes); 4906 *out = PyMem_Malloc(size+1); 4907 if (!*out) { 4908 PyErr_NoMemory(); 4909 return 0; 4910 } 4911 memcpy(*out, PyBytes_AsString(bytes), size+1); 4912 Py_DECREF(bytes); 4913 return 1; 4914} 4915#endif 4916 4917#if defined(HAVE_EXECV) || defined (HAVE_FEXECVE) 4918static char** 4919parse_envlist(PyObject* env, Py_ssize_t *envc_ptr) 4920{ 4921 char **envlist; 4922 Py_ssize_t i, pos, envc; 4923 PyObject *keys=NULL, *vals=NULL; 4924 PyObject *key, *val, *key2, *val2; 4925 char *p, *k, *v; 4926 size_t len; 4927 4928 i = PyMapping_Size(env); 4929 if (i < 0) 4930 return NULL; 4931 envlist = PyMem_NEW(char *, i + 1); 4932 if (envlist == NULL) { 4933 PyErr_NoMemory(); 4934 return NULL; 4935 } 4936 envc = 0; 4937 keys = PyMapping_Keys(env); 4938 if (!keys) 4939 goto error; 4940 vals = PyMapping_Values(env); 4941 if (!vals) 4942 goto error; 4943 if (!PyList_Check(keys) || !PyList_Check(vals)) { 4944 PyErr_Format(PyExc_TypeError, 4945 "env.keys() or env.values() is not a list"); 4946 goto error; 4947 } 4948 4949 for (pos = 0; pos < i; pos++) { 4950 key = PyList_GetItem(keys, pos); 4951 val = PyList_GetItem(vals, pos); 4952 if (!key || !val) 4953 goto error; 4954 4955 if (PyUnicode_FSConverter(key, &key2) == 0) 4956 goto error; 4957 if (PyUnicode_FSConverter(val, &val2) == 0) { 4958 Py_DECREF(key2); 4959 goto error; 4960 } 4961 4962 k = PyBytes_AsString(key2); 4963 v = PyBytes_AsString(val2); 4964 len = PyBytes_GET_SIZE(key2) + PyBytes_GET_SIZE(val2) + 2; 4965 4966 p = PyMem_NEW(char, len); 4967 if (p == NULL) { 4968 PyErr_NoMemory(); 4969 Py_DECREF(key2); 4970 Py_DECREF(val2); 4971 goto error; 4972 } 4973 PyOS_snprintf(p, len, "%s=%s", k, v); 4974 envlist[envc++] = p; 4975 Py_DECREF(key2); 4976 Py_DECREF(val2); 4977 } 4978 Py_DECREF(vals); 4979 Py_DECREF(keys); 4980 4981 envlist[envc] = 0; 4982 *envc_ptr = envc; 4983 return envlist; 4984 4985error: 4986 Py_XDECREF(keys); 4987 Py_XDECREF(vals); 4988 while (--envc >= 0) 4989 PyMem_DEL(envlist[envc]); 4990 PyMem_DEL(envlist); 4991 return NULL; 4992} 4993 4994static char** 4995parse_arglist(PyObject* argv, Py_ssize_t *argc) 4996{ 4997 int i; 4998 char **argvlist = PyMem_NEW(char *, *argc+1); 4999 if (argvlist == NULL) { 5000 PyErr_NoMemory(); 5001 return NULL; 5002 } 5003 for (i = 0; i < *argc; i++) { 5004 PyObject* item = PySequence_ITEM(argv, i); 5005 if (item == NULL) 5006 goto fail; 5007 if (!fsconvert_strdup(item, &argvlist[i])) { 5008 Py_DECREF(item); 5009 goto fail; 5010 } 5011 Py_DECREF(item); 5012 } 5013 argvlist[*argc] = NULL; 5014 return argvlist; 5015fail: 5016 *argc = i; 5017 free_string_array(argvlist, *argc); 5018 return NULL; 5019} 5020#endif 5021 5022 5023#ifdef HAVE_EXECV 5024/*[clinic input] 5025os.execv 5026 5027 path: FSConverter 5028 Path of executable file. 5029 argv: object 5030 Tuple or list of strings. 5031 / 5032 5033Execute an executable path with arguments, replacing current process. 5034[clinic start generated code]*/ 5035 5036static PyObject * 5037os_execv_impl(PyModuleDef *module, PyObject *path, PyObject *argv) 5038/*[clinic end generated code: output=9221f08143146fff input=96041559925e5229]*/ 5039{ 5040 char *path_char; 5041 char **argvlist; 5042 Py_ssize_t argc; 5043 5044 /* execv has two arguments: (path, argv), where 5045 argv is a list or tuple of strings. */ 5046 5047 path_char = PyBytes_AsString(path); 5048 if (!PyList_Check(argv) && !PyTuple_Check(argv)) { 5049 PyErr_SetString(PyExc_TypeError, 5050 "execv() arg 2 must be a tuple or list"); 5051 return NULL; 5052 } 5053 argc = PySequence_Size(argv); 5054 if (argc < 1) { 5055 PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty"); 5056 return NULL; 5057 } 5058 5059 argvlist = parse_arglist(argv, &argc); 5060 if (argvlist == NULL) { 5061 return NULL; 5062 } 5063 5064 execv(path_char, argvlist); 5065 5066 /* If we get here it's definitely an error */ 5067 5068 free_string_array(argvlist, argc); 5069 return posix_error(); 5070} 5071 5072 5073/*[clinic input] 5074os.execve 5075 5076 path: path_t(allow_fd='PATH_HAVE_FEXECVE') 5077 Path of executable file. 5078 argv: object 5079 Tuple or list of strings. 5080 env: object 5081 Dictionary of strings mapping to strings. 5082 5083Execute an executable path with arguments, replacing current process. 5084[clinic start generated code]*/ 5085 5086static PyObject * 5087os_execve_impl(PyModuleDef *module, path_t *path, PyObject *argv, 5088 PyObject *env) 5089/*[clinic end generated code: output=181884fcdb21508e input=626804fa092606d9]*/ 5090{ 5091 char **argvlist = NULL; 5092 char **envlist; 5093 Py_ssize_t argc, envc; 5094 5095 /* execve has three arguments: (path, argv, env), where 5096 argv is a list or tuple of strings and env is a dictionary 5097 like posix.environ. */ 5098 5099 if (!PyList_Check(argv) && !PyTuple_Check(argv)) { 5100 PyErr_SetString(PyExc_TypeError, 5101 "execve: argv must be a tuple or list"); 5102 goto fail; 5103 } 5104 argc = PySequence_Size(argv); 5105 if (!PyMapping_Check(env)) { 5106 PyErr_SetString(PyExc_TypeError, 5107 "execve: environment must be a mapping object"); 5108 goto fail; 5109 } 5110 5111 argvlist = parse_arglist(argv, &argc); 5112 if (argvlist == NULL) { 5113 goto fail; 5114 } 5115 5116 envlist = parse_envlist(env, &envc); 5117 if (envlist == NULL) 5118 goto fail; 5119 5120#ifdef HAVE_FEXECVE 5121 if (path->fd > -1) 5122 fexecve(path->fd, argvlist, envlist); 5123 else 5124#endif 5125 execve(path->narrow, argvlist, envlist); 5126 5127 /* If we get here it's definitely an error */ 5128 5129 path_error(path); 5130 5131 while (--envc >= 0) 5132 PyMem_DEL(envlist[envc]); 5133 PyMem_DEL(envlist); 5134 fail: 5135 if (argvlist) 5136 free_string_array(argvlist, argc); 5137 return NULL; 5138} 5139#endif /* HAVE_EXECV */ 5140 5141 5142#ifdef HAVE_SPAWNV 5143/*[clinic input] 5144os.spawnv 5145 5146 mode: int 5147 Mode of process creation. 5148 path: FSConverter 5149 Path of executable file. 5150 argv: object 5151 Tuple or list of strings. 5152 / 5153 5154Execute the program specified by path in a new process. 5155[clinic start generated code]*/ 5156 5157static PyObject * 5158os_spawnv_impl(PyModuleDef *module, int mode, PyObject *path, PyObject *argv) 5159/*[clinic end generated code: output=140a7945484c8cc5 input=042c91dfc1e6debc]*/ 5160{ 5161 char *path_char; 5162 char **argvlist; 5163 int i; 5164 Py_ssize_t argc; 5165 Py_intptr_t spawnval; 5166 PyObject *(*getitem)(PyObject *, Py_ssize_t); 5167 5168 /* spawnv has three arguments: (mode, path, argv), where 5169 argv is a list or tuple of strings. */ 5170 5171 path_char = PyBytes_AsString(path); 5172 if (PyList_Check(argv)) { 5173 argc = PyList_Size(argv); 5174 getitem = PyList_GetItem; 5175 } 5176 else if (PyTuple_Check(argv)) { 5177 argc = PyTuple_Size(argv); 5178 getitem = PyTuple_GetItem; 5179 } 5180 else { 5181 PyErr_SetString(PyExc_TypeError, 5182 "spawnv() arg 2 must be a tuple or list"); 5183 return NULL; 5184 } 5185 5186 argvlist = PyMem_NEW(char *, argc+1); 5187 if (argvlist == NULL) { 5188 return PyErr_NoMemory(); 5189 } 5190 for (i = 0; i < argc; i++) { 5191 if (!fsconvert_strdup((*getitem)(argv, i), 5192 &argvlist[i])) { 5193 free_string_array(argvlist, i); 5194 PyErr_SetString( 5195 PyExc_TypeError, 5196 "spawnv() arg 2 must contain only strings"); 5197 return NULL; 5198 } 5199 } 5200 argvlist[argc] = NULL; 5201 5202 if (mode == _OLD_P_OVERLAY) 5203 mode = _P_OVERLAY; 5204 5205 Py_BEGIN_ALLOW_THREADS 5206 spawnval = _spawnv(mode, path_char, argvlist); 5207 Py_END_ALLOW_THREADS 5208 5209 free_string_array(argvlist, argc); 5210 5211 if (spawnval == -1) 5212 return posix_error(); 5213 else 5214 return Py_BuildValue(_Py_PARSE_INTPTR, spawnval); 5215} 5216 5217 5218/*[clinic input] 5219os.spawnve 5220 5221 mode: int 5222 Mode of process creation. 5223 path: FSConverter 5224 Path of executable file. 5225 argv: object 5226 Tuple or list of strings. 5227 env: object 5228 Dictionary of strings mapping to strings. 5229 / 5230 5231Execute the program specified by path in a new process. 5232[clinic start generated code]*/ 5233 5234static PyObject * 5235os_spawnve_impl(PyModuleDef *module, int mode, PyObject *path, 5236 PyObject *argv, PyObject *env) 5237/*[clinic end generated code: output=e7f5f0703610531f input=02362fd937963f8f]*/ 5238{ 5239 char *path_char; 5240 char **argvlist; 5241 char **envlist; 5242 PyObject *res = NULL; 5243 Py_ssize_t argc, i, envc; 5244 Py_intptr_t spawnval; 5245 PyObject *(*getitem)(PyObject *, Py_ssize_t); 5246 Py_ssize_t lastarg = 0; 5247 5248 /* spawnve has four arguments: (mode, path, argv, env), where 5249 argv is a list or tuple of strings and env is a dictionary 5250 like posix.environ. */ 5251 5252 path_char = PyBytes_AsString(path); 5253 if (PyList_Check(argv)) { 5254 argc = PyList_Size(argv); 5255 getitem = PyList_GetItem; 5256 } 5257 else if (PyTuple_Check(argv)) { 5258 argc = PyTuple_Size(argv); 5259 getitem = PyTuple_GetItem; 5260 } 5261 else { 5262 PyErr_SetString(PyExc_TypeError, 5263 "spawnve() arg 2 must be a tuple or list"); 5264 goto fail_0; 5265 } 5266 if (!PyMapping_Check(env)) { 5267 PyErr_SetString(PyExc_TypeError, 5268 "spawnve() arg 3 must be a mapping object"); 5269 goto fail_0; 5270 } 5271 5272 argvlist = PyMem_NEW(char *, argc+1); 5273 if (argvlist == NULL) { 5274 PyErr_NoMemory(); 5275 goto fail_0; 5276 } 5277 for (i = 0; i < argc; i++) { 5278 if (!fsconvert_strdup((*getitem)(argv, i), 5279 &argvlist[i])) 5280 { 5281 lastarg = i; 5282 goto fail_1; 5283 } 5284 } 5285 lastarg = argc; 5286 argvlist[argc] = NULL; 5287 5288 envlist = parse_envlist(env, &envc); 5289 if (envlist == NULL) 5290 goto fail_1; 5291 5292 if (mode == _OLD_P_OVERLAY) 5293 mode = _P_OVERLAY; 5294 5295 Py_BEGIN_ALLOW_THREADS 5296 spawnval = _spawnve(mode, path_char, argvlist, envlist); 5297 Py_END_ALLOW_THREADS 5298 5299 if (spawnval == -1) 5300 (void) posix_error(); 5301 else 5302 res = Py_BuildValue(_Py_PARSE_INTPTR, spawnval); 5303 5304 while (--envc >= 0) 5305 PyMem_DEL(envlist[envc]); 5306 PyMem_DEL(envlist); 5307 fail_1: 5308 free_string_array(argvlist, lastarg); 5309 fail_0: 5310 return res; 5311} 5312 5313#endif /* HAVE_SPAWNV */ 5314 5315 5316#ifdef HAVE_FORK1 5317/*[clinic input] 5318os.fork1 5319 5320Fork a child process with a single multiplexed (i.e., not bound) thread. 5321 5322Return 0 to child process and PID of child to parent process. 5323[clinic start generated code]*/ 5324 5325static PyObject * 5326os_fork1_impl(PyModuleDef *module) 5327/*[clinic end generated code: output=e27b4f66419c9dcf input=12db02167893926e]*/ 5328{ 5329 pid_t pid; 5330 int result = 0; 5331 _PyImport_AcquireLock(); 5332 pid = fork1(); 5333 if (pid == 0) { 5334 /* child: this clobbers and resets the import lock. */ 5335 PyOS_AfterFork(); 5336 } else { 5337 /* parent: release the import lock. */ 5338 result = _PyImport_ReleaseLock(); 5339 } 5340 if (pid == -1) 5341 return posix_error(); 5342 if (result < 0) { 5343 /* Don't clobber the OSError if the fork failed. */ 5344 PyErr_SetString(PyExc_RuntimeError, 5345 "not holding the import lock"); 5346 return NULL; 5347 } 5348 return PyLong_FromPid(pid); 5349} 5350#endif /* HAVE_FORK1 */ 5351 5352 5353#ifdef HAVE_FORK 5354/*[clinic input] 5355os.fork 5356 5357Fork a child process. 5358 5359Return 0 to child process and PID of child to parent process. 5360[clinic start generated code]*/ 5361 5362static PyObject * 5363os_fork_impl(PyModuleDef *module) 5364/*[clinic end generated code: output=898b1ecd3498ba12 input=13c956413110eeaa]*/ 5365{ 5366 pid_t pid; 5367 int result = 0; 5368 _PyImport_AcquireLock(); 5369 pid = fork(); 5370 if (pid == 0) { 5371 /* child: this clobbers and resets the import lock. */ 5372 PyOS_AfterFork(); 5373 } else { 5374 /* parent: release the import lock. */ 5375 result = _PyImport_ReleaseLock(); 5376 } 5377 if (pid == -1) 5378 return posix_error(); 5379 if (result < 0) { 5380 /* Don't clobber the OSError if the fork failed. */ 5381 PyErr_SetString(PyExc_RuntimeError, 5382 "not holding the import lock"); 5383 return NULL; 5384 } 5385 return PyLong_FromPid(pid); 5386} 5387#endif /* HAVE_FORK */ 5388 5389 5390#ifdef HAVE_SCHED_H 5391#ifdef HAVE_SCHED_GET_PRIORITY_MAX 5392/*[clinic input] 5393os.sched_get_priority_max 5394 5395 policy: int 5396 5397Get the maximum scheduling priority for policy. 5398[clinic start generated code]*/ 5399 5400static PyObject * 5401os_sched_get_priority_max_impl(PyModuleDef *module, int policy) 5402/*[clinic end generated code: output=a6a30fa5071f2d81 input=2097b7998eca6874]*/ 5403{ 5404 int max; 5405 5406 max = sched_get_priority_max(policy); 5407 if (max < 0) 5408 return posix_error(); 5409 return PyLong_FromLong(max); 5410} 5411 5412 5413/*[clinic input] 5414os.sched_get_priority_min 5415 5416 policy: int 5417 5418Get the minimum scheduling priority for policy. 5419[clinic start generated code]*/ 5420 5421static PyObject * 5422os_sched_get_priority_min_impl(PyModuleDef *module, int policy) 5423/*[clinic end generated code: output=5ca3ed6bc43e9b20 input=21bc8fa0d70983bf]*/ 5424{ 5425 int min = sched_get_priority_min(policy); 5426 if (min < 0) 5427 return posix_error(); 5428 return PyLong_FromLong(min); 5429} 5430#endif /* HAVE_SCHED_GET_PRIORITY_MAX */ 5431 5432 5433#ifdef HAVE_SCHED_SETSCHEDULER 5434/*[clinic input] 5435os.sched_getscheduler 5436 pid: pid_t 5437 / 5438 5439Get the scheduling policy for the process identifiedy by pid. 5440 5441Passing 0 for pid returns the scheduling policy for the calling process. 5442[clinic start generated code]*/ 5443 5444static PyObject * 5445os_sched_getscheduler_impl(PyModuleDef *module, pid_t pid) 5446/*[clinic end generated code: output=8cd63c15caf54fa9 input=5f14cfd1f189e1a0]*/ 5447{ 5448 int policy; 5449 5450 policy = sched_getscheduler(pid); 5451 if (policy < 0) 5452 return posix_error(); 5453 return PyLong_FromLong(policy); 5454} 5455#endif /* HAVE_SCHED_SETSCHEDULER */ 5456 5457 5458#if defined(HAVE_SCHED_SETSCHEDULER) || defined(HAVE_SCHED_SETPARAM) 5459/*[clinic input] 5460class os.sched_param "PyObject *" "&SchedParamType" 5461 5462@classmethod 5463os.sched_param.__new__ 5464 5465 sched_priority: object 5466 A scheduling parameter. 5467 5468Current has only one field: sched_priority"); 5469[clinic start generated code]*/ 5470 5471static PyObject * 5472os_sched_param_impl(PyTypeObject *type, PyObject *sched_priority) 5473/*[clinic end generated code: output=48f4067d60f48c13 input=73a4c22f7071fc62]*/ 5474{ 5475 PyObject *res; 5476 5477 res = PyStructSequence_New(type); 5478 if (!res) 5479 return NULL; 5480 Py_INCREF(sched_priority); 5481 PyStructSequence_SET_ITEM(res, 0, sched_priority); 5482 return res; 5483} 5484 5485 5486PyDoc_VAR(os_sched_param__doc__); 5487 5488static PyStructSequence_Field sched_param_fields[] = { 5489 {"sched_priority", "the scheduling priority"}, 5490 {0} 5491}; 5492 5493static PyStructSequence_Desc sched_param_desc = { 5494 "sched_param", /* name */ 5495 os_sched_param__doc__, /* doc */ 5496 sched_param_fields, 5497 1 5498}; 5499 5500static int 5501convert_sched_param(PyObject *param, struct sched_param *res) 5502{ 5503 long priority; 5504 5505 if (Py_TYPE(param) != &SchedParamType) { 5506 PyErr_SetString(PyExc_TypeError, "must have a sched_param object"); 5507 return 0; 5508 } 5509 priority = PyLong_AsLong(PyStructSequence_GET_ITEM(param, 0)); 5510 if (priority == -1 && PyErr_Occurred()) 5511 return 0; 5512 if (priority > INT_MAX || priority < INT_MIN) { 5513 PyErr_SetString(PyExc_OverflowError, "sched_priority out of range"); 5514 return 0; 5515 } 5516 res->sched_priority = Py_SAFE_DOWNCAST(priority, long, int); 5517 return 1; 5518} 5519#endif /* defined(HAVE_SCHED_SETSCHEDULER) || defined(HAVE_SCHED_SETPARAM) */ 5520 5521 5522#ifdef HAVE_SCHED_SETSCHEDULER 5523/*[clinic input] 5524os.sched_setscheduler 5525 5526 pid: pid_t 5527 policy: int 5528 param: sched_param 5529 / 5530 5531Set the scheduling policy for the process identified by pid. 5532 5533If pid is 0, the calling process is changed. 5534param is an instance of sched_param. 5535[clinic start generated code]*/ 5536 5537static PyObject * 5538os_sched_setscheduler_impl(PyModuleDef *module, pid_t pid, int policy, 5539 struct sched_param *param) 5540/*[clinic end generated code: output=37053e5c528c35c9 input=c581f9469a5327dd]*/ 5541{ 5542 /* 5543 ** sched_setscheduler() returns 0 in Linux, but the previous 5544 ** scheduling policy under Solaris/Illumos, and others. 5545 ** On error, -1 is returned in all Operating Systems. 5546 */ 5547 if (sched_setscheduler(pid, policy, param) == -1) 5548 return posix_error(); 5549 Py_RETURN_NONE; 5550} 5551#endif /* HAVE_SCHED_SETSCHEDULER*/ 5552 5553 5554#ifdef HAVE_SCHED_SETPARAM 5555/*[clinic input] 5556os.sched_getparam 5557 pid: pid_t 5558 / 5559 5560Returns scheduling parameters for the process identified by pid. 5561 5562If pid is 0, returns parameters for the calling process. 5563Return value is an instance of sched_param. 5564[clinic start generated code]*/ 5565 5566static PyObject * 5567os_sched_getparam_impl(PyModuleDef *module, pid_t pid) 5568/*[clinic end generated code: output=f42c5bd2604ecd08 input=18a1ef9c2efae296]*/ 5569{ 5570 struct sched_param param; 5571 PyObject *result; 5572 PyObject *priority; 5573 5574 if (sched_getparam(pid, ¶m)) 5575 return posix_error(); 5576 result = PyStructSequence_New(&SchedParamType); 5577 if (!result) 5578 return NULL; 5579 priority = PyLong_FromLong(param.sched_priority); 5580 if (!priority) { 5581 Py_DECREF(result); 5582 return NULL; 5583 } 5584 PyStructSequence_SET_ITEM(result, 0, priority); 5585 return result; 5586} 5587 5588 5589/*[clinic input] 5590os.sched_setparam 5591 pid: pid_t 5592 param: sched_param 5593 / 5594 5595Set scheduling parameters for the process identified by pid. 5596 5597If pid is 0, sets parameters for the calling process. 5598param should be an instance of sched_param. 5599[clinic start generated code]*/ 5600 5601static PyObject * 5602os_sched_setparam_impl(PyModuleDef *module, pid_t pid, 5603 struct sched_param *param) 5604/*[clinic end generated code: output=b7a3c589436cec9b input=6b8d6dfcecdc21bd]*/ 5605{ 5606 if (sched_setparam(pid, param)) 5607 return posix_error(); 5608 Py_RETURN_NONE; 5609} 5610#endif /* HAVE_SCHED_SETPARAM */ 5611 5612 5613#ifdef HAVE_SCHED_RR_GET_INTERVAL 5614/*[clinic input] 5615os.sched_rr_get_interval -> double 5616 pid: pid_t 5617 / 5618 5619Return the round-robin quantum for the process identified by pid, in seconds. 5620 5621Value returned is a float. 5622[clinic start generated code]*/ 5623 5624static double 5625os_sched_rr_get_interval_impl(PyModuleDef *module, pid_t pid) 5626/*[clinic end generated code: output=7adc137a86dea581 input=2a973da15cca6fae]*/ 5627{ 5628 struct timespec interval; 5629 if (sched_rr_get_interval(pid, &interval)) { 5630 posix_error(); 5631 return -1.0; 5632 } 5633 return (double)interval.tv_sec + 1e-9*interval.tv_nsec; 5634} 5635#endif /* HAVE_SCHED_RR_GET_INTERVAL */ 5636 5637 5638/*[clinic input] 5639os.sched_yield 5640 5641Voluntarily relinquish the CPU. 5642[clinic start generated code]*/ 5643 5644static PyObject * 5645os_sched_yield_impl(PyModuleDef *module) 5646/*[clinic end generated code: output=d7bd51869c4cb6a8 input=e54d6f98189391d4]*/ 5647{ 5648 if (sched_yield()) 5649 return posix_error(); 5650 Py_RETURN_NONE; 5651} 5652 5653#ifdef HAVE_SCHED_SETAFFINITY 5654/* The minimum number of CPUs allocated in a cpu_set_t */ 5655static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT; 5656 5657/*[clinic input] 5658os.sched_setaffinity 5659 pid: pid_t 5660 mask : object 5661 / 5662 5663Set the CPU affinity of the process identified by pid to mask. 5664 5665mask should be an iterable of integers identifying CPUs. 5666[clinic start generated code]*/ 5667 5668static PyObject * 5669os_sched_setaffinity_impl(PyModuleDef *module, pid_t pid, PyObject *mask) 5670/*[clinic end generated code: output=582bcbf40d3253a9 input=a0791a597c7085ba]*/ 5671{ 5672 int ncpus; 5673 size_t setsize; 5674 cpu_set_t *cpu_set = NULL; 5675 PyObject *iterator = NULL, *item; 5676 5677 iterator = PyObject_GetIter(mask); 5678 if (iterator == NULL) 5679 return NULL; 5680 5681 ncpus = NCPUS_START; 5682 setsize = CPU_ALLOC_SIZE(ncpus); 5683 cpu_set = CPU_ALLOC(ncpus); 5684 if (cpu_set == NULL) { 5685 PyErr_NoMemory(); 5686 goto error; 5687 } 5688 CPU_ZERO_S(setsize, cpu_set); 5689 5690 while ((item = PyIter_Next(iterator))) { 5691 long cpu; 5692 if (!PyLong_Check(item)) { 5693 PyErr_Format(PyExc_TypeError, 5694 "expected an iterator of ints, " 5695 "but iterator yielded %R", 5696 Py_TYPE(item)); 5697 Py_DECREF(item); 5698 goto error; 5699 } 5700 cpu = PyLong_AsLong(item); 5701 Py_DECREF(item); 5702 if (cpu < 0) { 5703 if (!PyErr_Occurred()) 5704 PyErr_SetString(PyExc_ValueError, "negative CPU number"); 5705 goto error; 5706 } 5707 if (cpu > INT_MAX - 1) { 5708 PyErr_SetString(PyExc_OverflowError, "CPU number too large"); 5709 goto error; 5710 } 5711 if (cpu >= ncpus) { 5712 /* Grow CPU mask to fit the CPU number */ 5713 int newncpus = ncpus; 5714 cpu_set_t *newmask; 5715 size_t newsetsize; 5716 while (newncpus <= cpu) { 5717 if (newncpus > INT_MAX / 2) 5718 newncpus = cpu + 1; 5719 else 5720 newncpus = newncpus * 2; 5721 } 5722 newmask = CPU_ALLOC(newncpus); 5723 if (newmask == NULL) { 5724 PyErr_NoMemory(); 5725 goto error; 5726 } 5727 newsetsize = CPU_ALLOC_SIZE(newncpus); 5728 CPU_ZERO_S(newsetsize, newmask); 5729 memcpy(newmask, cpu_set, setsize); 5730 CPU_FREE(cpu_set); 5731 setsize = newsetsize; 5732 cpu_set = newmask; 5733 ncpus = newncpus; 5734 } 5735 CPU_SET_S(cpu, setsize, cpu_set); 5736 } 5737 Py_CLEAR(iterator); 5738 5739 if (sched_setaffinity(pid, setsize, cpu_set)) { 5740 posix_error(); 5741 goto error; 5742 } 5743 CPU_FREE(cpu_set); 5744 Py_RETURN_NONE; 5745 5746error: 5747 if (cpu_set) 5748 CPU_FREE(cpu_set); 5749 Py_XDECREF(iterator); 5750 return NULL; 5751} 5752 5753 5754/*[clinic input] 5755os.sched_getaffinity 5756 pid: pid_t 5757 / 5758 5759Return the affinity of the process identified by pid (or the current process if zero). 5760 5761The affinity is returned as a set of CPU identifiers. 5762[clinic start generated code]*/ 5763 5764static PyObject * 5765os_sched_getaffinity_impl(PyModuleDef *module, pid_t pid) 5766/*[clinic end generated code: output=b431a8f310e369e7 input=983ce7cb4a565980]*/ 5767{ 5768 int cpu, ncpus, count; 5769 size_t setsize; 5770 cpu_set_t *mask = NULL; 5771 PyObject *res = NULL; 5772 5773 ncpus = NCPUS_START; 5774 while (1) { 5775 setsize = CPU_ALLOC_SIZE(ncpus); 5776 mask = CPU_ALLOC(ncpus); 5777 if (mask == NULL) 5778 return PyErr_NoMemory(); 5779 if (sched_getaffinity(pid, setsize, mask) == 0) 5780 break; 5781 CPU_FREE(mask); 5782 if (errno != EINVAL) 5783 return posix_error(); 5784 if (ncpus > INT_MAX / 2) { 5785 PyErr_SetString(PyExc_OverflowError, "could not allocate " 5786 "a large enough CPU set"); 5787 return NULL; 5788 } 5789 ncpus = ncpus * 2; 5790 } 5791 5792 res = PySet_New(NULL); 5793 if (res == NULL) 5794 goto error; 5795 for (cpu = 0, count = CPU_COUNT_S(setsize, mask); count; cpu++) { 5796 if (CPU_ISSET_S(cpu, setsize, mask)) { 5797 PyObject *cpu_num = PyLong_FromLong(cpu); 5798 --count; 5799 if (cpu_num == NULL) 5800 goto error; 5801 if (PySet_Add(res, cpu_num)) { 5802 Py_DECREF(cpu_num); 5803 goto error; 5804 } 5805 Py_DECREF(cpu_num); 5806 } 5807 } 5808 CPU_FREE(mask); 5809 return res; 5810 5811error: 5812 if (mask) 5813 CPU_FREE(mask); 5814 Py_XDECREF(res); 5815 return NULL; 5816} 5817 5818#endif /* HAVE_SCHED_SETAFFINITY */ 5819 5820#endif /* HAVE_SCHED_H */ 5821 5822 5823/* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */ 5824/* IRIX has both /dev/ptc and /dev/ptmx, use ptmx */ 5825#if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX) 5826#define DEV_PTY_FILE "/dev/ptc" 5827#define HAVE_DEV_PTMX 5828#else 5829#define DEV_PTY_FILE "/dev/ptmx" 5830#endif 5831 5832#if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX) 5833#ifdef HAVE_PTY_H 5834#include <pty.h> 5835#else 5836#ifdef HAVE_LIBUTIL_H 5837#include <libutil.h> 5838#else 5839#ifdef HAVE_UTIL_H 5840#include <util.h> 5841#endif /* HAVE_UTIL_H */ 5842#endif /* HAVE_LIBUTIL_H */ 5843#endif /* HAVE_PTY_H */ 5844#ifdef HAVE_STROPTS_H 5845#include <stropts.h> 5846#endif 5847#endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX */ 5848 5849 5850#if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) 5851/*[clinic input] 5852os.openpty 5853 5854Open a pseudo-terminal. 5855 5856Return a tuple of (master_fd, slave_fd) containing open file descriptors 5857for both the master and slave ends. 5858[clinic start generated code]*/ 5859 5860static PyObject * 5861os_openpty_impl(PyModuleDef *module) 5862/*[clinic end generated code: output=358e571c1ba135ee input=f3d99fd99e762907]*/ 5863{ 5864 int master_fd = -1, slave_fd = -1; 5865#ifndef HAVE_OPENPTY 5866 char * slave_name; 5867#endif 5868#if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY) 5869 PyOS_sighandler_t sig_saved; 5870#ifdef sun 5871 extern char *ptsname(int fildes); 5872#endif 5873#endif 5874 5875#ifdef HAVE_OPENPTY 5876 if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0) 5877 goto posix_error; 5878 5879 if (_Py_set_inheritable(master_fd, 0, NULL) < 0) 5880 goto error; 5881 if (_Py_set_inheritable(slave_fd, 0, NULL) < 0) 5882 goto error; 5883 5884#elif defined(HAVE__GETPTY) 5885 slave_name = _getpty(&master_fd, O_RDWR, 0666, 0); 5886 if (slave_name == NULL) 5887 goto posix_error; 5888 if (_Py_set_inheritable(master_fd, 0, NULL) < 0) 5889 goto error; 5890 5891 slave_fd = _Py_open(slave_name, O_RDWR); 5892 if (slave_fd < 0) 5893 goto error; 5894 5895#else 5896 master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */ 5897 if (master_fd < 0) 5898 goto posix_error; 5899 5900 sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL); 5901 5902 /* change permission of slave */ 5903 if (grantpt(master_fd) < 0) { 5904 PyOS_setsig(SIGCHLD, sig_saved); 5905 goto posix_error; 5906 } 5907 5908 /* unlock slave */ 5909 if (unlockpt(master_fd) < 0) { 5910 PyOS_setsig(SIGCHLD, sig_saved); 5911 goto posix_error; 5912 } 5913 5914 PyOS_setsig(SIGCHLD, sig_saved); 5915 5916 slave_name = ptsname(master_fd); /* get name of slave */ 5917 if (slave_name == NULL) 5918 goto posix_error; 5919 5920 slave_fd = _Py_open(slave_name, O_RDWR | O_NOCTTY); /* open slave */ 5921 if (slave_fd == -1) 5922 goto error; 5923 5924 if (_Py_set_inheritable(master_fd, 0, NULL) < 0) 5925 goto posix_error; 5926 5927#if !defined(__CYGWIN__) && !defined(HAVE_DEV_PTC) 5928 ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */ 5929 ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */ 5930#ifndef __hpux 5931 ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */ 5932#endif /* __hpux */ 5933#endif /* HAVE_CYGWIN */ 5934#endif /* HAVE_OPENPTY */ 5935 5936 return Py_BuildValue("(ii)", master_fd, slave_fd); 5937 5938posix_error: 5939 posix_error(); 5940error: 5941 if (master_fd != -1) 5942 close(master_fd); 5943 if (slave_fd != -1) 5944 close(slave_fd); 5945 return NULL; 5946} 5947#endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */ 5948 5949 5950#ifdef HAVE_FORKPTY 5951/*[clinic input] 5952os.forkpty 5953 5954Fork a new process with a new pseudo-terminal as controlling tty. 5955 5956Returns a tuple of (pid, master_fd). 5957Like fork(), return pid of 0 to the child process, 5958and pid of child to the parent process. 5959To both, return fd of newly opened pseudo-terminal. 5960[clinic start generated code]*/ 5961 5962static PyObject * 5963os_forkpty_impl(PyModuleDef *module) 5964/*[clinic end generated code: output=a11b8391dce3cb57 input=f1f7f4bae3966010]*/ 5965{ 5966 int master_fd = -1, result = 0; 5967 pid_t pid; 5968 5969 _PyImport_AcquireLock(); 5970 pid = forkpty(&master_fd, NULL, NULL, NULL); 5971 if (pid == 0) { 5972 /* child: this clobbers and resets the import lock. */ 5973 PyOS_AfterFork(); 5974 } else { 5975 /* parent: release the import lock. */ 5976 result = _PyImport_ReleaseLock(); 5977 } 5978 if (pid == -1) 5979 return posix_error(); 5980 if (result < 0) { 5981 /* Don't clobber the OSError if the fork failed. */ 5982 PyErr_SetString(PyExc_RuntimeError, 5983 "not holding the import lock"); 5984 return NULL; 5985 } 5986 return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd); 5987} 5988#endif /* HAVE_FORKPTY */ 5989 5990 5991#ifdef HAVE_GETEGID 5992/*[clinic input] 5993os.getegid 5994 5995Return the current process's effective group id. 5996[clinic start generated code]*/ 5997 5998static PyObject * 5999os_getegid_impl(PyModuleDef *module) 6000/*[clinic end generated code: output=90f433a8c0b1d919 input=1596f79ad1107d5d]*/ 6001{ 6002 return _PyLong_FromGid(getegid()); 6003} 6004#endif /* HAVE_GETEGID */ 6005 6006 6007#ifdef HAVE_GETEUID 6008/*[clinic input] 6009os.geteuid 6010 6011Return the current process's effective user id. 6012[clinic start generated code]*/ 6013 6014static PyObject * 6015os_geteuid_impl(PyModuleDef *module) 6016/*[clinic end generated code: output=1a532c4a66874357 input=4644c662d3bd9f19]*/ 6017{ 6018 return _PyLong_FromUid(geteuid()); 6019} 6020#endif /* HAVE_GETEUID */ 6021 6022 6023#ifdef HAVE_GETGID 6024/*[clinic input] 6025os.getgid 6026 6027Return the current process's group id. 6028[clinic start generated code]*/ 6029 6030static PyObject * 6031os_getgid_impl(PyModuleDef *module) 6032/*[clinic end generated code: output=91a22021b74ea46b input=58796344cd87c0f6]*/ 6033{ 6034 return _PyLong_FromGid(getgid()); 6035} 6036#endif /* HAVE_GETGID */ 6037 6038 6039/*[clinic input] 6040os.getpid 6041 6042Return the current process id. 6043[clinic start generated code]*/ 6044 6045static PyObject * 6046os_getpid_impl(PyModuleDef *module) 6047/*[clinic end generated code: output=8fbf3a934ee09e62 input=5a9a00f0ab68aa00]*/ 6048{ 6049 return PyLong_FromPid(getpid()); 6050} 6051 6052#ifdef HAVE_GETGROUPLIST 6053 6054/* AC 3.5: funny apple logic below */ 6055PyDoc_STRVAR(posix_getgrouplist__doc__, 6056"getgrouplist(user, group) -> list of groups to which a user belongs\n\n\ 6057Returns a list of groups to which a user belongs.\n\n\ 6058 user: username to lookup\n\ 6059 group: base group id of the user"); 6060 6061static PyObject * 6062posix_getgrouplist(PyObject *self, PyObject *args) 6063{ 6064#ifdef NGROUPS_MAX 6065#define MAX_GROUPS NGROUPS_MAX 6066#else 6067 /* defined to be 16 on Solaris7, so this should be a small number */ 6068#define MAX_GROUPS 64 6069#endif 6070 6071 const char *user; 6072 int i, ngroups; 6073 PyObject *list; 6074#ifdef __APPLE__ 6075 int *groups, basegid; 6076#else 6077 gid_t *groups, basegid; 6078#endif 6079 ngroups = MAX_GROUPS; 6080 6081#ifdef __APPLE__ 6082 if (!PyArg_ParseTuple(args, "si:getgrouplist", &user, &basegid)) 6083 return NULL; 6084#else 6085 if (!PyArg_ParseTuple(args, "sO&:getgrouplist", &user, 6086 _Py_Gid_Converter, &basegid)) 6087 return NULL; 6088#endif 6089 6090#ifdef __APPLE__ 6091 groups = PyMem_New(int, ngroups); 6092#else 6093 groups = PyMem_New(gid_t, ngroups); 6094#endif 6095 if (groups == NULL) 6096 return PyErr_NoMemory(); 6097 6098 if (getgrouplist(user, basegid, groups, &ngroups) == -1) { 6099 PyMem_Del(groups); 6100 return posix_error(); 6101 } 6102 6103 list = PyList_New(ngroups); 6104 if (list == NULL) { 6105 PyMem_Del(groups); 6106 return NULL; 6107 } 6108 6109 for (i = 0; i < ngroups; i++) { 6110#ifdef __APPLE__ 6111 PyObject *o = PyLong_FromUnsignedLong((unsigned long)groups[i]); 6112#else 6113 PyObject *o = _PyLong_FromGid(groups[i]); 6114#endif 6115 if (o == NULL) { 6116 Py_DECREF(list); 6117 PyMem_Del(groups); 6118 return NULL; 6119 } 6120 PyList_SET_ITEM(list, i, o); 6121 } 6122 6123 PyMem_Del(groups); 6124 6125 return list; 6126} 6127#endif /* HAVE_GETGROUPLIST */ 6128 6129 6130#ifdef HAVE_GETGROUPS 6131/*[clinic input] 6132os.getgroups 6133 6134Return list of supplemental group IDs for the process. 6135[clinic start generated code]*/ 6136 6137static PyObject * 6138os_getgroups_impl(PyModuleDef *module) 6139/*[clinic end generated code: output=6e7c4fd2db6d5c60 input=d3f109412e6a155c]*/ 6140{ 6141 PyObject *result = NULL; 6142 6143#ifdef NGROUPS_MAX 6144#define MAX_GROUPS NGROUPS_MAX 6145#else 6146 /* defined to be 16 on Solaris7, so this should be a small number */ 6147#define MAX_GROUPS 64 6148#endif 6149 gid_t grouplist[MAX_GROUPS]; 6150 6151 /* On MacOSX getgroups(2) can return more than MAX_GROUPS results 6152 * This is a helper variable to store the intermediate result when 6153 * that happens. 6154 * 6155 * To keep the code readable the OSX behaviour is unconditional, 6156 * according to the POSIX spec this should be safe on all unix-y 6157 * systems. 6158 */ 6159 gid_t* alt_grouplist = grouplist; 6160 int n; 6161 6162#ifdef __APPLE__ 6163 /* Issue #17557: As of OS X 10.8, getgroups(2) no longer raises EINVAL if 6164 * there are more groups than can fit in grouplist. Therefore, on OS X 6165 * always first call getgroups with length 0 to get the actual number 6166 * of groups. 6167 */ 6168 n = getgroups(0, NULL); 6169 if (n < 0) { 6170 return posix_error(); 6171 } else if (n <= MAX_GROUPS) { 6172 /* groups will fit in existing array */ 6173 alt_grouplist = grouplist; 6174 } else { 6175 alt_grouplist = PyMem_New(gid_t, n); 6176 if (alt_grouplist == NULL) { 6177 errno = EINVAL; 6178 return posix_error(); 6179 } 6180 } 6181 6182 n = getgroups(n, alt_grouplist); 6183 if (n == -1) { 6184 if (alt_grouplist != grouplist) { 6185 PyMem_Free(alt_grouplist); 6186 } 6187 return posix_error(); 6188 } 6189#else 6190 n = getgroups(MAX_GROUPS, grouplist); 6191 if (n < 0) { 6192 if (errno == EINVAL) { 6193 n = getgroups(0, NULL); 6194 if (n == -1) { 6195 return posix_error(); 6196 } 6197 if (n == 0) { 6198 /* Avoid malloc(0) */ 6199 alt_grouplist = grouplist; 6200 } else { 6201 alt_grouplist = PyMem_New(gid_t, n); 6202 if (alt_grouplist == NULL) { 6203 errno = EINVAL; 6204 return posix_error(); 6205 } 6206 n = getgroups(n, alt_grouplist); 6207 if (n == -1) { 6208 PyMem_Free(alt_grouplist); 6209 return posix_error(); 6210 } 6211 } 6212 } else { 6213 return posix_error(); 6214 } 6215 } 6216#endif 6217 6218 result = PyList_New(n); 6219 if (result != NULL) { 6220 int i; 6221 for (i = 0; i < n; ++i) { 6222 PyObject *o = _PyLong_FromGid(alt_grouplist[i]); 6223 if (o == NULL) { 6224 Py_DECREF(result); 6225 result = NULL; 6226 break; 6227 } 6228 PyList_SET_ITEM(result, i, o); 6229 } 6230 } 6231 6232 if (alt_grouplist != grouplist) { 6233 PyMem_Free(alt_grouplist); 6234 } 6235 6236 return result; 6237} 6238#endif /* HAVE_GETGROUPS */ 6239 6240#ifdef HAVE_INITGROUPS 6241PyDoc_STRVAR(posix_initgroups__doc__, 6242"initgroups(username, gid) -> None\n\n\ 6243Call the system initgroups() to initialize the group access list with all of\n\ 6244the groups of which the specified username is a member, plus the specified\n\ 6245group id."); 6246 6247/* AC 3.5: funny apple logic */ 6248static PyObject * 6249posix_initgroups(PyObject *self, PyObject *args) 6250{ 6251 PyObject *oname; 6252 char *username; 6253 int res; 6254#ifdef __APPLE__ 6255 int gid; 6256#else 6257 gid_t gid; 6258#endif 6259 6260#ifdef __APPLE__ 6261 if (!PyArg_ParseTuple(args, "O&i:initgroups", 6262 PyUnicode_FSConverter, &oname, 6263 &gid)) 6264#else 6265 if (!PyArg_ParseTuple(args, "O&O&:initgroups", 6266 PyUnicode_FSConverter, &oname, 6267 _Py_Gid_Converter, &gid)) 6268#endif 6269 return NULL; 6270 username = PyBytes_AS_STRING(oname); 6271 6272 res = initgroups(username, gid); 6273 Py_DECREF(oname); 6274 if (res == -1) 6275 return PyErr_SetFromErrno(PyExc_OSError); 6276 6277 Py_INCREF(Py_None); 6278 return Py_None; 6279} 6280#endif /* HAVE_INITGROUPS */ 6281 6282 6283#ifdef HAVE_GETPGID 6284/*[clinic input] 6285os.getpgid 6286 6287 pid: pid_t 6288 6289Call the system call getpgid(), and return the result. 6290[clinic start generated code]*/ 6291 6292static PyObject * 6293os_getpgid_impl(PyModuleDef *module, pid_t pid) 6294/*[clinic end generated code: output=70e713b4d54b7c61 input=39d710ae3baaf1c7]*/ 6295{ 6296 pid_t pgid = getpgid(pid); 6297 if (pgid < 0) 6298 return posix_error(); 6299 return PyLong_FromPid(pgid); 6300} 6301#endif /* HAVE_GETPGID */ 6302 6303 6304#ifdef HAVE_GETPGRP 6305/*[clinic input] 6306os.getpgrp 6307 6308Return the current process group id. 6309[clinic start generated code]*/ 6310 6311static PyObject * 6312os_getpgrp_impl(PyModuleDef *module) 6313/*[clinic end generated code: output=cf3403585846811f input=6846fb2bb9a3705e]*/ 6314{ 6315#ifdef GETPGRP_HAVE_ARG 6316 return PyLong_FromPid(getpgrp(0)); 6317#else /* GETPGRP_HAVE_ARG */ 6318 return PyLong_FromPid(getpgrp()); 6319#endif /* GETPGRP_HAVE_ARG */ 6320} 6321#endif /* HAVE_GETPGRP */ 6322 6323 6324#ifdef HAVE_SETPGRP 6325/*[clinic input] 6326os.setpgrp 6327 6328Make the current process the leader of its process group. 6329[clinic start generated code]*/ 6330 6331static PyObject * 6332os_setpgrp_impl(PyModuleDef *module) 6333/*[clinic end generated code: output=59650f55a963d7ac input=1f0619fcb5731e7e]*/ 6334{ 6335#ifdef SETPGRP_HAVE_ARG 6336 if (setpgrp(0, 0) < 0) 6337#else /* SETPGRP_HAVE_ARG */ 6338 if (setpgrp() < 0) 6339#endif /* SETPGRP_HAVE_ARG */ 6340 return posix_error(); 6341 Py_INCREF(Py_None); 6342 return Py_None; 6343} 6344#endif /* HAVE_SETPGRP */ 6345 6346#ifdef HAVE_GETPPID 6347 6348#ifdef MS_WINDOWS 6349#include <tlhelp32.h> 6350 6351static PyObject* 6352win32_getppid() 6353{ 6354 HANDLE snapshot; 6355 pid_t mypid; 6356 PyObject* result = NULL; 6357 BOOL have_record; 6358 PROCESSENTRY32 pe; 6359 6360 mypid = getpid(); /* This function never fails */ 6361 6362 snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); 6363 if (snapshot == INVALID_HANDLE_VALUE) 6364 return PyErr_SetFromWindowsErr(GetLastError()); 6365 6366 pe.dwSize = sizeof(pe); 6367 have_record = Process32First(snapshot, &pe); 6368 while (have_record) { 6369 if (mypid == (pid_t)pe.th32ProcessID) { 6370 /* We could cache the ulong value in a static variable. */ 6371 result = PyLong_FromPid((pid_t)pe.th32ParentProcessID); 6372 break; 6373 } 6374 6375 have_record = Process32Next(snapshot, &pe); 6376 } 6377 6378 /* If our loop exits and our pid was not found (result will be NULL) 6379 * then GetLastError will return ERROR_NO_MORE_FILES. This is an 6380 * error anyway, so let's raise it. */ 6381 if (!result) 6382 result = PyErr_SetFromWindowsErr(GetLastError()); 6383 6384 CloseHandle(snapshot); 6385 6386 return result; 6387} 6388#endif /*MS_WINDOWS*/ 6389 6390 6391/*[clinic input] 6392os.getppid 6393 6394Return the parent's process id. 6395 6396If the parent process has already exited, Windows machines will still 6397return its id; others systems will return the id of the 'init' process (1). 6398[clinic start generated code]*/ 6399 6400static PyObject * 6401os_getppid_impl(PyModuleDef *module) 6402/*[clinic end generated code: output=4e49c8e7a8738cd2 input=e637cb87539c030e]*/ 6403{ 6404#ifdef MS_WINDOWS 6405 return win32_getppid(); 6406#else 6407 return PyLong_FromPid(getppid()); 6408#endif 6409} 6410#endif /* HAVE_GETPPID */ 6411 6412 6413#ifdef HAVE_GETLOGIN 6414/*[clinic input] 6415os.getlogin 6416 6417Return the actual login name. 6418[clinic start generated code]*/ 6419 6420static PyObject * 6421os_getlogin_impl(PyModuleDef *module) 6422/*[clinic end generated code: output=037ebdb3e4b5dac1 input=2a21ab1e917163df]*/ 6423{ 6424 PyObject *result = NULL; 6425#ifdef MS_WINDOWS 6426 wchar_t user_name[UNLEN + 1]; 6427 DWORD num_chars = Py_ARRAY_LENGTH(user_name); 6428 6429 if (GetUserNameW(user_name, &num_chars)) { 6430 /* num_chars is the number of unicode chars plus null terminator */ 6431 result = PyUnicode_FromWideChar(user_name, num_chars - 1); 6432 } 6433 else 6434 result = PyErr_SetFromWindowsErr(GetLastError()); 6435#else 6436 char *name; 6437 int old_errno = errno; 6438 6439 errno = 0; 6440 name = getlogin(); 6441 if (name == NULL) { 6442 if (errno) 6443 posix_error(); 6444 else 6445 PyErr_SetString(PyExc_OSError, "unable to determine login name"); 6446 } 6447 else 6448 result = PyUnicode_DecodeFSDefault(name); 6449 errno = old_errno; 6450#endif 6451 return result; 6452} 6453#endif /* HAVE_GETLOGIN */ 6454 6455 6456#ifdef HAVE_GETUID 6457/*[clinic input] 6458os.getuid 6459 6460Return the current process's user id. 6461[clinic start generated code]*/ 6462 6463static PyObject * 6464os_getuid_impl(PyModuleDef *module) 6465/*[clinic end generated code: output=03a8b894cefb3fa5 input=b53c8b35f110a516]*/ 6466{ 6467 return _PyLong_FromUid(getuid()); 6468} 6469#endif /* HAVE_GETUID */ 6470 6471 6472#ifdef MS_WINDOWS 6473#define HAVE_KILL 6474#endif /* MS_WINDOWS */ 6475 6476#ifdef HAVE_KILL 6477/*[clinic input] 6478os.kill 6479 6480 pid: pid_t 6481 signal: Py_ssize_t 6482 / 6483 6484Kill a process with a signal. 6485[clinic start generated code]*/ 6486 6487static PyObject * 6488os_kill_impl(PyModuleDef *module, pid_t pid, Py_ssize_t signal) 6489/*[clinic end generated code: output=74f907dd00a83c26 input=61a36b86ca275ab9]*/ 6490#ifndef MS_WINDOWS 6491{ 6492 if (kill(pid, (int)signal) == -1) 6493 return posix_error(); 6494 Py_RETURN_NONE; 6495} 6496#else /* !MS_WINDOWS */ 6497{ 6498 PyObject *result; 6499 DWORD sig = (DWORD)signal; 6500 DWORD err; 6501 HANDLE handle; 6502 6503 /* Console processes which share a common console can be sent CTRL+C or 6504 CTRL+BREAK events, provided they handle said events. */ 6505 if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) { 6506 if (GenerateConsoleCtrlEvent(sig, (DWORD)pid) == 0) { 6507 err = GetLastError(); 6508 PyErr_SetFromWindowsErr(err); 6509 } 6510 else 6511 Py_RETURN_NONE; 6512 } 6513 6514 /* If the signal is outside of what GenerateConsoleCtrlEvent can use, 6515 attempt to open and terminate the process. */ 6516 handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, (DWORD)pid); 6517 if (handle == NULL) { 6518 err = GetLastError(); 6519 return PyErr_SetFromWindowsErr(err); 6520 } 6521 6522 if (TerminateProcess(handle, sig) == 0) { 6523 err = GetLastError(); 6524 result = PyErr_SetFromWindowsErr(err); 6525 } else { 6526 Py_INCREF(Py_None); 6527 result = Py_None; 6528 } 6529 6530 CloseHandle(handle); 6531 return result; 6532} 6533#endif /* !MS_WINDOWS */ 6534#endif /* HAVE_KILL */ 6535 6536 6537#ifdef HAVE_KILLPG 6538/*[clinic input] 6539os.killpg 6540 6541 pgid: pid_t 6542 signal: int 6543 / 6544 6545Kill a process group with a signal. 6546[clinic start generated code]*/ 6547 6548static PyObject * 6549os_killpg_impl(PyModuleDef *module, pid_t pgid, int signal) 6550/*[clinic end generated code: output=3434a766ef945f93 input=38b5449eb8faec19]*/ 6551{ 6552 /* XXX some man pages make the `pgid` parameter an int, others 6553 a pid_t. Since getpgrp() returns a pid_t, we assume killpg should 6554 take the same type. Moreover, pid_t is always at least as wide as 6555 int (else compilation of this module fails), which is safe. */ 6556 if (killpg(pgid, signal) == -1) 6557 return posix_error(); 6558 Py_RETURN_NONE; 6559} 6560#endif /* HAVE_KILLPG */ 6561 6562 6563#ifdef HAVE_PLOCK 6564#ifdef HAVE_SYS_LOCK_H 6565#include <sys/lock.h> 6566#endif 6567 6568/*[clinic input] 6569os.plock 6570 op: int 6571 / 6572 6573Lock program segments into memory."); 6574[clinic start generated code]*/ 6575 6576static PyObject * 6577os_plock_impl(PyModuleDef *module, int op) 6578/*[clinic end generated code: output=5cb851f81b914984 input=e6e5e348e1525f60]*/ 6579{ 6580 if (plock(op) == -1) 6581 return posix_error(); 6582 Py_RETURN_NONE; 6583} 6584#endif /* HAVE_PLOCK */ 6585 6586 6587#ifdef HAVE_SETUID 6588/*[clinic input] 6589os.setuid 6590 6591 uid: uid_t 6592 / 6593 6594Set the current process's user id. 6595[clinic start generated code]*/ 6596 6597static PyObject * 6598os_setuid_impl(PyModuleDef *module, uid_t uid) 6599/*[clinic end generated code: output=941ea9a8d1e5d565 input=c921a3285aa22256]*/ 6600{ 6601 if (setuid(uid) < 0) 6602 return posix_error(); 6603 Py_RETURN_NONE; 6604} 6605#endif /* HAVE_SETUID */ 6606 6607 6608#ifdef HAVE_SETEUID 6609/*[clinic input] 6610os.seteuid 6611 6612 euid: uid_t 6613 / 6614 6615Set the current process's effective user id. 6616[clinic start generated code]*/ 6617 6618static PyObject * 6619os_seteuid_impl(PyModuleDef *module, uid_t euid) 6620/*[clinic end generated code: output=66f4f6823a648d6d input=ba93d927e4781aa9]*/ 6621{ 6622 if (seteuid(euid) < 0) 6623 return posix_error(); 6624 Py_RETURN_NONE; 6625} 6626#endif /* HAVE_SETEUID */ 6627 6628 6629#ifdef HAVE_SETEGID 6630/*[clinic input] 6631os.setegid 6632 6633 egid: gid_t 6634 / 6635 6636Set the current process's effective group id. 6637[clinic start generated code]*/ 6638 6639static PyObject * 6640os_setegid_impl(PyModuleDef *module, gid_t egid) 6641/*[clinic end generated code: output=ca094a69a081a60f input=4080526d0ccd6ce3]*/ 6642{ 6643 if (setegid(egid) < 0) 6644 return posix_error(); 6645 Py_RETURN_NONE; 6646} 6647#endif /* HAVE_SETEGID */ 6648 6649 6650#ifdef HAVE_SETREUID 6651/*[clinic input] 6652os.setreuid 6653 6654 ruid: uid_t 6655 euid: uid_t 6656 / 6657 6658Set the current process's real and effective user ids. 6659[clinic start generated code]*/ 6660 6661static PyObject * 6662os_setreuid_impl(PyModuleDef *module, uid_t ruid, uid_t euid) 6663/*[clinic end generated code: output=b2938c3e73d27ec7 input=0ca8978de663880c]*/ 6664{ 6665 if (setreuid(ruid, euid) < 0) { 6666 return posix_error(); 6667 } else { 6668 Py_INCREF(Py_None); 6669 return Py_None; 6670 } 6671} 6672#endif /* HAVE_SETREUID */ 6673 6674 6675#ifdef HAVE_SETREGID 6676/*[clinic input] 6677os.setregid 6678 6679 rgid: gid_t 6680 egid: gid_t 6681 / 6682 6683Set the current process's real and effective group ids. 6684[clinic start generated code]*/ 6685 6686static PyObject * 6687os_setregid_impl(PyModuleDef *module, gid_t rgid, gid_t egid) 6688/*[clinic end generated code: output=db18f1839ababe3d input=c59499f72846db78]*/ 6689{ 6690 if (setregid(rgid, egid) < 0) 6691 return posix_error(); 6692 Py_RETURN_NONE; 6693} 6694#endif /* HAVE_SETREGID */ 6695 6696 6697#ifdef HAVE_SETGID 6698/*[clinic input] 6699os.setgid 6700 gid: gid_t 6701 / 6702 6703Set the current process's group id. 6704[clinic start generated code]*/ 6705 6706static PyObject * 6707os_setgid_impl(PyModuleDef *module, gid_t gid) 6708/*[clinic end generated code: output=756cb42c6abd9d87 input=27d30c4059045dc6]*/ 6709{ 6710 if (setgid(gid) < 0) 6711 return posix_error(); 6712 Py_RETURN_NONE; 6713} 6714#endif /* HAVE_SETGID */ 6715 6716 6717#ifdef HAVE_SETGROUPS 6718/*[clinic input] 6719os.setgroups 6720 6721 groups: object 6722 / 6723 6724Set the groups of the current process to list. 6725[clinic start generated code]*/ 6726 6727static PyObject * 6728os_setgroups(PyModuleDef *module, PyObject *groups) 6729/*[clinic end generated code: output=7945c2e3cc817c58 input=fa742ca3daf85a7e]*/ 6730{ 6731 int i, len; 6732 gid_t grouplist[MAX_GROUPS]; 6733 6734 if (!PySequence_Check(groups)) { 6735 PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence"); 6736 return NULL; 6737 } 6738 len = PySequence_Size(groups); 6739 if (len > MAX_GROUPS) { 6740 PyErr_SetString(PyExc_ValueError, "too many groups"); 6741 return NULL; 6742 } 6743 for(i = 0; i < len; i++) { 6744 PyObject *elem; 6745 elem = PySequence_GetItem(groups, i); 6746 if (!elem) 6747 return NULL; 6748 if (!PyLong_Check(elem)) { 6749 PyErr_SetString(PyExc_TypeError, 6750 "groups must be integers"); 6751 Py_DECREF(elem); 6752 return NULL; 6753 } else { 6754 if (!_Py_Gid_Converter(elem, &grouplist[i])) { 6755 Py_DECREF(elem); 6756 return NULL; 6757 } 6758 } 6759 Py_DECREF(elem); 6760 } 6761 6762 if (setgroups(len, grouplist) < 0) 6763 return posix_error(); 6764 Py_INCREF(Py_None); 6765 return Py_None; 6766} 6767#endif /* HAVE_SETGROUPS */ 6768 6769#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4) 6770static PyObject * 6771wait_helper(pid_t pid, int status, struct rusage *ru) 6772{ 6773 PyObject *result; 6774 static PyObject *struct_rusage; 6775 _Py_IDENTIFIER(struct_rusage); 6776 6777 if (pid == -1) 6778 return posix_error(); 6779 6780 if (struct_rusage == NULL) { 6781 PyObject *m = PyImport_ImportModuleNoBlock("resource"); 6782 if (m == NULL) 6783 return NULL; 6784 struct_rusage = _PyObject_GetAttrId(m, &PyId_struct_rusage); 6785 Py_DECREF(m); 6786 if (struct_rusage == NULL) 6787 return NULL; 6788 } 6789 6790 /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */ 6791 result = PyStructSequence_New((PyTypeObject*) struct_rusage); 6792 if (!result) 6793 return NULL; 6794 6795#ifndef doubletime 6796#define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001) 6797#endif 6798 6799 PyStructSequence_SET_ITEM(result, 0, 6800 PyFloat_FromDouble(doubletime(ru->ru_utime))); 6801 PyStructSequence_SET_ITEM(result, 1, 6802 PyFloat_FromDouble(doubletime(ru->ru_stime))); 6803#define SET_INT(result, index, value)\ 6804 PyStructSequence_SET_ITEM(result, index, PyLong_FromLong(value)) 6805 SET_INT(result, 2, ru->ru_maxrss); 6806 SET_INT(result, 3, ru->ru_ixrss); 6807 SET_INT(result, 4, ru->ru_idrss); 6808 SET_INT(result, 5, ru->ru_isrss); 6809 SET_INT(result, 6, ru->ru_minflt); 6810 SET_INT(result, 7, ru->ru_majflt); 6811 SET_INT(result, 8, ru->ru_nswap); 6812 SET_INT(result, 9, ru->ru_inblock); 6813 SET_INT(result, 10, ru->ru_oublock); 6814 SET_INT(result, 11, ru->ru_msgsnd); 6815 SET_INT(result, 12, ru->ru_msgrcv); 6816 SET_INT(result, 13, ru->ru_nsignals); 6817 SET_INT(result, 14, ru->ru_nvcsw); 6818 SET_INT(result, 15, ru->ru_nivcsw); 6819#undef SET_INT 6820 6821 if (PyErr_Occurred()) { 6822 Py_DECREF(result); 6823 return NULL; 6824 } 6825 6826 return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result); 6827} 6828#endif /* HAVE_WAIT3 || HAVE_WAIT4 */ 6829 6830 6831#ifdef HAVE_WAIT3 6832/*[clinic input] 6833os.wait3 6834 6835 options: int 6836Wait for completion of a child process. 6837 6838Returns a tuple of information about the child process: 6839 (pid, status, rusage) 6840[clinic start generated code]*/ 6841 6842static PyObject * 6843os_wait3_impl(PyModuleDef *module, int options) 6844/*[clinic end generated code: output=e18af4924dc54945 input=8ac4c56956b61710]*/ 6845{ 6846 pid_t pid; 6847 struct rusage ru; 6848 int async_err = 0; 6849 WAIT_TYPE status; 6850 WAIT_STATUS_INT(status) = 0; 6851 6852 do { 6853 Py_BEGIN_ALLOW_THREADS 6854 pid = wait3(&status, options, &ru); 6855 Py_END_ALLOW_THREADS 6856 } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); 6857 if (pid < 0) 6858 return (!async_err) ? posix_error() : NULL; 6859 6860 return wait_helper(pid, WAIT_STATUS_INT(status), &ru); 6861} 6862#endif /* HAVE_WAIT3 */ 6863 6864 6865#ifdef HAVE_WAIT4 6866/*[clinic input] 6867 6868os.wait4 6869 6870 pid: pid_t 6871 options: int 6872 6873Wait for completion of a specific child process. 6874 6875Returns a tuple of information about the child process: 6876 (pid, status, rusage) 6877[clinic start generated code]*/ 6878 6879static PyObject * 6880os_wait4_impl(PyModuleDef *module, pid_t pid, int options) 6881/*[clinic end generated code: output=714f19e6ff01e099 input=d11deed0750600ba]*/ 6882{ 6883 pid_t res; 6884 struct rusage ru; 6885 int async_err = 0; 6886 WAIT_TYPE status; 6887 WAIT_STATUS_INT(status) = 0; 6888 6889 do { 6890 Py_BEGIN_ALLOW_THREADS 6891 res = wait4(pid, &status, options, &ru); 6892 Py_END_ALLOW_THREADS 6893 } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); 6894 if (res < 0) 6895 return (!async_err) ? posix_error() : NULL; 6896 6897 return wait_helper(res, WAIT_STATUS_INT(status), &ru); 6898} 6899#endif /* HAVE_WAIT4 */ 6900 6901 6902#if defined(HAVE_WAITID) && !defined(__APPLE__) 6903/*[clinic input] 6904os.waitid 6905 6906 idtype: idtype_t 6907 Must be one of be P_PID, P_PGID or P_ALL. 6908 id: id_t 6909 The id to wait on. 6910 options: int 6911 Constructed from the ORing of one or more of WEXITED, WSTOPPED 6912 or WCONTINUED and additionally may be ORed with WNOHANG or WNOWAIT. 6913 / 6914 6915Returns the result of waiting for a process or processes. 6916 6917Returns either waitid_result or None if WNOHANG is specified and there are 6918no children in a waitable state. 6919[clinic start generated code]*/ 6920 6921static PyObject * 6922os_waitid_impl(PyModuleDef *module, idtype_t idtype, id_t id, int options) 6923/*[clinic end generated code: output=5c0192750e22fa2e input=d8e7f76e052b7920]*/ 6924{ 6925 PyObject *result; 6926 int res; 6927 int async_err = 0; 6928 siginfo_t si; 6929 si.si_pid = 0; 6930 6931 do { 6932 Py_BEGIN_ALLOW_THREADS 6933 res = waitid(idtype, id, &si, options); 6934 Py_END_ALLOW_THREADS 6935 } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); 6936 if (res < 0) 6937 return (!async_err) ? posix_error() : NULL; 6938 6939 if (si.si_pid == 0) 6940 Py_RETURN_NONE; 6941 6942 result = PyStructSequence_New(&WaitidResultType); 6943 if (!result) 6944 return NULL; 6945 6946 PyStructSequence_SET_ITEM(result, 0, PyLong_FromPid(si.si_pid)); 6947 PyStructSequence_SET_ITEM(result, 1, _PyLong_FromUid(si.si_uid)); 6948 PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong((long)(si.si_signo))); 6949 PyStructSequence_SET_ITEM(result, 3, PyLong_FromLong((long)(si.si_status))); 6950 PyStructSequence_SET_ITEM(result, 4, PyLong_FromLong((long)(si.si_code))); 6951 if (PyErr_Occurred()) { 6952 Py_DECREF(result); 6953 return NULL; 6954 } 6955 6956 return result; 6957} 6958#endif /* defined(HAVE_WAITID) && !defined(__APPLE__) */ 6959 6960 6961#if defined(HAVE_WAITPID) 6962/*[clinic input] 6963os.waitpid 6964 pid: pid_t 6965 options: int 6966 / 6967 6968Wait for completion of a given child process. 6969 6970Returns a tuple of information regarding the child process: 6971 (pid, status) 6972 6973The options argument is ignored on Windows. 6974[clinic start generated code]*/ 6975 6976static PyObject * 6977os_waitpid_impl(PyModuleDef *module, pid_t pid, int options) 6978/*[clinic end generated code: output=5e3593353d54b15b input=0bf1666b8758fda3]*/ 6979{ 6980 pid_t res; 6981 int async_err = 0; 6982 WAIT_TYPE status; 6983 WAIT_STATUS_INT(status) = 0; 6984 6985 do { 6986 Py_BEGIN_ALLOW_THREADS 6987 res = waitpid(pid, &status, options); 6988 Py_END_ALLOW_THREADS 6989 } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); 6990 if (res < 0) 6991 return (!async_err) ? posix_error() : NULL; 6992 6993 return Py_BuildValue("Ni", PyLong_FromPid(res), WAIT_STATUS_INT(status)); 6994} 6995#elif defined(HAVE_CWAIT) 6996/* MS C has a variant of waitpid() that's usable for most purposes. */ 6997/*[clinic input] 6998os.waitpid 6999 pid: Py_intptr_t 7000 options: int 7001 / 7002 7003Wait for completion of a given process. 7004 7005Returns a tuple of information regarding the process: 7006 (pid, status << 8) 7007 7008The options argument is ignored on Windows. 7009[clinic start generated code]*/ 7010 7011static PyObject * 7012os_waitpid_impl(PyModuleDef *module, Py_intptr_t pid, int options) 7013/*[clinic end generated code: output=fc1d520db019625f input=444c8f51cca5b862]*/ 7014{ 7015 int status; 7016 Py_intptr_t res; 7017 int async_err = 0; 7018 7019 do { 7020 Py_BEGIN_ALLOW_THREADS 7021 res = _cwait(&status, pid, options); 7022 Py_END_ALLOW_THREADS 7023 } while (res < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); 7024 if (res < 0) 7025 return (!async_err) ? posix_error() : NULL; 7026 7027 /* shift the status left a byte so this is more like the POSIX waitpid */ 7028 return Py_BuildValue(_Py_PARSE_INTPTR "i", res, status << 8); 7029} 7030#endif 7031 7032 7033#ifdef HAVE_WAIT 7034/*[clinic input] 7035os.wait 7036 7037Wait for completion of a child process. 7038 7039Returns a tuple of information about the child process: 7040 (pid, status) 7041[clinic start generated code]*/ 7042 7043static PyObject * 7044os_wait_impl(PyModuleDef *module) 7045/*[clinic end generated code: output=4a7f4978393e0654 input=03b0182d4a4700ce]*/ 7046{ 7047 pid_t pid; 7048 int async_err = 0; 7049 WAIT_TYPE status; 7050 WAIT_STATUS_INT(status) = 0; 7051 7052 do { 7053 Py_BEGIN_ALLOW_THREADS 7054 pid = wait(&status); 7055 Py_END_ALLOW_THREADS 7056 } while (pid < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); 7057 if (pid < 0) 7058 return (!async_err) ? posix_error() : NULL; 7059 7060 return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status)); 7061} 7062#endif /* HAVE_WAIT */ 7063 7064 7065#if defined(HAVE_READLINK) || defined(MS_WINDOWS) 7066PyDoc_STRVAR(readlink__doc__, 7067"readlink(path, *, dir_fd=None) -> path\n\n\ 7068Return a string representing the path to which the symbolic link points.\n\ 7069\n\ 7070If dir_fd is not None, it should be a file descriptor open to a directory,\n\ 7071 and path should be relative; path will then be relative to that directory.\n\ 7072dir_fd may not be implemented on your platform.\n\ 7073 If it is unavailable, using it will raise a NotImplementedError."); 7074#endif 7075 7076#ifdef HAVE_READLINK 7077 7078/* AC 3.5: merge win32 and not together */ 7079static PyObject * 7080posix_readlink(PyObject *self, PyObject *args, PyObject *kwargs) 7081{ 7082 path_t path; 7083 int dir_fd = DEFAULT_DIR_FD; 7084 char buffer[MAXPATHLEN]; 7085 ssize_t length; 7086 PyObject *return_value = NULL; 7087 static char *keywords[] = {"path", "dir_fd", NULL}; 7088 7089 memset(&path, 0, sizeof(path)); 7090 path.function_name = "readlink"; 7091 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|$O&:readlink", keywords, 7092 path_converter, &path, 7093 READLINKAT_DIR_FD_CONVERTER, &dir_fd)) 7094 return NULL; 7095 7096 Py_BEGIN_ALLOW_THREADS 7097#ifdef HAVE_READLINKAT 7098 if (dir_fd != DEFAULT_DIR_FD) 7099 length = readlinkat(dir_fd, path.narrow, buffer, sizeof(buffer)); 7100 else 7101#endif 7102 length = readlink(path.narrow, buffer, sizeof(buffer)); 7103 Py_END_ALLOW_THREADS 7104 7105 if (length < 0) { 7106 return_value = path_error(&path); 7107 goto exit; 7108 } 7109 7110 if (PyUnicode_Check(path.object)) 7111 return_value = PyUnicode_DecodeFSDefaultAndSize(buffer, length); 7112 else 7113 return_value = PyBytes_FromStringAndSize(buffer, length); 7114exit: 7115 path_cleanup(&path); 7116 return return_value; 7117} 7118 7119#endif /* HAVE_READLINK */ 7120 7121#if !defined(HAVE_READLINK) && defined(MS_WINDOWS) 7122 7123static PyObject * 7124win_readlink(PyObject *self, PyObject *args, PyObject *kwargs) 7125{ 7126 wchar_t *path; 7127 DWORD n_bytes_returned; 7128 DWORD io_result; 7129 PyObject *po, *result; 7130 int dir_fd; 7131 HANDLE reparse_point_handle; 7132 7133 char target_buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; 7134 REPARSE_DATA_BUFFER *rdb = (REPARSE_DATA_BUFFER *)target_buffer; 7135 wchar_t *print_name; 7136 7137 static char *keywords[] = {"path", "dir_fd", NULL}; 7138 7139 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "U|$O&:readlink", keywords, 7140 &po, 7141 dir_fd_unavailable, &dir_fd 7142 )) 7143 return NULL; 7144 7145 path = PyUnicode_AsUnicode(po); 7146 if (path == NULL) 7147 return NULL; 7148 7149 /* First get a handle to the reparse point */ 7150 Py_BEGIN_ALLOW_THREADS 7151 reparse_point_handle = CreateFileW( 7152 path, 7153 0, 7154 0, 7155 0, 7156 OPEN_EXISTING, 7157 FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS, 7158 0); 7159 Py_END_ALLOW_THREADS 7160 7161 if (reparse_point_handle==INVALID_HANDLE_VALUE) 7162 return win32_error_object("readlink", po); 7163 7164 Py_BEGIN_ALLOW_THREADS 7165 /* New call DeviceIoControl to read the reparse point */ 7166 io_result = DeviceIoControl( 7167 reparse_point_handle, 7168 FSCTL_GET_REPARSE_POINT, 7169 0, 0, /* in buffer */ 7170 target_buffer, sizeof(target_buffer), 7171 &n_bytes_returned, 7172 0 /* we're not using OVERLAPPED_IO */ 7173 ); 7174 CloseHandle(reparse_point_handle); 7175 Py_END_ALLOW_THREADS 7176 7177 if (io_result==0) 7178 return win32_error_object("readlink", po); 7179 7180 if (rdb->ReparseTag != IO_REPARSE_TAG_SYMLINK) 7181 { 7182 PyErr_SetString(PyExc_ValueError, 7183 "not a symbolic link"); 7184 return NULL; 7185 } 7186 print_name = rdb->SymbolicLinkReparseBuffer.PathBuffer + 7187 rdb->SymbolicLinkReparseBuffer.PrintNameOffset; 7188 7189 result = PyUnicode_FromWideChar(print_name, 7190 rdb->SymbolicLinkReparseBuffer.PrintNameLength/2); 7191 return result; 7192} 7193 7194#endif /* !defined(HAVE_READLINK) && defined(MS_WINDOWS) */ 7195 7196 7197 7198#ifdef HAVE_SYMLINK 7199 7200#if defined(MS_WINDOWS) 7201 7202/* Grab CreateSymbolicLinkW dynamically from kernel32 */ 7203static DWORD (CALLBACK *Py_CreateSymbolicLinkW)(LPWSTR, LPWSTR, DWORD) = NULL; 7204static DWORD (CALLBACK *Py_CreateSymbolicLinkA)(LPSTR, LPSTR, DWORD) = NULL; 7205 7206static int 7207check_CreateSymbolicLink(void) 7208{ 7209 HINSTANCE hKernel32; 7210 /* only recheck */ 7211 if (Py_CreateSymbolicLinkW && Py_CreateSymbolicLinkA) 7212 return 1; 7213 hKernel32 = GetModuleHandleW(L"KERNEL32"); 7214 *(FARPROC*)&Py_CreateSymbolicLinkW = GetProcAddress(hKernel32, 7215 "CreateSymbolicLinkW"); 7216 *(FARPROC*)&Py_CreateSymbolicLinkA = GetProcAddress(hKernel32, 7217 "CreateSymbolicLinkA"); 7218 return (Py_CreateSymbolicLinkW && Py_CreateSymbolicLinkA); 7219} 7220 7221/* Remove the last portion of the path */ 7222static void 7223_dirnameW(WCHAR *path) 7224{ 7225 WCHAR *ptr; 7226 7227 /* walk the path from the end until a backslash is encountered */ 7228 for(ptr = path + wcslen(path); ptr != path; ptr--) { 7229 if (*ptr == L'\\' || *ptr == L'/') 7230 break; 7231 } 7232 *ptr = 0; 7233} 7234 7235/* Remove the last portion of the path */ 7236static void 7237_dirnameA(char *path) 7238{ 7239 char *ptr; 7240 7241 /* walk the path from the end until a backslash is encountered */ 7242 for(ptr = path + strlen(path); ptr != path; ptr--) { 7243 if (*ptr == '\\' || *ptr == '/') 7244 break; 7245 } 7246 *ptr = 0; 7247} 7248 7249/* Is this path absolute? */ 7250static int 7251_is_absW(const WCHAR *path) 7252{ 7253 return path[0] == L'\\' || path[0] == L'/' || path[1] == L':'; 7254 7255} 7256 7257/* Is this path absolute? */ 7258static int 7259_is_absA(const char *path) 7260{ 7261 return path[0] == '\\' || path[0] == '/' || path[1] == ':'; 7262 7263} 7264 7265/* join root and rest with a backslash */ 7266static void 7267_joinW(WCHAR *dest_path, const WCHAR *root, const WCHAR *rest) 7268{ 7269 size_t root_len; 7270 7271 if (_is_absW(rest)) { 7272 wcscpy(dest_path, rest); 7273 return; 7274 } 7275 7276 root_len = wcslen(root); 7277 7278 wcscpy(dest_path, root); 7279 if(root_len) { 7280 dest_path[root_len] = L'\\'; 7281 root_len++; 7282 } 7283 wcscpy(dest_path+root_len, rest); 7284} 7285 7286/* join root and rest with a backslash */ 7287static void 7288_joinA(char *dest_path, const char *root, const char *rest) 7289{ 7290 size_t root_len; 7291 7292 if (_is_absA(rest)) { 7293 strcpy(dest_path, rest); 7294 return; 7295 } 7296 7297 root_len = strlen(root); 7298 7299 strcpy(dest_path, root); 7300 if(root_len) { 7301 dest_path[root_len] = '\\'; 7302 root_len++; 7303 } 7304 strcpy(dest_path+root_len, rest); 7305} 7306 7307/* Return True if the path at src relative to dest is a directory */ 7308static int 7309_check_dirW(WCHAR *src, WCHAR *dest) 7310{ 7311 WIN32_FILE_ATTRIBUTE_DATA src_info; 7312 WCHAR dest_parent[MAX_PATH]; 7313 WCHAR src_resolved[MAX_PATH] = L""; 7314 7315 /* dest_parent = os.path.dirname(dest) */ 7316 wcscpy(dest_parent, dest); 7317 _dirnameW(dest_parent); 7318 /* src_resolved = os.path.join(dest_parent, src) */ 7319 _joinW(src_resolved, dest_parent, src); 7320 return ( 7321 GetFileAttributesExW(src_resolved, GetFileExInfoStandard, &src_info) 7322 && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY 7323 ); 7324} 7325 7326/* Return True if the path at src relative to dest is a directory */ 7327static int 7328_check_dirA(char *src, char *dest) 7329{ 7330 WIN32_FILE_ATTRIBUTE_DATA src_info; 7331 char dest_parent[MAX_PATH]; 7332 char src_resolved[MAX_PATH] = ""; 7333 7334 /* dest_parent = os.path.dirname(dest) */ 7335 strcpy(dest_parent, dest); 7336 _dirnameA(dest_parent); 7337 /* src_resolved = os.path.join(dest_parent, src) */ 7338 _joinA(src_resolved, dest_parent, src); 7339 return ( 7340 GetFileAttributesExA(src_resolved, GetFileExInfoStandard, &src_info) 7341 && src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY 7342 ); 7343} 7344#endif 7345 7346 7347/*[clinic input] 7348os.symlink 7349 src: path_t 7350 dst: path_t 7351 target_is_directory: bool = False 7352 * 7353 dir_fd: dir_fd(requires='symlinkat')=None 7354 7355# "symlink(src, dst, target_is_directory=False, *, dir_fd=None)\n\n\ 7356 7357Create a symbolic link pointing to src named dst. 7358 7359target_is_directory is required on Windows if the target is to be 7360 interpreted as a directory. (On Windows, symlink requires 7361 Windows 6.0 or greater, and raises a NotImplementedError otherwise.) 7362 target_is_directory is ignored on non-Windows platforms. 7363 7364If dir_fd is not None, it should be a file descriptor open to a directory, 7365 and path should be relative; path will then be relative to that directory. 7366dir_fd may not be implemented on your platform. 7367 If it is unavailable, using it will raise a NotImplementedError. 7368 7369[clinic start generated code]*/ 7370 7371static PyObject * 7372os_symlink_impl(PyModuleDef *module, path_t *src, path_t *dst, 7373 int target_is_directory, int dir_fd) 7374/*[clinic end generated code: output=a01b4bcf32403ccd input=e820ec4472547bc3]*/ 7375{ 7376#ifdef MS_WINDOWS 7377 DWORD result; 7378#else 7379 int result; 7380#endif 7381 7382#ifdef MS_WINDOWS 7383 if (!check_CreateSymbolicLink()) { 7384 PyErr_SetString(PyExc_NotImplementedError, 7385 "CreateSymbolicLink functions not found"); 7386 return NULL; 7387 } 7388 if (!win32_can_symlink) { 7389 PyErr_SetString(PyExc_OSError, "symbolic link privilege not held"); 7390 return NULL; 7391 } 7392#endif 7393 7394 if ((src->narrow && dst->wide) || (src->wide && dst->narrow)) { 7395 PyErr_SetString(PyExc_ValueError, 7396 "symlink: src and dst must be the same type"); 7397 return NULL; 7398 } 7399 7400#ifdef MS_WINDOWS 7401 7402 Py_BEGIN_ALLOW_THREADS 7403 if (dst->wide) { 7404 /* if src is a directory, ensure target_is_directory==1 */ 7405 target_is_directory |= _check_dirW(src->wide, dst->wide); 7406 result = Py_CreateSymbolicLinkW(dst->wide, src->wide, 7407 target_is_directory); 7408 } 7409 else { 7410 /* if src is a directory, ensure target_is_directory==1 */ 7411 target_is_directory |= _check_dirA(src->narrow, dst->narrow); 7412 result = Py_CreateSymbolicLinkA(dst->narrow, src->narrow, 7413 target_is_directory); 7414 } 7415 Py_END_ALLOW_THREADS 7416 7417 if (!result) 7418 return path_error2(src, dst); 7419 7420#else 7421 7422 Py_BEGIN_ALLOW_THREADS 7423#if HAVE_SYMLINKAT 7424 if (dir_fd != DEFAULT_DIR_FD) 7425 result = symlinkat(src->narrow, dir_fd, dst->narrow); 7426 else 7427#endif 7428 result = symlink(src->narrow, dst->narrow); 7429 Py_END_ALLOW_THREADS 7430 7431 if (result) 7432 return path_error2(src, dst); 7433#endif 7434 7435 Py_RETURN_NONE; 7436} 7437#endif /* HAVE_SYMLINK */ 7438 7439 7440 7441 7442static PyStructSequence_Field times_result_fields[] = { 7443 {"user", "user time"}, 7444 {"system", "system time"}, 7445 {"children_user", "user time of children"}, 7446 {"children_system", "system time of children"}, 7447 {"elapsed", "elapsed time since an arbitrary point in the past"}, 7448 {NULL} 7449}; 7450 7451PyDoc_STRVAR(times_result__doc__, 7452"times_result: Result from os.times().\n\n\ 7453This object may be accessed either as a tuple of\n\ 7454 (user, system, children_user, children_system, elapsed),\n\ 7455or via the attributes user, system, children_user, children_system,\n\ 7456and elapsed.\n\ 7457\n\ 7458See os.times for more information."); 7459 7460static PyStructSequence_Desc times_result_desc = { 7461 "times_result", /* name */ 7462 times_result__doc__, /* doc */ 7463 times_result_fields, 7464 5 7465}; 7466 7467static PyTypeObject TimesResultType; 7468 7469#ifdef MS_WINDOWS 7470#define HAVE_TIMES /* mandatory, for the method table */ 7471#endif 7472 7473#ifdef HAVE_TIMES 7474 7475static PyObject * 7476build_times_result(double user, double system, 7477 double children_user, double children_system, 7478 double elapsed) 7479{ 7480 PyObject *value = PyStructSequence_New(&TimesResultType); 7481 if (value == NULL) 7482 return NULL; 7483 7484#define SET(i, field) \ 7485 { \ 7486 PyObject *o = PyFloat_FromDouble(field); \ 7487 if (!o) { \ 7488 Py_DECREF(value); \ 7489 return NULL; \ 7490 } \ 7491 PyStructSequence_SET_ITEM(value, i, o); \ 7492 } \ 7493 7494 SET(0, user); 7495 SET(1, system); 7496 SET(2, children_user); 7497 SET(3, children_system); 7498 SET(4, elapsed); 7499 7500#undef SET 7501 7502 return value; 7503} 7504 7505 7506#ifndef MS_WINDOWS 7507#define NEED_TICKS_PER_SECOND 7508static long ticks_per_second = -1; 7509#endif /* MS_WINDOWS */ 7510 7511/*[clinic input] 7512os.times 7513 7514Return a collection containing process timing information. 7515 7516The object returned behaves like a named tuple with these fields: 7517 (utime, stime, cutime, cstime, elapsed_time) 7518All fields are floating point numbers. 7519[clinic start generated code]*/ 7520 7521static PyObject * 7522os_times_impl(PyModuleDef *module) 7523/*[clinic end generated code: output=df0a63ebe6e6f091 input=2bf9df3d6ab2e48b]*/ 7524#ifdef MS_WINDOWS 7525{ 7526 FILETIME create, exit, kernel, user; 7527 HANDLE hProc; 7528 hProc = GetCurrentProcess(); 7529 GetProcessTimes(hProc, &create, &exit, &kernel, &user); 7530 /* The fields of a FILETIME structure are the hi and lo part 7531 of a 64-bit value expressed in 100 nanosecond units. 7532 1e7 is one second in such units; 1e-7 the inverse. 7533 429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7. 7534 */ 7535 return build_times_result( 7536 (double)(user.dwHighDateTime*429.4967296 + 7537 user.dwLowDateTime*1e-7), 7538 (double)(kernel.dwHighDateTime*429.4967296 + 7539 kernel.dwLowDateTime*1e-7), 7540 (double)0, 7541 (double)0, 7542 (double)0); 7543} 7544#else /* MS_WINDOWS */ 7545{ 7546 7547 7548 struct tms t; 7549 clock_t c; 7550 errno = 0; 7551 c = times(&t); 7552 if (c == (clock_t) -1) 7553 return posix_error(); 7554 return build_times_result( 7555 (double)t.tms_utime / ticks_per_second, 7556 (double)t.tms_stime / ticks_per_second, 7557 (double)t.tms_cutime / ticks_per_second, 7558 (double)t.tms_cstime / ticks_per_second, 7559 (double)c / ticks_per_second); 7560} 7561#endif /* MS_WINDOWS */ 7562#endif /* HAVE_TIMES */ 7563 7564 7565#ifdef HAVE_GETSID 7566/*[clinic input] 7567os.getsid 7568 7569 pid: pid_t 7570 / 7571 7572Call the system call getsid(pid) and return the result. 7573[clinic start generated code]*/ 7574 7575static PyObject * 7576os_getsid_impl(PyModuleDef *module, pid_t pid) 7577/*[clinic end generated code: output=a074f80c0e6bfb38 input=eeb2b923a30ce04e]*/ 7578{ 7579 int sid; 7580 sid = getsid(pid); 7581 if (sid < 0) 7582 return posix_error(); 7583 return PyLong_FromLong((long)sid); 7584} 7585#endif /* HAVE_GETSID */ 7586 7587 7588#ifdef HAVE_SETSID 7589/*[clinic input] 7590os.setsid 7591 7592Call the system call setsid(). 7593[clinic start generated code]*/ 7594 7595static PyObject * 7596os_setsid_impl(PyModuleDef *module) 7597/*[clinic end generated code: output=398fc152ae327330 input=5fff45858e2f0776]*/ 7598{ 7599 if (setsid() < 0) 7600 return posix_error(); 7601 Py_RETURN_NONE; 7602} 7603#endif /* HAVE_SETSID */ 7604 7605 7606#ifdef HAVE_SETPGID 7607/*[clinic input] 7608os.setpgid 7609 7610 pid: pid_t 7611 pgrp: pid_t 7612 / 7613 7614Call the system call setpgid(pid, pgrp). 7615[clinic start generated code]*/ 7616 7617static PyObject * 7618os_setpgid_impl(PyModuleDef *module, pid_t pid, pid_t pgrp) 7619/*[clinic end generated code: output=7079a8e932912841 input=fceb395eca572e1a]*/ 7620{ 7621 if (setpgid(pid, pgrp) < 0) 7622 return posix_error(); 7623 Py_RETURN_NONE; 7624} 7625#endif /* HAVE_SETPGID */ 7626 7627 7628#ifdef HAVE_TCGETPGRP 7629/*[clinic input] 7630os.tcgetpgrp 7631 7632 fd: int 7633 / 7634 7635Return the process group associated with the terminal specified by fd. 7636[clinic start generated code]*/ 7637 7638static PyObject * 7639os_tcgetpgrp_impl(PyModuleDef *module, int fd) 7640/*[clinic end generated code: output=ebb6dc5f111c7dc0 input=7f6c18eac10ada86]*/ 7641{ 7642 pid_t pgid = tcgetpgrp(fd); 7643 if (pgid < 0) 7644 return posix_error(); 7645 return PyLong_FromPid(pgid); 7646} 7647#endif /* HAVE_TCGETPGRP */ 7648 7649 7650#ifdef HAVE_TCSETPGRP 7651/*[clinic input] 7652os.tcsetpgrp 7653 7654 fd: int 7655 pgid: pid_t 7656 / 7657 7658Set the process group associated with the terminal specified by fd. 7659[clinic start generated code]*/ 7660 7661static PyObject * 7662os_tcsetpgrp_impl(PyModuleDef *module, int fd, pid_t pgid) 7663/*[clinic end generated code: output=3e4b05177462cd22 input=5bdc997c6a619020]*/ 7664{ 7665 if (tcsetpgrp(fd, pgid) < 0) 7666 return posix_error(); 7667 Py_RETURN_NONE; 7668} 7669#endif /* HAVE_TCSETPGRP */ 7670 7671/* Functions acting on file descriptors */ 7672 7673#ifdef O_CLOEXEC 7674extern int _Py_open_cloexec_works; 7675#endif 7676 7677 7678/*[clinic input] 7679os.open -> int 7680 path: path_t 7681 flags: int 7682 mode: int = 0o777 7683 * 7684 dir_fd: dir_fd(requires='openat') = None 7685 7686# "open(path, flags, mode=0o777, *, dir_fd=None)\n\n\ 7687 7688Open a file for low level IO. Returns a file descriptor (integer). 7689 7690If dir_fd is not None, it should be a file descriptor open to a directory, 7691 and path should be relative; path will then be relative to that directory. 7692dir_fd may not be implemented on your platform. 7693 If it is unavailable, using it will raise a NotImplementedError. 7694[clinic start generated code]*/ 7695 7696static int 7697os_open_impl(PyModuleDef *module, path_t *path, int flags, int mode, 7698 int dir_fd) 7699/*[clinic end generated code: output=47e8cc63559f5ddd input=ad8623b29acd2934]*/ 7700{ 7701 int fd; 7702 int async_err = 0; 7703 7704#ifdef O_CLOEXEC 7705 int *atomic_flag_works = &_Py_open_cloexec_works; 7706#elif !defined(MS_WINDOWS) 7707 int *atomic_flag_works = NULL; 7708#endif 7709 7710#ifdef MS_WINDOWS 7711 flags |= O_NOINHERIT; 7712#elif defined(O_CLOEXEC) 7713 flags |= O_CLOEXEC; 7714#endif 7715 7716 _Py_BEGIN_SUPPRESS_IPH 7717 do { 7718 Py_BEGIN_ALLOW_THREADS 7719#ifdef MS_WINDOWS 7720 if (path->wide) 7721 fd = _wopen(path->wide, flags, mode); 7722 else 7723#endif 7724#ifdef HAVE_OPENAT 7725 if (dir_fd != DEFAULT_DIR_FD) 7726 fd = openat(dir_fd, path->narrow, flags, mode); 7727 else 7728#endif 7729 fd = open(path->narrow, flags, mode); 7730 Py_END_ALLOW_THREADS 7731 } while (fd < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); 7732 _Py_END_SUPPRESS_IPH 7733 7734 if (fd < 0) { 7735 if (!async_err) 7736 PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path->object); 7737 return -1; 7738 } 7739 7740#ifndef MS_WINDOWS 7741 if (_Py_set_inheritable(fd, 0, atomic_flag_works) < 0) { 7742 close(fd); 7743 return -1; 7744 } 7745#endif 7746 7747 return fd; 7748} 7749 7750 7751/*[clinic input] 7752os.close 7753 7754 fd: int 7755 7756Close a file descriptor. 7757[clinic start generated code]*/ 7758 7759static PyObject * 7760os_close_impl(PyModuleDef *module, int fd) 7761/*[clinic end generated code: output=47bf2ea536445a26 input=2bc42451ca5c3223]*/ 7762{ 7763 int res; 7764 if (!_PyVerify_fd(fd)) 7765 return posix_error(); 7766 /* We do not want to retry upon EINTR: see http://lwn.net/Articles/576478/ 7767 * and http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html 7768 * for more details. 7769 */ 7770 Py_BEGIN_ALLOW_THREADS 7771 _Py_BEGIN_SUPPRESS_IPH 7772 res = close(fd); 7773 _Py_END_SUPPRESS_IPH 7774 Py_END_ALLOW_THREADS 7775 if (res < 0) 7776 return posix_error(); 7777 Py_RETURN_NONE; 7778} 7779 7780 7781/*[clinic input] 7782os.closerange 7783 7784 fd_low: int 7785 fd_high: int 7786 / 7787 7788Closes all file descriptors in [fd_low, fd_high), ignoring errors. 7789[clinic start generated code]*/ 7790 7791static PyObject * 7792os_closerange_impl(PyModuleDef *module, int fd_low, int fd_high) 7793/*[clinic end generated code: output=70e6adb95220ba96 input=5855a3d053ebd4ec]*/ 7794{ 7795 int i; 7796 Py_BEGIN_ALLOW_THREADS 7797 _Py_BEGIN_SUPPRESS_IPH 7798 for (i = fd_low; i < fd_high; i++) 7799 if (_PyVerify_fd(i)) 7800 close(i); 7801 _Py_END_SUPPRESS_IPH 7802 Py_END_ALLOW_THREADS 7803 Py_RETURN_NONE; 7804} 7805 7806 7807/*[clinic input] 7808os.dup -> int 7809 7810 fd: int 7811 / 7812 7813Return a duplicate of a file descriptor. 7814[clinic start generated code]*/ 7815 7816static int 7817os_dup_impl(PyModuleDef *module, int fd) 7818/*[clinic end generated code: output=f4bbac8c7652d05e input=6f10f7ea97f7852a]*/ 7819{ 7820 return _Py_dup(fd); 7821} 7822 7823 7824/*[clinic input] 7825os.dup2 7826 fd: int 7827 fd2: int 7828 inheritable: bool=True 7829 7830Duplicate file descriptor. 7831[clinic start generated code]*/ 7832 7833static PyObject * 7834os_dup2_impl(PyModuleDef *module, int fd, int fd2, int inheritable) 7835/*[clinic end generated code: output=9a099d95881a7923 input=76e96f511be0352f]*/ 7836{ 7837 int res; 7838#if defined(HAVE_DUP3) && \ 7839 !(defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC)) 7840 /* dup3() is available on Linux 2.6.27+ and glibc 2.9 */ 7841 int dup3_works = -1; 7842#endif 7843 7844 if (!_PyVerify_fd_dup2(fd, fd2)) 7845 return posix_error(); 7846 7847 /* dup2() can fail with EINTR if the target FD is already open, because it 7848 * then has to be closed. See os_close_impl() for why we don't handle EINTR 7849 * upon close(), and therefore below. 7850 */ 7851#ifdef MS_WINDOWS 7852 Py_BEGIN_ALLOW_THREADS 7853 _Py_BEGIN_SUPPRESS_IPH 7854 res = dup2(fd, fd2); 7855 _Py_END_SUPPRESS_IPH 7856 Py_END_ALLOW_THREADS 7857 if (res < 0) 7858 return posix_error(); 7859 7860 /* Character files like console cannot be make non-inheritable */ 7861 if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) { 7862 close(fd2); 7863 return NULL; 7864 } 7865 7866#elif defined(HAVE_FCNTL_H) && defined(F_DUP2FD_CLOEXEC) 7867 Py_BEGIN_ALLOW_THREADS 7868 if (!inheritable) 7869 res = fcntl(fd, F_DUP2FD_CLOEXEC, fd2); 7870 else 7871 res = dup2(fd, fd2); 7872 Py_END_ALLOW_THREADS 7873 if (res < 0) 7874 return posix_error(); 7875 7876#else 7877 7878#ifdef HAVE_DUP3 7879 if (!inheritable && dup3_works != 0) { 7880 Py_BEGIN_ALLOW_THREADS 7881 res = dup3(fd, fd2, O_CLOEXEC); 7882 Py_END_ALLOW_THREADS 7883 if (res < 0) { 7884 if (dup3_works == -1) 7885 dup3_works = (errno != ENOSYS); 7886 if (dup3_works) 7887 return posix_error(); 7888 } 7889 } 7890 7891 if (inheritable || dup3_works == 0) 7892 { 7893#endif 7894 Py_BEGIN_ALLOW_THREADS 7895 res = dup2(fd, fd2); 7896 Py_END_ALLOW_THREADS 7897 if (res < 0) 7898 return posix_error(); 7899 7900 if (!inheritable && _Py_set_inheritable(fd2, 0, NULL) < 0) { 7901 close(fd2); 7902 return NULL; 7903 } 7904#ifdef HAVE_DUP3 7905 } 7906#endif 7907 7908#endif 7909 7910 Py_RETURN_NONE; 7911} 7912 7913 7914#ifdef HAVE_LOCKF 7915/*[clinic input] 7916os.lockf 7917 7918 fd: int 7919 An open file descriptor. 7920 command: int 7921 One of F_LOCK, F_TLOCK, F_ULOCK or F_TEST. 7922 length: Py_off_t 7923 The number of bytes to lock, starting at the current position. 7924 / 7925 7926Apply, test or remove a POSIX lock on an open file descriptor. 7927 7928[clinic start generated code]*/ 7929 7930static PyObject * 7931os_lockf_impl(PyModuleDef *module, int fd, int command, Py_off_t length) 7932/*[clinic end generated code: output=25ff778f9e2fbf1b input=65da41d2106e9b79]*/ 7933{ 7934 int res; 7935 7936 Py_BEGIN_ALLOW_THREADS 7937 res = lockf(fd, command, length); 7938 Py_END_ALLOW_THREADS 7939 7940 if (res < 0) 7941 return posix_error(); 7942 7943 Py_RETURN_NONE; 7944} 7945#endif /* HAVE_LOCKF */ 7946 7947 7948/*[clinic input] 7949os.lseek -> Py_off_t 7950 7951 fd: int 7952 position: Py_off_t 7953 how: int 7954 / 7955 7956Set the position of a file descriptor. Return the new position. 7957 7958Return the new cursor position in number of bytes 7959relative to the beginning of the file. 7960[clinic start generated code]*/ 7961 7962static Py_off_t 7963os_lseek_impl(PyModuleDef *module, int fd, Py_off_t position, int how) 7964/*[clinic end generated code: output=65d4ab96d664998c input=902654ad3f96a6d3]*/ 7965{ 7966 Py_off_t result; 7967 7968 if (!_PyVerify_fd(fd)) { 7969 posix_error(); 7970 return -1; 7971 } 7972#ifdef SEEK_SET 7973 /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */ 7974 switch (how) { 7975 case 0: how = SEEK_SET; break; 7976 case 1: how = SEEK_CUR; break; 7977 case 2: how = SEEK_END; break; 7978 } 7979#endif /* SEEK_END */ 7980 7981 if (PyErr_Occurred()) 7982 return -1; 7983 7984 if (!_PyVerify_fd(fd)) { 7985 posix_error(); 7986 return -1; 7987 } 7988 Py_BEGIN_ALLOW_THREADS 7989 _Py_BEGIN_SUPPRESS_IPH 7990#ifdef MS_WINDOWS 7991 result = _lseeki64(fd, position, how); 7992#else 7993 result = lseek(fd, position, how); 7994#endif 7995 _Py_END_SUPPRESS_IPH 7996 Py_END_ALLOW_THREADS 7997 if (result < 0) 7998 posix_error(); 7999 8000 return result; 8001} 8002 8003 8004/*[clinic input] 8005os.read 8006 fd: int 8007 length: Py_ssize_t 8008 / 8009 8010Read from a file descriptor. Returns a bytes object. 8011[clinic start generated code]*/ 8012 8013static PyObject * 8014os_read_impl(PyModuleDef *module, int fd, Py_ssize_t length) 8015/*[clinic end generated code: output=be24f44178455e8b input=1df2eaa27c0bf1d3]*/ 8016{ 8017 Py_ssize_t n; 8018 PyObject *buffer; 8019 8020 if (length < 0) { 8021 errno = EINVAL; 8022 return posix_error(); 8023 } 8024 8025#ifdef MS_WINDOWS 8026 /* On Windows, the count parameter of read() is an int */ 8027 if (length > INT_MAX) 8028 length = INT_MAX; 8029#endif 8030 8031 buffer = PyBytes_FromStringAndSize((char *)NULL, length); 8032 if (buffer == NULL) 8033 return NULL; 8034 8035 n = _Py_read(fd, PyBytes_AS_STRING(buffer), length); 8036 if (n == -1) { 8037 Py_DECREF(buffer); 8038 return NULL; 8039 } 8040 8041 if (n != length) 8042 _PyBytes_Resize(&buffer, n); 8043 8044 return buffer; 8045} 8046 8047#if (defined(HAVE_SENDFILE) && (defined(__FreeBSD__) || defined(__DragonFly__) \ 8048 || defined(__APPLE__))) || defined(HAVE_READV) || defined(HAVE_WRITEV) 8049static Py_ssize_t 8050iov_setup(struct iovec **iov, Py_buffer **buf, PyObject *seq, int cnt, int type) 8051{ 8052 int i, j; 8053 Py_ssize_t blen, total = 0; 8054 8055 *iov = PyMem_New(struct iovec, cnt); 8056 if (*iov == NULL) { 8057 PyErr_NoMemory(); 8058 return -1; 8059 } 8060 8061 *buf = PyMem_New(Py_buffer, cnt); 8062 if (*buf == NULL) { 8063 PyMem_Del(*iov); 8064 PyErr_NoMemory(); 8065 return -1; 8066 } 8067 8068 for (i = 0; i < cnt; i++) { 8069 PyObject *item = PySequence_GetItem(seq, i); 8070 if (item == NULL) 8071 goto fail; 8072 if (PyObject_GetBuffer(item, &(*buf)[i], type) == -1) { 8073 Py_DECREF(item); 8074 goto fail; 8075 } 8076 Py_DECREF(item); 8077 (*iov)[i].iov_base = (*buf)[i].buf; 8078 blen = (*buf)[i].len; 8079 (*iov)[i].iov_len = blen; 8080 total += blen; 8081 } 8082 return total; 8083 8084fail: 8085 PyMem_Del(*iov); 8086 for (j = 0; j < i; j++) { 8087 PyBuffer_Release(&(*buf)[j]); 8088 } 8089 PyMem_Del(*buf); 8090 return -1; 8091} 8092 8093static void 8094iov_cleanup(struct iovec *iov, Py_buffer *buf, int cnt) 8095{ 8096 int i; 8097 PyMem_Del(iov); 8098 for (i = 0; i < cnt; i++) { 8099 PyBuffer_Release(&buf[i]); 8100 } 8101 PyMem_Del(buf); 8102} 8103#endif 8104 8105 8106#ifdef HAVE_READV 8107/*[clinic input] 8108os.readv -> Py_ssize_t 8109 8110 fd: int 8111 buffers: object 8112 / 8113 8114Read from a file descriptor fd into an iterable of buffers. 8115 8116The buffers should be mutable buffers accepting bytes. 8117readv will transfer data into each buffer until it is full 8118and then move on to the next buffer in the sequence to hold 8119the rest of the data. 8120 8121readv returns the total number of bytes read, 8122which may be less than the total capacity of all the buffers. 8123[clinic start generated code]*/ 8124 8125static Py_ssize_t 8126os_readv_impl(PyModuleDef *module, int fd, PyObject *buffers) 8127/*[clinic end generated code: output=00fc56ff1800059f input=e679eb5dbfa0357d]*/ 8128{ 8129 int cnt; 8130 Py_ssize_t n; 8131 int async_err = 0; 8132 struct iovec *iov; 8133 Py_buffer *buf; 8134 8135 if (!PySequence_Check(buffers)) { 8136 PyErr_SetString(PyExc_TypeError, 8137 "readv() arg 2 must be a sequence"); 8138 return -1; 8139 } 8140 8141 cnt = PySequence_Size(buffers); 8142 8143 if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_WRITABLE) < 0) 8144 return -1; 8145 8146 do { 8147 Py_BEGIN_ALLOW_THREADS 8148 n = readv(fd, iov, cnt); 8149 Py_END_ALLOW_THREADS 8150 } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); 8151 8152 iov_cleanup(iov, buf, cnt); 8153 if (n < 0) { 8154 if (!async_err) 8155 posix_error(); 8156 return -1; 8157 } 8158 8159 return n; 8160} 8161#endif /* HAVE_READV */ 8162 8163 8164#ifdef HAVE_PREAD 8165/*[clinic input] 8166# TODO length should be size_t! but Python doesn't support parsing size_t yet. 8167os.pread 8168 8169 fd: int 8170 length: int 8171 offset: Py_off_t 8172 / 8173 8174Read a number of bytes from a file descriptor starting at a particular offset. 8175 8176Read length bytes from file descriptor fd, starting at offset bytes from 8177the beginning of the file. The file offset remains unchanged. 8178[clinic start generated code]*/ 8179 8180static PyObject * 8181os_pread_impl(PyModuleDef *module, int fd, int length, Py_off_t offset) 8182/*[clinic end generated code: output=90d1fed87f68fa33 input=084948dcbaa35d4c]*/ 8183{ 8184 Py_ssize_t n; 8185 int async_err = 0; 8186 PyObject *buffer; 8187 8188 if (length < 0) { 8189 errno = EINVAL; 8190 return posix_error(); 8191 } 8192 buffer = PyBytes_FromStringAndSize((char *)NULL, length); 8193 if (buffer == NULL) 8194 return NULL; 8195 if (!_PyVerify_fd(fd)) { 8196 Py_DECREF(buffer); 8197 return posix_error(); 8198 } 8199 8200 do { 8201 Py_BEGIN_ALLOW_THREADS 8202 _Py_BEGIN_SUPPRESS_IPH 8203 n = pread(fd, PyBytes_AS_STRING(buffer), length, offset); 8204 _Py_END_SUPPRESS_IPH 8205 Py_END_ALLOW_THREADS 8206 } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); 8207 8208 if (n < 0) { 8209 Py_DECREF(buffer); 8210 return (!async_err) ? posix_error() : NULL; 8211 } 8212 if (n != length) 8213 _PyBytes_Resize(&buffer, n); 8214 return buffer; 8215} 8216#endif /* HAVE_PREAD */ 8217 8218 8219/*[clinic input] 8220os.write -> Py_ssize_t 8221 8222 fd: int 8223 data: Py_buffer 8224 / 8225 8226Write a bytes object to a file descriptor. 8227[clinic start generated code]*/ 8228 8229static Py_ssize_t 8230os_write_impl(PyModuleDef *module, int fd, Py_buffer *data) 8231/*[clinic end generated code: output=58845c93c9ee1dda input=3207e28963234f3c]*/ 8232{ 8233 return _Py_write(fd, data->buf, data->len); 8234} 8235 8236#ifdef HAVE_SENDFILE 8237PyDoc_STRVAR(posix_sendfile__doc__, 8238"sendfile(out, in, offset, count) -> byteswritten\n\ 8239sendfile(out, in, offset, count[, headers][, trailers], flags=0)\n\ 8240 -> byteswritten\n\ 8241Copy count bytes from file descriptor in to file descriptor out."); 8242 8243/* AC 3.5: don't bother converting, has optional group*/ 8244static PyObject * 8245posix_sendfile(PyObject *self, PyObject *args, PyObject *kwdict) 8246{ 8247 int in, out; 8248 Py_ssize_t ret; 8249 int async_err = 0; 8250 off_t offset; 8251 8252#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__) 8253#ifndef __APPLE__ 8254 Py_ssize_t len; 8255#endif 8256 PyObject *headers = NULL, *trailers = NULL; 8257 Py_buffer *hbuf, *tbuf; 8258 off_t sbytes; 8259 struct sf_hdtr sf; 8260 int flags = 0; 8261 /* Beware that "in" clashes with Python's own "in" operator keyword */ 8262 static char *keywords[] = {"out", "in", 8263 "offset", "count", 8264 "headers", "trailers", "flags", NULL}; 8265 8266 sf.headers = NULL; 8267 sf.trailers = NULL; 8268 8269#ifdef __APPLE__ 8270 if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiO&O&|OOi:sendfile", 8271 keywords, &out, &in, Py_off_t_converter, &offset, Py_off_t_converter, &sbytes, 8272#else 8273 if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiO&n|OOi:sendfile", 8274 keywords, &out, &in, Py_off_t_converter, &offset, &len, 8275#endif 8276 &headers, &trailers, &flags)) 8277 return NULL; 8278 if (headers != NULL) { 8279 if (!PySequence_Check(headers)) { 8280 PyErr_SetString(PyExc_TypeError, 8281 "sendfile() headers must be a sequence"); 8282 return NULL; 8283 } else { 8284 Py_ssize_t i = 0; /* Avoid uninitialized warning */ 8285 sf.hdr_cnt = PySequence_Size(headers); 8286 if (sf.hdr_cnt > 0 && 8287 (i = iov_setup(&(sf.headers), &hbuf, 8288 headers, sf.hdr_cnt, PyBUF_SIMPLE)) < 0) 8289 return NULL; 8290#ifdef __APPLE__ 8291 sbytes += i; 8292#endif 8293 } 8294 } 8295 if (trailers != NULL) { 8296 if (!PySequence_Check(trailers)) { 8297 PyErr_SetString(PyExc_TypeError, 8298 "sendfile() trailers must be a sequence"); 8299 return NULL; 8300 } else { 8301 Py_ssize_t i = 0; /* Avoid uninitialized warning */ 8302 sf.trl_cnt = PySequence_Size(trailers); 8303 if (sf.trl_cnt > 0 && 8304 (i = iov_setup(&(sf.trailers), &tbuf, 8305 trailers, sf.trl_cnt, PyBUF_SIMPLE)) < 0) 8306 return NULL; 8307#ifdef __APPLE__ 8308 sbytes += i; 8309#endif 8310 } 8311 } 8312 8313 _Py_BEGIN_SUPPRESS_IPH 8314 do { 8315 Py_BEGIN_ALLOW_THREADS 8316#ifdef __APPLE__ 8317 ret = sendfile(in, out, offset, &sbytes, &sf, flags); 8318#else 8319 ret = sendfile(in, out, offset, len, &sf, &sbytes, flags); 8320#endif 8321 Py_END_ALLOW_THREADS 8322 } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); 8323 _Py_END_SUPPRESS_IPH 8324 8325 if (sf.headers != NULL) 8326 iov_cleanup(sf.headers, hbuf, sf.hdr_cnt); 8327 if (sf.trailers != NULL) 8328 iov_cleanup(sf.trailers, tbuf, sf.trl_cnt); 8329 8330 if (ret < 0) { 8331 if ((errno == EAGAIN) || (errno == EBUSY)) { 8332 if (sbytes != 0) { 8333 // some data has been sent 8334 goto done; 8335 } 8336 else { 8337 // no data has been sent; upper application is supposed 8338 // to retry on EAGAIN or EBUSY 8339 return posix_error(); 8340 } 8341 } 8342 return (!async_err) ? posix_error() : NULL; 8343 } 8344 goto done; 8345 8346done: 8347 #if !defined(HAVE_LARGEFILE_SUPPORT) 8348 return Py_BuildValue("l", sbytes); 8349 #else 8350 return Py_BuildValue("L", sbytes); 8351 #endif 8352 8353#else 8354 Py_ssize_t count; 8355 PyObject *offobj; 8356 static char *keywords[] = {"out", "in", 8357 "offset", "count", NULL}; 8358 if (!PyArg_ParseTupleAndKeywords(args, kwdict, "iiOn:sendfile", 8359 keywords, &out, &in, &offobj, &count)) 8360 return NULL; 8361#ifdef linux 8362 if (offobj == Py_None) { 8363 do { 8364 Py_BEGIN_ALLOW_THREADS 8365 ret = sendfile(out, in, NULL, count); 8366 Py_END_ALLOW_THREADS 8367 } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); 8368 if (ret < 0) 8369 return (!async_err) ? posix_error() : NULL; 8370 return Py_BuildValue("n", ret); 8371 } 8372#endif 8373 if (!Py_off_t_converter(offobj, &offset)) 8374 return NULL; 8375 8376 do { 8377 Py_BEGIN_ALLOW_THREADS 8378 ret = sendfile(out, in, &offset, count); 8379 Py_END_ALLOW_THREADS 8380 } while (ret < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); 8381 if (ret < 0) 8382 return (!async_err) ? posix_error() : NULL; 8383 return Py_BuildValue("n", ret); 8384#endif 8385} 8386#endif /* HAVE_SENDFILE */ 8387 8388 8389/*[clinic input] 8390os.fstat 8391 8392 fd : int 8393 8394Perform a stat system call on the given file descriptor. 8395 8396Like stat(), but for an open file descriptor. 8397Equivalent to os.stat(fd). 8398[clinic start generated code]*/ 8399 8400static PyObject * 8401os_fstat_impl(PyModuleDef *module, int fd) 8402/*[clinic end generated code: output=d71fe98bf042b626 input=27e0e0ebbe5600c9]*/ 8403{ 8404 STRUCT_STAT st; 8405 int res; 8406 int async_err = 0; 8407 8408 do { 8409 Py_BEGIN_ALLOW_THREADS 8410 res = FSTAT(fd, &st); 8411 Py_END_ALLOW_THREADS 8412 } while (res != 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); 8413 if (res != 0) { 8414#ifdef MS_WINDOWS 8415 return PyErr_SetFromWindowsErr(0); 8416#else 8417 return (!async_err) ? posix_error() : NULL; 8418#endif 8419 } 8420 8421 return _pystat_fromstructstat(&st); 8422} 8423 8424 8425/*[clinic input] 8426os.isatty -> bool 8427 fd: int 8428 / 8429 8430Return True if the fd is connected to a terminal. 8431 8432Return True if the file descriptor is an open file descriptor 8433connected to the slave end of a terminal. 8434[clinic start generated code]*/ 8435 8436static int 8437os_isatty_impl(PyModuleDef *module, int fd) 8438/*[clinic end generated code: output=acec9d3c29d16d33 input=08ce94aa1eaf7b5e]*/ 8439{ 8440 int return_value; 8441 if (!_PyVerify_fd(fd)) 8442 return 0; 8443 _Py_BEGIN_SUPPRESS_IPH 8444 return_value = isatty(fd); 8445 _Py_END_SUPPRESS_IPH 8446 return return_value; 8447} 8448 8449 8450#ifdef HAVE_PIPE 8451/*[clinic input] 8452os.pipe 8453 8454Create a pipe. 8455 8456Returns a tuple of two file descriptors: 8457 (read_fd, write_fd) 8458[clinic start generated code]*/ 8459 8460static PyObject * 8461os_pipe_impl(PyModuleDef *module) 8462/*[clinic end generated code: output=6b0cd3f868ec3c40 input=02535e8c8fa6c4d4]*/ 8463{ 8464 int fds[2]; 8465#ifdef MS_WINDOWS 8466 HANDLE read, write; 8467 SECURITY_ATTRIBUTES attr; 8468 BOOL ok; 8469#else 8470 int res; 8471#endif 8472 8473#ifdef MS_WINDOWS 8474 attr.nLength = sizeof(attr); 8475 attr.lpSecurityDescriptor = NULL; 8476 attr.bInheritHandle = FALSE; 8477 8478 Py_BEGIN_ALLOW_THREADS 8479 ok = CreatePipe(&read, &write, &attr, 0); 8480 if (ok) { 8481 fds[0] = _open_osfhandle((Py_intptr_t)read, _O_RDONLY); 8482 fds[1] = _open_osfhandle((Py_intptr_t)write, _O_WRONLY); 8483 if (fds[0] == -1 || fds[1] == -1) { 8484 CloseHandle(read); 8485 CloseHandle(write); 8486 ok = 0; 8487 } 8488 } 8489 Py_END_ALLOW_THREADS 8490 8491 if (!ok) 8492 return PyErr_SetFromWindowsErr(0); 8493#else 8494 8495#ifdef HAVE_PIPE2 8496 Py_BEGIN_ALLOW_THREADS 8497 res = pipe2(fds, O_CLOEXEC); 8498 Py_END_ALLOW_THREADS 8499 8500 if (res != 0 && errno == ENOSYS) 8501 { 8502#endif 8503 Py_BEGIN_ALLOW_THREADS 8504 res = pipe(fds); 8505 Py_END_ALLOW_THREADS 8506 8507 if (res == 0) { 8508 if (_Py_set_inheritable(fds[0], 0, NULL) < 0) { 8509 close(fds[0]); 8510 close(fds[1]); 8511 return NULL; 8512 } 8513 if (_Py_set_inheritable(fds[1], 0, NULL) < 0) { 8514 close(fds[0]); 8515 close(fds[1]); 8516 return NULL; 8517 } 8518 } 8519#ifdef HAVE_PIPE2 8520 } 8521#endif 8522 8523 if (res != 0) 8524 return PyErr_SetFromErrno(PyExc_OSError); 8525#endif /* !MS_WINDOWS */ 8526 return Py_BuildValue("(ii)", fds[0], fds[1]); 8527} 8528#endif /* HAVE_PIPE */ 8529 8530 8531#ifdef HAVE_PIPE2 8532/*[clinic input] 8533os.pipe2 8534 8535 flags: int 8536 / 8537 8538Create a pipe with flags set atomically. 8539 8540Returns a tuple of two file descriptors: 8541 (read_fd, write_fd) 8542 8543flags can be constructed by ORing together one or more of these values: 8544O_NONBLOCK, O_CLOEXEC. 8545[clinic start generated code]*/ 8546 8547static PyObject * 8548os_pipe2_impl(PyModuleDef *module, int flags) 8549/*[clinic end generated code: output=c15b6075d0c6b2e7 input=f261b6e7e63c6817]*/ 8550{ 8551 int fds[2]; 8552 int res; 8553 8554 res = pipe2(fds, flags); 8555 if (res != 0) 8556 return posix_error(); 8557 return Py_BuildValue("(ii)", fds[0], fds[1]); 8558} 8559#endif /* HAVE_PIPE2 */ 8560 8561 8562#ifdef HAVE_WRITEV 8563/*[clinic input] 8564os.writev -> Py_ssize_t 8565 fd: int 8566 buffers: object 8567 / 8568 8569Iterate over buffers, and write the contents of each to a file descriptor. 8570 8571Returns the total number of bytes written. 8572buffers must be a sequence of bytes-like objects. 8573[clinic start generated code]*/ 8574 8575static Py_ssize_t 8576os_writev_impl(PyModuleDef *module, int fd, PyObject *buffers) 8577/*[clinic end generated code: output=a48925dbf2d5c238 input=5b8d17fe4189d2fe]*/ 8578{ 8579 int cnt; 8580 Py_ssize_t result; 8581 int async_err = 0; 8582 struct iovec *iov; 8583 Py_buffer *buf; 8584 8585 if (!PySequence_Check(buffers)) { 8586 PyErr_SetString(PyExc_TypeError, 8587 "writev() arg 2 must be a sequence"); 8588 return -1; 8589 } 8590 cnt = PySequence_Size(buffers); 8591 8592 if (iov_setup(&iov, &buf, buffers, cnt, PyBUF_SIMPLE) < 0) { 8593 return -1; 8594 } 8595 8596 do { 8597 Py_BEGIN_ALLOW_THREADS 8598 result = writev(fd, iov, cnt); 8599 Py_END_ALLOW_THREADS 8600 } while (result < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); 8601 8602 iov_cleanup(iov, buf, cnt); 8603 if (result < 0 && !async_err) 8604 posix_error(); 8605 8606 return result; 8607} 8608#endif /* HAVE_WRITEV */ 8609 8610 8611#ifdef HAVE_PWRITE 8612/*[clinic input] 8613os.pwrite -> Py_ssize_t 8614 8615 fd: int 8616 buffer: Py_buffer 8617 offset: Py_off_t 8618 / 8619 8620Write bytes to a file descriptor starting at a particular offset. 8621 8622Write buffer to fd, starting at offset bytes from the beginning of 8623the file. Returns the number of bytes writte. Does not change the 8624current file offset. 8625[clinic start generated code]*/ 8626 8627static Py_ssize_t 8628os_pwrite_impl(PyModuleDef *module, int fd, Py_buffer *buffer, 8629 Py_off_t offset) 8630/*[clinic end generated code: output=93aabdb40e17d325 input=19903f1b3dd26377]*/ 8631{ 8632 Py_ssize_t size; 8633 int async_err = 0; 8634 8635 if (!_PyVerify_fd(fd)) { 8636 posix_error(); 8637 return -1; 8638 } 8639 8640 do { 8641 Py_BEGIN_ALLOW_THREADS 8642 _Py_BEGIN_SUPPRESS_IPH 8643 size = pwrite(fd, buffer->buf, (size_t)buffer->len, offset); 8644 _Py_END_SUPPRESS_IPH 8645 Py_END_ALLOW_THREADS 8646 } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals())); 8647 8648 if (size < 0 && !async_err) 8649 posix_error(); 8650 return size; 8651} 8652#endif /* HAVE_PWRITE */ 8653 8654 8655#ifdef HAVE_MKFIFO 8656/*[clinic input] 8657os.mkfifo 8658 8659 path: path_t 8660 mode: int=0o666 8661 * 8662 dir_fd: dir_fd(requires='mkfifoat')=None 8663 8664Create a "fifo" (a POSIX named pipe). 8665 8666If dir_fd is not None, it should be a file descriptor open to a directory, 8667 and path should be relative; path will then be relative to that directory. 8668dir_fd may not be implemented on your platform. 8669 If it is unavailable, using it will raise a NotImplementedError. 8670[clinic start generated code]*/ 8671 8672static PyObject * 8673os_mkfifo_impl(PyModuleDef *module, path_t *path, int mode, int dir_fd) 8674/*[clinic end generated code: output=8f5f5e72c630049a input=73032e98a36e0e19]*/ 8675{ 8676 int result; 8677 int async_err = 0; 8678 8679 do { 8680 Py_BEGIN_ALLOW_THREADS 8681#ifdef HAVE_MKFIFOAT 8682 if (dir_fd != DEFAULT_DIR_FD) 8683 result = mkfifoat(dir_fd, path->narrow, mode); 8684 else 8685#endif 8686 result = mkfifo(path->narrow, mode); 8687 Py_END_ALLOW_THREADS 8688 } while (result != 0 && errno == EINTR && 8689 !(async_err = PyErr_CheckSignals())); 8690 if (result != 0) 8691 return (!async_err) ? posix_error() : NULL; 8692 8693 Py_RETURN_NONE; 8694} 8695#endif /* HAVE_MKFIFO */ 8696 8697 8698#if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) 8699/*[clinic input] 8700os.mknod 8701 8702 path: path_t 8703 mode: int=0o600 8704 device: dev_t=0 8705 * 8706 dir_fd: dir_fd(requires='mknodat')=None 8707 8708Create a node in the file system. 8709 8710Create a node in the file system (file, device special file or named pipe) 8711at path. mode specifies both the permissions to use and the 8712type of node to be created, being combined (bitwise OR) with one of 8713S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO. If S_IFCHR or S_IFBLK is set on mode, 8714device defines the newly created device special file (probably using 8715os.makedev()). Otherwise device is ignored. 8716 8717If dir_fd is not None, it should be a file descriptor open to a directory, 8718 and path should be relative; path will then be relative to that directory. 8719dir_fd may not be implemented on your platform. 8720 If it is unavailable, using it will raise a NotImplementedError. 8721[clinic start generated code]*/ 8722 8723static PyObject * 8724os_mknod_impl(PyModuleDef *module, path_t *path, int mode, dev_t device, 8725 int dir_fd) 8726/*[clinic end generated code: output=5151a8a9f754d272 input=ee44531551a4d83b]*/ 8727{ 8728 int result; 8729 int async_err = 0; 8730 8731 do { 8732 Py_BEGIN_ALLOW_THREADS 8733#ifdef HAVE_MKNODAT 8734 if (dir_fd != DEFAULT_DIR_FD) 8735 result = mknodat(dir_fd, path->narrow, mode, device); 8736 else 8737#endif 8738 result = mknod(path->narrow, mode, device); 8739 Py_END_ALLOW_THREADS 8740 } while (result != 0 && errno == EINTR && 8741 !(async_err = PyErr_CheckSignals())); 8742 if (result != 0) 8743 return (!async_err) ? posix_error() : NULL; 8744 8745 Py_RETURN_NONE; 8746} 8747#endif /* defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV) */ 8748 8749 8750#ifdef HAVE_DEVICE_MACROS 8751/*[clinic input] 8752os.major -> unsigned_int 8753 8754 device: dev_t 8755 / 8756 8757Extracts a device major number from a raw device number. 8758[clinic start generated code]*/ 8759 8760static unsigned int 8761os_major_impl(PyModuleDef *module, dev_t device) 8762/*[clinic end generated code: output=ba55693ab49bac34 input=1e16a4d30c4d4462]*/ 8763{ 8764 return major(device); 8765} 8766 8767 8768/*[clinic input] 8769os.minor -> unsigned_int 8770 8771 device: dev_t 8772 / 8773 8774Extracts a device minor number from a raw device number. 8775[clinic start generated code]*/ 8776 8777static unsigned int 8778os_minor_impl(PyModuleDef *module, dev_t device) 8779/*[clinic end generated code: output=2867219ebf274e27 input=0842c6d23f24c65e]*/ 8780{ 8781 return minor(device); 8782} 8783 8784 8785/*[clinic input] 8786os.makedev -> dev_t 8787 8788 major: int 8789 minor: int 8790 / 8791 8792Composes a raw device number from the major and minor device numbers. 8793[clinic start generated code]*/ 8794 8795static dev_t 8796os_makedev_impl(PyModuleDef *module, int major, int minor) 8797/*[clinic end generated code: output=7cb6264352437660 input=4b9fd8fc73cbe48f]*/ 8798{ 8799 return makedev(major, minor); 8800} 8801#endif /* HAVE_DEVICE_MACROS */ 8802 8803 8804#if defined HAVE_FTRUNCATE || defined MS_WINDOWS 8805/*[clinic input] 8806os.ftruncate 8807 8808 fd: int 8809 length: Py_off_t 8810 / 8811 8812Truncate a file, specified by file descriptor, to a specific length. 8813[clinic start generated code]*/ 8814 8815static PyObject * 8816os_ftruncate_impl(PyModuleDef *module, int fd, Py_off_t length) 8817/*[clinic end generated code: output=3666f401d76bf834 input=63b43641e52818f2]*/ 8818{ 8819 int result; 8820 int async_err = 0; 8821 8822 if (!_PyVerify_fd(fd)) 8823 return posix_error(); 8824 8825 do { 8826 Py_BEGIN_ALLOW_THREADS 8827 _Py_BEGIN_SUPPRESS_IPH 8828#ifdef MS_WINDOWS 8829 result = _chsize_s(fd, length); 8830#else 8831 result = ftruncate(fd, length); 8832#endif 8833 _Py_END_SUPPRESS_IPH 8834 Py_END_ALLOW_THREADS 8835 } while (result != 0 && errno == EINTR && 8836 !(async_err = PyErr_CheckSignals())); 8837 if (result != 0) 8838 return (!async_err) ? posix_error() : NULL; 8839 Py_RETURN_NONE; 8840} 8841#endif /* HAVE_FTRUNCATE || MS_WINDOWS */ 8842 8843 8844#if defined HAVE_TRUNCATE || defined MS_WINDOWS 8845/*[clinic input] 8846os.truncate 8847 path: path_t(allow_fd='PATH_HAVE_FTRUNCATE') 8848 length: Py_off_t 8849 8850Truncate a file, specified by path, to a specific length. 8851 8852On some platforms, path may also be specified as an open file descriptor. 8853 If this functionality is unavailable, using it raises an exception. 8854[clinic start generated code]*/ 8855 8856static PyObject * 8857os_truncate_impl(PyModuleDef *module, path_t *path, Py_off_t length) 8858/*[clinic end generated code: output=f60a9e08370e9e2e input=77229cf0b50a9b77]*/ 8859{ 8860 int result; 8861#ifdef MS_WINDOWS 8862 int fd; 8863#endif 8864 8865 if (path->fd != -1) 8866 return os_ftruncate_impl(module, path->fd, length); 8867 8868 Py_BEGIN_ALLOW_THREADS 8869 _Py_BEGIN_SUPPRESS_IPH 8870#ifdef MS_WINDOWS 8871 if (path->wide) 8872 fd = _wopen(path->wide, _O_WRONLY | _O_BINARY | _O_NOINHERIT); 8873 else 8874 fd = _open(path->narrow, _O_WRONLY | _O_BINARY | _O_NOINHERIT); 8875 if (fd < 0) 8876 result = -1; 8877 else { 8878 result = _chsize_s(fd, length); 8879 close(fd); 8880 if (result < 0) 8881 errno = result; 8882 } 8883#else 8884 result = truncate(path->narrow, length); 8885#endif 8886 _Py_END_SUPPRESS_IPH 8887 Py_END_ALLOW_THREADS 8888 if (result < 0) 8889 return path_error(path); 8890 8891 Py_RETURN_NONE; 8892} 8893#endif /* HAVE_TRUNCATE || MS_WINDOWS */ 8894 8895 8896/* Issue #22396: On 32-bit AIX platform, the prototypes of os.posix_fadvise() 8897 and os.posix_fallocate() in system headers are wrong if _LARGE_FILES is 8898 defined, which is the case in Python on AIX. AIX bug report: 8899 http://www-01.ibm.com/support/docview.wss?uid=isg1IV56170 */ 8900#if defined(_AIX) && defined(_LARGE_FILES) && !defined(__64BIT__) 8901# define POSIX_FADVISE_AIX_BUG 8902#endif 8903 8904 8905#if defined(HAVE_POSIX_FALLOCATE) && !defined(POSIX_FADVISE_AIX_BUG) 8906/*[clinic input] 8907os.posix_fallocate 8908 8909 fd: int 8910 offset: Py_off_t 8911 length: Py_off_t 8912 / 8913 8914Ensure a file has allocated at least a particular number of bytes on disk. 8915 8916Ensure that the file specified by fd encompasses a range of bytes 8917starting at offset bytes from the beginning and continuing for length bytes. 8918[clinic start generated code]*/ 8919 8920static PyObject * 8921os_posix_fallocate_impl(PyModuleDef *module, int fd, Py_off_t offset, 8922 Py_off_t length) 8923/*[clinic end generated code: output=7f6f87a8c751e1b4 input=d7a2ef0ab2ca52fb]*/ 8924{ 8925 int result; 8926 int async_err = 0; 8927 8928 do { 8929 Py_BEGIN_ALLOW_THREADS 8930 result = posix_fallocate(fd, offset, length); 8931 Py_END_ALLOW_THREADS 8932 } while (result != 0 && errno == EINTR && 8933 !(async_err = PyErr_CheckSignals())); 8934 if (result != 0) 8935 return (!async_err) ? posix_error() : NULL; 8936 Py_RETURN_NONE; 8937} 8938#endif /* HAVE_POSIX_FALLOCATE) && !POSIX_FADVISE_AIX_BUG */ 8939 8940 8941#if defined(HAVE_POSIX_FADVISE) && !defined(POSIX_FADVISE_AIX_BUG) 8942/*[clinic input] 8943os.posix_fadvise 8944 8945 fd: int 8946 offset: Py_off_t 8947 length: Py_off_t 8948 advice: int 8949 / 8950 8951Announce an intention to access data in a specific pattern. 8952 8953Announce an intention to access data in a specific pattern, thus allowing 8954the kernel to make optimizations. 8955The advice applies to the region of the file specified by fd starting at 8956offset and continuing for length bytes. 8957advice is one of POSIX_FADV_NORMAL, POSIX_FADV_SEQUENTIAL, 8958POSIX_FADV_RANDOM, POSIX_FADV_NOREUSE, POSIX_FADV_WILLNEED, or 8959POSIX_FADV_DONTNEED. 8960[clinic start generated code]*/ 8961 8962static PyObject * 8963os_posix_fadvise_impl(PyModuleDef *module, int fd, Py_off_t offset, 8964 Py_off_t length, int advice) 8965/*[clinic end generated code: output=457ce6a67189e10d input=0fbe554edc2f04b5]*/ 8966{ 8967 int result; 8968 int async_err = 0; 8969 8970 do { 8971 Py_BEGIN_ALLOW_THREADS 8972 result = posix_fadvise(fd, offset, length, advice); 8973 Py_END_ALLOW_THREADS 8974 } while (result != 0 && errno == EINTR && 8975 !(async_err = PyErr_CheckSignals())); 8976 if (result != 0) 8977 return (!async_err) ? posix_error() : NULL; 8978 Py_RETURN_NONE; 8979} 8980#endif /* HAVE_POSIX_FADVISE && !POSIX_FADVISE_AIX_BUG */ 8981 8982#ifdef HAVE_PUTENV 8983 8984/* Save putenv() parameters as values here, so we can collect them when they 8985 * get re-set with another call for the same key. */ 8986static PyObject *posix_putenv_garbage; 8987 8988static void 8989posix_putenv_garbage_setitem(PyObject *name, PyObject *value) 8990{ 8991 /* Install the first arg and newstr in posix_putenv_garbage; 8992 * this will cause previous value to be collected. This has to 8993 * happen after the real putenv() call because the old value 8994 * was still accessible until then. */ 8995 if (PyDict_SetItem(posix_putenv_garbage, name, value)) 8996 /* really not much we can do; just leak */ 8997 PyErr_Clear(); 8998 else 8999 Py_DECREF(value); 9000} 9001 9002 9003#ifdef MS_WINDOWS 9004/*[clinic input] 9005os.putenv 9006 9007 name: unicode 9008 value: unicode 9009 / 9010 9011Change or add an environment variable. 9012[clinic start generated code]*/ 9013 9014static PyObject * 9015os_putenv_impl(PyModuleDef *module, PyObject *name, PyObject *value) 9016/*[clinic end generated code: output=a2438cf95e5a0c1c input=ba586581c2e6105f]*/ 9017{ 9018 wchar_t *env; 9019 9020 PyObject *unicode = PyUnicode_FromFormat("%U=%U", name, value); 9021 if (unicode == NULL) { 9022 PyErr_NoMemory(); 9023 return NULL; 9024 } 9025 if (_MAX_ENV < PyUnicode_GET_LENGTH(unicode)) { 9026 PyErr_Format(PyExc_ValueError, 9027 "the environment variable is longer than %u characters", 9028 _MAX_ENV); 9029 goto error; 9030 } 9031 9032 env = PyUnicode_AsUnicode(unicode); 9033 if (env == NULL) 9034 goto error; 9035 if (_wputenv(env)) { 9036 posix_error(); 9037 goto error; 9038 } 9039 9040 posix_putenv_garbage_setitem(name, unicode); 9041 Py_RETURN_NONE; 9042 9043error: 9044 Py_DECREF(unicode); 9045 return NULL; 9046} 9047#else /* MS_WINDOWS */ 9048/*[clinic input] 9049os.putenv 9050 9051 name: FSConverter 9052 value: FSConverter 9053 / 9054 9055Change or add an environment variable. 9056[clinic start generated code]*/ 9057 9058static PyObject * 9059os_putenv_impl(PyModuleDef *module, PyObject *name, PyObject *value) 9060/*[clinic end generated code: output=a2438cf95e5a0c1c input=a97bc6152f688d31]*/ 9061{ 9062 PyObject *bytes = NULL; 9063 char *env; 9064 char *name_string = PyBytes_AsString(name); 9065 char *value_string = PyBytes_AsString(value); 9066 9067 bytes = PyBytes_FromFormat("%s=%s", name_string, value_string); 9068 if (bytes == NULL) { 9069 PyErr_NoMemory(); 9070 return NULL; 9071 } 9072 9073 env = PyBytes_AS_STRING(bytes); 9074 if (putenv(env)) { 9075 Py_DECREF(bytes); 9076 return posix_error(); 9077 } 9078 9079 posix_putenv_garbage_setitem(name, bytes); 9080 Py_RETURN_NONE; 9081} 9082#endif /* MS_WINDOWS */ 9083#endif /* HAVE_PUTENV */ 9084 9085 9086#ifdef HAVE_UNSETENV 9087/*[clinic input] 9088os.unsetenv 9089 name: FSConverter 9090 / 9091 9092Delete an environment variable. 9093[clinic start generated code]*/ 9094 9095static PyObject * 9096os_unsetenv_impl(PyModuleDef *module, PyObject *name) 9097/*[clinic end generated code: output=25994b57016a2dc9 input=2bb5288a599c7107]*/ 9098{ 9099#ifndef HAVE_BROKEN_UNSETENV 9100 int err; 9101#endif 9102 9103#ifdef HAVE_BROKEN_UNSETENV 9104 unsetenv(PyBytes_AS_STRING(name)); 9105#else 9106 err = unsetenv(PyBytes_AS_STRING(name)); 9107 if (err) 9108 return posix_error(); 9109#endif 9110 9111 /* Remove the key from posix_putenv_garbage; 9112 * this will cause it to be collected. This has to 9113 * happen after the real unsetenv() call because the 9114 * old value was still accessible until then. 9115 */ 9116 if (PyDict_DelItem(posix_putenv_garbage, name)) { 9117 /* really not much we can do; just leak */ 9118 PyErr_Clear(); 9119 } 9120 Py_RETURN_NONE; 9121} 9122#endif /* HAVE_UNSETENV */ 9123 9124 9125/*[clinic input] 9126os.strerror 9127 9128 code: int 9129 / 9130 9131Translate an error code to a message string. 9132[clinic start generated code]*/ 9133 9134static PyObject * 9135os_strerror_impl(PyModuleDef *module, int code) 9136/*[clinic end generated code: output=0280c6af51e5c9fe input=75a8673d97915a91]*/ 9137{ 9138 char *message = strerror(code); 9139 if (message == NULL) { 9140 PyErr_SetString(PyExc_ValueError, 9141 "strerror() argument out of range"); 9142 return NULL; 9143 } 9144 return PyUnicode_DecodeLocale(message, "surrogateescape"); 9145} 9146 9147 9148#ifdef HAVE_SYS_WAIT_H 9149#ifdef WCOREDUMP 9150/*[clinic input] 9151os.WCOREDUMP -> bool 9152 9153 status: int 9154 / 9155 9156Return True if the process returning status was dumped to a core file. 9157[clinic start generated code]*/ 9158 9159static int 9160os_WCOREDUMP_impl(PyModuleDef *module, int status) 9161/*[clinic end generated code: output=134f70bbe63fbf41 input=8b05e7ab38528d04]*/ 9162{ 9163 WAIT_TYPE wait_status; 9164 WAIT_STATUS_INT(wait_status) = status; 9165 return WCOREDUMP(wait_status); 9166} 9167#endif /* WCOREDUMP */ 9168 9169 9170#ifdef WIFCONTINUED 9171/*[clinic input] 9172os.WIFCONTINUED -> bool 9173 9174 status: int 9175 9176Return True if a particular process was continued from a job control stop. 9177 9178Return True if the process returning status was continued from a 9179job control stop. 9180[clinic start generated code]*/ 9181 9182static int 9183os_WIFCONTINUED_impl(PyModuleDef *module, int status) 9184/*[clinic end generated code: output=9cdd26543ebb6dcd input=e777e7d38eb25bd9]*/ 9185{ 9186 WAIT_TYPE wait_status; 9187 WAIT_STATUS_INT(wait_status) = status; 9188 return WIFCONTINUED(wait_status); 9189} 9190#endif /* WIFCONTINUED */ 9191 9192 9193#ifdef WIFSTOPPED 9194/*[clinic input] 9195os.WIFSTOPPED -> bool 9196 9197 status: int 9198 9199Return True if the process returning status was stopped. 9200[clinic start generated code]*/ 9201 9202static int 9203os_WIFSTOPPED_impl(PyModuleDef *module, int status) 9204/*[clinic end generated code: output=73bf35e44994a724 input=043cb7f1289ef904]*/ 9205{ 9206 WAIT_TYPE wait_status; 9207 WAIT_STATUS_INT(wait_status) = status; 9208 return WIFSTOPPED(wait_status); 9209} 9210#endif /* WIFSTOPPED */ 9211 9212 9213#ifdef WIFSIGNALED 9214/*[clinic input] 9215os.WIFSIGNALED -> bool 9216 9217 status: int 9218 9219Return True if the process returning status was terminated by a signal. 9220[clinic start generated code]*/ 9221 9222static int 9223os_WIFSIGNALED_impl(PyModuleDef *module, int status) 9224/*[clinic end generated code: output=2697975771872420 input=d55ba7cc9ce5dc43]*/ 9225{ 9226 WAIT_TYPE wait_status; 9227 WAIT_STATUS_INT(wait_status) = status; 9228 return WIFSIGNALED(wait_status); 9229} 9230#endif /* WIFSIGNALED */ 9231 9232 9233#ifdef WIFEXITED 9234/*[clinic input] 9235os.WIFEXITED -> bool 9236 9237 status: int 9238 9239Return True if the process returning status exited via the exit() system call. 9240[clinic start generated code]*/ 9241 9242static int 9243os_WIFEXITED_impl(PyModuleDef *module, int status) 9244/*[clinic end generated code: output=ca8f8c61f0b8532e input=d63775a6791586c0]*/ 9245{ 9246 WAIT_TYPE wait_status; 9247 WAIT_STATUS_INT(wait_status) = status; 9248 return WIFEXITED(wait_status); 9249} 9250#endif /* WIFEXITED */ 9251 9252 9253#ifdef WEXITSTATUS 9254/*[clinic input] 9255os.WEXITSTATUS -> int 9256 9257 status: int 9258 9259Return the process return code from status. 9260[clinic start generated code]*/ 9261 9262static int 9263os_WEXITSTATUS_impl(PyModuleDef *module, int status) 9264/*[clinic end generated code: output=ea54da23d9e0f6af input=e1fb4944e377585b]*/ 9265{ 9266 WAIT_TYPE wait_status; 9267 WAIT_STATUS_INT(wait_status) = status; 9268 return WEXITSTATUS(wait_status); 9269} 9270#endif /* WEXITSTATUS */ 9271 9272 9273#ifdef WTERMSIG 9274/*[clinic input] 9275os.WTERMSIG -> int 9276 9277 status: int 9278 9279Return the signal that terminated the process that provided the status value. 9280[clinic start generated code]*/ 9281 9282static int 9283os_WTERMSIG_impl(PyModuleDef *module, int status) 9284/*[clinic end generated code: output=4d25367026cb852c input=727fd7f84ec3f243]*/ 9285{ 9286 WAIT_TYPE wait_status; 9287 WAIT_STATUS_INT(wait_status) = status; 9288 return WTERMSIG(wait_status); 9289} 9290#endif /* WTERMSIG */ 9291 9292 9293#ifdef WSTOPSIG 9294/*[clinic input] 9295os.WSTOPSIG -> int 9296 9297 status: int 9298 9299Return the signal that stopped the process that provided the status value. 9300[clinic start generated code]*/ 9301 9302static int 9303os_WSTOPSIG_impl(PyModuleDef *module, int status) 9304/*[clinic end generated code: output=54eb9c13b001adb4 input=46ebf1d1b293c5c1]*/ 9305{ 9306 WAIT_TYPE wait_status; 9307 WAIT_STATUS_INT(wait_status) = status; 9308 return WSTOPSIG(wait_status); 9309} 9310#endif /* WSTOPSIG */ 9311#endif /* HAVE_SYS_WAIT_H */ 9312 9313 9314#if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) 9315#ifdef _SCO_DS 9316/* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the 9317 needed definitions in sys/statvfs.h */ 9318#define _SVID3 9319#endif 9320#include <sys/statvfs.h> 9321 9322static PyObject* 9323_pystatvfs_fromstructstatvfs(struct statvfs st) { 9324 PyObject *v = PyStructSequence_New(&StatVFSResultType); 9325 if (v == NULL) 9326 return NULL; 9327 9328#if !defined(HAVE_LARGEFILE_SUPPORT) 9329 PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize)); 9330 PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize)); 9331 PyStructSequence_SET_ITEM(v, 2, PyLong_FromLong((long) st.f_blocks)); 9332 PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long) st.f_bfree)); 9333 PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong((long) st.f_bavail)); 9334 PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong((long) st.f_files)); 9335 PyStructSequence_SET_ITEM(v, 6, PyLong_FromLong((long) st.f_ffree)); 9336 PyStructSequence_SET_ITEM(v, 7, PyLong_FromLong((long) st.f_favail)); 9337 PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag)); 9338 PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax)); 9339#else 9340 PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize)); 9341 PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize)); 9342 PyStructSequence_SET_ITEM(v, 2, 9343 PyLong_FromLongLong((PY_LONG_LONG) st.f_blocks)); 9344 PyStructSequence_SET_ITEM(v, 3, 9345 PyLong_FromLongLong((PY_LONG_LONG) st.f_bfree)); 9346 PyStructSequence_SET_ITEM(v, 4, 9347 PyLong_FromLongLong((PY_LONG_LONG) st.f_bavail)); 9348 PyStructSequence_SET_ITEM(v, 5, 9349 PyLong_FromLongLong((PY_LONG_LONG) st.f_files)); 9350 PyStructSequence_SET_ITEM(v, 6, 9351 PyLong_FromLongLong((PY_LONG_LONG) st.f_ffree)); 9352 PyStructSequence_SET_ITEM(v, 7, 9353 PyLong_FromLongLong((PY_LONG_LONG) st.f_favail)); 9354 PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag)); 9355 PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax)); 9356#endif 9357 if (PyErr_Occurred()) { 9358 Py_DECREF(v); 9359 return NULL; 9360 } 9361 9362 return v; 9363} 9364 9365 9366/*[clinic input] 9367os.fstatvfs 9368 fd: int 9369 / 9370 9371Perform an fstatvfs system call on the given fd. 9372 9373Equivalent to statvfs(fd). 9374[clinic start generated code]*/ 9375 9376static PyObject * 9377os_fstatvfs_impl(PyModuleDef *module, int fd) 9378/*[clinic end generated code: output=584a94a754497ac0 input=d8122243ac50975e]*/ 9379{ 9380 int result; 9381 int async_err = 0; 9382 struct statvfs st; 9383 9384 do { 9385 Py_BEGIN_ALLOW_THREADS 9386 result = fstatvfs(fd, &st); 9387 Py_END_ALLOW_THREADS 9388 } while (result != 0 && errno == EINTR && 9389 !(async_err = PyErr_CheckSignals())); 9390 if (result != 0) 9391 return (!async_err) ? posix_error() : NULL; 9392 9393 return _pystatvfs_fromstructstatvfs(st); 9394} 9395#endif /* defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H) */ 9396 9397 9398#if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) 9399#include <sys/statvfs.h> 9400/*[clinic input] 9401os.statvfs 9402 9403 path: path_t(allow_fd='PATH_HAVE_FSTATVFS') 9404 9405Perform a statvfs system call on the given path. 9406 9407path may always be specified as a string. 9408On some platforms, path may also be specified as an open file descriptor. 9409 If this functionality is unavailable, using it raises an exception. 9410[clinic start generated code]*/ 9411 9412static PyObject * 9413os_statvfs_impl(PyModuleDef *module, path_t *path) 9414/*[clinic end generated code: output=5ced07a2cf931f41 input=3f5c35791c669bd9]*/ 9415{ 9416 int result; 9417 struct statvfs st; 9418 9419 Py_BEGIN_ALLOW_THREADS 9420#ifdef HAVE_FSTATVFS 9421 if (path->fd != -1) { 9422#ifdef __APPLE__ 9423 /* handle weak-linking on Mac OS X 10.3 */ 9424 if (fstatvfs == NULL) { 9425 fd_specified("statvfs", path->fd); 9426 return NULL; 9427 } 9428#endif 9429 result = fstatvfs(path->fd, &st); 9430 } 9431 else 9432#endif 9433 result = statvfs(path->narrow, &st); 9434 Py_END_ALLOW_THREADS 9435 9436 if (result) { 9437 return path_error(path); 9438 } 9439 9440 return _pystatvfs_fromstructstatvfs(st); 9441} 9442#endif /* defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H) */ 9443 9444 9445#ifdef MS_WINDOWS 9446/*[clinic input] 9447os._getdiskusage 9448 9449 path: Py_UNICODE 9450 9451Return disk usage statistics about the given path as a (total, free) tuple. 9452[clinic start generated code]*/ 9453 9454static PyObject * 9455os__getdiskusage_impl(PyModuleDef *module, Py_UNICODE *path) 9456/*[clinic end generated code: output=60a9cf33449db1dd input=6458133aed893c78]*/ 9457{ 9458 BOOL retval; 9459 ULARGE_INTEGER _, total, free; 9460 9461 Py_BEGIN_ALLOW_THREADS 9462 retval = GetDiskFreeSpaceExW(path, &_, &total, &free); 9463 Py_END_ALLOW_THREADS 9464 if (retval == 0) 9465 return PyErr_SetFromWindowsErr(0); 9466 9467 return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart); 9468} 9469#endif /* MS_WINDOWS */ 9470 9471 9472/* This is used for fpathconf(), pathconf(), confstr() and sysconf(). 9473 * It maps strings representing configuration variable names to 9474 * integer values, allowing those functions to be called with the 9475 * magic names instead of polluting the module's namespace with tons of 9476 * rarely-used constants. There are three separate tables that use 9477 * these definitions. 9478 * 9479 * This code is always included, even if none of the interfaces that 9480 * need it are included. The #if hackery needed to avoid it would be 9481 * sufficiently pervasive that it's not worth the loss of readability. 9482 */ 9483struct constdef { 9484 char *name; 9485 int value; 9486}; 9487 9488static int 9489conv_confname(PyObject *arg, int *valuep, struct constdef *table, 9490 size_t tablesize) 9491{ 9492 if (PyLong_Check(arg)) { 9493 int value = _PyLong_AsInt(arg); 9494 if (value == -1 && PyErr_Occurred()) 9495 return 0; 9496 *valuep = value; 9497 return 1; 9498 } 9499 else { 9500 /* look up the value in the table using a binary search */ 9501 size_t lo = 0; 9502 size_t mid; 9503 size_t hi = tablesize; 9504 int cmp; 9505 const char *confname; 9506 if (!PyUnicode_Check(arg)) { 9507 PyErr_SetString(PyExc_TypeError, 9508 "configuration names must be strings or integers"); 9509 return 0; 9510 } 9511 confname = _PyUnicode_AsString(arg); 9512 if (confname == NULL) 9513 return 0; 9514 while (lo < hi) { 9515 mid = (lo + hi) / 2; 9516 cmp = strcmp(confname, table[mid].name); 9517 if (cmp < 0) 9518 hi = mid; 9519 else if (cmp > 0) 9520 lo = mid + 1; 9521 else { 9522 *valuep = table[mid].value; 9523 return 1; 9524 } 9525 } 9526 PyErr_SetString(PyExc_ValueError, "unrecognized configuration name"); 9527 return 0; 9528 } 9529} 9530 9531 9532#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF) 9533static struct constdef posix_constants_pathconf[] = { 9534#ifdef _PC_ABI_AIO_XFER_MAX 9535 {"PC_ABI_AIO_XFER_MAX", _PC_ABI_AIO_XFER_MAX}, 9536#endif 9537#ifdef _PC_ABI_ASYNC_IO 9538 {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO}, 9539#endif 9540#ifdef _PC_ASYNC_IO 9541 {"PC_ASYNC_IO", _PC_ASYNC_IO}, 9542#endif 9543#ifdef _PC_CHOWN_RESTRICTED 9544 {"PC_CHOWN_RESTRICTED", _PC_CHOWN_RESTRICTED}, 9545#endif 9546#ifdef _PC_FILESIZEBITS 9547 {"PC_FILESIZEBITS", _PC_FILESIZEBITS}, 9548#endif 9549#ifdef _PC_LAST 9550 {"PC_LAST", _PC_LAST}, 9551#endif 9552#ifdef _PC_LINK_MAX 9553 {"PC_LINK_MAX", _PC_LINK_MAX}, 9554#endif 9555#ifdef _PC_MAX_CANON 9556 {"PC_MAX_CANON", _PC_MAX_CANON}, 9557#endif 9558#ifdef _PC_MAX_INPUT 9559 {"PC_MAX_INPUT", _PC_MAX_INPUT}, 9560#endif 9561#ifdef _PC_NAME_MAX 9562 {"PC_NAME_MAX", _PC_NAME_MAX}, 9563#endif 9564#ifdef _PC_NO_TRUNC 9565 {"PC_NO_TRUNC", _PC_NO_TRUNC}, 9566#endif 9567#ifdef _PC_PATH_MAX 9568 {"PC_PATH_MAX", _PC_PATH_MAX}, 9569#endif 9570#ifdef _PC_PIPE_BUF 9571 {"PC_PIPE_BUF", _PC_PIPE_BUF}, 9572#endif 9573#ifdef _PC_PRIO_IO 9574 {"PC_PRIO_IO", _PC_PRIO_IO}, 9575#endif 9576#ifdef _PC_SOCK_MAXBUF 9577 {"PC_SOCK_MAXBUF", _PC_SOCK_MAXBUF}, 9578#endif 9579#ifdef _PC_SYNC_IO 9580 {"PC_SYNC_IO", _PC_SYNC_IO}, 9581#endif 9582#ifdef _PC_VDISABLE 9583 {"PC_VDISABLE", _PC_VDISABLE}, 9584#endif 9585#ifdef _PC_ACL_ENABLED 9586 {"PC_ACL_ENABLED", _PC_ACL_ENABLED}, 9587#endif 9588#ifdef _PC_MIN_HOLE_SIZE 9589 {"PC_MIN_HOLE_SIZE", _PC_MIN_HOLE_SIZE}, 9590#endif 9591#ifdef _PC_ALLOC_SIZE_MIN 9592 {"PC_ALLOC_SIZE_MIN", _PC_ALLOC_SIZE_MIN}, 9593#endif 9594#ifdef _PC_REC_INCR_XFER_SIZE 9595 {"PC_REC_INCR_XFER_SIZE", _PC_REC_INCR_XFER_SIZE}, 9596#endif 9597#ifdef _PC_REC_MAX_XFER_SIZE 9598 {"PC_REC_MAX_XFER_SIZE", _PC_REC_MAX_XFER_SIZE}, 9599#endif 9600#ifdef _PC_REC_MIN_XFER_SIZE 9601 {"PC_REC_MIN_XFER_SIZE", _PC_REC_MIN_XFER_SIZE}, 9602#endif 9603#ifdef _PC_REC_XFER_ALIGN 9604 {"PC_REC_XFER_ALIGN", _PC_REC_XFER_ALIGN}, 9605#endif 9606#ifdef _PC_SYMLINK_MAX 9607 {"PC_SYMLINK_MAX", _PC_SYMLINK_MAX}, 9608#endif 9609#ifdef _PC_XATTR_ENABLED 9610 {"PC_XATTR_ENABLED", _PC_XATTR_ENABLED}, 9611#endif 9612#ifdef _PC_XATTR_EXISTS 9613 {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS}, 9614#endif 9615#ifdef _PC_TIMESTAMP_RESOLUTION 9616 {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION}, 9617#endif 9618}; 9619 9620static int 9621conv_path_confname(PyObject *arg, int *valuep) 9622{ 9623 return conv_confname(arg, valuep, posix_constants_pathconf, 9624 sizeof(posix_constants_pathconf) 9625 / sizeof(struct constdef)); 9626} 9627#endif 9628 9629 9630#ifdef HAVE_FPATHCONF 9631/*[clinic input] 9632os.fpathconf -> long 9633 9634 fd: int 9635 name: path_confname 9636 / 9637 9638Return the configuration limit name for the file descriptor fd. 9639 9640If there is no limit, return -1. 9641[clinic start generated code]*/ 9642 9643static long 9644os_fpathconf_impl(PyModuleDef *module, int fd, int name) 9645/*[clinic end generated code: output=082b2922d4441de7 input=5942a024d3777810]*/ 9646{ 9647 long limit; 9648 9649 errno = 0; 9650 limit = fpathconf(fd, name); 9651 if (limit == -1 && errno != 0) 9652 posix_error(); 9653 9654 return limit; 9655} 9656#endif /* HAVE_FPATHCONF */ 9657 9658 9659#ifdef HAVE_PATHCONF 9660/*[clinic input] 9661os.pathconf -> long 9662 path: path_t(allow_fd='PATH_HAVE_FPATHCONF') 9663 name: path_confname 9664 9665Return the configuration limit name for the file or directory path. 9666 9667If there is no limit, return -1. 9668On some platforms, path may also be specified as an open file descriptor. 9669 If this functionality is unavailable, using it raises an exception. 9670[clinic start generated code]*/ 9671 9672static long 9673os_pathconf_impl(PyModuleDef *module, path_t *path, int name) 9674/*[clinic end generated code: output=3713029e9501f5ab input=bc3e2a985af27e5e]*/ 9675{ 9676 long limit; 9677 9678 errno = 0; 9679#ifdef HAVE_FPATHCONF 9680 if (path->fd != -1) 9681 limit = fpathconf(path->fd, name); 9682 else 9683#endif 9684 limit = pathconf(path->narrow, name); 9685 if (limit == -1 && errno != 0) { 9686 if (errno == EINVAL) 9687 /* could be a path or name problem */ 9688 posix_error(); 9689 else 9690 path_error(path); 9691 } 9692 9693 return limit; 9694} 9695#endif /* HAVE_PATHCONF */ 9696 9697#ifdef HAVE_CONFSTR 9698static struct constdef posix_constants_confstr[] = { 9699#ifdef _CS_ARCHITECTURE 9700 {"CS_ARCHITECTURE", _CS_ARCHITECTURE}, 9701#endif 9702#ifdef _CS_GNU_LIBC_VERSION 9703 {"CS_GNU_LIBC_VERSION", _CS_GNU_LIBC_VERSION}, 9704#endif 9705#ifdef _CS_GNU_LIBPTHREAD_VERSION 9706 {"CS_GNU_LIBPTHREAD_VERSION", _CS_GNU_LIBPTHREAD_VERSION}, 9707#endif 9708#ifdef _CS_HOSTNAME 9709 {"CS_HOSTNAME", _CS_HOSTNAME}, 9710#endif 9711#ifdef _CS_HW_PROVIDER 9712 {"CS_HW_PROVIDER", _CS_HW_PROVIDER}, 9713#endif 9714#ifdef _CS_HW_SERIAL 9715 {"CS_HW_SERIAL", _CS_HW_SERIAL}, 9716#endif 9717#ifdef _CS_INITTAB_NAME 9718 {"CS_INITTAB_NAME", _CS_INITTAB_NAME}, 9719#endif 9720#ifdef _CS_LFS64_CFLAGS 9721 {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS}, 9722#endif 9723#ifdef _CS_LFS64_LDFLAGS 9724 {"CS_LFS64_LDFLAGS", _CS_LFS64_LDFLAGS}, 9725#endif 9726#ifdef _CS_LFS64_LIBS 9727 {"CS_LFS64_LIBS", _CS_LFS64_LIBS}, 9728#endif 9729#ifdef _CS_LFS64_LINTFLAGS 9730 {"CS_LFS64_LINTFLAGS", _CS_LFS64_LINTFLAGS}, 9731#endif 9732#ifdef _CS_LFS_CFLAGS 9733 {"CS_LFS_CFLAGS", _CS_LFS_CFLAGS}, 9734#endif 9735#ifdef _CS_LFS_LDFLAGS 9736 {"CS_LFS_LDFLAGS", _CS_LFS_LDFLAGS}, 9737#endif 9738#ifdef _CS_LFS_LIBS 9739 {"CS_LFS_LIBS", _CS_LFS_LIBS}, 9740#endif 9741#ifdef _CS_LFS_LINTFLAGS 9742 {"CS_LFS_LINTFLAGS", _CS_LFS_LINTFLAGS}, 9743#endif 9744#ifdef _CS_MACHINE 9745 {"CS_MACHINE", _CS_MACHINE}, 9746#endif 9747#ifdef _CS_PATH 9748 {"CS_PATH", _CS_PATH}, 9749#endif 9750#ifdef _CS_RELEASE 9751 {"CS_RELEASE", _CS_RELEASE}, 9752#endif 9753#ifdef _CS_SRPC_DOMAIN 9754 {"CS_SRPC_DOMAIN", _CS_SRPC_DOMAIN}, 9755#endif 9756#ifdef _CS_SYSNAME 9757 {"CS_SYSNAME", _CS_SYSNAME}, 9758#endif 9759#ifdef _CS_VERSION 9760 {"CS_VERSION", _CS_VERSION}, 9761#endif 9762#ifdef _CS_XBS5_ILP32_OFF32_CFLAGS 9763 {"CS_XBS5_ILP32_OFF32_CFLAGS", _CS_XBS5_ILP32_OFF32_CFLAGS}, 9764#endif 9765#ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS 9766 {"CS_XBS5_ILP32_OFF32_LDFLAGS", _CS_XBS5_ILP32_OFF32_LDFLAGS}, 9767#endif 9768#ifdef _CS_XBS5_ILP32_OFF32_LIBS 9769 {"CS_XBS5_ILP32_OFF32_LIBS", _CS_XBS5_ILP32_OFF32_LIBS}, 9770#endif 9771#ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS 9772 {"CS_XBS5_ILP32_OFF32_LINTFLAGS", _CS_XBS5_ILP32_OFF32_LINTFLAGS}, 9773#endif 9774#ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS 9775 {"CS_XBS5_ILP32_OFFBIG_CFLAGS", _CS_XBS5_ILP32_OFFBIG_CFLAGS}, 9776#endif 9777#ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS 9778 {"CS_XBS5_ILP32_OFFBIG_LDFLAGS", _CS_XBS5_ILP32_OFFBIG_LDFLAGS}, 9779#endif 9780#ifdef _CS_XBS5_ILP32_OFFBIG_LIBS 9781 {"CS_XBS5_ILP32_OFFBIG_LIBS", _CS_XBS5_ILP32_OFFBIG_LIBS}, 9782#endif 9783#ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS 9784 {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS", _CS_XBS5_ILP32_OFFBIG_LINTFLAGS}, 9785#endif 9786#ifdef _CS_XBS5_LP64_OFF64_CFLAGS 9787 {"CS_XBS5_LP64_OFF64_CFLAGS", _CS_XBS5_LP64_OFF64_CFLAGS}, 9788#endif 9789#ifdef _CS_XBS5_LP64_OFF64_LDFLAGS 9790 {"CS_XBS5_LP64_OFF64_LDFLAGS", _CS_XBS5_LP64_OFF64_LDFLAGS}, 9791#endif 9792#ifdef _CS_XBS5_LP64_OFF64_LIBS 9793 {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS}, 9794#endif 9795#ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS 9796 {"CS_XBS5_LP64_OFF64_LINTFLAGS", _CS_XBS5_LP64_OFF64_LINTFLAGS}, 9797#endif 9798#ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS 9799 {"CS_XBS5_LPBIG_OFFBIG_CFLAGS", _CS_XBS5_LPBIG_OFFBIG_CFLAGS}, 9800#endif 9801#ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS 9802 {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS", _CS_XBS5_LPBIG_OFFBIG_LDFLAGS}, 9803#endif 9804#ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS 9805 {"CS_XBS5_LPBIG_OFFBIG_LIBS", _CS_XBS5_LPBIG_OFFBIG_LIBS}, 9806#endif 9807#ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS 9808 {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS", _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS}, 9809#endif 9810#ifdef _MIPS_CS_AVAIL_PROCESSORS 9811 {"MIPS_CS_AVAIL_PROCESSORS", _MIPS_CS_AVAIL_PROCESSORS}, 9812#endif 9813#ifdef _MIPS_CS_BASE 9814 {"MIPS_CS_BASE", _MIPS_CS_BASE}, 9815#endif 9816#ifdef _MIPS_CS_HOSTID 9817 {"MIPS_CS_HOSTID", _MIPS_CS_HOSTID}, 9818#endif 9819#ifdef _MIPS_CS_HW_NAME 9820 {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME}, 9821#endif 9822#ifdef _MIPS_CS_NUM_PROCESSORS 9823 {"MIPS_CS_NUM_PROCESSORS", _MIPS_CS_NUM_PROCESSORS}, 9824#endif 9825#ifdef _MIPS_CS_OSREL_MAJ 9826 {"MIPS_CS_OSREL_MAJ", _MIPS_CS_OSREL_MAJ}, 9827#endif 9828#ifdef _MIPS_CS_OSREL_MIN 9829 {"MIPS_CS_OSREL_MIN", _MIPS_CS_OSREL_MIN}, 9830#endif 9831#ifdef _MIPS_CS_OSREL_PATCH 9832 {"MIPS_CS_OSREL_PATCH", _MIPS_CS_OSREL_PATCH}, 9833#endif 9834#ifdef _MIPS_CS_OS_NAME 9835 {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME}, 9836#endif 9837#ifdef _MIPS_CS_OS_PROVIDER 9838 {"MIPS_CS_OS_PROVIDER", _MIPS_CS_OS_PROVIDER}, 9839#endif 9840#ifdef _MIPS_CS_PROCESSORS 9841 {"MIPS_CS_PROCESSORS", _MIPS_CS_PROCESSORS}, 9842#endif 9843#ifdef _MIPS_CS_SERIAL 9844 {"MIPS_CS_SERIAL", _MIPS_CS_SERIAL}, 9845#endif 9846#ifdef _MIPS_CS_VENDOR 9847 {"MIPS_CS_VENDOR", _MIPS_CS_VENDOR}, 9848#endif 9849}; 9850 9851static int 9852conv_confstr_confname(PyObject *arg, int *valuep) 9853{ 9854 return conv_confname(arg, valuep, posix_constants_confstr, 9855 sizeof(posix_constants_confstr) 9856 / sizeof(struct constdef)); 9857} 9858 9859 9860/*[clinic input] 9861os.confstr 9862 9863 name: confstr_confname 9864 / 9865 9866Return a string-valued system configuration variable. 9867[clinic start generated code]*/ 9868 9869static PyObject * 9870os_confstr_impl(PyModuleDef *module, int name) 9871/*[clinic end generated code: output=6ff79c9eed8c2daf input=18fb4d0567242e65]*/ 9872{ 9873 PyObject *result = NULL; 9874 char buffer[255]; 9875 size_t len; 9876 9877 errno = 0; 9878 len = confstr(name, buffer, sizeof(buffer)); 9879 if (len == 0) { 9880 if (errno) { 9881 posix_error(); 9882 return NULL; 9883 } 9884 else { 9885 Py_RETURN_NONE; 9886 } 9887 } 9888 9889 if (len >= sizeof(buffer)) { 9890 size_t len2; 9891 char *buf = PyMem_Malloc(len); 9892 if (buf == NULL) 9893 return PyErr_NoMemory(); 9894 len2 = confstr(name, buf, len); 9895 assert(len == len2); 9896 result = PyUnicode_DecodeFSDefaultAndSize(buf, len2-1); 9897 PyMem_Free(buf); 9898 } 9899 else 9900 result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1); 9901 return result; 9902} 9903#endif /* HAVE_CONFSTR */ 9904 9905 9906#ifdef HAVE_SYSCONF 9907static struct constdef posix_constants_sysconf[] = { 9908#ifdef _SC_2_CHAR_TERM 9909 {"SC_2_CHAR_TERM", _SC_2_CHAR_TERM}, 9910#endif 9911#ifdef _SC_2_C_BIND 9912 {"SC_2_C_BIND", _SC_2_C_BIND}, 9913#endif 9914#ifdef _SC_2_C_DEV 9915 {"SC_2_C_DEV", _SC_2_C_DEV}, 9916#endif 9917#ifdef _SC_2_C_VERSION 9918 {"SC_2_C_VERSION", _SC_2_C_VERSION}, 9919#endif 9920#ifdef _SC_2_FORT_DEV 9921 {"SC_2_FORT_DEV", _SC_2_FORT_DEV}, 9922#endif 9923#ifdef _SC_2_FORT_RUN 9924 {"SC_2_FORT_RUN", _SC_2_FORT_RUN}, 9925#endif 9926#ifdef _SC_2_LOCALEDEF 9927 {"SC_2_LOCALEDEF", _SC_2_LOCALEDEF}, 9928#endif 9929#ifdef _SC_2_SW_DEV 9930 {"SC_2_SW_DEV", _SC_2_SW_DEV}, 9931#endif 9932#ifdef _SC_2_UPE 9933 {"SC_2_UPE", _SC_2_UPE}, 9934#endif 9935#ifdef _SC_2_VERSION 9936 {"SC_2_VERSION", _SC_2_VERSION}, 9937#endif 9938#ifdef _SC_ABI_ASYNCHRONOUS_IO 9939 {"SC_ABI_ASYNCHRONOUS_IO", _SC_ABI_ASYNCHRONOUS_IO}, 9940#endif 9941#ifdef _SC_ACL 9942 {"SC_ACL", _SC_ACL}, 9943#endif 9944#ifdef _SC_AIO_LISTIO_MAX 9945 {"SC_AIO_LISTIO_MAX", _SC_AIO_LISTIO_MAX}, 9946#endif 9947#ifdef _SC_AIO_MAX 9948 {"SC_AIO_MAX", _SC_AIO_MAX}, 9949#endif 9950#ifdef _SC_AIO_PRIO_DELTA_MAX 9951 {"SC_AIO_PRIO_DELTA_MAX", _SC_AIO_PRIO_DELTA_MAX}, 9952#endif 9953#ifdef _SC_ARG_MAX 9954 {"SC_ARG_MAX", _SC_ARG_MAX}, 9955#endif 9956#ifdef _SC_ASYNCHRONOUS_IO 9957 {"SC_ASYNCHRONOUS_IO", _SC_ASYNCHRONOUS_IO}, 9958#endif 9959#ifdef _SC_ATEXIT_MAX 9960 {"SC_ATEXIT_MAX", _SC_ATEXIT_MAX}, 9961#endif 9962#ifdef _SC_AUDIT 9963 {"SC_AUDIT", _SC_AUDIT}, 9964#endif 9965#ifdef _SC_AVPHYS_PAGES 9966 {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES}, 9967#endif 9968#ifdef _SC_BC_BASE_MAX 9969 {"SC_BC_BASE_MAX", _SC_BC_BASE_MAX}, 9970#endif 9971#ifdef _SC_BC_DIM_MAX 9972 {"SC_BC_DIM_MAX", _SC_BC_DIM_MAX}, 9973#endif 9974#ifdef _SC_BC_SCALE_MAX 9975 {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX}, 9976#endif 9977#ifdef _SC_BC_STRING_MAX 9978 {"SC_BC_STRING_MAX", _SC_BC_STRING_MAX}, 9979#endif 9980#ifdef _SC_CAP 9981 {"SC_CAP", _SC_CAP}, 9982#endif 9983#ifdef _SC_CHARCLASS_NAME_MAX 9984 {"SC_CHARCLASS_NAME_MAX", _SC_CHARCLASS_NAME_MAX}, 9985#endif 9986#ifdef _SC_CHAR_BIT 9987 {"SC_CHAR_BIT", _SC_CHAR_BIT}, 9988#endif 9989#ifdef _SC_CHAR_MAX 9990 {"SC_CHAR_MAX", _SC_CHAR_MAX}, 9991#endif 9992#ifdef _SC_CHAR_MIN 9993 {"SC_CHAR_MIN", _SC_CHAR_MIN}, 9994#endif 9995#ifdef _SC_CHILD_MAX 9996 {"SC_CHILD_MAX", _SC_CHILD_MAX}, 9997#endif 9998#ifdef _SC_CLK_TCK 9999 {"SC_CLK_TCK", _SC_CLK_TCK}, 10000#endif 10001#ifdef _SC_COHER_BLKSZ 10002 {"SC_COHER_BLKSZ", _SC_COHER_BLKSZ}, 10003#endif 10004#ifdef _SC_COLL_WEIGHTS_MAX 10005 {"SC_COLL_WEIGHTS_MAX", _SC_COLL_WEIGHTS_MAX}, 10006#endif 10007#ifdef _SC_DCACHE_ASSOC 10008 {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC}, 10009#endif 10010#ifdef _SC_DCACHE_BLKSZ 10011 {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ}, 10012#endif 10013#ifdef _SC_DCACHE_LINESZ 10014 {"SC_DCACHE_LINESZ", _SC_DCACHE_LINESZ}, 10015#endif 10016#ifdef _SC_DCACHE_SZ 10017 {"SC_DCACHE_SZ", _SC_DCACHE_SZ}, 10018#endif 10019#ifdef _SC_DCACHE_TBLKSZ 10020 {"SC_DCACHE_TBLKSZ", _SC_DCACHE_TBLKSZ}, 10021#endif 10022#ifdef _SC_DELAYTIMER_MAX 10023 {"SC_DELAYTIMER_MAX", _SC_DELAYTIMER_MAX}, 10024#endif 10025#ifdef _SC_EQUIV_CLASS_MAX 10026 {"SC_EQUIV_CLASS_MAX", _SC_EQUIV_CLASS_MAX}, 10027#endif 10028#ifdef _SC_EXPR_NEST_MAX 10029 {"SC_EXPR_NEST_MAX", _SC_EXPR_NEST_MAX}, 10030#endif 10031#ifdef _SC_FSYNC 10032 {"SC_FSYNC", _SC_FSYNC}, 10033#endif 10034#ifdef _SC_GETGR_R_SIZE_MAX 10035 {"SC_GETGR_R_SIZE_MAX", _SC_GETGR_R_SIZE_MAX}, 10036#endif 10037#ifdef _SC_GETPW_R_SIZE_MAX 10038 {"SC_GETPW_R_SIZE_MAX", _SC_GETPW_R_SIZE_MAX}, 10039#endif 10040#ifdef _SC_ICACHE_ASSOC 10041 {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC}, 10042#endif 10043#ifdef _SC_ICACHE_BLKSZ 10044 {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ}, 10045#endif 10046#ifdef _SC_ICACHE_LINESZ 10047 {"SC_ICACHE_LINESZ", _SC_ICACHE_LINESZ}, 10048#endif 10049#ifdef _SC_ICACHE_SZ 10050 {"SC_ICACHE_SZ", _SC_ICACHE_SZ}, 10051#endif 10052#ifdef _SC_INF 10053 {"SC_INF", _SC_INF}, 10054#endif 10055#ifdef _SC_INT_MAX 10056 {"SC_INT_MAX", _SC_INT_MAX}, 10057#endif 10058#ifdef _SC_INT_MIN 10059 {"SC_INT_MIN", _SC_INT_MIN}, 10060#endif 10061#ifdef _SC_IOV_MAX 10062 {"SC_IOV_MAX", _SC_IOV_MAX}, 10063#endif 10064#ifdef _SC_IP_SECOPTS 10065 {"SC_IP_SECOPTS", _SC_IP_SECOPTS}, 10066#endif 10067#ifdef _SC_JOB_CONTROL 10068 {"SC_JOB_CONTROL", _SC_JOB_CONTROL}, 10069#endif 10070#ifdef _SC_KERN_POINTERS 10071 {"SC_KERN_POINTERS", _SC_KERN_POINTERS}, 10072#endif 10073#ifdef _SC_KERN_SIM 10074 {"SC_KERN_SIM", _SC_KERN_SIM}, 10075#endif 10076#ifdef _SC_LINE_MAX 10077 {"SC_LINE_MAX", _SC_LINE_MAX}, 10078#endif 10079#ifdef _SC_LOGIN_NAME_MAX 10080 {"SC_LOGIN_NAME_MAX", _SC_LOGIN_NAME_MAX}, 10081#endif 10082#ifdef _SC_LOGNAME_MAX 10083 {"SC_LOGNAME_MAX", _SC_LOGNAME_MAX}, 10084#endif 10085#ifdef _SC_LONG_BIT 10086 {"SC_LONG_BIT", _SC_LONG_BIT}, 10087#endif 10088#ifdef _SC_MAC 10089 {"SC_MAC", _SC_MAC}, 10090#endif 10091#ifdef _SC_MAPPED_FILES 10092 {"SC_MAPPED_FILES", _SC_MAPPED_FILES}, 10093#endif 10094#ifdef _SC_MAXPID 10095 {"SC_MAXPID", _SC_MAXPID}, 10096#endif 10097#ifdef _SC_MB_LEN_MAX 10098 {"SC_MB_LEN_MAX", _SC_MB_LEN_MAX}, 10099#endif 10100#ifdef _SC_MEMLOCK 10101 {"SC_MEMLOCK", _SC_MEMLOCK}, 10102#endif 10103#ifdef _SC_MEMLOCK_RANGE 10104 {"SC_MEMLOCK_RANGE", _SC_MEMLOCK_RANGE}, 10105#endif 10106#ifdef _SC_MEMORY_PROTECTION 10107 {"SC_MEMORY_PROTECTION", _SC_MEMORY_PROTECTION}, 10108#endif 10109#ifdef _SC_MESSAGE_PASSING 10110 {"SC_MESSAGE_PASSING", _SC_MESSAGE_PASSING}, 10111#endif 10112#ifdef _SC_MMAP_FIXED_ALIGNMENT 10113 {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT}, 10114#endif 10115#ifdef _SC_MQ_OPEN_MAX 10116 {"SC_MQ_OPEN_MAX", _SC_MQ_OPEN_MAX}, 10117#endif 10118#ifdef _SC_MQ_PRIO_MAX 10119 {"SC_MQ_PRIO_MAX", _SC_MQ_PRIO_MAX}, 10120#endif 10121#ifdef _SC_NACLS_MAX 10122 {"SC_NACLS_MAX", _SC_NACLS_MAX}, 10123#endif 10124#ifdef _SC_NGROUPS_MAX 10125 {"SC_NGROUPS_MAX", _SC_NGROUPS_MAX}, 10126#endif 10127#ifdef _SC_NL_ARGMAX 10128 {"SC_NL_ARGMAX", _SC_NL_ARGMAX}, 10129#endif 10130#ifdef _SC_NL_LANGMAX 10131 {"SC_NL_LANGMAX", _SC_NL_LANGMAX}, 10132#endif 10133#ifdef _SC_NL_MSGMAX 10134 {"SC_NL_MSGMAX", _SC_NL_MSGMAX}, 10135#endif 10136#ifdef _SC_NL_NMAX 10137 {"SC_NL_NMAX", _SC_NL_NMAX}, 10138#endif 10139#ifdef _SC_NL_SETMAX 10140 {"SC_NL_SETMAX", _SC_NL_SETMAX}, 10141#endif 10142#ifdef _SC_NL_TEXTMAX 10143 {"SC_NL_TEXTMAX", _SC_NL_TEXTMAX}, 10144#endif 10145#ifdef _SC_NPROCESSORS_CONF 10146 {"SC_NPROCESSORS_CONF", _SC_NPROCESSORS_CONF}, 10147#endif 10148#ifdef _SC_NPROCESSORS_ONLN 10149 {"SC_NPROCESSORS_ONLN", _SC_NPROCESSORS_ONLN}, 10150#endif 10151#ifdef _SC_NPROC_CONF 10152 {"SC_NPROC_CONF", _SC_NPROC_CONF}, 10153#endif 10154#ifdef _SC_NPROC_ONLN 10155 {"SC_NPROC_ONLN", _SC_NPROC_ONLN}, 10156#endif 10157#ifdef _SC_NZERO 10158 {"SC_NZERO", _SC_NZERO}, 10159#endif 10160#ifdef _SC_OPEN_MAX 10161 {"SC_OPEN_MAX", _SC_OPEN_MAX}, 10162#endif 10163#ifdef _SC_PAGESIZE 10164 {"SC_PAGESIZE", _SC_PAGESIZE}, 10165#endif 10166#ifdef _SC_PAGE_SIZE 10167 {"SC_PAGE_SIZE", _SC_PAGE_SIZE}, 10168#endif 10169#ifdef _SC_PASS_MAX 10170 {"SC_PASS_MAX", _SC_PASS_MAX}, 10171#endif 10172#ifdef _SC_PHYS_PAGES 10173 {"SC_PHYS_PAGES", _SC_PHYS_PAGES}, 10174#endif 10175#ifdef _SC_PII 10176 {"SC_PII", _SC_PII}, 10177#endif 10178#ifdef _SC_PII_INTERNET 10179 {"SC_PII_INTERNET", _SC_PII_INTERNET}, 10180#endif 10181#ifdef _SC_PII_INTERNET_DGRAM 10182 {"SC_PII_INTERNET_DGRAM", _SC_PII_INTERNET_DGRAM}, 10183#endif 10184#ifdef _SC_PII_INTERNET_STREAM 10185 {"SC_PII_INTERNET_STREAM", _SC_PII_INTERNET_STREAM}, 10186#endif 10187#ifdef _SC_PII_OSI 10188 {"SC_PII_OSI", _SC_PII_OSI}, 10189#endif 10190#ifdef _SC_PII_OSI_CLTS 10191 {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS}, 10192#endif 10193#ifdef _SC_PII_OSI_COTS 10194 {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS}, 10195#endif 10196#ifdef _SC_PII_OSI_M 10197 {"SC_PII_OSI_M", _SC_PII_OSI_M}, 10198#endif 10199#ifdef _SC_PII_SOCKET 10200 {"SC_PII_SOCKET", _SC_PII_SOCKET}, 10201#endif 10202#ifdef _SC_PII_XTI 10203 {"SC_PII_XTI", _SC_PII_XTI}, 10204#endif 10205#ifdef _SC_POLL 10206 {"SC_POLL", _SC_POLL}, 10207#endif 10208#ifdef _SC_PRIORITIZED_IO 10209 {"SC_PRIORITIZED_IO", _SC_PRIORITIZED_IO}, 10210#endif 10211#ifdef _SC_PRIORITY_SCHEDULING 10212 {"SC_PRIORITY_SCHEDULING", _SC_PRIORITY_SCHEDULING}, 10213#endif 10214#ifdef _SC_REALTIME_SIGNALS 10215 {"SC_REALTIME_SIGNALS", _SC_REALTIME_SIGNALS}, 10216#endif 10217#ifdef _SC_RE_DUP_MAX 10218 {"SC_RE_DUP_MAX", _SC_RE_DUP_MAX}, 10219#endif 10220#ifdef _SC_RTSIG_MAX 10221 {"SC_RTSIG_MAX", _SC_RTSIG_MAX}, 10222#endif 10223#ifdef _SC_SAVED_IDS 10224 {"SC_SAVED_IDS", _SC_SAVED_IDS}, 10225#endif 10226#ifdef _SC_SCHAR_MAX 10227 {"SC_SCHAR_MAX", _SC_SCHAR_MAX}, 10228#endif 10229#ifdef _SC_SCHAR_MIN 10230 {"SC_SCHAR_MIN", _SC_SCHAR_MIN}, 10231#endif 10232#ifdef _SC_SELECT 10233 {"SC_SELECT", _SC_SELECT}, 10234#endif 10235#ifdef _SC_SEMAPHORES 10236 {"SC_SEMAPHORES", _SC_SEMAPHORES}, 10237#endif 10238#ifdef _SC_SEM_NSEMS_MAX 10239 {"SC_SEM_NSEMS_MAX", _SC_SEM_NSEMS_MAX}, 10240#endif 10241#ifdef _SC_SEM_VALUE_MAX 10242 {"SC_SEM_VALUE_MAX", _SC_SEM_VALUE_MAX}, 10243#endif 10244#ifdef _SC_SHARED_MEMORY_OBJECTS 10245 {"SC_SHARED_MEMORY_OBJECTS", _SC_SHARED_MEMORY_OBJECTS}, 10246#endif 10247#ifdef _SC_SHRT_MAX 10248 {"SC_SHRT_MAX", _SC_SHRT_MAX}, 10249#endif 10250#ifdef _SC_SHRT_MIN 10251 {"SC_SHRT_MIN", _SC_SHRT_MIN}, 10252#endif 10253#ifdef _SC_SIGQUEUE_MAX 10254 {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX}, 10255#endif 10256#ifdef _SC_SIGRT_MAX 10257 {"SC_SIGRT_MAX", _SC_SIGRT_MAX}, 10258#endif 10259#ifdef _SC_SIGRT_MIN 10260 {"SC_SIGRT_MIN", _SC_SIGRT_MIN}, 10261#endif 10262#ifdef _SC_SOFTPOWER 10263 {"SC_SOFTPOWER", _SC_SOFTPOWER}, 10264#endif 10265#ifdef _SC_SPLIT_CACHE 10266 {"SC_SPLIT_CACHE", _SC_SPLIT_CACHE}, 10267#endif 10268#ifdef _SC_SSIZE_MAX 10269 {"SC_SSIZE_MAX", _SC_SSIZE_MAX}, 10270#endif 10271#ifdef _SC_STACK_PROT 10272 {"SC_STACK_PROT", _SC_STACK_PROT}, 10273#endif 10274#ifdef _SC_STREAM_MAX 10275 {"SC_STREAM_MAX", _SC_STREAM_MAX}, 10276#endif 10277#ifdef _SC_SYNCHRONIZED_IO 10278 {"SC_SYNCHRONIZED_IO", _SC_SYNCHRONIZED_IO}, 10279#endif 10280#ifdef _SC_THREADS 10281 {"SC_THREADS", _SC_THREADS}, 10282#endif 10283#ifdef _SC_THREAD_ATTR_STACKADDR 10284 {"SC_THREAD_ATTR_STACKADDR", _SC_THREAD_ATTR_STACKADDR}, 10285#endif 10286#ifdef _SC_THREAD_ATTR_STACKSIZE 10287 {"SC_THREAD_ATTR_STACKSIZE", _SC_THREAD_ATTR_STACKSIZE}, 10288#endif 10289#ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS 10290 {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS}, 10291#endif 10292#ifdef _SC_THREAD_KEYS_MAX 10293 {"SC_THREAD_KEYS_MAX", _SC_THREAD_KEYS_MAX}, 10294#endif 10295#ifdef _SC_THREAD_PRIORITY_SCHEDULING 10296 {"SC_THREAD_PRIORITY_SCHEDULING", _SC_THREAD_PRIORITY_SCHEDULING}, 10297#endif 10298#ifdef _SC_THREAD_PRIO_INHERIT 10299 {"SC_THREAD_PRIO_INHERIT", _SC_THREAD_PRIO_INHERIT}, 10300#endif 10301#ifdef _SC_THREAD_PRIO_PROTECT 10302 {"SC_THREAD_PRIO_PROTECT", _SC_THREAD_PRIO_PROTECT}, 10303#endif 10304#ifdef _SC_THREAD_PROCESS_SHARED 10305 {"SC_THREAD_PROCESS_SHARED", _SC_THREAD_PROCESS_SHARED}, 10306#endif 10307#ifdef _SC_THREAD_SAFE_FUNCTIONS 10308 {"SC_THREAD_SAFE_FUNCTIONS", _SC_THREAD_SAFE_FUNCTIONS}, 10309#endif 10310#ifdef _SC_THREAD_STACK_MIN 10311 {"SC_THREAD_STACK_MIN", _SC_THREAD_STACK_MIN}, 10312#endif 10313#ifdef _SC_THREAD_THREADS_MAX 10314 {"SC_THREAD_THREADS_MAX", _SC_THREAD_THREADS_MAX}, 10315#endif 10316#ifdef _SC_TIMERS 10317 {"SC_TIMERS", _SC_TIMERS}, 10318#endif 10319#ifdef _SC_TIMER_MAX 10320 {"SC_TIMER_MAX", _SC_TIMER_MAX}, 10321#endif 10322#ifdef _SC_TTY_NAME_MAX 10323 {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX}, 10324#endif 10325#ifdef _SC_TZNAME_MAX 10326 {"SC_TZNAME_MAX", _SC_TZNAME_MAX}, 10327#endif 10328#ifdef _SC_T_IOV_MAX 10329 {"SC_T_IOV_MAX", _SC_T_IOV_MAX}, 10330#endif 10331#ifdef _SC_UCHAR_MAX 10332 {"SC_UCHAR_MAX", _SC_UCHAR_MAX}, 10333#endif 10334#ifdef _SC_UINT_MAX 10335 {"SC_UINT_MAX", _SC_UINT_MAX}, 10336#endif 10337#ifdef _SC_UIO_MAXIOV 10338 {"SC_UIO_MAXIOV", _SC_UIO_MAXIOV}, 10339#endif 10340#ifdef _SC_ULONG_MAX 10341 {"SC_ULONG_MAX", _SC_ULONG_MAX}, 10342#endif 10343#ifdef _SC_USHRT_MAX 10344 {"SC_USHRT_MAX", _SC_USHRT_MAX}, 10345#endif 10346#ifdef _SC_VERSION 10347 {"SC_VERSION", _SC_VERSION}, 10348#endif 10349#ifdef _SC_WORD_BIT 10350 {"SC_WORD_BIT", _SC_WORD_BIT}, 10351#endif 10352#ifdef _SC_XBS5_ILP32_OFF32 10353 {"SC_XBS5_ILP32_OFF32", _SC_XBS5_ILP32_OFF32}, 10354#endif 10355#ifdef _SC_XBS5_ILP32_OFFBIG 10356 {"SC_XBS5_ILP32_OFFBIG", _SC_XBS5_ILP32_OFFBIG}, 10357#endif 10358#ifdef _SC_XBS5_LP64_OFF64 10359 {"SC_XBS5_LP64_OFF64", _SC_XBS5_LP64_OFF64}, 10360#endif 10361#ifdef _SC_XBS5_LPBIG_OFFBIG 10362 {"SC_XBS5_LPBIG_OFFBIG", _SC_XBS5_LPBIG_OFFBIG}, 10363#endif 10364#ifdef _SC_XOPEN_CRYPT 10365 {"SC_XOPEN_CRYPT", _SC_XOPEN_CRYPT}, 10366#endif 10367#ifdef _SC_XOPEN_ENH_I18N 10368 {"SC_XOPEN_ENH_I18N", _SC_XOPEN_ENH_I18N}, 10369#endif 10370#ifdef _SC_XOPEN_LEGACY 10371 {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY}, 10372#endif 10373#ifdef _SC_XOPEN_REALTIME 10374 {"SC_XOPEN_REALTIME", _SC_XOPEN_REALTIME}, 10375#endif 10376#ifdef _SC_XOPEN_REALTIME_THREADS 10377 {"SC_XOPEN_REALTIME_THREADS", _SC_XOPEN_REALTIME_THREADS}, 10378#endif 10379#ifdef _SC_XOPEN_SHM 10380 {"SC_XOPEN_SHM", _SC_XOPEN_SHM}, 10381#endif 10382#ifdef _SC_XOPEN_UNIX 10383 {"SC_XOPEN_UNIX", _SC_XOPEN_UNIX}, 10384#endif 10385#ifdef _SC_XOPEN_VERSION 10386 {"SC_XOPEN_VERSION", _SC_XOPEN_VERSION}, 10387#endif 10388#ifdef _SC_XOPEN_XCU_VERSION 10389 {"SC_XOPEN_XCU_VERSION", _SC_XOPEN_XCU_VERSION}, 10390#endif 10391#ifdef _SC_XOPEN_XPG2 10392 {"SC_XOPEN_XPG2", _SC_XOPEN_XPG2}, 10393#endif 10394#ifdef _SC_XOPEN_XPG3 10395 {"SC_XOPEN_XPG3", _SC_XOPEN_XPG3}, 10396#endif 10397#ifdef _SC_XOPEN_XPG4 10398 {"SC_XOPEN_XPG4", _SC_XOPEN_XPG4}, 10399#endif 10400}; 10401 10402static int 10403conv_sysconf_confname(PyObject *arg, int *valuep) 10404{ 10405 return conv_confname(arg, valuep, posix_constants_sysconf, 10406 sizeof(posix_constants_sysconf) 10407 / sizeof(struct constdef)); 10408} 10409 10410 10411/*[clinic input] 10412os.sysconf -> long 10413 name: sysconf_confname 10414 / 10415 10416Return an integer-valued system configuration variable. 10417[clinic start generated code]*/ 10418 10419static long 10420os_sysconf_impl(PyModuleDef *module, int name) 10421/*[clinic end generated code: output=ed567306f58d69c4 input=279e3430a33f29e4]*/ 10422{ 10423 long value; 10424 10425 errno = 0; 10426 value = sysconf(name); 10427 if (value == -1 && errno != 0) 10428 posix_error(); 10429 return value; 10430} 10431#endif /* HAVE_SYSCONF */ 10432 10433 10434/* This code is used to ensure that the tables of configuration value names 10435 * are in sorted order as required by conv_confname(), and also to build 10436 * the exported dictionaries that are used to publish information about the 10437 * names available on the host platform. 10438 * 10439 * Sorting the table at runtime ensures that the table is properly ordered 10440 * when used, even for platforms we're not able to test on. It also makes 10441 * it easier to add additional entries to the tables. 10442 */ 10443 10444static int 10445cmp_constdefs(const void *v1, const void *v2) 10446{ 10447 const struct constdef *c1 = 10448 (const struct constdef *) v1; 10449 const struct constdef *c2 = 10450 (const struct constdef *) v2; 10451 10452 return strcmp(c1->name, c2->name); 10453} 10454 10455static int 10456setup_confname_table(struct constdef *table, size_t tablesize, 10457 char *tablename, PyObject *module) 10458{ 10459 PyObject *d = NULL; 10460 size_t i; 10461 10462 qsort(table, tablesize, sizeof(struct constdef), cmp_constdefs); 10463 d = PyDict_New(); 10464 if (d == NULL) 10465 return -1; 10466 10467 for (i=0; i < tablesize; ++i) { 10468 PyObject *o = PyLong_FromLong(table[i].value); 10469 if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) { 10470 Py_XDECREF(o); 10471 Py_DECREF(d); 10472 return -1; 10473 } 10474 Py_DECREF(o); 10475 } 10476 return PyModule_AddObject(module, tablename, d); 10477} 10478 10479/* Return -1 on failure, 0 on success. */ 10480static int 10481setup_confname_tables(PyObject *module) 10482{ 10483#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF) 10484 if (setup_confname_table(posix_constants_pathconf, 10485 sizeof(posix_constants_pathconf) 10486 / sizeof(struct constdef), 10487 "pathconf_names", module)) 10488 return -1; 10489#endif 10490#ifdef HAVE_CONFSTR 10491 if (setup_confname_table(posix_constants_confstr, 10492 sizeof(posix_constants_confstr) 10493 / sizeof(struct constdef), 10494 "confstr_names", module)) 10495 return -1; 10496#endif 10497#ifdef HAVE_SYSCONF 10498 if (setup_confname_table(posix_constants_sysconf, 10499 sizeof(posix_constants_sysconf) 10500 / sizeof(struct constdef), 10501 "sysconf_names", module)) 10502 return -1; 10503#endif 10504 return 0; 10505} 10506 10507 10508/*[clinic input] 10509os.abort 10510 10511Abort the interpreter immediately. 10512 10513This function 'dumps core' or otherwise fails in the hardest way possible 10514on the hosting operating system. This function never returns. 10515[clinic start generated code]*/ 10516 10517static PyObject * 10518os_abort_impl(PyModuleDef *module) 10519/*[clinic end generated code: output=486bb96647c299b3 input=cf2c7d98bc504047]*/ 10520{ 10521 abort(); 10522 /*NOTREACHED*/ 10523 Py_FatalError("abort() called from Python code didn't abort!"); 10524 return NULL; 10525} 10526 10527#ifdef MS_WINDOWS 10528/* AC 3.5: change to path_t? but that might change exceptions */ 10529PyDoc_STRVAR(win32_startfile__doc__, 10530"startfile(filepath [, operation])\n\ 10531\n\ 10532Start a file with its associated application.\n\ 10533\n\ 10534When \"operation\" is not specified or \"open\", this acts like\n\ 10535double-clicking the file in Explorer, or giving the file name as an\n\ 10536argument to the DOS \"start\" command: the file is opened with whatever\n\ 10537application (if any) its extension is associated.\n\ 10538When another \"operation\" is given, it specifies what should be done with\n\ 10539the file. A typical operation is \"print\".\n\ 10540\n\ 10541startfile returns as soon as the associated application is launched.\n\ 10542There is no option to wait for the application to close, and no way\n\ 10543to retrieve the application's exit status.\n\ 10544\n\ 10545The filepath is relative to the current directory. If you want to use\n\ 10546an absolute path, make sure the first character is not a slash (\"/\");\n\ 10547the underlying Win32 ShellExecute function doesn't work if it is."); 10548 10549/* Grab ShellExecute dynamically from shell32 */ 10550static int has_ShellExecute = -1; 10551static HINSTANCE (CALLBACK *Py_ShellExecuteA)(HWND, LPCSTR, LPCSTR, LPCSTR, 10552 LPCSTR, INT); 10553static HINSTANCE (CALLBACK *Py_ShellExecuteW)(HWND, LPCWSTR, LPCWSTR, LPCWSTR, 10554 LPCWSTR, INT); 10555static int 10556check_ShellExecute() 10557{ 10558 HINSTANCE hShell32; 10559 10560 /* only recheck */ 10561 if (-1 == has_ShellExecute) { 10562 Py_BEGIN_ALLOW_THREADS 10563 hShell32 = LoadLibraryW(L"SHELL32"); 10564 Py_END_ALLOW_THREADS 10565 if (hShell32) { 10566 *(FARPROC*)&Py_ShellExecuteA = GetProcAddress(hShell32, 10567 "ShellExecuteA"); 10568 *(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32, 10569 "ShellExecuteW"); 10570 has_ShellExecute = Py_ShellExecuteA && 10571 Py_ShellExecuteW; 10572 } else { 10573 has_ShellExecute = 0; 10574 } 10575 } 10576 return has_ShellExecute; 10577} 10578 10579 10580static PyObject * 10581win32_startfile(PyObject *self, PyObject *args) 10582{ 10583 PyObject *ofilepath; 10584 char *filepath; 10585 char *operation = NULL; 10586 wchar_t *wpath, *woperation; 10587 HINSTANCE rc; 10588 10589 PyObject *unipath, *uoperation = NULL; 10590 10591 if(!check_ShellExecute()) { 10592 /* If the OS doesn't have ShellExecute, return a 10593 NotImplementedError. */ 10594 return PyErr_Format(PyExc_NotImplementedError, 10595 "startfile not available on this platform"); 10596 } 10597 10598 if (!PyArg_ParseTuple(args, "U|s:startfile", 10599 &unipath, &operation)) { 10600 PyErr_Clear(); 10601 goto normal; 10602 } 10603 10604 if (operation) { 10605 uoperation = PyUnicode_DecodeASCII(operation, 10606 strlen(operation), NULL); 10607 if (!uoperation) { 10608 PyErr_Clear(); 10609 operation = NULL; 10610 goto normal; 10611 } 10612 } 10613 10614 wpath = PyUnicode_AsUnicode(unipath); 10615 if (wpath == NULL) 10616 goto normal; 10617 if (uoperation) { 10618 woperation = PyUnicode_AsUnicode(uoperation); 10619 if (woperation == NULL) 10620 goto normal; 10621 } 10622 else 10623 woperation = NULL; 10624 10625 Py_BEGIN_ALLOW_THREADS 10626 rc = Py_ShellExecuteW((HWND)0, woperation, wpath, 10627 NULL, NULL, SW_SHOWNORMAL); 10628 Py_END_ALLOW_THREADS 10629 10630 Py_XDECREF(uoperation); 10631 if (rc <= (HINSTANCE)32) { 10632 win32_error_object("startfile", unipath); 10633 return NULL; 10634 } 10635 Py_INCREF(Py_None); 10636 return Py_None; 10637 10638normal: 10639 if (!PyArg_ParseTuple(args, "O&|s:startfile", 10640 PyUnicode_FSConverter, &ofilepath, 10641 &operation)) 10642 return NULL; 10643 if (win32_warn_bytes_api()) { 10644 Py_DECREF(ofilepath); 10645 return NULL; 10646 } 10647 filepath = PyBytes_AsString(ofilepath); 10648 Py_BEGIN_ALLOW_THREADS 10649 rc = Py_ShellExecuteA((HWND)0, operation, filepath, 10650 NULL, NULL, SW_SHOWNORMAL); 10651 Py_END_ALLOW_THREADS 10652 if (rc <= (HINSTANCE)32) { 10653 PyObject *errval = win32_error("startfile", filepath); 10654 Py_DECREF(ofilepath); 10655 return errval; 10656 } 10657 Py_DECREF(ofilepath); 10658 Py_INCREF(Py_None); 10659 return Py_None; 10660} 10661#endif /* MS_WINDOWS */ 10662 10663 10664#ifdef HAVE_GETLOADAVG 10665/*[clinic input] 10666os.getloadavg 10667 10668Return average recent system load information. 10669 10670Return the number of processes in the system run queue averaged over 10671the last 1, 5, and 15 minutes as a tuple of three floats. 10672Raises OSError if the load average was unobtainable. 10673[clinic start generated code]*/ 10674 10675static PyObject * 10676os_getloadavg_impl(PyModuleDef *module) 10677/*[clinic end generated code: output=2b64c5b675d74c14 input=3d6d826b76d8a34e]*/ 10678{ 10679 double loadavg[3]; 10680 if (getloadavg(loadavg, 3)!=3) { 10681 PyErr_SetString(PyExc_OSError, "Load averages are unobtainable"); 10682 return NULL; 10683 } else 10684 return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]); 10685} 10686#endif /* HAVE_GETLOADAVG */ 10687 10688 10689/*[clinic input] 10690os.device_encoding 10691 fd: int 10692 10693Return a string describing the encoding of a terminal's file descriptor. 10694 10695The file descriptor must be attached to a terminal. 10696If the device is not a terminal, return None. 10697[clinic start generated code]*/ 10698 10699static PyObject * 10700os_device_encoding_impl(PyModuleDef *module, int fd) 10701/*[clinic end generated code: output=34f14e33468419c1 input=9e1d4a42b66df312]*/ 10702{ 10703 return _Py_device_encoding(fd); 10704} 10705 10706 10707#ifdef HAVE_SETRESUID 10708/*[clinic input] 10709os.setresuid 10710 10711 ruid: uid_t 10712 euid: uid_t 10713 suid: uid_t 10714 / 10715 10716Set the current process's real, effective, and saved user ids. 10717[clinic start generated code]*/ 10718 10719static PyObject * 10720os_setresuid_impl(PyModuleDef *module, uid_t ruid, uid_t euid, uid_t suid) 10721/*[clinic end generated code: output=92cc330812c6ed0f input=9e33cb79a82792f3]*/ 10722{ 10723 if (setresuid(ruid, euid, suid) < 0) 10724 return posix_error(); 10725 Py_RETURN_NONE; 10726} 10727#endif /* HAVE_SETRESUID */ 10728 10729 10730#ifdef HAVE_SETRESGID 10731/*[clinic input] 10732os.setresgid 10733 10734 rgid: gid_t 10735 egid: gid_t 10736 sgid: gid_t 10737 / 10738 10739Set the current process's real, effective, and saved group ids. 10740[clinic start generated code]*/ 10741 10742static PyObject * 10743os_setresgid_impl(PyModuleDef *module, gid_t rgid, gid_t egid, gid_t sgid) 10744/*[clinic end generated code: output=e91dc4842a604429 input=33e9e0785ef426b1]*/ 10745{ 10746 if (setresgid(rgid, egid, sgid) < 0) 10747 return posix_error(); 10748 Py_RETURN_NONE; 10749} 10750#endif /* HAVE_SETRESGID */ 10751 10752 10753#ifdef HAVE_GETRESUID 10754/*[clinic input] 10755os.getresuid 10756 10757Return a tuple of the current process's real, effective, and saved user ids. 10758[clinic start generated code]*/ 10759 10760static PyObject * 10761os_getresuid_impl(PyModuleDef *module) 10762/*[clinic end generated code: output=9ddef62faae8e477 input=41ccfa8e1f6517ad]*/ 10763{ 10764 uid_t ruid, euid, suid; 10765 if (getresuid(&ruid, &euid, &suid) < 0) 10766 return posix_error(); 10767 return Py_BuildValue("(NNN)", _PyLong_FromUid(ruid), 10768 _PyLong_FromUid(euid), 10769 _PyLong_FromUid(suid)); 10770} 10771#endif /* HAVE_GETRESUID */ 10772 10773 10774#ifdef HAVE_GETRESGID 10775/*[clinic input] 10776os.getresgid 10777 10778Return a tuple of the current process's real, effective, and saved group ids. 10779[clinic start generated code]*/ 10780 10781static PyObject * 10782os_getresgid_impl(PyModuleDef *module) 10783/*[clinic end generated code: output=e1a553cbcf16234c input=517e68db9ca32df6]*/ 10784{ 10785 gid_t rgid, egid, sgid; 10786 if (getresgid(&rgid, &egid, &sgid) < 0) 10787 return posix_error(); 10788 return Py_BuildValue("(NNN)", _PyLong_FromGid(rgid), 10789 _PyLong_FromGid(egid), 10790 _PyLong_FromGid(sgid)); 10791} 10792#endif /* HAVE_GETRESGID */ 10793 10794 10795#ifdef USE_XATTRS 10796/*[clinic input] 10797os.getxattr 10798 10799 path: path_t(allow_fd=True) 10800 attribute: path_t 10801 * 10802 follow_symlinks: bool = True 10803 10804Return the value of extended attribute attribute on path. 10805 10806path may be either a string or an open file descriptor. 10807If follow_symlinks is False, and the last element of the path is a symbolic 10808 link, getxattr will examine the symbolic link itself instead of the file 10809 the link points to. 10810 10811[clinic start generated code]*/ 10812 10813static PyObject * 10814os_getxattr_impl(PyModuleDef *module, path_t *path, path_t *attribute, 10815 int follow_symlinks) 10816/*[clinic end generated code: output=cf2cede74bd5d412 input=8c8ea3bab78d89c2]*/ 10817{ 10818 Py_ssize_t i; 10819 PyObject *buffer = NULL; 10820 10821 if (fd_and_follow_symlinks_invalid("getxattr", path->fd, follow_symlinks)) 10822 return NULL; 10823 10824 for (i = 0; ; i++) { 10825 void *ptr; 10826 ssize_t result; 10827 static Py_ssize_t buffer_sizes[] = {128, XATTR_SIZE_MAX, 0}; 10828 Py_ssize_t buffer_size = buffer_sizes[i]; 10829 if (!buffer_size) { 10830 path_error(path); 10831 return NULL; 10832 } 10833 buffer = PyBytes_FromStringAndSize(NULL, buffer_size); 10834 if (!buffer) 10835 return NULL; 10836 ptr = PyBytes_AS_STRING(buffer); 10837 10838 Py_BEGIN_ALLOW_THREADS; 10839 if (path->fd >= 0) 10840 result = fgetxattr(path->fd, attribute->narrow, ptr, buffer_size); 10841 else if (follow_symlinks) 10842 result = getxattr(path->narrow, attribute->narrow, ptr, buffer_size); 10843 else 10844 result = lgetxattr(path->narrow, attribute->narrow, ptr, buffer_size); 10845 Py_END_ALLOW_THREADS; 10846 10847 if (result < 0) { 10848 Py_DECREF(buffer); 10849 if (errno == ERANGE) 10850 continue; 10851 path_error(path); 10852 return NULL; 10853 } 10854 10855 if (result != buffer_size) { 10856 /* Can only shrink. */ 10857 _PyBytes_Resize(&buffer, result); 10858 } 10859 break; 10860 } 10861 10862 return buffer; 10863} 10864 10865 10866/*[clinic input] 10867os.setxattr 10868 10869 path: path_t(allow_fd=True) 10870 attribute: path_t 10871 value: Py_buffer 10872 flags: int = 0 10873 * 10874 follow_symlinks: bool = True 10875 10876Set extended attribute attribute on path to value. 10877 10878path may be either a string or an open file descriptor. 10879If follow_symlinks is False, and the last element of the path is a symbolic 10880 link, setxattr will modify the symbolic link itself instead of the file 10881 the link points to. 10882 10883[clinic start generated code]*/ 10884 10885static PyObject * 10886os_setxattr_impl(PyModuleDef *module, path_t *path, path_t *attribute, 10887 Py_buffer *value, int flags, int follow_symlinks) 10888/*[clinic end generated code: output=1b395ef82880fea0 input=f0d26833992015c2]*/ 10889{ 10890 ssize_t result; 10891 10892 if (fd_and_follow_symlinks_invalid("setxattr", path->fd, follow_symlinks)) 10893 return NULL; 10894 10895 Py_BEGIN_ALLOW_THREADS; 10896 if (path->fd > -1) 10897 result = fsetxattr(path->fd, attribute->narrow, 10898 value->buf, value->len, flags); 10899 else if (follow_symlinks) 10900 result = setxattr(path->narrow, attribute->narrow, 10901 value->buf, value->len, flags); 10902 else 10903 result = lsetxattr(path->narrow, attribute->narrow, 10904 value->buf, value->len, flags); 10905 Py_END_ALLOW_THREADS; 10906 10907 if (result) { 10908 path_error(path); 10909 return NULL; 10910 } 10911 10912 Py_RETURN_NONE; 10913} 10914 10915 10916/*[clinic input] 10917os.removexattr 10918 10919 path: path_t(allow_fd=True) 10920 attribute: path_t 10921 * 10922 follow_symlinks: bool = True 10923 10924Remove extended attribute attribute on path. 10925 10926path may be either a string or an open file descriptor. 10927If follow_symlinks is False, and the last element of the path is a symbolic 10928 link, removexattr will modify the symbolic link itself instead of the file 10929 the link points to. 10930 10931[clinic start generated code]*/ 10932 10933static PyObject * 10934os_removexattr_impl(PyModuleDef *module, path_t *path, path_t *attribute, 10935 int follow_symlinks) 10936/*[clinic end generated code: output=f92bb39ab992650d input=cdb54834161e3329]*/ 10937{ 10938 ssize_t result; 10939 10940 if (fd_and_follow_symlinks_invalid("removexattr", path->fd, follow_symlinks)) 10941 return NULL; 10942 10943 Py_BEGIN_ALLOW_THREADS; 10944 if (path->fd > -1) 10945 result = fremovexattr(path->fd, attribute->narrow); 10946 else if (follow_symlinks) 10947 result = removexattr(path->narrow, attribute->narrow); 10948 else 10949 result = lremovexattr(path->narrow, attribute->narrow); 10950 Py_END_ALLOW_THREADS; 10951 10952 if (result) { 10953 return path_error(path); 10954 } 10955 10956 Py_RETURN_NONE; 10957} 10958 10959 10960/*[clinic input] 10961os.listxattr 10962 10963 path: path_t(allow_fd=True, nullable=True) = None 10964 * 10965 follow_symlinks: bool = True 10966 10967Return a list of extended attributes on path. 10968 10969path may be either None, a string, or an open file descriptor. 10970if path is None, listxattr will examine the current directory. 10971If follow_symlinks is False, and the last element of the path is a symbolic 10972 link, listxattr will examine the symbolic link itself instead of the file 10973 the link points to. 10974[clinic start generated code]*/ 10975 10976static PyObject * 10977os_listxattr_impl(PyModuleDef *module, path_t *path, int follow_symlinks) 10978/*[clinic end generated code: output=a87ad6ce56e42a4f input=08cca53ac0b07c13]*/ 10979{ 10980 Py_ssize_t i; 10981 PyObject *result = NULL; 10982 const char *name; 10983 char *buffer = NULL; 10984 10985 if (fd_and_follow_symlinks_invalid("listxattr", path->fd, follow_symlinks)) 10986 goto exit; 10987 10988 name = path->narrow ? path->narrow : "."; 10989 10990 for (i = 0; ; i++) { 10991 char *start, *trace, *end; 10992 ssize_t length; 10993 static Py_ssize_t buffer_sizes[] = { 256, XATTR_LIST_MAX, 0 }; 10994 Py_ssize_t buffer_size = buffer_sizes[i]; 10995 if (!buffer_size) { 10996 /* ERANGE */ 10997 path_error(path); 10998 break; 10999 } 11000 buffer = PyMem_MALLOC(buffer_size); 11001 if (!buffer) { 11002 PyErr_NoMemory(); 11003 break; 11004 } 11005 11006 Py_BEGIN_ALLOW_THREADS; 11007 if (path->fd > -1) 11008 length = flistxattr(path->fd, buffer, buffer_size); 11009 else if (follow_symlinks) 11010 length = listxattr(name, buffer, buffer_size); 11011 else 11012 length = llistxattr(name, buffer, buffer_size); 11013 Py_END_ALLOW_THREADS; 11014 11015 if (length < 0) { 11016 if (errno == ERANGE) { 11017 PyMem_FREE(buffer); 11018 buffer = NULL; 11019 continue; 11020 } 11021 path_error(path); 11022 break; 11023 } 11024 11025 result = PyList_New(0); 11026 if (!result) { 11027 goto exit; 11028 } 11029 11030 end = buffer + length; 11031 for (trace = start = buffer; trace != end; trace++) { 11032 if (!*trace) { 11033 int error; 11034 PyObject *attribute = PyUnicode_DecodeFSDefaultAndSize(start, 11035 trace - start); 11036 if (!attribute) { 11037 Py_DECREF(result); 11038 result = NULL; 11039 goto exit; 11040 } 11041 error = PyList_Append(result, attribute); 11042 Py_DECREF(attribute); 11043 if (error) { 11044 Py_DECREF(result); 11045 result = NULL; 11046 goto exit; 11047 } 11048 start = trace + 1; 11049 } 11050 } 11051 break; 11052 } 11053exit: 11054 if (buffer) 11055 PyMem_FREE(buffer); 11056 return result; 11057} 11058#endif /* USE_XATTRS */ 11059 11060 11061/*[clinic input] 11062os.urandom 11063 11064 size: Py_ssize_t 11065 / 11066 11067Return a bytes object containing random bytes suitable for cryptographic use. 11068[clinic start generated code]*/ 11069 11070static PyObject * 11071os_urandom_impl(PyModuleDef *module, Py_ssize_t size) 11072/*[clinic end generated code: output=e0011f021501f03b input=4067cdb1b6776c29]*/ 11073{ 11074 PyObject *bytes; 11075 int result; 11076 11077 if (size < 0) 11078 return PyErr_Format(PyExc_ValueError, 11079 "negative argument not allowed"); 11080 bytes = PyBytes_FromStringAndSize(NULL, size); 11081 if (bytes == NULL) 11082 return NULL; 11083 11084 result = _PyOS_URandom(PyBytes_AS_STRING(bytes), 11085 PyBytes_GET_SIZE(bytes)); 11086 if (result == -1) { 11087 Py_DECREF(bytes); 11088 return NULL; 11089 } 11090 return bytes; 11091} 11092 11093/* Terminal size querying */ 11094 11095static PyTypeObject TerminalSizeType; 11096 11097PyDoc_STRVAR(TerminalSize_docstring, 11098 "A tuple of (columns, lines) for holding terminal window size"); 11099 11100static PyStructSequence_Field TerminalSize_fields[] = { 11101 {"columns", "width of the terminal window in characters"}, 11102 {"lines", "height of the terminal window in characters"}, 11103 {NULL, NULL} 11104}; 11105 11106static PyStructSequence_Desc TerminalSize_desc = { 11107 "os.terminal_size", 11108 TerminalSize_docstring, 11109 TerminalSize_fields, 11110 2, 11111}; 11112 11113#if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) 11114/* AC 3.5: fd should accept None */ 11115PyDoc_STRVAR(termsize__doc__, 11116 "Return the size of the terminal window as (columns, lines).\n" \ 11117 "\n" \ 11118 "The optional argument fd (default standard output) specifies\n" \ 11119 "which file descriptor should be queried.\n" \ 11120 "\n" \ 11121 "If the file descriptor is not connected to a terminal, an OSError\n" \ 11122 "is thrown.\n" \ 11123 "\n" \ 11124 "This function will only be defined if an implementation is\n" \ 11125 "available for this system.\n" \ 11126 "\n" \ 11127 "shutil.get_terminal_size is the high-level function which should \n" \ 11128 "normally be used, os.get_terminal_size is the low-level implementation."); 11129 11130static PyObject* 11131get_terminal_size(PyObject *self, PyObject *args) 11132{ 11133 int columns, lines; 11134 PyObject *termsize; 11135 11136 int fd = fileno(stdout); 11137 /* Under some conditions stdout may not be connected and 11138 * fileno(stdout) may point to an invalid file descriptor. For example 11139 * GUI apps don't have valid standard streams by default. 11140 * 11141 * If this happens, and the optional fd argument is not present, 11142 * the ioctl below will fail returning EBADF. This is what we want. 11143 */ 11144 11145 if (!PyArg_ParseTuple(args, "|i", &fd)) 11146 return NULL; 11147 11148#ifdef TERMSIZE_USE_IOCTL 11149 { 11150 struct winsize w; 11151 if (ioctl(fd, TIOCGWINSZ, &w)) 11152 return PyErr_SetFromErrno(PyExc_OSError); 11153 columns = w.ws_col; 11154 lines = w.ws_row; 11155 } 11156#endif /* TERMSIZE_USE_IOCTL */ 11157 11158#ifdef TERMSIZE_USE_CONIO 11159 { 11160 DWORD nhandle; 11161 HANDLE handle; 11162 CONSOLE_SCREEN_BUFFER_INFO csbi; 11163 switch (fd) { 11164 case 0: nhandle = STD_INPUT_HANDLE; 11165 break; 11166 case 1: nhandle = STD_OUTPUT_HANDLE; 11167 break; 11168 case 2: nhandle = STD_ERROR_HANDLE; 11169 break; 11170 default: 11171 return PyErr_Format(PyExc_ValueError, "bad file descriptor"); 11172 } 11173 handle = GetStdHandle(nhandle); 11174 if (handle == NULL) 11175 return PyErr_Format(PyExc_OSError, "handle cannot be retrieved"); 11176 if (handle == INVALID_HANDLE_VALUE) 11177 return PyErr_SetFromWindowsErr(0); 11178 11179 if (!GetConsoleScreenBufferInfo(handle, &csbi)) 11180 return PyErr_SetFromWindowsErr(0); 11181 11182 columns = csbi.srWindow.Right - csbi.srWindow.Left + 1; 11183 lines = csbi.srWindow.Bottom - csbi.srWindow.Top + 1; 11184 } 11185#endif /* TERMSIZE_USE_CONIO */ 11186 11187 termsize = PyStructSequence_New(&TerminalSizeType); 11188 if (termsize == NULL) 11189 return NULL; 11190 PyStructSequence_SET_ITEM(termsize, 0, PyLong_FromLong(columns)); 11191 PyStructSequence_SET_ITEM(termsize, 1, PyLong_FromLong(lines)); 11192 if (PyErr_Occurred()) { 11193 Py_DECREF(termsize); 11194 return NULL; 11195 } 11196 return termsize; 11197} 11198#endif /* defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) */ 11199 11200 11201/*[clinic input] 11202os.cpu_count 11203 11204Return the number of CPUs in the system; return None if indeterminable. 11205 11206This number is not equivalent to the number of CPUs the current process can 11207use. The number of usable CPUs can be obtained with 11208``len(os.sched_getaffinity(0))`` 11209[clinic start generated code]*/ 11210 11211static PyObject * 11212os_cpu_count_impl(PyModuleDef *module) 11213/*[clinic end generated code: output=c59ee7f6bce832b8 input=e7c8f4ba6dbbadd3]*/ 11214{ 11215 int ncpu = 0; 11216#ifdef MS_WINDOWS 11217 SYSTEM_INFO sysinfo; 11218 GetSystemInfo(&sysinfo); 11219 ncpu = sysinfo.dwNumberOfProcessors; 11220#elif defined(__hpux) 11221 ncpu = mpctl(MPC_GETNUMSPUS, NULL, NULL); 11222#elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN) 11223 ncpu = sysconf(_SC_NPROCESSORS_ONLN); 11224#elif defined(__DragonFly__) || \ 11225 defined(__OpenBSD__) || \ 11226 defined(__FreeBSD__) || \ 11227 defined(__NetBSD__) || \ 11228 defined(__APPLE__) 11229 int mib[2]; 11230 size_t len = sizeof(ncpu); 11231 mib[0] = CTL_HW; 11232 mib[1] = HW_NCPU; 11233 if (sysctl(mib, 2, &ncpu, &len, NULL, 0) != 0) 11234 ncpu = 0; 11235#endif 11236 if (ncpu >= 1) 11237 return PyLong_FromLong(ncpu); 11238 else 11239 Py_RETURN_NONE; 11240} 11241 11242 11243/*[clinic input] 11244os.get_inheritable -> bool 11245 11246 fd: int 11247 / 11248 11249Get the close-on-exe flag of the specified file descriptor. 11250[clinic start generated code]*/ 11251 11252static int 11253os_get_inheritable_impl(PyModuleDef *module, int fd) 11254/*[clinic end generated code: output=36110bb36efaa21e input=89ac008dc9ab6b95]*/ 11255{ 11256 int return_value; 11257 if (!_PyVerify_fd(fd)) { 11258 posix_error(); 11259 return -1; 11260 } 11261 11262 _Py_BEGIN_SUPPRESS_IPH 11263 return_value = _Py_get_inheritable(fd); 11264 _Py_END_SUPPRESS_IPH 11265 return return_value; 11266} 11267 11268 11269/*[clinic input] 11270os.set_inheritable 11271 fd: int 11272 inheritable: int 11273 / 11274 11275Set the inheritable flag of the specified file descriptor. 11276[clinic start generated code]*/ 11277 11278static PyObject * 11279os_set_inheritable_impl(PyModuleDef *module, int fd, int inheritable) 11280/*[clinic end generated code: output=2ac5c6ce8623f045 input=9ceaead87a1e2402]*/ 11281{ 11282 int result; 11283 if (!_PyVerify_fd(fd)) 11284 return posix_error(); 11285 11286 _Py_BEGIN_SUPPRESS_IPH 11287 result = _Py_set_inheritable(fd, inheritable, NULL); 11288 _Py_END_SUPPRESS_IPH 11289 if (result < 0) 11290 return NULL; 11291 Py_RETURN_NONE; 11292} 11293 11294 11295#ifdef MS_WINDOWS 11296/*[clinic input] 11297os.get_handle_inheritable -> bool 11298 handle: Py_intptr_t 11299 / 11300 11301Get the close-on-exe flag of the specified file descriptor. 11302[clinic start generated code]*/ 11303 11304static int 11305os_get_handle_inheritable_impl(PyModuleDef *module, Py_intptr_t handle) 11306/*[clinic end generated code: output=3b7b3e1b43f312b6 input=5f7759443aae3dc5]*/ 11307{ 11308 DWORD flags; 11309 11310 if (!GetHandleInformation((HANDLE)handle, &flags)) { 11311 PyErr_SetFromWindowsErr(0); 11312 return -1; 11313 } 11314 11315 return flags & HANDLE_FLAG_INHERIT; 11316} 11317 11318 11319/*[clinic input] 11320os.set_handle_inheritable 11321 handle: Py_intptr_t 11322 inheritable: bool 11323 / 11324 11325Set the inheritable flag of the specified handle. 11326[clinic start generated code]*/ 11327 11328static PyObject * 11329os_set_handle_inheritable_impl(PyModuleDef *module, Py_intptr_t handle, 11330 int inheritable) 11331/*[clinic end generated code: output=d2e111a96c9eb296 input=e64b2b2730469def]*/ 11332{ 11333 DWORD flags = inheritable ? HANDLE_FLAG_INHERIT : 0; 11334 if (!SetHandleInformation((HANDLE)handle, HANDLE_FLAG_INHERIT, flags)) { 11335 PyErr_SetFromWindowsErr(0); 11336 return NULL; 11337 } 11338 Py_RETURN_NONE; 11339} 11340#endif /* MS_WINDOWS */ 11341 11342#ifndef MS_WINDOWS 11343PyDoc_STRVAR(get_blocking__doc__, 11344 "get_blocking(fd) -> bool\n" \ 11345 "\n" \ 11346 "Get the blocking mode of the file descriptor:\n" \ 11347 "False if the O_NONBLOCK flag is set, True if the flag is cleared."); 11348 11349static PyObject* 11350posix_get_blocking(PyObject *self, PyObject *args) 11351{ 11352 int fd; 11353 int blocking; 11354 11355 if (!PyArg_ParseTuple(args, "i:get_blocking", &fd)) 11356 return NULL; 11357 11358 if (!_PyVerify_fd(fd)) 11359 return posix_error(); 11360 11361 _Py_BEGIN_SUPPRESS_IPH 11362 blocking = _Py_get_blocking(fd); 11363 _Py_END_SUPPRESS_IPH 11364 if (blocking < 0) 11365 return NULL; 11366 return PyBool_FromLong(blocking); 11367} 11368 11369PyDoc_STRVAR(set_blocking__doc__, 11370 "set_blocking(fd, blocking)\n" \ 11371 "\n" \ 11372 "Set the blocking mode of the specified file descriptor.\n" \ 11373 "Set the O_NONBLOCK flag if blocking is False,\n" \ 11374 "clear the O_NONBLOCK flag otherwise."); 11375 11376static PyObject* 11377posix_set_blocking(PyObject *self, PyObject *args) 11378{ 11379 int fd, blocking, result; 11380 11381 if (!PyArg_ParseTuple(args, "ii:set_blocking", &fd, &blocking)) 11382 return NULL; 11383 11384 if (!_PyVerify_fd(fd)) 11385 return posix_error(); 11386 11387 _Py_BEGIN_SUPPRESS_IPH 11388 result = _Py_set_blocking(fd, blocking); 11389 _Py_END_SUPPRESS_IPH 11390 if (result < 0) 11391 return NULL; 11392 Py_RETURN_NONE; 11393} 11394#endif /* !MS_WINDOWS */ 11395 11396 11397PyDoc_STRVAR(posix_scandir__doc__, 11398"scandir(path='.') -> iterator of DirEntry objects for given path"); 11399 11400static char *follow_symlinks_keywords[] = {"follow_symlinks", NULL}; 11401 11402typedef struct { 11403 PyObject_HEAD 11404 PyObject *name; 11405 PyObject *path; 11406 PyObject *stat; 11407 PyObject *lstat; 11408#ifdef MS_WINDOWS 11409 struct _Py_stat_struct win32_lstat; 11410 __int64 win32_file_index; 11411 int got_file_index; 11412#else /* POSIX */ 11413#ifdef HAVE_DIRENT_D_TYPE 11414 unsigned char d_type; 11415#endif 11416 ino_t d_ino; 11417#endif 11418} DirEntry; 11419 11420static void 11421DirEntry_dealloc(DirEntry *entry) 11422{ 11423 Py_XDECREF(entry->name); 11424 Py_XDECREF(entry->path); 11425 Py_XDECREF(entry->stat); 11426 Py_XDECREF(entry->lstat); 11427 Py_TYPE(entry)->tp_free((PyObject *)entry); 11428} 11429 11430/* Forward reference */ 11431static int 11432DirEntry_test_mode(DirEntry *self, int follow_symlinks, unsigned short mode_bits); 11433 11434/* Set exception and return -1 on error, 0 for False, 1 for True */ 11435static int 11436DirEntry_is_symlink(DirEntry *self) 11437{ 11438#ifdef MS_WINDOWS 11439 return (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK; 11440#elif defined(HAVE_DIRENT_D_TYPE) 11441 /* POSIX */ 11442 if (self->d_type != DT_UNKNOWN) 11443 return self->d_type == DT_LNK; 11444 else 11445 return DirEntry_test_mode(self, 0, S_IFLNK); 11446#else 11447 /* POSIX without d_type */ 11448 return DirEntry_test_mode(self, 0, S_IFLNK); 11449#endif 11450} 11451 11452static PyObject * 11453DirEntry_py_is_symlink(DirEntry *self) 11454{ 11455 int result; 11456 11457 result = DirEntry_is_symlink(self); 11458 if (result == -1) 11459 return NULL; 11460 return PyBool_FromLong(result); 11461} 11462 11463static PyObject * 11464DirEntry_fetch_stat(DirEntry *self, int follow_symlinks) 11465{ 11466 int result; 11467 struct _Py_stat_struct st; 11468 11469#ifdef MS_WINDOWS 11470 wchar_t *path; 11471 11472 path = PyUnicode_AsUnicode(self->path); 11473 if (!path) 11474 return NULL; 11475 11476 if (follow_symlinks) 11477 result = win32_stat_w(path, &st); 11478 else 11479 result = win32_lstat_w(path, &st); 11480 11481 if (result != 0) { 11482 return PyErr_SetExcFromWindowsErrWithFilenameObject(PyExc_OSError, 11483 0, self->path); 11484 } 11485#else /* POSIX */ 11486 PyObject *bytes; 11487 char *path; 11488 11489 if (!PyUnicode_FSConverter(self->path, &bytes)) 11490 return NULL; 11491 path = PyBytes_AS_STRING(bytes); 11492 11493 if (follow_symlinks) 11494 result = STAT(path, &st); 11495 else 11496 result = LSTAT(path, &st); 11497 Py_DECREF(bytes); 11498 11499 if (result != 0) 11500 return PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, self->path); 11501#endif 11502 11503 return _pystat_fromstructstat(&st); 11504} 11505 11506static PyObject * 11507DirEntry_get_lstat(DirEntry *self) 11508{ 11509 if (!self->lstat) { 11510#ifdef MS_WINDOWS 11511 self->lstat = _pystat_fromstructstat(&self->win32_lstat); 11512#else /* POSIX */ 11513 self->lstat = DirEntry_fetch_stat(self, 0); 11514#endif 11515 } 11516 Py_XINCREF(self->lstat); 11517 return self->lstat; 11518} 11519 11520static PyObject * 11521DirEntry_get_stat(DirEntry *self, int follow_symlinks) 11522{ 11523 if (!follow_symlinks) 11524 return DirEntry_get_lstat(self); 11525 11526 if (!self->stat) { 11527 int result = DirEntry_is_symlink(self); 11528 if (result == -1) 11529 return NULL; 11530 else if (result) 11531 self->stat = DirEntry_fetch_stat(self, 1); 11532 else 11533 self->stat = DirEntry_get_lstat(self); 11534 } 11535 11536 Py_XINCREF(self->stat); 11537 return self->stat; 11538} 11539 11540static PyObject * 11541DirEntry_stat(DirEntry *self, PyObject *args, PyObject *kwargs) 11542{ 11543 int follow_symlinks = 1; 11544 11545 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|$p:DirEntry.stat", 11546 follow_symlinks_keywords, &follow_symlinks)) 11547 return NULL; 11548 11549 return DirEntry_get_stat(self, follow_symlinks); 11550} 11551 11552/* Set exception and return -1 on error, 0 for False, 1 for True */ 11553static int 11554DirEntry_test_mode(DirEntry *self, int follow_symlinks, unsigned short mode_bits) 11555{ 11556 PyObject *stat = NULL; 11557 PyObject *st_mode = NULL; 11558 long mode; 11559 int result; 11560#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE) 11561 int is_symlink; 11562 int need_stat; 11563#endif 11564#ifdef MS_WINDOWS 11565 unsigned long dir_bits; 11566#endif 11567 _Py_IDENTIFIER(st_mode); 11568 11569#ifdef MS_WINDOWS 11570 is_symlink = (self->win32_lstat.st_mode & S_IFMT) == S_IFLNK; 11571 need_stat = follow_symlinks && is_symlink; 11572#elif defined(HAVE_DIRENT_D_TYPE) 11573 is_symlink = self->d_type == DT_LNK; 11574 need_stat = self->d_type == DT_UNKNOWN || (follow_symlinks && is_symlink); 11575#endif 11576 11577#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE) 11578 if (need_stat) { 11579#endif 11580 stat = DirEntry_get_stat(self, follow_symlinks); 11581 if (!stat) { 11582 if (PyErr_ExceptionMatches(PyExc_FileNotFoundError)) { 11583 /* If file doesn't exist (anymore), then return False 11584 (i.e., say it's not a file/directory) */ 11585 PyErr_Clear(); 11586 return 0; 11587 } 11588 goto error; 11589 } 11590 st_mode = _PyObject_GetAttrId(stat, &PyId_st_mode); 11591 if (!st_mode) 11592 goto error; 11593 11594 mode = PyLong_AsLong(st_mode); 11595 if (mode == -1 && PyErr_Occurred()) 11596 goto error; 11597 Py_CLEAR(st_mode); 11598 Py_CLEAR(stat); 11599 result = (mode & S_IFMT) == mode_bits; 11600#if defined(MS_WINDOWS) || defined(HAVE_DIRENT_D_TYPE) 11601 } 11602 else if (is_symlink) { 11603 assert(mode_bits != S_IFLNK); 11604 result = 0; 11605 } 11606 else { 11607 assert(mode_bits == S_IFDIR || mode_bits == S_IFREG); 11608#ifdef MS_WINDOWS 11609 dir_bits = self->win32_lstat.st_file_attributes & FILE_ATTRIBUTE_DIRECTORY; 11610 if (mode_bits == S_IFDIR) 11611 result = dir_bits != 0; 11612 else 11613 result = dir_bits == 0; 11614#else /* POSIX */ 11615 if (mode_bits == S_IFDIR) 11616 result = self->d_type == DT_DIR; 11617 else 11618 result = self->d_type == DT_REG; 11619#endif 11620 } 11621#endif 11622 11623 return result; 11624 11625error: 11626 Py_XDECREF(st_mode); 11627 Py_XDECREF(stat); 11628 return -1; 11629} 11630 11631static PyObject * 11632DirEntry_py_test_mode(DirEntry *self, int follow_symlinks, unsigned short mode_bits) 11633{ 11634 int result; 11635 11636 result = DirEntry_test_mode(self, follow_symlinks, mode_bits); 11637 if (result == -1) 11638 return NULL; 11639 return PyBool_FromLong(result); 11640} 11641 11642static PyObject * 11643DirEntry_is_dir(DirEntry *self, PyObject *args, PyObject *kwargs) 11644{ 11645 int follow_symlinks = 1; 11646 11647 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|$p:DirEntry.is_dir", 11648 follow_symlinks_keywords, &follow_symlinks)) 11649 return NULL; 11650 11651 return DirEntry_py_test_mode(self, follow_symlinks, S_IFDIR); 11652} 11653 11654static PyObject * 11655DirEntry_is_file(DirEntry *self, PyObject *args, PyObject *kwargs) 11656{ 11657 int follow_symlinks = 1; 11658 11659 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|$p:DirEntry.is_file", 11660 follow_symlinks_keywords, &follow_symlinks)) 11661 return NULL; 11662 11663 return DirEntry_py_test_mode(self, follow_symlinks, S_IFREG); 11664} 11665 11666static PyObject * 11667DirEntry_inode(DirEntry *self) 11668{ 11669#ifdef MS_WINDOWS 11670 if (!self->got_file_index) { 11671 wchar_t *path; 11672 struct _Py_stat_struct stat; 11673 11674 path = PyUnicode_AsUnicode(self->path); 11675 if (!path) 11676 return NULL; 11677 11678 if (win32_lstat_w(path, &stat) != 0) { 11679 return PyErr_SetExcFromWindowsErrWithFilenameObject(PyExc_OSError, 11680 0, self->path); 11681 } 11682 11683 self->win32_file_index = stat.st_ino; 11684 self->got_file_index = 1; 11685 } 11686 return PyLong_FromLongLong((PY_LONG_LONG)self->win32_file_index); 11687#else /* POSIX */ 11688#ifdef HAVE_LARGEFILE_SUPPORT 11689 return PyLong_FromLongLong((PY_LONG_LONG)self->d_ino); 11690#else 11691 return PyLong_FromLong((long)self->d_ino); 11692#endif 11693#endif 11694} 11695 11696static PyObject * 11697DirEntry_repr(DirEntry *self) 11698{ 11699 return PyUnicode_FromFormat("<DirEntry %R>", self->name); 11700} 11701 11702static PyMemberDef DirEntry_members[] = { 11703 {"name", T_OBJECT_EX, offsetof(DirEntry, name), READONLY, 11704 "the entry's base filename, relative to scandir() \"path\" argument"}, 11705 {"path", T_OBJECT_EX, offsetof(DirEntry, path), READONLY, 11706 "the entry's full path name; equivalent to os.path.join(scandir_path, entry.name)"}, 11707 {NULL} 11708}; 11709 11710static PyMethodDef DirEntry_methods[] = { 11711 {"is_dir", (PyCFunction)DirEntry_is_dir, METH_VARARGS | METH_KEYWORDS, 11712 "return True if the entry is a directory; cached per entry" 11713 }, 11714 {"is_file", (PyCFunction)DirEntry_is_file, METH_VARARGS | METH_KEYWORDS, 11715 "return True if the entry is a file; cached per entry" 11716 }, 11717 {"is_symlink", (PyCFunction)DirEntry_py_is_symlink, METH_NOARGS, 11718 "return True if the entry is a symbolic link; cached per entry" 11719 }, 11720 {"stat", (PyCFunction)DirEntry_stat, METH_VARARGS | METH_KEYWORDS, 11721 "return stat_result object for the entry; cached per entry" 11722 }, 11723 {"inode", (PyCFunction)DirEntry_inode, METH_NOARGS, 11724 "return inode of the entry; cached per entry", 11725 }, 11726 {NULL} 11727}; 11728 11729static PyTypeObject DirEntryType = { 11730 PyVarObject_HEAD_INIT(NULL, 0) 11731 MODNAME ".DirEntry", /* tp_name */ 11732 sizeof(DirEntry), /* tp_basicsize */ 11733 0, /* tp_itemsize */ 11734 /* methods */ 11735 (destructor)DirEntry_dealloc, /* tp_dealloc */ 11736 0, /* tp_print */ 11737 0, /* tp_getattr */ 11738 0, /* tp_setattr */ 11739 0, /* tp_compare */ 11740 (reprfunc)DirEntry_repr, /* tp_repr */ 11741 0, /* tp_as_number */ 11742 0, /* tp_as_sequence */ 11743 0, /* tp_as_mapping */ 11744 0, /* tp_hash */ 11745 0, /* tp_call */ 11746 0, /* tp_str */ 11747 0, /* tp_getattro */ 11748 0, /* tp_setattro */ 11749 0, /* tp_as_buffer */ 11750 Py_TPFLAGS_DEFAULT, /* tp_flags */ 11751 0, /* tp_doc */ 11752 0, /* tp_traverse */ 11753 0, /* tp_clear */ 11754 0, /* tp_richcompare */ 11755 0, /* tp_weaklistoffset */ 11756 0, /* tp_iter */ 11757 0, /* tp_iternext */ 11758 DirEntry_methods, /* tp_methods */ 11759 DirEntry_members, /* tp_members */ 11760}; 11761 11762#ifdef MS_WINDOWS 11763 11764static wchar_t * 11765join_path_filenameW(wchar_t *path_wide, wchar_t* filename) 11766{ 11767 Py_ssize_t path_len; 11768 Py_ssize_t size; 11769 wchar_t *result; 11770 wchar_t ch; 11771 11772 if (!path_wide) { /* Default arg: "." */ 11773 path_wide = L"."; 11774 path_len = 1; 11775 } 11776 else { 11777 path_len = wcslen(path_wide); 11778 } 11779 11780 /* The +1's are for the path separator and the NUL */ 11781 size = path_len + 1 + wcslen(filename) + 1; 11782 result = PyMem_New(wchar_t, size); 11783 if (!result) { 11784 PyErr_NoMemory(); 11785 return NULL; 11786 } 11787 wcscpy(result, path_wide); 11788 if (path_len > 0) { 11789 ch = result[path_len - 1]; 11790 if (ch != SEP && ch != ALTSEP && ch != L':') 11791 result[path_len++] = SEP; 11792 wcscpy(result + path_len, filename); 11793 } 11794 return result; 11795} 11796 11797static PyObject * 11798DirEntry_from_find_data(path_t *path, WIN32_FIND_DATAW *dataW) 11799{ 11800 DirEntry *entry; 11801 BY_HANDLE_FILE_INFORMATION file_info; 11802 ULONG reparse_tag; 11803 wchar_t *joined_path; 11804 11805 entry = PyObject_New(DirEntry, &DirEntryType); 11806 if (!entry) 11807 return NULL; 11808 entry->name = NULL; 11809 entry->path = NULL; 11810 entry->stat = NULL; 11811 entry->lstat = NULL; 11812 entry->got_file_index = 0; 11813 11814 entry->name = PyUnicode_FromWideChar(dataW->cFileName, -1); 11815 if (!entry->name) 11816 goto error; 11817 11818 joined_path = join_path_filenameW(path->wide, dataW->cFileName); 11819 if (!joined_path) 11820 goto error; 11821 11822 entry->path = PyUnicode_FromWideChar(joined_path, -1); 11823 PyMem_Free(joined_path); 11824 if (!entry->path) 11825 goto error; 11826 11827 find_data_to_file_info_w(dataW, &file_info, &reparse_tag); 11828 _Py_attribute_data_to_stat(&file_info, reparse_tag, &entry->win32_lstat); 11829 11830 return (PyObject *)entry; 11831 11832error: 11833 Py_DECREF(entry); 11834 return NULL; 11835} 11836 11837#else /* POSIX */ 11838 11839static char * 11840join_path_filename(char *path_narrow, char* filename, Py_ssize_t filename_len) 11841{ 11842 Py_ssize_t path_len; 11843 Py_ssize_t size; 11844 char *result; 11845 11846 if (!path_narrow) { /* Default arg: "." */ 11847 path_narrow = "."; 11848 path_len = 1; 11849 } 11850 else { 11851 path_len = strlen(path_narrow); 11852 } 11853 11854 if (filename_len == -1) 11855 filename_len = strlen(filename); 11856 11857 /* The +1's are for the path separator and the NUL */ 11858 size = path_len + 1 + filename_len + 1; 11859 result = PyMem_New(char, size); 11860 if (!result) { 11861 PyErr_NoMemory(); 11862 return NULL; 11863 } 11864 strcpy(result, path_narrow); 11865 if (path_len > 0 && result[path_len - 1] != '/') 11866 result[path_len++] = '/'; 11867 strcpy(result + path_len, filename); 11868 return result; 11869} 11870 11871static PyObject * 11872DirEntry_from_posix_info(path_t *path, char *name, Py_ssize_t name_len, 11873 ino_t d_ino 11874#ifdef HAVE_DIRENT_D_TYPE 11875 , unsigned char d_type 11876#endif 11877 ) 11878{ 11879 DirEntry *entry; 11880 char *joined_path; 11881 11882 entry = PyObject_New(DirEntry, &DirEntryType); 11883 if (!entry) 11884 return NULL; 11885 entry->name = NULL; 11886 entry->path = NULL; 11887 entry->stat = NULL; 11888 entry->lstat = NULL; 11889 11890 joined_path = join_path_filename(path->narrow, name, name_len); 11891 if (!joined_path) 11892 goto error; 11893 11894 if (!path->narrow || !PyBytes_Check(path->object)) { 11895 entry->name = PyUnicode_DecodeFSDefaultAndSize(name, name_len); 11896 entry->path = PyUnicode_DecodeFSDefault(joined_path); 11897 } 11898 else { 11899 entry->name = PyBytes_FromStringAndSize(name, name_len); 11900 entry->path = PyBytes_FromString(joined_path); 11901 } 11902 PyMem_Free(joined_path); 11903 if (!entry->name || !entry->path) 11904 goto error; 11905 11906#ifdef HAVE_DIRENT_D_TYPE 11907 entry->d_type = d_type; 11908#endif 11909 entry->d_ino = d_ino; 11910 11911 return (PyObject *)entry; 11912 11913error: 11914 Py_XDECREF(entry); 11915 return NULL; 11916} 11917 11918#endif 11919 11920 11921typedef struct { 11922 PyObject_HEAD 11923 path_t path; 11924#ifdef MS_WINDOWS 11925 HANDLE handle; 11926 WIN32_FIND_DATAW file_data; 11927 int first_time; 11928#else /* POSIX */ 11929 DIR *dirp; 11930#endif 11931} ScandirIterator; 11932 11933#ifdef MS_WINDOWS 11934 11935static void 11936ScandirIterator_close(ScandirIterator *iterator) 11937{ 11938 if (iterator->handle == INVALID_HANDLE_VALUE) 11939 return; 11940 11941 Py_BEGIN_ALLOW_THREADS 11942 FindClose(iterator->handle); 11943 Py_END_ALLOW_THREADS 11944 iterator->handle = INVALID_HANDLE_VALUE; 11945} 11946 11947static PyObject * 11948ScandirIterator_iternext(ScandirIterator *iterator) 11949{ 11950 WIN32_FIND_DATAW *file_data = &iterator->file_data; 11951 BOOL success; 11952 11953 /* Happens if the iterator is iterated twice */ 11954 if (iterator->handle == INVALID_HANDLE_VALUE) { 11955 PyErr_SetNone(PyExc_StopIteration); 11956 return NULL; 11957 } 11958 11959 while (1) { 11960 if (!iterator->first_time) { 11961 Py_BEGIN_ALLOW_THREADS 11962 success = FindNextFileW(iterator->handle, file_data); 11963 Py_END_ALLOW_THREADS 11964 if (!success) { 11965 if (GetLastError() != ERROR_NO_MORE_FILES) 11966 return path_error(&iterator->path); 11967 /* No more files found in directory, stop iterating */ 11968 break; 11969 } 11970 } 11971 iterator->first_time = 0; 11972 11973 /* Skip over . and .. */ 11974 if (wcscmp(file_data->cFileName, L".") != 0 && 11975 wcscmp(file_data->cFileName, L"..") != 0) 11976 return DirEntry_from_find_data(&iterator->path, file_data); 11977 11978 /* Loop till we get a non-dot directory or finish iterating */ 11979 } 11980 11981 ScandirIterator_close(iterator); 11982 11983 PyErr_SetNone(PyExc_StopIteration); 11984 return NULL; 11985} 11986 11987#else /* POSIX */ 11988 11989static void 11990ScandirIterator_close(ScandirIterator *iterator) 11991{ 11992 if (!iterator->dirp) 11993 return; 11994 11995 Py_BEGIN_ALLOW_THREADS 11996 closedir(iterator->dirp); 11997 Py_END_ALLOW_THREADS 11998 iterator->dirp = NULL; 11999 return; 12000} 12001 12002static PyObject * 12003ScandirIterator_iternext(ScandirIterator *iterator) 12004{ 12005 struct dirent *direntp; 12006 Py_ssize_t name_len; 12007 int is_dot; 12008 12009 /* Happens if the iterator is iterated twice */ 12010 if (!iterator->dirp) { 12011 PyErr_SetNone(PyExc_StopIteration); 12012 return NULL; 12013 } 12014 12015 while (1) { 12016 errno = 0; 12017 Py_BEGIN_ALLOW_THREADS 12018 direntp = readdir(iterator->dirp); 12019 Py_END_ALLOW_THREADS 12020 12021 if (!direntp) { 12022 if (errno != 0) 12023 return path_error(&iterator->path); 12024 /* No more files found in directory, stop iterating */ 12025 break; 12026 } 12027 12028 /* Skip over . and .. */ 12029 name_len = NAMLEN(direntp); 12030 is_dot = direntp->d_name[0] == '.' && 12031 (name_len == 1 || (direntp->d_name[1] == '.' && name_len == 2)); 12032 if (!is_dot) { 12033 return DirEntry_from_posix_info(&iterator->path, direntp->d_name, 12034 name_len, direntp->d_ino 12035#ifdef HAVE_DIRENT_D_TYPE 12036 , direntp->d_type 12037#endif 12038 ); 12039 } 12040 12041 /* Loop till we get a non-dot directory or finish iterating */ 12042 } 12043 12044 ScandirIterator_close(iterator); 12045 12046 PyErr_SetNone(PyExc_StopIteration); 12047 return NULL; 12048} 12049 12050#endif 12051 12052static void 12053ScandirIterator_dealloc(ScandirIterator *iterator) 12054{ 12055 ScandirIterator_close(iterator); 12056 Py_XDECREF(iterator->path.object); 12057 path_cleanup(&iterator->path); 12058 Py_TYPE(iterator)->tp_free((PyObject *)iterator); 12059} 12060 12061static PyTypeObject ScandirIteratorType = { 12062 PyVarObject_HEAD_INIT(NULL, 0) 12063 MODNAME ".ScandirIterator", /* tp_name */ 12064 sizeof(ScandirIterator), /* tp_basicsize */ 12065 0, /* tp_itemsize */ 12066 /* methods */ 12067 (destructor)ScandirIterator_dealloc, /* tp_dealloc */ 12068 0, /* tp_print */ 12069 0, /* tp_getattr */ 12070 0, /* tp_setattr */ 12071 0, /* tp_compare */ 12072 0, /* tp_repr */ 12073 0, /* tp_as_number */ 12074 0, /* tp_as_sequence */ 12075 0, /* tp_as_mapping */ 12076 0, /* tp_hash */ 12077 0, /* tp_call */ 12078 0, /* tp_str */ 12079 0, /* tp_getattro */ 12080 0, /* tp_setattro */ 12081 0, /* tp_as_buffer */ 12082 Py_TPFLAGS_DEFAULT, /* tp_flags */ 12083 0, /* tp_doc */ 12084 0, /* tp_traverse */ 12085 0, /* tp_clear */ 12086 0, /* tp_richcompare */ 12087 0, /* tp_weaklistoffset */ 12088 PyObject_SelfIter, /* tp_iter */ 12089 (iternextfunc)ScandirIterator_iternext, /* tp_iternext */ 12090}; 12091 12092static PyObject * 12093posix_scandir(PyObject *self, PyObject *args, PyObject *kwargs) 12094{ 12095 ScandirIterator *iterator; 12096 static char *keywords[] = {"path", NULL}; 12097#ifdef MS_WINDOWS 12098 wchar_t *path_strW; 12099#else 12100 char *path; 12101#endif 12102 12103 iterator = PyObject_New(ScandirIterator, &ScandirIteratorType); 12104 if (!iterator) 12105 return NULL; 12106 memset(&iterator->path, 0, sizeof(path_t)); 12107 iterator->path.function_name = "scandir"; 12108 iterator->path.nullable = 1; 12109 12110#ifdef MS_WINDOWS 12111 iterator->handle = INVALID_HANDLE_VALUE; 12112#else 12113 iterator->dirp = NULL; 12114#endif 12115 12116 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O&:scandir", keywords, 12117 path_converter, &iterator->path)) 12118 goto error; 12119 12120 /* path_converter doesn't keep path.object around, so do it 12121 manually for the lifetime of the iterator here (the refcount 12122 is decremented in ScandirIterator_dealloc) 12123 */ 12124 Py_XINCREF(iterator->path.object); 12125 12126#ifdef MS_WINDOWS 12127 if (iterator->path.narrow) { 12128 PyErr_SetString(PyExc_TypeError, 12129 "os.scandir() doesn't support bytes path on Windows, use Unicode instead"); 12130 goto error; 12131 } 12132 iterator->first_time = 1; 12133 12134 path_strW = join_path_filenameW(iterator->path.wide, L"*.*"); 12135 if (!path_strW) 12136 goto error; 12137 12138 Py_BEGIN_ALLOW_THREADS 12139 iterator->handle = FindFirstFileW(path_strW, &iterator->file_data); 12140 Py_END_ALLOW_THREADS 12141 12142 PyMem_Free(path_strW); 12143 12144 if (iterator->handle == INVALID_HANDLE_VALUE) { 12145 path_error(&iterator->path); 12146 goto error; 12147 } 12148#else /* POSIX */ 12149 if (iterator->path.narrow) 12150 path = iterator->path.narrow; 12151 else 12152 path = "."; 12153 12154 errno = 0; 12155 Py_BEGIN_ALLOW_THREADS 12156 iterator->dirp = opendir(path); 12157 Py_END_ALLOW_THREADS 12158 12159 if (!iterator->dirp) { 12160 path_error(&iterator->path); 12161 goto error; 12162 } 12163#endif 12164 12165 return (PyObject *)iterator; 12166 12167error: 12168 Py_DECREF(iterator); 12169 return NULL; 12170} 12171 12172 12173#include "clinic/posixmodule.c.h" 12174 12175/*[clinic input] 12176dump buffer 12177[clinic start generated code]*/ 12178/*[clinic end generated code: output=da39a3ee5e6b4b0d input=524ce2e021e4eba6]*/ 12179 12180 12181static PyMethodDef posix_methods[] = { 12182 12183 OS_STAT_METHODDEF 12184 OS_ACCESS_METHODDEF 12185 OS_TTYNAME_METHODDEF 12186 OS_CHDIR_METHODDEF 12187 OS_CHFLAGS_METHODDEF 12188 OS_CHMOD_METHODDEF 12189 OS_FCHMOD_METHODDEF 12190 OS_LCHMOD_METHODDEF 12191 OS_CHOWN_METHODDEF 12192 OS_FCHOWN_METHODDEF 12193 OS_LCHOWN_METHODDEF 12194 OS_LCHFLAGS_METHODDEF 12195 OS_CHROOT_METHODDEF 12196 OS_CTERMID_METHODDEF 12197 OS_GETCWD_METHODDEF 12198 OS_GETCWDB_METHODDEF 12199 OS_LINK_METHODDEF 12200 OS_LISTDIR_METHODDEF 12201 OS_LSTAT_METHODDEF 12202 OS_MKDIR_METHODDEF 12203 OS_NICE_METHODDEF 12204 OS_GETPRIORITY_METHODDEF 12205 OS_SETPRIORITY_METHODDEF 12206#ifdef HAVE_READLINK 12207 {"readlink", (PyCFunction)posix_readlink, 12208 METH_VARARGS | METH_KEYWORDS, 12209 readlink__doc__}, 12210#endif /* HAVE_READLINK */ 12211#if !defined(HAVE_READLINK) && defined(MS_WINDOWS) 12212 {"readlink", (PyCFunction)win_readlink, 12213 METH_VARARGS | METH_KEYWORDS, 12214 readlink__doc__}, 12215#endif /* !defined(HAVE_READLINK) && defined(MS_WINDOWS) */ 12216 OS_RENAME_METHODDEF 12217 OS_REPLACE_METHODDEF 12218 OS_RMDIR_METHODDEF 12219 {"stat_float_times", stat_float_times, METH_VARARGS, stat_float_times__doc__}, 12220 OS_SYMLINK_METHODDEF 12221 OS_SYSTEM_METHODDEF 12222 OS_UMASK_METHODDEF 12223 OS_UNAME_METHODDEF 12224 OS_UNLINK_METHODDEF 12225 OS_REMOVE_METHODDEF 12226 OS_UTIME_METHODDEF 12227 OS_TIMES_METHODDEF 12228 OS__EXIT_METHODDEF 12229 OS_EXECV_METHODDEF 12230 OS_EXECVE_METHODDEF 12231 OS_SPAWNV_METHODDEF 12232 OS_SPAWNVE_METHODDEF 12233 OS_FORK1_METHODDEF 12234 OS_FORK_METHODDEF 12235 OS_SCHED_GET_PRIORITY_MAX_METHODDEF 12236 OS_SCHED_GET_PRIORITY_MIN_METHODDEF 12237 OS_SCHED_GETPARAM_METHODDEF 12238 OS_SCHED_GETSCHEDULER_METHODDEF 12239 OS_SCHED_RR_GET_INTERVAL_METHODDEF 12240 OS_SCHED_SETPARAM_METHODDEF 12241 OS_SCHED_SETSCHEDULER_METHODDEF 12242 OS_SCHED_YIELD_METHODDEF 12243 OS_SCHED_SETAFFINITY_METHODDEF 12244 OS_SCHED_GETAFFINITY_METHODDEF 12245 OS_OPENPTY_METHODDEF 12246 OS_FORKPTY_METHODDEF 12247 OS_GETEGID_METHODDEF 12248 OS_GETEUID_METHODDEF 12249 OS_GETGID_METHODDEF 12250#ifdef HAVE_GETGROUPLIST 12251 {"getgrouplist", posix_getgrouplist, METH_VARARGS, posix_getgrouplist__doc__}, 12252#endif 12253 OS_GETGROUPS_METHODDEF 12254 OS_GETPID_METHODDEF 12255 OS_GETPGRP_METHODDEF 12256 OS_GETPPID_METHODDEF 12257 OS_GETUID_METHODDEF 12258 OS_GETLOGIN_METHODDEF 12259 OS_KILL_METHODDEF 12260 OS_KILLPG_METHODDEF 12261 OS_PLOCK_METHODDEF 12262#ifdef MS_WINDOWS 12263 {"startfile", win32_startfile, METH_VARARGS, win32_startfile__doc__}, 12264#endif 12265 OS_SETUID_METHODDEF 12266 OS_SETEUID_METHODDEF 12267 OS_SETREUID_METHODDEF 12268 OS_SETGID_METHODDEF 12269 OS_SETEGID_METHODDEF 12270 OS_SETREGID_METHODDEF 12271 OS_SETGROUPS_METHODDEF 12272#ifdef HAVE_INITGROUPS 12273 {"initgroups", posix_initgroups, METH_VARARGS, posix_initgroups__doc__}, 12274#endif /* HAVE_INITGROUPS */ 12275 OS_GETPGID_METHODDEF 12276 OS_SETPGRP_METHODDEF 12277 OS_WAIT_METHODDEF 12278 OS_WAIT3_METHODDEF 12279 OS_WAIT4_METHODDEF 12280 OS_WAITID_METHODDEF 12281 OS_WAITPID_METHODDEF 12282 OS_GETSID_METHODDEF 12283 OS_SETSID_METHODDEF 12284 OS_SETPGID_METHODDEF 12285 OS_TCGETPGRP_METHODDEF 12286 OS_TCSETPGRP_METHODDEF 12287 OS_OPEN_METHODDEF 12288 OS_CLOSE_METHODDEF 12289 OS_CLOSERANGE_METHODDEF 12290 OS_DEVICE_ENCODING_METHODDEF 12291 OS_DUP_METHODDEF 12292 OS_DUP2_METHODDEF 12293 OS_LOCKF_METHODDEF 12294 OS_LSEEK_METHODDEF 12295 OS_READ_METHODDEF 12296 OS_READV_METHODDEF 12297 OS_PREAD_METHODDEF 12298 OS_WRITE_METHODDEF 12299 OS_WRITEV_METHODDEF 12300 OS_PWRITE_METHODDEF 12301#ifdef HAVE_SENDFILE 12302 {"sendfile", (PyCFunction)posix_sendfile, METH_VARARGS | METH_KEYWORDS, 12303 posix_sendfile__doc__}, 12304#endif 12305 OS_FSTAT_METHODDEF 12306 OS_ISATTY_METHODDEF 12307 OS_PIPE_METHODDEF 12308 OS_PIPE2_METHODDEF 12309 OS_MKFIFO_METHODDEF 12310 OS_MKNOD_METHODDEF 12311 OS_MAJOR_METHODDEF 12312 OS_MINOR_METHODDEF 12313 OS_MAKEDEV_METHODDEF 12314 OS_FTRUNCATE_METHODDEF 12315 OS_TRUNCATE_METHODDEF 12316 OS_POSIX_FALLOCATE_METHODDEF 12317 OS_POSIX_FADVISE_METHODDEF 12318 OS_PUTENV_METHODDEF 12319 OS_UNSETENV_METHODDEF 12320 OS_STRERROR_METHODDEF 12321 OS_FCHDIR_METHODDEF 12322 OS_FSYNC_METHODDEF 12323 OS_SYNC_METHODDEF 12324 OS_FDATASYNC_METHODDEF 12325 OS_WCOREDUMP_METHODDEF 12326 OS_WIFCONTINUED_METHODDEF 12327 OS_WIFSTOPPED_METHODDEF 12328 OS_WIFSIGNALED_METHODDEF 12329 OS_WIFEXITED_METHODDEF 12330 OS_WEXITSTATUS_METHODDEF 12331 OS_WTERMSIG_METHODDEF 12332 OS_WSTOPSIG_METHODDEF 12333 OS_FSTATVFS_METHODDEF 12334 OS_STATVFS_METHODDEF 12335 OS_CONFSTR_METHODDEF 12336 OS_SYSCONF_METHODDEF 12337 OS_FPATHCONF_METHODDEF 12338 OS_PATHCONF_METHODDEF 12339 OS_ABORT_METHODDEF 12340 OS__GETFULLPATHNAME_METHODDEF 12341 OS__ISDIR_METHODDEF 12342 OS__GETDISKUSAGE_METHODDEF 12343 OS__GETFINALPATHNAME_METHODDEF 12344 OS__GETVOLUMEPATHNAME_METHODDEF 12345 OS_GETLOADAVG_METHODDEF 12346 OS_URANDOM_METHODDEF 12347 OS_SETRESUID_METHODDEF 12348 OS_SETRESGID_METHODDEF 12349 OS_GETRESUID_METHODDEF 12350 OS_GETRESGID_METHODDEF 12351 12352 OS_GETXATTR_METHODDEF 12353 OS_SETXATTR_METHODDEF 12354 OS_REMOVEXATTR_METHODDEF 12355 OS_LISTXATTR_METHODDEF 12356 12357#if defined(TERMSIZE_USE_CONIO) || defined(TERMSIZE_USE_IOCTL) 12358 {"get_terminal_size", get_terminal_size, METH_VARARGS, termsize__doc__}, 12359#endif 12360 OS_CPU_COUNT_METHODDEF 12361 OS_GET_INHERITABLE_METHODDEF 12362 OS_SET_INHERITABLE_METHODDEF 12363 OS_GET_HANDLE_INHERITABLE_METHODDEF 12364 OS_SET_HANDLE_INHERITABLE_METHODDEF 12365#ifndef MS_WINDOWS 12366 {"get_blocking", posix_get_blocking, METH_VARARGS, get_blocking__doc__}, 12367 {"set_blocking", posix_set_blocking, METH_VARARGS, set_blocking__doc__}, 12368#endif 12369 {"scandir", (PyCFunction)posix_scandir, 12370 METH_VARARGS | METH_KEYWORDS, 12371 posix_scandir__doc__}, 12372 {NULL, NULL} /* Sentinel */ 12373}; 12374 12375 12376#if defined(HAVE_SYMLINK) && defined(MS_WINDOWS) 12377static int 12378enable_symlink() 12379{ 12380 HANDLE tok; 12381 TOKEN_PRIVILEGES tok_priv; 12382 LUID luid; 12383 int meth_idx = 0; 12384 12385 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &tok)) 12386 return 0; 12387 12388 if (!LookupPrivilegeValue(NULL, SE_CREATE_SYMBOLIC_LINK_NAME, &luid)) 12389 return 0; 12390 12391 tok_priv.PrivilegeCount = 1; 12392 tok_priv.Privileges[0].Luid = luid; 12393 tok_priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 12394 12395 if (!AdjustTokenPrivileges(tok, FALSE, &tok_priv, 12396 sizeof(TOKEN_PRIVILEGES), 12397 (PTOKEN_PRIVILEGES) NULL, (PDWORD) NULL)) 12398 return 0; 12399 12400 /* ERROR_NOT_ALL_ASSIGNED returned when the privilege can't be assigned. */ 12401 return GetLastError() == ERROR_NOT_ALL_ASSIGNED ? 0 : 1; 12402} 12403#endif /* defined(HAVE_SYMLINK) && defined(MS_WINDOWS) */ 12404 12405static int 12406all_ins(PyObject *m) 12407{ 12408#ifdef F_OK 12409 if (PyModule_AddIntMacro(m, F_OK)) return -1; 12410#endif 12411#ifdef R_OK 12412 if (PyModule_AddIntMacro(m, R_OK)) return -1; 12413#endif 12414#ifdef W_OK 12415 if (PyModule_AddIntMacro(m, W_OK)) return -1; 12416#endif 12417#ifdef X_OK 12418 if (PyModule_AddIntMacro(m, X_OK)) return -1; 12419#endif 12420#ifdef NGROUPS_MAX 12421 if (PyModule_AddIntMacro(m, NGROUPS_MAX)) return -1; 12422#endif 12423#ifdef TMP_MAX 12424 if (PyModule_AddIntMacro(m, TMP_MAX)) return -1; 12425#endif 12426#ifdef WCONTINUED 12427 if (PyModule_AddIntMacro(m, WCONTINUED)) return -1; 12428#endif 12429#ifdef WNOHANG 12430 if (PyModule_AddIntMacro(m, WNOHANG)) return -1; 12431#endif 12432#ifdef WUNTRACED 12433 if (PyModule_AddIntMacro(m, WUNTRACED)) return -1; 12434#endif 12435#ifdef O_RDONLY 12436 if (PyModule_AddIntMacro(m, O_RDONLY)) return -1; 12437#endif 12438#ifdef O_WRONLY 12439 if (PyModule_AddIntMacro(m, O_WRONLY)) return -1; 12440#endif 12441#ifdef O_RDWR 12442 if (PyModule_AddIntMacro(m, O_RDWR)) return -1; 12443#endif 12444#ifdef O_NDELAY 12445 if (PyModule_AddIntMacro(m, O_NDELAY)) return -1; 12446#endif 12447#ifdef O_NONBLOCK 12448 if (PyModule_AddIntMacro(m, O_NONBLOCK)) return -1; 12449#endif 12450#ifdef O_APPEND 12451 if (PyModule_AddIntMacro(m, O_APPEND)) return -1; 12452#endif 12453#ifdef O_DSYNC 12454 if (PyModule_AddIntMacro(m, O_DSYNC)) return -1; 12455#endif 12456#ifdef O_RSYNC 12457 if (PyModule_AddIntMacro(m, O_RSYNC)) return -1; 12458#endif 12459#ifdef O_SYNC 12460 if (PyModule_AddIntMacro(m, O_SYNC)) return -1; 12461#endif 12462#ifdef O_NOCTTY 12463 if (PyModule_AddIntMacro(m, O_NOCTTY)) return -1; 12464#endif 12465#ifdef O_CREAT 12466 if (PyModule_AddIntMacro(m, O_CREAT)) return -1; 12467#endif 12468#ifdef O_EXCL 12469 if (PyModule_AddIntMacro(m, O_EXCL)) return -1; 12470#endif 12471#ifdef O_TRUNC 12472 if (PyModule_AddIntMacro(m, O_TRUNC)) return -1; 12473#endif 12474#ifdef O_BINARY 12475 if (PyModule_AddIntMacro(m, O_BINARY)) return -1; 12476#endif 12477#ifdef O_TEXT 12478 if (PyModule_AddIntMacro(m, O_TEXT)) return -1; 12479#endif 12480#ifdef O_XATTR 12481 if (PyModule_AddIntMacro(m, O_XATTR)) return -1; 12482#endif 12483#ifdef O_LARGEFILE 12484 if (PyModule_AddIntMacro(m, O_LARGEFILE)) return -1; 12485#endif 12486#ifdef O_SHLOCK 12487 if (PyModule_AddIntMacro(m, O_SHLOCK)) return -1; 12488#endif 12489#ifdef O_EXLOCK 12490 if (PyModule_AddIntMacro(m, O_EXLOCK)) return -1; 12491#endif 12492#ifdef O_EXEC 12493 if (PyModule_AddIntMacro(m, O_EXEC)) return -1; 12494#endif 12495#ifdef O_SEARCH 12496 if (PyModule_AddIntMacro(m, O_SEARCH)) return -1; 12497#endif 12498#ifdef O_PATH 12499 if (PyModule_AddIntMacro(m, O_PATH)) return -1; 12500#endif 12501#ifdef O_TTY_INIT 12502 if (PyModule_AddIntMacro(m, O_TTY_INIT)) return -1; 12503#endif 12504#ifdef O_TMPFILE 12505 if (PyModule_AddIntMacro(m, O_TMPFILE)) return -1; 12506#endif 12507#ifdef PRIO_PROCESS 12508 if (PyModule_AddIntMacro(m, PRIO_PROCESS)) return -1; 12509#endif 12510#ifdef PRIO_PGRP 12511 if (PyModule_AddIntMacro(m, PRIO_PGRP)) return -1; 12512#endif 12513#ifdef PRIO_USER 12514 if (PyModule_AddIntMacro(m, PRIO_USER)) return -1; 12515#endif 12516#ifdef O_CLOEXEC 12517 if (PyModule_AddIntMacro(m, O_CLOEXEC)) return -1; 12518#endif 12519#ifdef O_ACCMODE 12520 if (PyModule_AddIntMacro(m, O_ACCMODE)) return -1; 12521#endif 12522 12523 12524#ifdef SEEK_HOLE 12525 if (PyModule_AddIntMacro(m, SEEK_HOLE)) return -1; 12526#endif 12527#ifdef SEEK_DATA 12528 if (PyModule_AddIntMacro(m, SEEK_DATA)) return -1; 12529#endif 12530 12531/* MS Windows */ 12532#ifdef O_NOINHERIT 12533 /* Don't inherit in child processes. */ 12534 if (PyModule_AddIntMacro(m, O_NOINHERIT)) return -1; 12535#endif 12536#ifdef _O_SHORT_LIVED 12537 /* Optimize for short life (keep in memory). */ 12538 /* MS forgot to define this one with a non-underscore form too. */ 12539 if (PyModule_AddIntConstant(m, "O_SHORT_LIVED", _O_SHORT_LIVED)) return -1; 12540#endif 12541#ifdef O_TEMPORARY 12542 /* Automatically delete when last handle is closed. */ 12543 if (PyModule_AddIntMacro(m, O_TEMPORARY)) return -1; 12544#endif 12545#ifdef O_RANDOM 12546 /* Optimize for random access. */ 12547 if (PyModule_AddIntMacro(m, O_RANDOM)) return -1; 12548#endif 12549#ifdef O_SEQUENTIAL 12550 /* Optimize for sequential access. */ 12551 if (PyModule_AddIntMacro(m, O_SEQUENTIAL)) return -1; 12552#endif 12553 12554/* GNU extensions. */ 12555#ifdef O_ASYNC 12556 /* Send a SIGIO signal whenever input or output 12557 becomes available on file descriptor */ 12558 if (PyModule_AddIntMacro(m, O_ASYNC)) return -1; 12559#endif 12560#ifdef O_DIRECT 12561 /* Direct disk access. */ 12562 if (PyModule_AddIntMacro(m, O_DIRECT)) return -1; 12563#endif 12564#ifdef O_DIRECTORY 12565 /* Must be a directory. */ 12566 if (PyModule_AddIntMacro(m, O_DIRECTORY)) return -1; 12567#endif 12568#ifdef O_NOFOLLOW 12569 /* Do not follow links. */ 12570 if (PyModule_AddIntMacro(m, O_NOFOLLOW)) return -1; 12571#endif 12572#ifdef O_NOLINKS 12573 /* Fails if link count of the named file is greater than 1 */ 12574 if (PyModule_AddIntMacro(m, O_NOLINKS)) return -1; 12575#endif 12576#ifdef O_NOATIME 12577 /* Do not update the access time. */ 12578 if (PyModule_AddIntMacro(m, O_NOATIME)) return -1; 12579#endif 12580 12581 /* These come from sysexits.h */ 12582#ifdef EX_OK 12583 if (PyModule_AddIntMacro(m, EX_OK)) return -1; 12584#endif /* EX_OK */ 12585#ifdef EX_USAGE 12586 if (PyModule_AddIntMacro(m, EX_USAGE)) return -1; 12587#endif /* EX_USAGE */ 12588#ifdef EX_DATAERR 12589 if (PyModule_AddIntMacro(m, EX_DATAERR)) return -1; 12590#endif /* EX_DATAERR */ 12591#ifdef EX_NOINPUT 12592 if (PyModule_AddIntMacro(m, EX_NOINPUT)) return -1; 12593#endif /* EX_NOINPUT */ 12594#ifdef EX_NOUSER 12595 if (PyModule_AddIntMacro(m, EX_NOUSER)) return -1; 12596#endif /* EX_NOUSER */ 12597#ifdef EX_NOHOST 12598 if (PyModule_AddIntMacro(m, EX_NOHOST)) return -1; 12599#endif /* EX_NOHOST */ 12600#ifdef EX_UNAVAILABLE 12601 if (PyModule_AddIntMacro(m, EX_UNAVAILABLE)) return -1; 12602#endif /* EX_UNAVAILABLE */ 12603#ifdef EX_SOFTWARE 12604 if (PyModule_AddIntMacro(m, EX_SOFTWARE)) return -1; 12605#endif /* EX_SOFTWARE */ 12606#ifdef EX_OSERR 12607 if (PyModule_AddIntMacro(m, EX_OSERR)) return -1; 12608#endif /* EX_OSERR */ 12609#ifdef EX_OSFILE 12610 if (PyModule_AddIntMacro(m, EX_OSFILE)) return -1; 12611#endif /* EX_OSFILE */ 12612#ifdef EX_CANTCREAT 12613 if (PyModule_AddIntMacro(m, EX_CANTCREAT)) return -1; 12614#endif /* EX_CANTCREAT */ 12615#ifdef EX_IOERR 12616 if (PyModule_AddIntMacro(m, EX_IOERR)) return -1; 12617#endif /* EX_IOERR */ 12618#ifdef EX_TEMPFAIL 12619 if (PyModule_AddIntMacro(m, EX_TEMPFAIL)) return -1; 12620#endif /* EX_TEMPFAIL */ 12621#ifdef EX_PROTOCOL 12622 if (PyModule_AddIntMacro(m, EX_PROTOCOL)) return -1; 12623#endif /* EX_PROTOCOL */ 12624#ifdef EX_NOPERM 12625 if (PyModule_AddIntMacro(m, EX_NOPERM)) return -1; 12626#endif /* EX_NOPERM */ 12627#ifdef EX_CONFIG 12628 if (PyModule_AddIntMacro(m, EX_CONFIG)) return -1; 12629#endif /* EX_CONFIG */ 12630#ifdef EX_NOTFOUND 12631 if (PyModule_AddIntMacro(m, EX_NOTFOUND)) return -1; 12632#endif /* EX_NOTFOUND */ 12633 12634 /* statvfs */ 12635#ifdef ST_RDONLY 12636 if (PyModule_AddIntMacro(m, ST_RDONLY)) return -1; 12637#endif /* ST_RDONLY */ 12638#ifdef ST_NOSUID 12639 if (PyModule_AddIntMacro(m, ST_NOSUID)) return -1; 12640#endif /* ST_NOSUID */ 12641 12642 /* GNU extensions */ 12643#ifdef ST_NODEV 12644 if (PyModule_AddIntMacro(m, ST_NODEV)) return -1; 12645#endif /* ST_NODEV */ 12646#ifdef ST_NOEXEC 12647 if (PyModule_AddIntMacro(m, ST_NOEXEC)) return -1; 12648#endif /* ST_NOEXEC */ 12649#ifdef ST_SYNCHRONOUS 12650 if (PyModule_AddIntMacro(m, ST_SYNCHRONOUS)) return -1; 12651#endif /* ST_SYNCHRONOUS */ 12652#ifdef ST_MANDLOCK 12653 if (PyModule_AddIntMacro(m, ST_MANDLOCK)) return -1; 12654#endif /* ST_MANDLOCK */ 12655#ifdef ST_WRITE 12656 if (PyModule_AddIntMacro(m, ST_WRITE)) return -1; 12657#endif /* ST_WRITE */ 12658#ifdef ST_APPEND 12659 if (PyModule_AddIntMacro(m, ST_APPEND)) return -1; 12660#endif /* ST_APPEND */ 12661#ifdef ST_NOATIME 12662 if (PyModule_AddIntMacro(m, ST_NOATIME)) return -1; 12663#endif /* ST_NOATIME */ 12664#ifdef ST_NODIRATIME 12665 if (PyModule_AddIntMacro(m, ST_NODIRATIME)) return -1; 12666#endif /* ST_NODIRATIME */ 12667#ifdef ST_RELATIME 12668 if (PyModule_AddIntMacro(m, ST_RELATIME)) return -1; 12669#endif /* ST_RELATIME */ 12670 12671 /* FreeBSD sendfile() constants */ 12672#ifdef SF_NODISKIO 12673 if (PyModule_AddIntMacro(m, SF_NODISKIO)) return -1; 12674#endif 12675#ifdef SF_MNOWAIT 12676 if (PyModule_AddIntMacro(m, SF_MNOWAIT)) return -1; 12677#endif 12678#ifdef SF_SYNC 12679 if (PyModule_AddIntMacro(m, SF_SYNC)) return -1; 12680#endif 12681 12682 /* constants for posix_fadvise */ 12683#ifdef POSIX_FADV_NORMAL 12684 if (PyModule_AddIntMacro(m, POSIX_FADV_NORMAL)) return -1; 12685#endif 12686#ifdef POSIX_FADV_SEQUENTIAL 12687 if (PyModule_AddIntMacro(m, POSIX_FADV_SEQUENTIAL)) return -1; 12688#endif 12689#ifdef POSIX_FADV_RANDOM 12690 if (PyModule_AddIntMacro(m, POSIX_FADV_RANDOM)) return -1; 12691#endif 12692#ifdef POSIX_FADV_NOREUSE 12693 if (PyModule_AddIntMacro(m, POSIX_FADV_NOREUSE)) return -1; 12694#endif 12695#ifdef POSIX_FADV_WILLNEED 12696 if (PyModule_AddIntMacro(m, POSIX_FADV_WILLNEED)) return -1; 12697#endif 12698#ifdef POSIX_FADV_DONTNEED 12699 if (PyModule_AddIntMacro(m, POSIX_FADV_DONTNEED)) return -1; 12700#endif 12701 12702 /* constants for waitid */ 12703#if defined(HAVE_SYS_WAIT_H) && defined(HAVE_WAITID) 12704 if (PyModule_AddIntMacro(m, P_PID)) return -1; 12705 if (PyModule_AddIntMacro(m, P_PGID)) return -1; 12706 if (PyModule_AddIntMacro(m, P_ALL)) return -1; 12707#endif 12708#ifdef WEXITED 12709 if (PyModule_AddIntMacro(m, WEXITED)) return -1; 12710#endif 12711#ifdef WNOWAIT 12712 if (PyModule_AddIntMacro(m, WNOWAIT)) return -1; 12713#endif 12714#ifdef WSTOPPED 12715 if (PyModule_AddIntMacro(m, WSTOPPED)) return -1; 12716#endif 12717#ifdef CLD_EXITED 12718 if (PyModule_AddIntMacro(m, CLD_EXITED)) return -1; 12719#endif 12720#ifdef CLD_DUMPED 12721 if (PyModule_AddIntMacro(m, CLD_DUMPED)) return -1; 12722#endif 12723#ifdef CLD_TRAPPED 12724 if (PyModule_AddIntMacro(m, CLD_TRAPPED)) return -1; 12725#endif 12726#ifdef CLD_CONTINUED 12727 if (PyModule_AddIntMacro(m, CLD_CONTINUED)) return -1; 12728#endif 12729 12730 /* constants for lockf */ 12731#ifdef F_LOCK 12732 if (PyModule_AddIntMacro(m, F_LOCK)) return -1; 12733#endif 12734#ifdef F_TLOCK 12735 if (PyModule_AddIntMacro(m, F_TLOCK)) return -1; 12736#endif 12737#ifdef F_ULOCK 12738 if (PyModule_AddIntMacro(m, F_ULOCK)) return -1; 12739#endif 12740#ifdef F_TEST 12741 if (PyModule_AddIntMacro(m, F_TEST)) return -1; 12742#endif 12743 12744#ifdef HAVE_SPAWNV 12745 if (PyModule_AddIntConstant(m, "P_WAIT", _P_WAIT)) return -1; 12746 if (PyModule_AddIntConstant(m, "P_NOWAIT", _P_NOWAIT)) return -1; 12747 if (PyModule_AddIntConstant(m, "P_OVERLAY", _OLD_P_OVERLAY)) return -1; 12748 if (PyModule_AddIntConstant(m, "P_NOWAITO", _P_NOWAITO)) return -1; 12749 if (PyModule_AddIntConstant(m, "P_DETACH", _P_DETACH)) return -1; 12750#endif 12751 12752#ifdef HAVE_SCHED_H 12753 if (PyModule_AddIntMacro(m, SCHED_OTHER)) return -1; 12754 if (PyModule_AddIntMacro(m, SCHED_FIFO)) return -1; 12755 if (PyModule_AddIntMacro(m, SCHED_RR)) return -1; 12756#ifdef SCHED_SPORADIC 12757 if (PyModule_AddIntMacro(m, SCHED_SPORADIC) return -1; 12758#endif 12759#ifdef SCHED_BATCH 12760 if (PyModule_AddIntMacro(m, SCHED_BATCH)) return -1; 12761#endif 12762#ifdef SCHED_IDLE 12763 if (PyModule_AddIntMacro(m, SCHED_IDLE)) return -1; 12764#endif 12765#ifdef SCHED_RESET_ON_FORK 12766 if (PyModule_AddIntMacro(m, SCHED_RESET_ON_FORK)) return -1; 12767#endif 12768#ifdef SCHED_SYS 12769 if (PyModule_AddIntMacro(m, SCHED_SYS)) return -1; 12770#endif 12771#ifdef SCHED_IA 12772 if (PyModule_AddIntMacro(m, SCHED_IA)) return -1; 12773#endif 12774#ifdef SCHED_FSS 12775 if (PyModule_AddIntMacro(m, SCHED_FSS)) return -1; 12776#endif 12777#ifdef SCHED_FX 12778 if (PyModule_AddIntConstant(m, "SCHED_FX", SCHED_FSS)) return -1; 12779#endif 12780#endif 12781 12782#ifdef USE_XATTRS 12783 if (PyModule_AddIntMacro(m, XATTR_CREATE)) return -1; 12784 if (PyModule_AddIntMacro(m, XATTR_REPLACE)) return -1; 12785 if (PyModule_AddIntMacro(m, XATTR_SIZE_MAX)) return -1; 12786#endif 12787 12788#ifdef RTLD_LAZY 12789 if (PyModule_AddIntMacro(m, RTLD_LAZY)) return -1; 12790#endif 12791#ifdef RTLD_NOW 12792 if (PyModule_AddIntMacro(m, RTLD_NOW)) return -1; 12793#endif 12794#ifdef RTLD_GLOBAL 12795 if (PyModule_AddIntMacro(m, RTLD_GLOBAL)) return -1; 12796#endif 12797#ifdef RTLD_LOCAL 12798 if (PyModule_AddIntMacro(m, RTLD_LOCAL)) return -1; 12799#endif 12800#ifdef RTLD_NODELETE 12801 if (PyModule_AddIntMacro(m, RTLD_NODELETE)) return -1; 12802#endif 12803#ifdef RTLD_NOLOAD 12804 if (PyModule_AddIntMacro(m, RTLD_NOLOAD)) return -1; 12805#endif 12806#ifdef RTLD_DEEPBIND 12807 if (PyModule_AddIntMacro(m, RTLD_DEEPBIND)) return -1; 12808#endif 12809 12810 return 0; 12811} 12812 12813 12814static struct PyModuleDef posixmodule = { 12815 PyModuleDef_HEAD_INIT, 12816 MODNAME, 12817 posix__doc__, 12818 -1, 12819 posix_methods, 12820 NULL, 12821 NULL, 12822 NULL, 12823 NULL 12824}; 12825 12826 12827static char *have_functions[] = { 12828 12829#ifdef HAVE_FACCESSAT 12830 "HAVE_FACCESSAT", 12831#endif 12832 12833#ifdef HAVE_FCHDIR 12834 "HAVE_FCHDIR", 12835#endif 12836 12837#ifdef HAVE_FCHMOD 12838 "HAVE_FCHMOD", 12839#endif 12840 12841#ifdef HAVE_FCHMODAT 12842 "HAVE_FCHMODAT", 12843#endif 12844 12845#ifdef HAVE_FCHOWN 12846 "HAVE_FCHOWN", 12847#endif 12848 12849#ifdef HAVE_FCHOWNAT 12850 "HAVE_FCHOWNAT", 12851#endif 12852 12853#ifdef HAVE_FEXECVE 12854 "HAVE_FEXECVE", 12855#endif 12856 12857#ifdef HAVE_FDOPENDIR 12858 "HAVE_FDOPENDIR", 12859#endif 12860 12861#ifdef HAVE_FPATHCONF 12862 "HAVE_FPATHCONF", 12863#endif 12864 12865#ifdef HAVE_FSTATAT 12866 "HAVE_FSTATAT", 12867#endif 12868 12869#ifdef HAVE_FSTATVFS 12870 "HAVE_FSTATVFS", 12871#endif 12872 12873#if defined HAVE_FTRUNCATE || defined MS_WINDOWS 12874 "HAVE_FTRUNCATE", 12875#endif 12876 12877#ifdef HAVE_FUTIMENS 12878 "HAVE_FUTIMENS", 12879#endif 12880 12881#ifdef HAVE_FUTIMES 12882 "HAVE_FUTIMES", 12883#endif 12884 12885#ifdef HAVE_FUTIMESAT 12886 "HAVE_FUTIMESAT", 12887#endif 12888 12889#ifdef HAVE_LINKAT 12890 "HAVE_LINKAT", 12891#endif 12892 12893#ifdef HAVE_LCHFLAGS 12894 "HAVE_LCHFLAGS", 12895#endif 12896 12897#ifdef HAVE_LCHMOD 12898 "HAVE_LCHMOD", 12899#endif 12900 12901#ifdef HAVE_LCHOWN 12902 "HAVE_LCHOWN", 12903#endif 12904 12905#ifdef HAVE_LSTAT 12906 "HAVE_LSTAT", 12907#endif 12908 12909#ifdef HAVE_LUTIMES 12910 "HAVE_LUTIMES", 12911#endif 12912 12913#ifdef HAVE_MKDIRAT 12914 "HAVE_MKDIRAT", 12915#endif 12916 12917#ifdef HAVE_MKFIFOAT 12918 "HAVE_MKFIFOAT", 12919#endif 12920 12921#ifdef HAVE_MKNODAT 12922 "HAVE_MKNODAT", 12923#endif 12924 12925#ifdef HAVE_OPENAT 12926 "HAVE_OPENAT", 12927#endif 12928 12929#ifdef HAVE_READLINKAT 12930 "HAVE_READLINKAT", 12931#endif 12932 12933#ifdef HAVE_RENAMEAT 12934 "HAVE_RENAMEAT", 12935#endif 12936 12937#ifdef HAVE_SYMLINKAT 12938 "HAVE_SYMLINKAT", 12939#endif 12940 12941#ifdef HAVE_UNLINKAT 12942 "HAVE_UNLINKAT", 12943#endif 12944 12945#ifdef HAVE_UTIMENSAT 12946 "HAVE_UTIMENSAT", 12947#endif 12948 12949#ifdef MS_WINDOWS 12950 "MS_WINDOWS", 12951#endif 12952 12953 NULL 12954}; 12955 12956 12957PyMODINIT_FUNC 12958INITFUNC(void) 12959{ 12960 PyObject *m, *v; 12961 PyObject *list; 12962 char **trace; 12963 12964#if defined(HAVE_SYMLINK) && defined(MS_WINDOWS) 12965 win32_can_symlink = enable_symlink(); 12966#endif 12967 12968 m = PyModule_Create(&posixmodule); 12969 if (m == NULL) 12970 return NULL; 12971 12972 /* Initialize environ dictionary */ 12973 v = convertenviron(); 12974 Py_XINCREF(v); 12975 if (v == NULL || PyModule_AddObject(m, "environ", v) != 0) 12976 return NULL; 12977 Py_DECREF(v); 12978 12979 if (all_ins(m)) 12980 return NULL; 12981 12982 if (setup_confname_tables(m)) 12983 return NULL; 12984 12985 Py_INCREF(PyExc_OSError); 12986 PyModule_AddObject(m, "error", PyExc_OSError); 12987 12988#ifdef HAVE_PUTENV 12989 if (posix_putenv_garbage == NULL) 12990 posix_putenv_garbage = PyDict_New(); 12991#endif 12992 12993 if (!initialized) { 12994#if defined(HAVE_WAITID) && !defined(__APPLE__) 12995 waitid_result_desc.name = MODNAME ".waitid_result"; 12996 if (PyStructSequence_InitType2(&WaitidResultType, &waitid_result_desc) < 0) 12997 return NULL; 12998#endif 12999 13000 stat_result_desc.name = "os.stat_result"; /* see issue #19209 */ 13001 stat_result_desc.fields[7].name = PyStructSequence_UnnamedField; 13002 stat_result_desc.fields[8].name = PyStructSequence_UnnamedField; 13003 stat_result_desc.fields[9].name = PyStructSequence_UnnamedField; 13004 if (PyStructSequence_InitType2(&StatResultType, &stat_result_desc) < 0) 13005 return NULL; 13006 structseq_new = StatResultType.tp_new; 13007 StatResultType.tp_new = statresult_new; 13008 13009 statvfs_result_desc.name = "os.statvfs_result"; /* see issue #19209 */ 13010 if (PyStructSequence_InitType2(&StatVFSResultType, 13011 &statvfs_result_desc) < 0) 13012 return NULL; 13013#ifdef NEED_TICKS_PER_SECOND 13014# if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK) 13015 ticks_per_second = sysconf(_SC_CLK_TCK); 13016# elif defined(HZ) 13017 ticks_per_second = HZ; 13018# else 13019 ticks_per_second = 60; /* magic fallback value; may be bogus */ 13020# endif 13021#endif 13022 13023#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) 13024 sched_param_desc.name = MODNAME ".sched_param"; 13025 if (PyStructSequence_InitType2(&SchedParamType, &sched_param_desc) < 0) 13026 return NULL; 13027 SchedParamType.tp_new = os_sched_param; 13028#endif 13029 13030 /* initialize TerminalSize_info */ 13031 if (PyStructSequence_InitType2(&TerminalSizeType, 13032 &TerminalSize_desc) < 0) 13033 return NULL; 13034 13035 /* initialize scandir types */ 13036 if (PyType_Ready(&ScandirIteratorType) < 0) 13037 return NULL; 13038 if (PyType_Ready(&DirEntryType) < 0) 13039 return NULL; 13040 } 13041#if defined(HAVE_WAITID) && !defined(__APPLE__) 13042 Py_INCREF((PyObject*) &WaitidResultType); 13043 PyModule_AddObject(m, "waitid_result", (PyObject*) &WaitidResultType); 13044#endif 13045 Py_INCREF((PyObject*) &StatResultType); 13046 PyModule_AddObject(m, "stat_result", (PyObject*) &StatResultType); 13047 Py_INCREF((PyObject*) &StatVFSResultType); 13048 PyModule_AddObject(m, "statvfs_result", 13049 (PyObject*) &StatVFSResultType); 13050 13051#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) 13052 Py_INCREF(&SchedParamType); 13053 PyModule_AddObject(m, "sched_param", (PyObject *)&SchedParamType); 13054#endif 13055 13056 times_result_desc.name = MODNAME ".times_result"; 13057 if (PyStructSequence_InitType2(&TimesResultType, ×_result_desc) < 0) 13058 return NULL; 13059 PyModule_AddObject(m, "times_result", (PyObject *)&TimesResultType); 13060 13061 uname_result_desc.name = MODNAME ".uname_result"; 13062 if (PyStructSequence_InitType2(&UnameResultType, &uname_result_desc) < 0) 13063 return NULL; 13064 PyModule_AddObject(m, "uname_result", (PyObject *)&UnameResultType); 13065 13066#ifdef __APPLE__ 13067 /* 13068 * Step 2 of weak-linking support on Mac OS X. 13069 * 13070 * The code below removes functions that are not available on the 13071 * currently active platform. 13072 * 13073 * This block allow one to use a python binary that was build on 13074 * OSX 10.4 on OSX 10.3, without losing access to new APIs on 13075 * OSX 10.4. 13076 */ 13077#ifdef HAVE_FSTATVFS 13078 if (fstatvfs == NULL) { 13079 if (PyObject_DelAttrString(m, "fstatvfs") == -1) { 13080 return NULL; 13081 } 13082 } 13083#endif /* HAVE_FSTATVFS */ 13084 13085#ifdef HAVE_STATVFS 13086 if (statvfs == NULL) { 13087 if (PyObject_DelAttrString(m, "statvfs") == -1) { 13088 return NULL; 13089 } 13090 } 13091#endif /* HAVE_STATVFS */ 13092 13093# ifdef HAVE_LCHOWN 13094 if (lchown == NULL) { 13095 if (PyObject_DelAttrString(m, "lchown") == -1) { 13096 return NULL; 13097 } 13098 } 13099#endif /* HAVE_LCHOWN */ 13100 13101 13102#endif /* __APPLE__ */ 13103 13104 Py_INCREF(&TerminalSizeType); 13105 PyModule_AddObject(m, "terminal_size", (PyObject*) &TerminalSizeType); 13106 13107 billion = PyLong_FromLong(1000000000); 13108 if (!billion) 13109 return NULL; 13110 13111 /* suppress "function not used" warnings */ 13112 { 13113 int ignored; 13114 fd_specified("", -1); 13115 follow_symlinks_specified("", 1); 13116 dir_fd_and_follow_symlinks_invalid("chmod", DEFAULT_DIR_FD, 1); 13117 dir_fd_converter(Py_None, &ignored); 13118 dir_fd_unavailable(Py_None, &ignored); 13119 } 13120 13121 /* 13122 * provide list of locally available functions 13123 * so os.py can populate support_* lists 13124 */ 13125 list = PyList_New(0); 13126 if (!list) 13127 return NULL; 13128 for (trace = have_functions; *trace; trace++) { 13129 PyObject *unicode = PyUnicode_DecodeASCII(*trace, strlen(*trace), NULL); 13130 if (!unicode) 13131 return NULL; 13132 if (PyList_Append(list, unicode)) 13133 return NULL; 13134 Py_DECREF(unicode); 13135 } 13136 PyModule_AddObject(m, "_have_functions", list); 13137 13138 initialized = 1; 13139 13140 return m; 13141} 13142 13143#ifdef __cplusplus 13144} 13145#endif 13146