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