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