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