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