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