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