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