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