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