Python-2.7.3/Modules/posixmodule.c

Location Tool Test ID Function Issue
/builddir/build/BUILD/Python-2.7.3/Modules/posixmodule.c:2926:0 cppcheck uninitvar Uninitialized variable: res
/builddir/build/BUILD/Python-2.7.3/Modules/posixmodule.c:2926:0 cppcheck uninitvar Uninitialized variable: res
   1 /* POSIX module implementation */
   2 
   3 /* This file is also used for Windows NT/MS-Win and OS/2.  In that case the
   4    module actually calls itself 'nt' or 'os2', not 'posix', and a few
   5    functions are either unimplemented or implemented differently.  The source
   6    assumes that for Windows NT, the macro 'MS_WINDOWS' is defined independent
   7    of the compiler used.  Different compilers define their own feature
   8    test macro, e.g. '__BORLANDC__' or '_MSC_VER'.  For OS/2, the compiler
   9    independent macro PYOS_OS2 should be defined.  On OS/2 the default
  10    compiler is assumed to be IBM's VisualAge C++ (VACPP).  PYCC_GCC is used
  11    as the compiler specific macro for the EMX port of gcc to OS/2. */
  12 
  13 #ifdef __APPLE__
  14    /*
  15     * Step 1 of support for weak-linking a number of symbols existing on
  16     * OSX 10.4 and later, see the comment in the #ifdef __APPLE__ block
  17     * at the end of this file for more information.
  18     */
  19 #  pragma weak lchown
  20 #  pragma weak statvfs
  21 #  pragma weak fstatvfs
  22 
  23 #endif /* __APPLE__ */
  24 
  25 #define PY_SSIZE_T_CLEAN
  26 
  27 #include "Python.h"
  28 #include "structseq.h"
  29 
  30 #if defined(__VMS)
  31 #    include <unixio.h>
  32 #endif /* defined(__VMS) */
  33 
  34 #ifdef __cplusplus
  35 extern "C" {
  36 #endif
  37 
  38 PyDoc_STRVAR(posix__doc__,
  39 "This module provides access to operating system functionality that is\n\
  40 standardized by the C Standard and the POSIX standard (a thinly\n\
  41 disguised Unix interface).  Refer to the library manual and\n\
  42 corresponding Unix manual entries for more information on calls.");
  43 
  44 #ifndef Py_USING_UNICODE
  45 /* This is used in signatures of functions. */
  46 #define Py_UNICODE void
  47 #endif
  48 
  49 #if defined(PYOS_OS2)
  50 #define  INCL_DOS
  51 #define  INCL_DOSERRORS
  52 #define  INCL_DOSPROCESS
  53 #define  INCL_NOPMAPI
  54 #include <os2.h>
  55 #if defined(PYCC_GCC)
  56 #include <ctype.h>
  57 #include <io.h>
  58 #include <stdio.h>
  59 #include <process.h>
  60 #endif
  61 #include "osdefs.h"
  62 #endif
  63 
  64 #ifdef HAVE_SYS_TYPES_H
  65 #include <sys/types.h>
  66 #endif /* HAVE_SYS_TYPES_H */
  67 
  68 #ifdef HAVE_SYS_STAT_H
  69 #include <sys/stat.h>
  70 #endif /* HAVE_SYS_STAT_H */
  71 
  72 #ifdef HAVE_SYS_WAIT_H
  73 #include <sys/wait.h>           /* For WNOHANG */
  74 #endif
  75 
  76 #ifdef HAVE_SIGNAL_H
  77 #include <signal.h>
  78 #endif
  79 
  80 #ifdef HAVE_FCNTL_H
  81 #include <fcntl.h>
  82 #endif /* HAVE_FCNTL_H */
  83 
  84 #ifdef HAVE_GRP_H
  85 #include <grp.h>
  86 #endif
  87 
  88 #ifdef HAVE_SYSEXITS_H
  89 #include <sysexits.h>
  90 #endif /* HAVE_SYSEXITS_H */
  91 
  92 #ifdef HAVE_SYS_LOADAVG_H
  93 #include <sys/loadavg.h>
  94 #endif
  95 
  96 /* Various compilers have only certain posix functions */
  97 /* XXX Gosh I wish these were all moved into pyconfig.h */
  98 #if defined(PYCC_VACPP) && defined(PYOS_OS2)
  99 #include <process.h>
 100 #else
 101 #if defined(__WATCOMC__) && !defined(__QNX__)           /* Watcom compiler */
 102 #define HAVE_GETCWD     1
 103 #define HAVE_OPENDIR    1
 104 #define HAVE_SYSTEM     1
 105 #if defined(__OS2__)
 106 #define HAVE_EXECV      1
 107 #define HAVE_WAIT       1
 108 #endif
 109 #include <process.h>
 110 #else
 111 #ifdef __BORLANDC__             /* Borland compiler */
 112 #define HAVE_EXECV      1
 113 #define HAVE_GETCWD     1
 114 #define HAVE_OPENDIR    1
 115 #define HAVE_PIPE       1
 116 #define HAVE_POPEN      1
 117 #define HAVE_SYSTEM     1
 118 #define HAVE_WAIT       1
 119 #else
 120 #ifdef _MSC_VER         /* Microsoft compiler */
 121 #define HAVE_GETCWD     1
 122 #define HAVE_SPAWNV     1
 123 #define HAVE_EXECV      1
 124 #define HAVE_PIPE       1
 125 #define HAVE_POPEN      1
 126 #define HAVE_SYSTEM     1
 127 #define HAVE_CWAIT      1
 128 #define HAVE_FSYNC      1
 129 #define fsync _commit
 130 #else
 131 #if defined(PYOS_OS2) && defined(PYCC_GCC) || defined(__VMS)
 132 /* Everything needed is defined in PC/os2emx/pyconfig.h or vms/pyconfig.h */
 133 #else                   /* all other compilers */
 134 /* Unix functions that the configure script doesn't check for */
 135 #define HAVE_EXECV      1
 136 #define HAVE_FORK       1
 137 #if defined(__USLC__) && defined(__SCO_VERSION__)       /* SCO UDK Compiler */
 138 #define HAVE_FORK1      1
 139 #endif
 140 #define HAVE_GETCWD     1
 141 #define HAVE_GETEGID    1
 142 #define HAVE_GETEUID    1
 143 #define HAVE_GETGID     1
 144 #define HAVE_GETPPID    1
 145 #define HAVE_GETUID     1
 146 #define HAVE_KILL       1
 147 #define HAVE_OPENDIR    1
 148 #define HAVE_PIPE       1
 149 #ifndef __rtems__
 150 #define HAVE_POPEN      1
 151 #endif
 152 #define HAVE_SYSTEM     1
 153 #define HAVE_WAIT       1
 154 #define HAVE_TTYNAME    1
 155 #endif  /* PYOS_OS2 && PYCC_GCC && __VMS */
 156 #endif  /* _MSC_VER */
 157 #endif  /* __BORLANDC__ */
 158 #endif  /* ! __WATCOMC__ || __QNX__ */
 159 #endif /* ! __IBMC__ */
 160 
 161 #ifndef _MSC_VER
 162 
 163 #if defined(__sgi)&&_COMPILER_VERSION>=700
 164 /* declare ctermid_r if compiling with MIPSPro 7.x in ANSI C mode
 165    (default) */
 166 extern char        *ctermid_r(char *);
 167 #endif
 168 
 169 #ifndef HAVE_UNISTD_H
 170 #if defined(PYCC_VACPP)
 171 extern int mkdir(char *);
 172 #else
 173 #if ( defined(__WATCOMC__) || defined(_MSC_VER) ) && !defined(__QNX__)
 174 extern int mkdir(const char *);
 175 #else
 176 extern int mkdir(const char *, mode_t);
 177 #endif
 178 #endif
 179 #if defined(__IBMC__) || defined(__IBMCPP__)
 180 extern int chdir(char *);
 181 extern int rmdir(char *);
 182 #else
 183 extern int chdir(const char *);
 184 extern int rmdir(const char *);
 185 #endif
 186 #ifdef __BORLANDC__
 187 extern int chmod(const char *, int);
 188 #else
 189 extern int chmod(const char *, mode_t);
 190 #endif
 191 /*#ifdef HAVE_FCHMOD
 192 extern int fchmod(int, mode_t);
 193 #endif*/
 194 /*#ifdef HAVE_LCHMOD
 195 extern int lchmod(const char *, mode_t);
 196 #endif*/
 197 extern int chown(const char *, uid_t, gid_t);
 198 extern char *getcwd(char *, int);
 199 extern char *strerror(int);
 200 extern int link(const char *, const char *);
 201 extern int rename(const char *, const char *);
 202 extern int stat(const char *, struct stat *);
 203 extern int unlink(const char *);
 204 extern int pclose(FILE *);
 205 #ifdef HAVE_SYMLINK
 206 extern int symlink(const char *, const char *);
 207 #endif /* HAVE_SYMLINK */
 208 #ifdef HAVE_LSTAT
 209 extern int lstat(const char *, struct stat *);
 210 #endif /* HAVE_LSTAT */
 211 #endif /* !HAVE_UNISTD_H */
 212 
 213 #endif /* !_MSC_VER */
 214 
 215 #ifdef HAVE_UTIME_H
 216 #include <utime.h>
 217 #endif /* HAVE_UTIME_H */
 218 
 219 #ifdef HAVE_SYS_UTIME_H
 220 #include <sys/utime.h>
 221 #define HAVE_UTIME_H /* pretend we do for the rest of this file */
 222 #endif /* HAVE_SYS_UTIME_H */
 223 
 224 #ifdef HAVE_SYS_TIMES_H
 225 #include <sys/times.h>
 226 #endif /* HAVE_SYS_TIMES_H */
 227 
 228 #ifdef HAVE_SYS_PARAM_H
 229 #include <sys/param.h>
 230 #endif /* HAVE_SYS_PARAM_H */
 231 
 232 #ifdef HAVE_SYS_UTSNAME_H
 233 #include <sys/utsname.h>
 234 #endif /* HAVE_SYS_UTSNAME_H */
 235 
 236 #ifdef HAVE_DIRENT_H
 237 #include <dirent.h>
 238 #define NAMLEN(dirent) strlen((dirent)->d_name)
 239 #else
 240 #if defined(__WATCOMC__) && !defined(__QNX__)
 241 #include <direct.h>
 242 #define NAMLEN(dirent) strlen((dirent)->d_name)
 243 #else
 244 #define dirent direct
 245 #define NAMLEN(dirent) (dirent)->d_namlen
 246 #endif
 247 #ifdef HAVE_SYS_NDIR_H
 248 #include <sys/ndir.h>
 249 #endif
 250 #ifdef HAVE_SYS_DIR_H
 251 #include <sys/dir.h>
 252 #endif
 253 #ifdef HAVE_NDIR_H
 254 #include <ndir.h>
 255 #endif
 256 #endif
 257 
 258 #ifdef _MSC_VER
 259 #ifdef HAVE_DIRECT_H
 260 #include <direct.h>
 261 #endif
 262 #ifdef HAVE_IO_H
 263 #include <io.h>
 264 #endif
 265 #ifdef HAVE_PROCESS_H
 266 #include <process.h>
 267 #endif
 268 #include "osdefs.h"
 269 #include <malloc.h>
 270 #include <windows.h>
 271 #include <shellapi.h>   /* for ShellExecute() */
 272 #define popen   _popen
 273 #define pclose  _pclose
 274 #endif /* _MSC_VER */
 275 
 276 #if defined(PYCC_VACPP) && defined(PYOS_OS2)
 277 #include <io.h>
 278 #endif /* OS2 */
 279 
 280 #ifndef MAXPATHLEN
 281 #if defined(PATH_MAX) && PATH_MAX > 1024
 282 #define MAXPATHLEN PATH_MAX
 283 #else
 284 #define MAXPATHLEN 1024
 285 #endif
 286 #endif /* MAXPATHLEN */
 287 
 288 #ifdef UNION_WAIT
 289 /* Emulate some macros on systems that have a union instead of macros */
 290 
 291 #ifndef WIFEXITED
 292 #define WIFEXITED(u_wait) (!(u_wait).w_termsig && !(u_wait).w_coredump)
 293 #endif
 294 
 295 #ifndef WEXITSTATUS
 296 #define WEXITSTATUS(u_wait) (WIFEXITED(u_wait)?((u_wait).w_retcode):-1)
 297 #endif
 298 
 299 #ifndef WTERMSIG
 300 #define WTERMSIG(u_wait) ((u_wait).w_termsig)
 301 #endif
 302 
 303 #define WAIT_TYPE union wait
 304 #define WAIT_STATUS_INT(s) (s.w_status)
 305 
 306 #else /* !UNION_WAIT */
 307 #define WAIT_TYPE int
 308 #define WAIT_STATUS_INT(s) (s)
 309 #endif /* UNION_WAIT */
 310 
 311 /* Issue #1983: pid_t can be longer than a C long on some systems */
 312 #if !defined(SIZEOF_PID_T) || SIZEOF_PID_T == SIZEOF_INT
 313 #define PARSE_PID "i"
 314 #define PyLong_FromPid PyInt_FromLong
 315 #define PyLong_AsPid PyInt_AsLong
 316 #elif SIZEOF_PID_T == SIZEOF_LONG
 317 #define PARSE_PID "l"
 318 #define PyLong_FromPid PyInt_FromLong
 319 #define PyLong_AsPid PyInt_AsLong
 320 #elif defined(SIZEOF_LONG_LONG) && SIZEOF_PID_T == SIZEOF_LONG_LONG
 321 #define PARSE_PID "L"
 322 #define PyLong_FromPid PyLong_FromLongLong
 323 #define PyLong_AsPid PyInt_AsLongLong
 324 #else
 325 #error "sizeof(pid_t) is neither sizeof(int), sizeof(long) or sizeof(long long)"
 326 #endif /* SIZEOF_PID_T */
 327 
 328 /* Don't use the "_r" form if we don't need it (also, won't have a
 329    prototype for it, at least on Solaris -- maybe others as well?). */
 330 #if defined(HAVE_CTERMID_R) && defined(WITH_THREAD)
 331 #define USE_CTERMID_R
 332 #endif
 333 
 334 #if defined(HAVE_TMPNAM_R) && defined(WITH_THREAD)
 335 #define USE_TMPNAM_R
 336 #endif
 337 
 338 #if defined(MAJOR_IN_MKDEV)
 339 #include <sys/mkdev.h>
 340 #else
 341 #if defined(MAJOR_IN_SYSMACROS)
 342 #include <sys/sysmacros.h>
 343 #endif
 344 #if defined(HAVE_MKNOD) && defined(HAVE_SYS_MKDEV_H)
 345 #include <sys/mkdev.h>
 346 #endif
 347 #endif
 348 
 349 #if defined _MSC_VER && _MSC_VER >= 1400
 350 /* Microsoft CRT in VS2005 and higher will verify that a filehandle is
 351  * valid and throw an assertion if it isn't.
 352  * Normally, an invalid fd is likely to be a C program error and therefore
 353  * an assertion can be useful, but it does contradict the POSIX standard
 354  * which for write(2) states:
 355  *    "Otherwise, -1 shall be returned and errno set to indicate the error."
 356  *    "[EBADF] The fildes argument is not a valid file descriptor open for
 357  *     writing."
 358  * Furthermore, python allows the user to enter any old integer
 359  * as a fd and should merely raise a python exception on error.
 360  * The Microsoft CRT doesn't provide an official way to check for the
 361  * validity of a file descriptor, but we can emulate its internal behaviour
 362  * by using the exported __pinfo data member and knowledge of the
 363  * internal structures involved.
 364  * The structures below must be updated for each version of visual studio
 365  * according to the file internal.h in the CRT source, until MS comes
 366  * up with a less hacky way to do this.
 367  * (all of this is to avoid globally modifying the CRT behaviour using
 368  * _set_invalid_parameter_handler() and _CrtSetReportMode())
 369  */
 370 /* The actual size of the structure is determined at runtime.
 371  * Only the first items must be present.
 372  */
 373 typedef struct {
 374     intptr_t osfhnd;
 375     char osfile;
 376 } my_ioinfo;
 377 
 378 extern __declspec(dllimport) char * __pioinfo[];
 379 #define IOINFO_L2E 5
 380 #define IOINFO_ARRAY_ELTS   (1 << IOINFO_L2E)
 381 #define IOINFO_ARRAYS 64
 382 #define _NHANDLE_           (IOINFO_ARRAYS * IOINFO_ARRAY_ELTS)
 383 #define FOPEN 0x01
 384 #define _NO_CONSOLE_FILENO (intptr_t)-2
 385 
 386 /* This function emulates what the windows CRT does to validate file handles */
 387 int
 388 _PyVerify_fd(int fd)
 389 {
 390     const int i1 = fd >> IOINFO_L2E;
 391     const int i2 = fd & ((1 << IOINFO_L2E) - 1);
 392 
 393     static int sizeof_ioinfo = 0;
 394 
 395     /* Determine the actual size of the ioinfo structure,
 396      * as used by the CRT loaded in memory
 397      */
 398     if (sizeof_ioinfo == 0 && __pioinfo[0] != NULL) {
 399         sizeof_ioinfo = _msize(__pioinfo[0]) / IOINFO_ARRAY_ELTS;
 400     }
 401     if (sizeof_ioinfo == 0) {
 402         /* This should not happen... */
 403         goto fail;
 404     }
 405 
 406     /* See that it isn't a special CLEAR fileno */
 407     if (fd != _NO_CONSOLE_FILENO) {
 408         /* Microsoft CRT would check that 0<=fd<_nhandle but we can't do that.  Instead
 409          * we check pointer validity and other info
 410          */
 411         if (0 <= i1 && i1 < IOINFO_ARRAYS && __pioinfo[i1] != NULL) {
 412             /* finally, check that the file is open */
 413             my_ioinfo* info = (my_ioinfo*)(__pioinfo[i1] + i2 * sizeof_ioinfo);
 414             if (info->osfile & FOPEN) {
 415                 return 1;
 416             }
 417         }
 418     }
 419   fail:
 420     errno = EBADF;
 421     return 0;
 422 }
 423 
 424 /* the special case of checking dup2.  The target fd must be in a sensible range */
 425 static int
 426 _PyVerify_fd_dup2(int fd1, int fd2)
 427 {
 428     if (!_PyVerify_fd(fd1))
 429         return 0;
 430     if (fd2 == _NO_CONSOLE_FILENO)
 431         return 0;
 432     if ((unsigned)fd2 < _NHANDLE_)
 433         return 1;
 434     else
 435         return 0;
 436 }
 437 #else
 438 /* dummy version. _PyVerify_fd() is already defined in fileobject.h */
 439 #define _PyVerify_fd_dup2(A, B) (1)
 440 #endif
 441 
 442 /* Return a dictionary corresponding to the POSIX environment table */
 443 #ifdef WITH_NEXT_FRAMEWORK
 444 /* On Darwin/MacOSX a shared library or framework has no access to
 445 ** environ directly, we must obtain it with _NSGetEnviron().
 446 */
 447 #include <crt_externs.h>
 448 static char **environ;
 449 #elif !defined(_MSC_VER) && ( !defined(__WATCOMC__) || defined(__QNX__) )
 450 extern char **environ;
 451 #endif /* !_MSC_VER */
 452 
 453 static PyObject *
 454 convertenviron(void)
 455 {
 456     PyObject *d;
 457     char **e;
 458 #if defined(PYOS_OS2)
 459     APIRET rc;
 460     char   buffer[1024]; /* OS/2 Provides a Documented Max of 1024 Chars */
 461 #endif
 462     d = PyDict_New();
 463     if (d == NULL)
 464         return NULL;
 465 #ifdef WITH_NEXT_FRAMEWORK
 466     if (environ == NULL)
 467         environ = *_NSGetEnviron();
 468 #endif
 469     if (environ == NULL)
 470         return d;
 471     /* This part ignores errors */
 472     for (e = environ; *e != NULL; e++) {
 473         PyObject *k;
 474         PyObject *v;
 475         char *p = strchr(*e, '=');
 476         if (p == NULL)
 477             continue;
 478         k = PyString_FromStringAndSize(*e, (int)(p-*e));
 479         if (k == NULL) {
 480             PyErr_Clear();
 481             continue;
 482         }
 483         v = PyString_FromString(p+1);
 484         if (v == NULL) {
 485             PyErr_Clear();
 486             Py_DECREF(k);
 487             continue;
 488         }
 489         if (PyDict_GetItem(d, k) == NULL) {
 490             if (PyDict_SetItem(d, k, v) != 0)
 491                 PyErr_Clear();
 492         }
 493         Py_DECREF(k);
 494         Py_DECREF(v);
 495     }
 496 #if defined(PYOS_OS2)
 497     rc = DosQueryExtLIBPATH(buffer, BEGIN_LIBPATH);
 498     if (rc == NO_ERROR) { /* (not a type, envname is NOT 'BEGIN_LIBPATH') */
 499         PyObject *v = PyString_FromString(buffer);
 500             PyDict_SetItemString(d, "BEGINLIBPATH", v);
 501         Py_DECREF(v);
 502     }
 503     rc = DosQueryExtLIBPATH(buffer, END_LIBPATH);
 504     if (rc == NO_ERROR) { /* (not a typo, envname is NOT 'END_LIBPATH') */
 505         PyObject *v = PyString_FromString(buffer);
 506             PyDict_SetItemString(d, "ENDLIBPATH", v);
 507         Py_DECREF(v);
 508     }
 509 #endif
 510     return d;
 511 }
 512 
 513 
 514 /* Set a POSIX-specific error from errno, and return NULL */
 515 
 516 static PyObject *
 517 posix_error(void)
 518 {
 519     return PyErr_SetFromErrno(PyExc_OSError);
 520 }
 521 static PyObject *
 522 posix_error_with_filename(char* name)
 523 {
 524     return PyErr_SetFromErrnoWithFilename(PyExc_OSError, name);
 525 }
 526 
 527 #ifdef MS_WINDOWS
 528 static PyObject *
 529 posix_error_with_unicode_filename(Py_UNICODE* name)
 530 {
 531     return PyErr_SetFromErrnoWithUnicodeFilename(PyExc_OSError, name);
 532 }
 533 #endif /* MS_WINDOWS */
 534 
 535 
 536 static PyObject *
 537 posix_error_with_allocated_filename(char* name)
 538 {
 539     PyObject *rc = PyErr_SetFromErrnoWithFilename(PyExc_OSError, name);
 540     PyMem_Free(name);
 541     return rc;
 542 }
 543 
 544 #ifdef MS_WINDOWS
 545 static PyObject *
 546 win32_error(char* function, char* filename)
 547 {
 548     /* XXX We should pass the function name along in the future.
 549        (_winreg.c also wants to pass the function name.)
 550        This would however require an additional param to the
 551        Windows error object, which is non-trivial.
 552     */
 553     errno = GetLastError();
 554     if (filename)
 555         return PyErr_SetFromWindowsErrWithFilename(errno, filename);
 556     else
 557         return PyErr_SetFromWindowsErr(errno);
 558 }
 559 
 560 static PyObject *
 561 win32_error_unicode(char* function, Py_UNICODE* filename)
 562 {
 563     /* XXX - see win32_error for comments on 'function' */
 564     errno = GetLastError();
 565     if (filename)
 566         return PyErr_SetFromWindowsErrWithUnicodeFilename(errno, filename);
 567     else
 568         return PyErr_SetFromWindowsErr(errno);
 569 }
 570 
 571 static int
 572 convert_to_unicode(PyObject **param)
 573 {
 574     if (PyUnicode_CheckExact(*param))
 575         Py_INCREF(*param);
 576     else if (PyUnicode_Check(*param))
 577         /* For a Unicode subtype that's not a Unicode object,
 578            return a true Unicode object with the same data. */
 579         *param = PyUnicode_FromUnicode(PyUnicode_AS_UNICODE(*param),
 580                                        PyUnicode_GET_SIZE(*param));
 581     else
 582         *param = PyUnicode_FromEncodedObject(*param,
 583                                              Py_FileSystemDefaultEncoding,
 584                                              "strict");
 585     return (*param) != NULL;
 586 }
 587 
 588 #endif /* MS_WINDOWS */
 589 
 590 #if defined(PYOS_OS2)
 591 /**********************************************************************
 592  *         Helper Function to Trim and Format OS/2 Messages
 593  **********************************************************************/
 594 static void
 595 os2_formatmsg(char *msgbuf, int msglen, char *reason)
 596 {
 597     msgbuf[msglen] = '\0'; /* OS/2 Doesn't Guarantee a Terminator */
 598 
 599     if (strlen(msgbuf) > 0) { /* If Non-Empty Msg, Trim CRLF */
 600         char *lastc = &msgbuf[ strlen(msgbuf)-1 ];
 601 
 602         while (lastc > msgbuf && isspace(Py_CHARMASK(*lastc)))
 603             *lastc-- = '\0'; /* Trim Trailing Whitespace (CRLF) */
 604     }
 605 
 606     /* Add Optional Reason Text */
 607     if (reason) {
 608         strcat(msgbuf, " : ");
 609         strcat(msgbuf, reason);
 610     }
 611 }
 612 
 613 /**********************************************************************
 614  *             Decode an OS/2 Operating System Error Code
 615  *
 616  * A convenience function to lookup an OS/2 error code and return a
 617  * text message we can use to raise a Python exception.
 618  *
 619  * Notes:
 620  *   The messages for errors returned from the OS/2 kernel reside in
 621  *   the file OSO001.MSG in the \OS2 directory hierarchy.
 622  *
 623  **********************************************************************/
 624 static char *
 625 os2_strerror(char *msgbuf, int msgbuflen, int errorcode, char *reason)
 626 {
 627     APIRET rc;
 628     ULONG  msglen;
 629 
 630     /* Retrieve Kernel-Related Error Message from OSO001.MSG File */
 631     Py_BEGIN_ALLOW_THREADS
 632     rc = DosGetMessage(NULL, 0, msgbuf, msgbuflen,
 633                        errorcode, "oso001.msg", &msglen);
 634     Py_END_ALLOW_THREADS
 635 
 636     if (rc == NO_ERROR)
 637         os2_formatmsg(msgbuf, msglen, reason);
 638     else
 639         PyOS_snprintf(msgbuf, msgbuflen,
 640                       "unknown OS error #%d", errorcode);
 641 
 642     return msgbuf;
 643 }
 644 
 645 /* Set an OS/2-specific error and return NULL.  OS/2 kernel
 646    errors are not in a global variable e.g. 'errno' nor are
 647    they congruent with posix error numbers. */
 648 
 649 static PyObject *
 650 os2_error(int code)
 651 {
 652     char text[1024];
 653     PyObject *v;
 654 
 655     os2_strerror(text, sizeof(text), code, "");
 656 
 657     v = Py_BuildValue("(is)", code, text);
 658     if (v != NULL) {
 659         PyErr_SetObject(PyExc_OSError, v);
 660         Py_DECREF(v);
 661     }
 662     return NULL; /* Signal to Python that an Exception is Pending */
 663 }
 664 
 665 #endif /* OS2 */
 666 
 667 /* POSIX generic methods */
 668 
 669 static PyObject *
 670 posix_fildes(PyObject *fdobj, int (*func)(int))
 671 {
 672     int fd;
 673     int res;
 674     fd = PyObject_AsFileDescriptor(fdobj);
 675     if (fd < 0)
 676         return NULL;
 677     if (!_PyVerify_fd(fd))
 678         return posix_error();
 679     Py_BEGIN_ALLOW_THREADS
 680     res = (*func)(fd);
 681     Py_END_ALLOW_THREADS
 682     if (res < 0)
 683         return posix_error();
 684     Py_INCREF(Py_None);
 685     return Py_None;
 686 }
 687 
 688 static PyObject *
 689 posix_1str(PyObject *args, char *format, int (*func)(const char*))
 690 {
 691     char *path1 = NULL;
 692     int res;
 693     if (!PyArg_ParseTuple(args, format,
 694                           Py_FileSystemDefaultEncoding, &path1))
 695         return NULL;
 696     Py_BEGIN_ALLOW_THREADS
 697     res = (*func)(path1);
 698     Py_END_ALLOW_THREADS
 699     if (res < 0)
 700         return posix_error_with_allocated_filename(path1);
 701     PyMem_Free(path1);
 702     Py_INCREF(Py_None);
 703     return Py_None;
 704 }
 705 
 706 static PyObject *
 707 posix_2str(PyObject *args,
 708            char *format,
 709            int (*func)(const char *, const char *))
 710 {
 711     char *path1 = NULL, *path2 = NULL;
 712     int res;
 713     if (!PyArg_ParseTuple(args, format,
 714                           Py_FileSystemDefaultEncoding, &path1,
 715                           Py_FileSystemDefaultEncoding, &path2))
 716         return NULL;
 717     Py_BEGIN_ALLOW_THREADS
 718     res = (*func)(path1, path2);
 719     Py_END_ALLOW_THREADS
 720     PyMem_Free(path1);
 721     PyMem_Free(path2);
 722     if (res != 0)
 723         /* XXX how to report both path1 and path2??? */
 724         return posix_error();
 725     Py_INCREF(Py_None);
 726     return Py_None;
 727 }
 728 
 729 #ifdef MS_WINDOWS
 730 static PyObject*
 731 win32_1str(PyObject* args, char* func,
 732            char* format, BOOL (__stdcall *funcA)(LPCSTR),
 733            char* wformat, BOOL (__stdcall *funcW)(LPWSTR))
 734 {
 735     PyObject *uni;
 736     char *ansi;
 737     BOOL result;
 738 
 739     if (!PyArg_ParseTuple(args, wformat, &uni))
 740         PyErr_Clear();
 741     else {
 742         Py_BEGIN_ALLOW_THREADS
 743         result = funcW(PyUnicode_AsUnicode(uni));
 744         Py_END_ALLOW_THREADS
 745         if (!result)
 746             return win32_error_unicode(func, PyUnicode_AsUnicode(uni));
 747         Py_INCREF(Py_None);
 748         return Py_None;
 749     }
 750     if (!PyArg_ParseTuple(args, format, &ansi))
 751         return NULL;
 752     Py_BEGIN_ALLOW_THREADS
 753     result = funcA(ansi);
 754     Py_END_ALLOW_THREADS
 755     if (!result)
 756         return win32_error(func, ansi);
 757     Py_INCREF(Py_None);
 758     return Py_None;
 759 
 760 }
 761 
 762 /* This is a reimplementation of the C library's chdir function,
 763    but one that produces Win32 errors instead of DOS error codes.
 764    chdir is essentially a wrapper around SetCurrentDirectory; however,
 765    it also needs to set "magic" environment variables indicating
 766    the per-drive current directory, which are of the form =<drive>: */
 767 static BOOL __stdcall
 768 win32_chdir(LPCSTR path)
 769 {
 770     char new_path[MAX_PATH+1];
 771     int result;
 772     char env[4] = "=x:";
 773 
 774     if(!SetCurrentDirectoryA(path))
 775         return FALSE;
 776     result = GetCurrentDirectoryA(MAX_PATH+1, new_path);
 777     if (!result)
 778         return FALSE;
 779     /* In the ANSI API, there should not be any paths longer
 780        than MAX_PATH. */
 781     assert(result <= MAX_PATH+1);
 782     if (strncmp(new_path, "\\\\", 2) == 0 ||
 783         strncmp(new_path, "//", 2) == 0)
 784         /* UNC path, nothing to do. */
 785         return TRUE;
 786     env[1] = new_path[0];
 787     return SetEnvironmentVariableA(env, new_path);
 788 }
 789 
 790 /* The Unicode version differs from the ANSI version
 791    since the current directory might exceed MAX_PATH characters */
 792 static BOOL __stdcall
 793 win32_wchdir(LPCWSTR path)
 794 {
 795     wchar_t _new_path[MAX_PATH+1], *new_path = _new_path;
 796     int result;
 797     wchar_t env[4] = L"=x:";
 798 
 799     if(!SetCurrentDirectoryW(path))
 800         return FALSE;
 801     result = GetCurrentDirectoryW(MAX_PATH+1, new_path);
 802     if (!result)
 803         return FALSE;
 804     if (result > MAX_PATH+1) {
 805         new_path = malloc(result * sizeof(wchar_t));
 806         if (!new_path) {
 807             SetLastError(ERROR_OUTOFMEMORY);
 808             return FALSE;
 809         }
 810         result = GetCurrentDirectoryW(result, new_path);
 811         if (!result) {
 812             free(new_path);
 813             return FALSE;
 814         }
 815     }
 816     if (wcsncmp(new_path, L"\\\\", 2) == 0 ||
 817         wcsncmp(new_path, L"//", 2) == 0)
 818         /* UNC path, nothing to do. */
 819         return TRUE;
 820     env[1] = new_path[0];
 821     result = SetEnvironmentVariableW(env, new_path);
 822     if (new_path != _new_path)
 823         free(new_path);
 824     return result;
 825 }
 826 #endif
 827 
 828 /* choose the appropriate stat and fstat functions and return structs */
 829 #undef STAT
 830 #undef FSTAT
 831 #undef STRUCT_STAT
 832 #if defined(MS_WIN64) || defined(MS_WINDOWS)
 833 #       define STAT win32_stat
 834 #       define FSTAT win32_fstat
 835 #       define STRUCT_STAT struct win32_stat
 836 #else
 837 #       define STAT stat
 838 #       define FSTAT fstat
 839 #       define STRUCT_STAT struct stat
 840 #endif
 841 
 842 #ifdef MS_WINDOWS
 843 /* The CRT of Windows has a number of flaws wrt. its stat() implementation:
 844    - time stamps are restricted to second resolution
 845    - file modification times suffer from forth-and-back conversions between
 846      UTC and local time
 847    Therefore, we implement our own stat, based on the Win32 API directly.
 848 */
 849 #define HAVE_STAT_NSEC 1
 850 
 851 struct win32_stat{
 852     int st_dev;
 853     __int64 st_ino;
 854     unsigned short st_mode;
 855     int st_nlink;
 856     int st_uid;
 857     int st_gid;
 858     int st_rdev;
 859     __int64 st_size;
 860     time_t st_atime;
 861     int st_atime_nsec;
 862     time_t st_mtime;
 863     int st_mtime_nsec;
 864     time_t st_ctime;
 865     int st_ctime_nsec;
 866 };
 867 
 868 static __int64 secs_between_epochs = 11644473600; /* Seconds between 1.1.1601 and 1.1.1970 */
 869 
 870 static void
 871 FILE_TIME_to_time_t_nsec(FILETIME *in_ptr, time_t *time_out, int* nsec_out)
 872 {
 873     /* XXX endianness. Shouldn't matter, as all Windows implementations are little-endian */
 874     /* Cannot simply cast and dereference in_ptr,
 875        since it might not be aligned properly */
 876     __int64 in;
 877     memcpy(&in, in_ptr, sizeof(in));
 878     *nsec_out = (int)(in % 10000000) * 100; /* FILETIME is in units of 100 nsec. */
 879     *time_out = Py_SAFE_DOWNCAST((in / 10000000) - secs_between_epochs, __int64, time_t);
 880 }
 881 
 882 static void
 883 time_t_to_FILE_TIME(time_t time_in, int nsec_in, FILETIME *out_ptr)
 884 {
 885     /* XXX endianness */
 886     __int64 out;
 887     out = time_in + secs_between_epochs;
 888     out = out * 10000000 + nsec_in / 100;
 889     memcpy(out_ptr, &out, sizeof(out));
 890 }
 891 
 892 /* Below, we *know* that ugo+r is 0444 */
 893 #if _S_IREAD != 0400
 894 #error Unsupported C library
 895 #endif
 896 static int
 897 attributes_to_mode(DWORD attr)
 898 {
 899     int m = 0;
 900     if (attr & FILE_ATTRIBUTE_DIRECTORY)
 901         m |= _S_IFDIR | 0111; /* IFEXEC for user,group,other */
 902     else
 903         m |= _S_IFREG;
 904     if (attr & FILE_ATTRIBUTE_READONLY)
 905         m |= 0444;
 906     else
 907         m |= 0666;
 908     return m;
 909 }
 910 
 911 static int
 912 attribute_data_to_stat(WIN32_FILE_ATTRIBUTE_DATA *info, struct win32_stat *result)
 913 {
 914     memset(result, 0, sizeof(*result));
 915     result->st_mode = attributes_to_mode(info->dwFileAttributes);
 916     result->st_size = (((__int64)info->nFileSizeHigh)<<32) + info->nFileSizeLow;
 917     FILE_TIME_to_time_t_nsec(&info->ftCreationTime, &result->st_ctime, &result->st_ctime_nsec);
 918     FILE_TIME_to_time_t_nsec(&info->ftLastWriteTime, &result->st_mtime, &result->st_mtime_nsec);
 919     FILE_TIME_to_time_t_nsec(&info->ftLastAccessTime, &result->st_atime, &result->st_atime_nsec);
 920 
 921     return 0;
 922 }
 923 
 924 static BOOL
 925 attributes_from_dir(LPCSTR pszFile, LPWIN32_FILE_ATTRIBUTE_DATA pfad)
 926 {
 927     HANDLE hFindFile;
 928     WIN32_FIND_DATAA FileData;
 929     hFindFile = FindFirstFileA(pszFile, &FileData);
 930     if (hFindFile == INVALID_HANDLE_VALUE)
 931         return FALSE;
 932     FindClose(hFindFile);
 933     pfad->dwFileAttributes = FileData.dwFileAttributes;
 934     pfad->ftCreationTime   = FileData.ftCreationTime;
 935     pfad->ftLastAccessTime = FileData.ftLastAccessTime;
 936     pfad->ftLastWriteTime  = FileData.ftLastWriteTime;
 937     pfad->nFileSizeHigh    = FileData.nFileSizeHigh;
 938     pfad->nFileSizeLow     = FileData.nFileSizeLow;
 939     return TRUE;
 940 }
 941 
 942 static BOOL
 943 attributes_from_dir_w(LPCWSTR pszFile, LPWIN32_FILE_ATTRIBUTE_DATA pfad)
 944 {
 945     HANDLE hFindFile;
 946     WIN32_FIND_DATAW FileData;
 947     hFindFile = FindFirstFileW(pszFile, &FileData);
 948     if (hFindFile == INVALID_HANDLE_VALUE)
 949         return FALSE;
 950     FindClose(hFindFile);
 951     pfad->dwFileAttributes = FileData.dwFileAttributes;
 952     pfad->ftCreationTime   = FileData.ftCreationTime;
 953     pfad->ftLastAccessTime = FileData.ftLastAccessTime;
 954     pfad->ftLastWriteTime  = FileData.ftLastWriteTime;
 955     pfad->nFileSizeHigh    = FileData.nFileSizeHigh;
 956     pfad->nFileSizeLow     = FileData.nFileSizeLow;
 957     return TRUE;
 958 }
 959 
 960 static int
 961 win32_stat(const char* path, struct win32_stat *result)
 962 {
 963     WIN32_FILE_ATTRIBUTE_DATA info;
 964     int code;
 965     char *dot;
 966     if (!GetFileAttributesExA(path, GetFileExInfoStandard, &info)) {
 967         if (GetLastError() != ERROR_SHARING_VIOLATION) {
 968             /* Protocol violation: we explicitly clear errno, instead of
 969                setting it to a POSIX error. Callers should use GetLastError. */
 970             errno = 0;
 971             return -1;
 972         } else {
 973             /* Could not get attributes on open file. Fall back to
 974                reading the directory. */
 975             if (!attributes_from_dir(path, &info)) {
 976                 /* Very strange. This should not fail now */
 977                 errno = 0;
 978                 return -1;
 979             }
 980         }
 981     }
 982     code = attribute_data_to_stat(&info, result);
 983     if (code != 0)
 984         return code;
 985     /* Set S_IFEXEC if it is an .exe, .bat, ... */
 986     dot = strrchr(path, '.');
 987     if (dot) {
 988         if (stricmp(dot, ".bat") == 0 ||
 989         stricmp(dot, ".cmd") == 0 ||
 990         stricmp(dot, ".exe") == 0 ||
 991         stricmp(dot, ".com") == 0)
 992             result->st_mode |= 0111;
 993     }
 994     return code;
 995 }
 996 
 997 static int
 998 win32_wstat(const wchar_t* path, struct win32_stat *result)
 999 {
1000     int code;
1001     const wchar_t *dot;
1002     WIN32_FILE_ATTRIBUTE_DATA info;
1003     if (!GetFileAttributesExW(path, GetFileExInfoStandard, &info)) {
1004         if (GetLastError() != ERROR_SHARING_VIOLATION) {
1005             /* Protocol violation: we explicitly clear errno, instead of
1006                setting it to a POSIX error. Callers should use GetLastError. */
1007             errno = 0;
1008             return -1;
1009         } else {
1010             /* Could not get attributes on open file. Fall back to
1011                reading the directory. */
1012             if (!attributes_from_dir_w(path, &info)) {
1013                 /* Very strange. This should not fail now */
1014                 errno = 0;
1015                 return -1;
1016             }
1017         }
1018     }
1019     code = attribute_data_to_stat(&info, result);
1020     if (code < 0)
1021         return code;
1022     /* Set IFEXEC if it is an .exe, .bat, ... */
1023     dot = wcsrchr(path, '.');
1024     if (dot) {
1025         if (_wcsicmp(dot, L".bat") == 0 ||
1026             _wcsicmp(dot, L".cmd") == 0 ||
1027             _wcsicmp(dot, L".exe") == 0 ||
1028             _wcsicmp(dot, L".com") == 0)
1029             result->st_mode |= 0111;
1030     }
1031     return code;
1032 }
1033 
1034 static int
1035 win32_fstat(int file_number, struct win32_stat *result)
1036 {
1037     BY_HANDLE_FILE_INFORMATION info;
1038     HANDLE h;
1039     int type;
1040 
1041     h = (HANDLE)_get_osfhandle(file_number);
1042 
1043     /* Protocol violation: we explicitly clear errno, instead of
1044        setting it to a POSIX error. Callers should use GetLastError. */
1045     errno = 0;
1046 
1047     if (h == INVALID_HANDLE_VALUE) {
1048         /* This is really a C library error (invalid file handle).
1049            We set the Win32 error to the closes one matching. */
1050         SetLastError(ERROR_INVALID_HANDLE);
1051         return -1;
1052     }
1053     memset(result, 0, sizeof(*result));
1054 
1055     type = GetFileType(h);
1056     if (type == FILE_TYPE_UNKNOWN) {
1057         DWORD error = GetLastError();
1058         if (error != 0) {
1059         return -1;
1060         }
1061         /* else: valid but unknown file */
1062     }
1063 
1064     if (type != FILE_TYPE_DISK) {
1065         if (type == FILE_TYPE_CHAR)
1066             result->st_mode = _S_IFCHR;
1067         else if (type == FILE_TYPE_PIPE)
1068             result->st_mode = _S_IFIFO;
1069         return 0;
1070     }
1071 
1072     if (!GetFileInformationByHandle(h, &info)) {
1073         return -1;
1074     }
1075 
1076     /* similar to stat() */
1077     result->st_mode = attributes_to_mode(info.dwFileAttributes);
1078     result->st_size = (((__int64)info.nFileSizeHigh)<<32) + info.nFileSizeLow;
1079     FILE_TIME_to_time_t_nsec(&info.ftCreationTime, &result->st_ctime, &result->st_ctime_nsec);
1080     FILE_TIME_to_time_t_nsec(&info.ftLastWriteTime, &result->st_mtime, &result->st_mtime_nsec);
1081     FILE_TIME_to_time_t_nsec(&info.ftLastAccessTime, &result->st_atime, &result->st_atime_nsec);
1082     /* specific to fstat() */
1083     result->st_nlink = info.nNumberOfLinks;
1084     result->st_ino = (((__int64)info.nFileIndexHigh)<<32) + info.nFileIndexLow;
1085     return 0;
1086 }
1087 
1088 #endif /* MS_WINDOWS */
1089 
1090 PyDoc_STRVAR(stat_result__doc__,
1091 "stat_result: Result from stat or lstat.\n\n\
1092 This object may be accessed either as a tuple of\n\
1093   (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\
1094 or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\
1095 \n\
1096 Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\
1097 or st_flags, they are available as attributes only.\n\
1098 \n\
1099 See os.stat for more information.");
1100 
1101 static PyStructSequence_Field stat_result_fields[] = {
1102     {"st_mode",    "protection bits"},
1103     {"st_ino",     "inode"},
1104     {"st_dev",     "device"},
1105     {"st_nlink",   "number of hard links"},
1106     {"st_uid",     "user ID of owner"},
1107     {"st_gid",     "group ID of owner"},
1108     {"st_size",    "total size, in bytes"},
1109     /* The NULL is replaced with PyStructSequence_UnnamedField later. */
1110     {NULL,   "integer time of last access"},
1111     {NULL,   "integer time of last modification"},
1112     {NULL,   "integer time of last change"},
1113     {"st_atime",   "time of last access"},
1114     {"st_mtime",   "time of last modification"},
1115     {"st_ctime",   "time of last change"},
1116 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
1117     {"st_blksize", "blocksize for filesystem I/O"},
1118 #endif
1119 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
1120     {"st_blocks",  "number of blocks allocated"},
1121 #endif
1122 #ifdef HAVE_STRUCT_STAT_ST_RDEV
1123     {"st_rdev",    "device type (if inode device)"},
1124 #endif
1125 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
1126     {"st_flags",   "user defined flags for file"},
1127 #endif
1128 #ifdef HAVE_STRUCT_STAT_ST_GEN
1129     {"st_gen",    "generation number"},
1130 #endif
1131 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
1132     {"st_birthtime",   "time of creation"},
1133 #endif
1134     {0}
1135 };
1136 
1137 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
1138 #define ST_BLKSIZE_IDX 13
1139 #else
1140 #define ST_BLKSIZE_IDX 12
1141 #endif
1142 
1143 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
1144 #define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1)
1145 #else
1146 #define ST_BLOCKS_IDX ST_BLKSIZE_IDX
1147 #endif
1148 
1149 #ifdef HAVE_STRUCT_STAT_ST_RDEV
1150 #define ST_RDEV_IDX (ST_BLOCKS_IDX+1)
1151 #else
1152 #define ST_RDEV_IDX ST_BLOCKS_IDX
1153 #endif
1154 
1155 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
1156 #define ST_FLAGS_IDX (ST_RDEV_IDX+1)
1157 #else
1158 #define ST_FLAGS_IDX ST_RDEV_IDX
1159 #endif
1160 
1161 #ifdef HAVE_STRUCT_STAT_ST_GEN
1162 #define ST_GEN_IDX (ST_FLAGS_IDX+1)
1163 #else
1164 #define ST_GEN_IDX ST_FLAGS_IDX
1165 #endif
1166 
1167 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
1168 #define ST_BIRTHTIME_IDX (ST_GEN_IDX+1)
1169 #else
1170 #define ST_BIRTHTIME_IDX ST_GEN_IDX
1171 #endif
1172 
1173 static PyStructSequence_Desc stat_result_desc = {
1174     "stat_result", /* name */
1175     stat_result__doc__, /* doc */
1176     stat_result_fields,
1177     10
1178 };
1179 
1180 PyDoc_STRVAR(statvfs_result__doc__,
1181 "statvfs_result: Result from statvfs or fstatvfs.\n\n\
1182 This object may be accessed either as a tuple of\n\
1183   (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\
1184 or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\
1185 \n\
1186 See os.statvfs for more information.");
1187 
1188 static PyStructSequence_Field statvfs_result_fields[] = {
1189     {"f_bsize",  },
1190     {"f_frsize", },
1191     {"f_blocks", },
1192     {"f_bfree",  },
1193     {"f_bavail", },
1194     {"f_files",  },
1195     {"f_ffree",  },
1196     {"f_favail", },
1197     {"f_flag",   },
1198     {"f_namemax",},
1199     {0}
1200 };
1201 
1202 static PyStructSequence_Desc statvfs_result_desc = {
1203     "statvfs_result", /* name */
1204     statvfs_result__doc__, /* doc */
1205     statvfs_result_fields,
1206     10
1207 };
1208 
1209 static int initialized;
1210 static PyTypeObject StatResultType;
1211 static PyTypeObject StatVFSResultType;
1212 static newfunc structseq_new;
1213 
1214 static PyObject *
1215 statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1216 {
1217     PyStructSequence *result;
1218     int i;
1219 
1220     result = (PyStructSequence*)structseq_new(type, args, kwds);
1221     if (!result)
1222         return NULL;
1223     /* If we have been initialized from a tuple,
1224        st_?time might be set to None. Initialize it
1225        from the int slots.  */
1226     for (i = 7; i <= 9; i++) {
1227         if (result->ob_item[i+3] == Py_None) {
1228             Py_DECREF(Py_None);
1229             Py_INCREF(result->ob_item[i]);
1230             result->ob_item[i+3] = result->ob_item[i];
1231         }
1232     }
1233     return (PyObject*)result;
1234 }
1235 
1236 
1237 
1238 /* If true, st_?time is float. */
1239 static int _stat_float_times = 1;
1240 
1241 PyDoc_STRVAR(stat_float_times__doc__,
1242 "stat_float_times([newval]) -> oldval\n\n\
1243 Determine whether os.[lf]stat represents time stamps as float objects.\n\
1244 If newval is True, future calls to stat() return floats, if it is False,\n\
1245 future calls return ints. \n\
1246 If newval is omitted, return the current setting.\n");
1247 
1248 static PyObject*
1249 stat_float_times(PyObject* self, PyObject *args)
1250 {
1251     int newval = -1;
1252     if (!PyArg_ParseTuple(args, "|i:stat_float_times", &newval))
1253         return NULL;
1254     if (newval == -1)
1255         /* Return old value */
1256         return PyBool_FromLong(_stat_float_times);
1257     _stat_float_times = newval;
1258     Py_INCREF(Py_None);
1259     return Py_None;
1260 }
1261 
1262 static void
1263 fill_time(PyObject *v, int index, time_t sec, unsigned long nsec)
1264 {
1265     PyObject *fval,*ival;
1266 #if SIZEOF_TIME_T > SIZEOF_LONG
1267     ival = PyLong_FromLongLong((PY_LONG_LONG)sec);
1268 #else
1269     ival = PyInt_FromLong((long)sec);
1270 #endif
1271     if (!ival)
1272         return;
1273     if (_stat_float_times) {
1274         fval = PyFloat_FromDouble(sec + 1e-9*nsec);
1275     } else {
1276         fval = ival;
1277         Py_INCREF(fval);
1278     }
1279     PyStructSequence_SET_ITEM(v, index, ival);
1280     PyStructSequence_SET_ITEM(v, index+3, fval);
1281 }
1282 
1283 /* pack a system stat C structure into the Python stat tuple
1284    (used by posix_stat() and posix_fstat()) */
1285 static PyObject*
1286 _pystat_fromstructstat(STRUCT_STAT *st)
1287 {
1288     unsigned long ansec, mnsec, cnsec;
1289     PyObject *v = PyStructSequence_New(&StatResultType);
1290     if (v == NULL)
1291         return NULL;
1292 
1293     PyStructSequence_SET_ITEM(v, 0, PyInt_FromLong((long)st->st_mode));
1294 #ifdef HAVE_LARGEFILE_SUPPORT
1295     PyStructSequence_SET_ITEM(v, 1,
1296                               PyLong_FromLongLong((PY_LONG_LONG)st->st_ino));
1297 #else
1298     PyStructSequence_SET_ITEM(v, 1, PyInt_FromLong((long)st->st_ino));
1299 #endif
1300 #if defined(HAVE_LONG_LONG) && !defined(MS_WINDOWS)
1301     PyStructSequence_SET_ITEM(v, 2,
1302                               PyLong_FromLongLong((PY_LONG_LONG)st->st_dev));
1303 #else
1304     PyStructSequence_SET_ITEM(v, 2, PyInt_FromLong((long)st->st_dev));
1305 #endif
1306     PyStructSequence_SET_ITEM(v, 3, PyInt_FromLong((long)st->st_nlink));
1307     PyStructSequence_SET_ITEM(v, 4, _PyObject_FromUid(st->st_uid));
1308     PyStructSequence_SET_ITEM(v, 5, _PyObject_FromGid(st->st_gid));
1309 #ifdef HAVE_LARGEFILE_SUPPORT
1310     PyStructSequence_SET_ITEM(v, 6,
1311                               PyLong_FromLongLong((PY_LONG_LONG)st->st_size));
1312 #else
1313     PyStructSequence_SET_ITEM(v, 6, PyInt_FromLong(st->st_size));
1314 #endif
1315 
1316 #if defined(HAVE_STAT_TV_NSEC)
1317     ansec = st->st_atim.tv_nsec;
1318     mnsec = st->st_mtim.tv_nsec;
1319     cnsec = st->st_ctim.tv_nsec;
1320 #elif defined(HAVE_STAT_TV_NSEC2)
1321     ansec = st->st_atimespec.tv_nsec;
1322     mnsec = st->st_mtimespec.tv_nsec;
1323     cnsec = st->st_ctimespec.tv_nsec;
1324 #elif defined(HAVE_STAT_NSEC)
1325     ansec = st->st_atime_nsec;
1326     mnsec = st->st_mtime_nsec;
1327     cnsec = st->st_ctime_nsec;
1328 #else
1329     ansec = mnsec = cnsec = 0;
1330 #endif
1331     fill_time(v, 7, st->st_atime, ansec);
1332     fill_time(v, 8, st->st_mtime, mnsec);
1333     fill_time(v, 9, st->st_ctime, cnsec);
1334 
1335 #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
1336     PyStructSequence_SET_ITEM(v, ST_BLKSIZE_IDX,
1337                               PyInt_FromLong((long)st->st_blksize));
1338 #endif
1339 #ifdef HAVE_STRUCT_STAT_ST_BLOCKS
1340     PyStructSequence_SET_ITEM(v, ST_BLOCKS_IDX,
1341                               PyInt_FromLong((long)st->st_blocks));
1342 #endif
1343 #ifdef HAVE_STRUCT_STAT_ST_RDEV
1344     PyStructSequence_SET_ITEM(v, ST_RDEV_IDX,
1345                               PyInt_FromLong((long)st->st_rdev));
1346 #endif
1347 #ifdef HAVE_STRUCT_STAT_ST_GEN
1348     PyStructSequence_SET_ITEM(v, ST_GEN_IDX,
1349                               PyInt_FromLong((long)st->st_gen));
1350 #endif
1351 #ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
1352     {
1353       PyObject *val;
1354       unsigned long bsec,bnsec;
1355       bsec = (long)st->st_birthtime;
1356 #ifdef HAVE_STAT_TV_NSEC2
1357       bnsec = st->st_birthtimespec.tv_nsec;
1358 #else
1359       bnsec = 0;
1360 #endif
1361       if (_stat_float_times) {
1362         val = PyFloat_FromDouble(bsec + 1e-9*bnsec);
1363       } else {
1364         val = PyInt_FromLong((long)bsec);
1365       }
1366       PyStructSequence_SET_ITEM(v, ST_BIRTHTIME_IDX,
1367                                 val);
1368     }
1369 #endif
1370 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
1371     PyStructSequence_SET_ITEM(v, ST_FLAGS_IDX,
1372                               PyInt_FromLong((long)st->st_flags));
1373 #endif
1374 
1375     if (PyErr_Occurred()) {
1376         Py_DECREF(v);
1377         return NULL;
1378     }
1379 
1380     return v;
1381 }
1382 
1383 #ifdef MS_WINDOWS
1384 
1385 /* IsUNCRoot -- test whether the supplied path is of the form \\SERVER\SHARE\,
1386    where / can be used in place of \ and the trailing slash is optional.
1387    Both SERVER and SHARE must have at least one character.
1388 */
1389 
1390 #define ISSLASHA(c) ((c) == '\\' || (c) == '/')
1391 #define ISSLASHW(c) ((c) == L'\\' || (c) == L'/')
1392 #ifndef ARRAYSIZE
1393 #define ARRAYSIZE(a) (sizeof(a) / sizeof(a[0]))
1394 #endif
1395 
1396 static BOOL
1397 IsUNCRootA(char *path, int pathlen)
1398 {
1399     #define ISSLASH ISSLASHA
1400 
1401     int i, share;
1402 
1403     if (pathlen < 5 || !ISSLASH(path[0]) || !ISSLASH(path[1]))
1404         /* minimum UNCRoot is \\x\y */
1405         return FALSE;
1406     for (i = 2; i < pathlen ; i++)
1407         if (ISSLASH(path[i])) break;
1408     if (i == 2 || i == pathlen)
1409         /* do not allow \\\SHARE or \\SERVER */
1410         return FALSE;
1411     share = i+1;
1412     for (i = share; i < pathlen; i++)
1413         if (ISSLASH(path[i])) break;
1414     return (i != share && (i == pathlen || i == pathlen-1));
1415 
1416     #undef ISSLASH
1417 }
1418 
1419 static BOOL
1420 IsUNCRootW(Py_UNICODE *path, int pathlen)
1421 {
1422     #define ISSLASH ISSLASHW
1423 
1424     int i, share;
1425 
1426     if (pathlen < 5 || !ISSLASH(path[0]) || !ISSLASH(path[1]))
1427         /* minimum UNCRoot is \\x\y */
1428         return FALSE;
1429     for (i = 2; i < pathlen ; i++)
1430         if (ISSLASH(path[i])) break;
1431     if (i == 2 || i == pathlen)
1432         /* do not allow \\\SHARE or \\SERVER */
1433         return FALSE;
1434     share = i+1;
1435     for (i = share; i < pathlen; i++)
1436         if (ISSLASH(path[i])) break;
1437     return (i != share && (i == pathlen || i == pathlen-1));
1438 
1439     #undef ISSLASH
1440 }
1441 #endif /* MS_WINDOWS */
1442 
1443 static PyObject *
1444 posix_do_stat(PyObject *self, PyObject *args,
1445               char *format,
1446 #ifdef __VMS
1447               int (*statfunc)(const char *, STRUCT_STAT *, ...),
1448 #else
1449               int (*statfunc)(const char *, STRUCT_STAT *),
1450 #endif
1451               char *wformat,
1452               int (*wstatfunc)(const Py_UNICODE *, STRUCT_STAT *))
1453 {
1454     STRUCT_STAT st;
1455     char *path = NULL;          /* pass this to stat; do not free() it */
1456     char *pathfree = NULL;  /* this memory must be free'd */
1457     int res;
1458     PyObject *result;
1459 
1460 #ifdef MS_WINDOWS
1461     PyUnicodeObject *po;
1462     if (PyArg_ParseTuple(args, wformat, &po)) {
1463         Py_UNICODE *wpath = PyUnicode_AS_UNICODE(po);
1464 
1465         Py_BEGIN_ALLOW_THREADS
1466             /* PyUnicode_AS_UNICODE result OK without
1467                thread lock as it is a simple dereference. */
1468         res = wstatfunc(wpath, &st);
1469         Py_END_ALLOW_THREADS
1470 
1471         if (res != 0)
1472             return win32_error_unicode("stat", wpath);
1473         return _pystat_fromstructstat(&st);
1474     }
1475     /* Drop the argument parsing error as narrow strings
1476        are also valid. */
1477     PyErr_Clear();
1478 #endif
1479 
1480     if (!PyArg_ParseTuple(args, format,
1481                           Py_FileSystemDefaultEncoding, &path))
1482         return NULL;
1483     pathfree = path;
1484 
1485     Py_BEGIN_ALLOW_THREADS
1486     res = (*statfunc)(path, &st);
1487     Py_END_ALLOW_THREADS
1488 
1489     if (res != 0) {
1490 #ifdef MS_WINDOWS
1491         result = win32_error("stat", pathfree);
1492 #else
1493         result = posix_error_with_filename(pathfree);
1494 #endif
1495     }
1496     else
1497         result = _pystat_fromstructstat(&st);
1498 
1499     PyMem_Free(pathfree);
1500     return result;
1501 }
1502 
1503 /* POSIX methods */
1504 
1505 PyDoc_STRVAR(posix_access__doc__,
1506 "access(path, mode) -> True if granted, False otherwise\n\n\
1507 Use the real uid/gid to test for access to a path.  Note that most\n\
1508 operations will use the effective uid/gid, therefore this routine can\n\
1509 be used in a suid/sgid environment to test if the invoking user has the\n\
1510 specified access to the path.  The mode argument can be F_OK to test\n\
1511 existence, or the inclusive-OR of R_OK, W_OK, and X_OK.");
1512 
1513 static PyObject *
1514 posix_access(PyObject *self, PyObject *args)
1515 {
1516     char *path;
1517     int mode;
1518 
1519 #ifdef MS_WINDOWS
1520     DWORD attr;
1521     PyUnicodeObject *po;
1522     if (PyArg_ParseTuple(args, "Ui:access", &po, &mode)) {
1523         Py_BEGIN_ALLOW_THREADS
1524         /* PyUnicode_AS_UNICODE OK without thread lock as
1525            it is a simple dereference. */
1526         attr = GetFileAttributesW(PyUnicode_AS_UNICODE(po));
1527         Py_END_ALLOW_THREADS
1528         goto finish;
1529     }
1530     /* Drop the argument parsing error as narrow strings
1531        are also valid. */
1532     PyErr_Clear();
1533     if (!PyArg_ParseTuple(args, "eti:access",
1534                           Py_FileSystemDefaultEncoding, &path, &mode))
1535         return NULL;
1536     Py_BEGIN_ALLOW_THREADS
1537     attr = GetFileAttributesA(path);
1538     Py_END_ALLOW_THREADS
1539     PyMem_Free(path);
1540 finish:
1541     if (attr == 0xFFFFFFFF)
1542         /* File does not exist, or cannot read attributes */
1543         return PyBool_FromLong(0);
1544     /* Access is possible if either write access wasn't requested, or
1545        the file isn't read-only, or if it's a directory, as there are
1546        no read-only directories on Windows. */
1547     return PyBool_FromLong(!(mode & 2)
1548                            || !(attr & FILE_ATTRIBUTE_READONLY)
1549                            || (attr & FILE_ATTRIBUTE_DIRECTORY));
1550 #else /* MS_WINDOWS */
1551     int res;
1552     if (!PyArg_ParseTuple(args, "eti:access",
1553                           Py_FileSystemDefaultEncoding, &path, &mode))
1554         return NULL;
1555     Py_BEGIN_ALLOW_THREADS
1556     res = access(path, mode);
1557     Py_END_ALLOW_THREADS
1558     PyMem_Free(path);
1559     return PyBool_FromLong(res == 0);
1560 #endif /* MS_WINDOWS */
1561 }
1562 
1563 #ifndef F_OK
1564 #define F_OK 0
1565 #endif
1566 #ifndef R_OK
1567 #define R_OK 4
1568 #endif
1569 #ifndef W_OK
1570 #define W_OK 2
1571 #endif
1572 #ifndef X_OK
1573 #define X_OK 1
1574 #endif
1575 
1576 #ifdef HAVE_TTYNAME
1577 PyDoc_STRVAR(posix_ttyname__doc__,
1578 "ttyname(fd) -> string\n\n\
1579 Return the name of the terminal device connected to 'fd'.");
1580 
1581 static PyObject *
1582 posix_ttyname(PyObject *self, PyObject *args)
1583 {
1584     int id;
1585     char *ret;
1586 
1587     if (!PyArg_ParseTuple(args, "i:ttyname", &id))
1588         return NULL;
1589 
1590 #if defined(__VMS)
1591     /* file descriptor 0 only, the default input device (stdin) */
1592     if (id == 0) {
1593         ret = ttyname();
1594     }
1595     else {
1596         ret = NULL;
1597     }
1598 #else
1599     ret = ttyname(id);
1600 #endif
1601     if (ret == NULL)
1602         return posix_error();
1603     return PyString_FromString(ret);
1604 }
1605 #endif
1606 
1607 #ifdef HAVE_CTERMID
1608 PyDoc_STRVAR(posix_ctermid__doc__,
1609 "ctermid() -> string\n\n\
1610 Return the name of the controlling terminal for this process.");
1611 
1612 static PyObject *
1613 posix_ctermid(PyObject *self, PyObject *noargs)
1614 {
1615     char *ret;
1616     char buffer[L_ctermid];
1617 
1618 #ifdef USE_CTERMID_R
1619     ret = ctermid_r(buffer);
1620 #else
1621     ret = ctermid(buffer);
1622 #endif
1623     if (ret == NULL)
1624         return posix_error();
1625     return PyString_FromString(buffer);
1626 }
1627 #endif
1628 
1629 PyDoc_STRVAR(posix_chdir__doc__,
1630 "chdir(path)\n\n\
1631 Change the current working directory to the specified path.");
1632 
1633 static PyObject *
1634 posix_chdir(PyObject *self, PyObject *args)
1635 {
1636 #ifdef MS_WINDOWS
1637     return win32_1str(args, "chdir", "s:chdir", win32_chdir, "U:chdir", win32_wchdir);
1638 #elif defined(PYOS_OS2) && defined(PYCC_GCC)
1639     return posix_1str(args, "et:chdir", _chdir2);
1640 #elif defined(__VMS)
1641     return posix_1str(args, "et:chdir", (int (*)(const char *))chdir);
1642 #else
1643     return posix_1str(args, "et:chdir", chdir);
1644 #endif
1645 }
1646 
1647 #ifdef HAVE_FCHDIR
1648 PyDoc_STRVAR(posix_fchdir__doc__,
1649 "fchdir(fildes)\n\n\
1650 Change to the directory of the given file descriptor.  fildes must be\n\
1651 opened on a directory, not a file.");
1652 
1653 static PyObject *
1654 posix_fchdir(PyObject *self, PyObject *fdobj)
1655 {
1656     return posix_fildes(fdobj, fchdir);
1657 }
1658 #endif /* HAVE_FCHDIR */
1659 
1660 
1661 PyDoc_STRVAR(posix_chmod__doc__,
1662 "chmod(path, mode)\n\n\
1663 Change the access permissions of a file.");
1664 
1665 static PyObject *
1666 posix_chmod(PyObject *self, PyObject *args)
1667 {
1668     char *path = NULL;
1669     int i;
1670     int res;
1671 #ifdef MS_WINDOWS
1672     DWORD attr;
1673     PyUnicodeObject *po;
1674     if (PyArg_ParseTuple(args, "Ui|:chmod", &po, &i)) {
1675         Py_BEGIN_ALLOW_THREADS
1676         attr = GetFileAttributesW(PyUnicode_AS_UNICODE(po));
1677         if (attr != 0xFFFFFFFF) {
1678             if (i & _S_IWRITE)
1679                 attr &= ~FILE_ATTRIBUTE_READONLY;
1680             else
1681                 attr |= FILE_ATTRIBUTE_READONLY;
1682             res = SetFileAttributesW(PyUnicode_AS_UNICODE(po), attr);
1683         }
1684         else
1685             res = 0;
1686         Py_END_ALLOW_THREADS
1687         if (!res)
1688             return win32_error_unicode("chmod",
1689                                        PyUnicode_AS_UNICODE(po));
1690         Py_INCREF(Py_None);
1691         return Py_None;
1692     }
1693     /* Drop the argument parsing error as narrow strings
1694        are also valid. */
1695     PyErr_Clear();
1696 
1697     if (!PyArg_ParseTuple(args, "eti:chmod", Py_FileSystemDefaultEncoding,
1698                           &path, &i))
1699         return NULL;
1700     Py_BEGIN_ALLOW_THREADS
1701     attr = GetFileAttributesA(path);
1702     if (attr != 0xFFFFFFFF) {
1703         if (i & _S_IWRITE)
1704             attr &= ~FILE_ATTRIBUTE_READONLY;
1705         else
1706             attr |= FILE_ATTRIBUTE_READONLY;
1707         res = SetFileAttributesA(path, attr);
1708     }
1709     else
1710         res = 0;
1711     Py_END_ALLOW_THREADS
1712     if (!res) {
1713         win32_error("chmod", path);
1714         PyMem_Free(path);
1715         return NULL;
1716     }
1717     PyMem_Free(path);
1718     Py_INCREF(Py_None);
1719     return Py_None;
1720 #else /* MS_WINDOWS */
1721     if (!PyArg_ParseTuple(args, "eti:chmod", Py_FileSystemDefaultEncoding,
1722                           &path, &i))
1723         return NULL;
1724     Py_BEGIN_ALLOW_THREADS
1725     res = chmod(path, i);
1726     Py_END_ALLOW_THREADS
1727     if (res < 0)
1728         return posix_error_with_allocated_filename(path);
1729     PyMem_Free(path);
1730     Py_INCREF(Py_None);
1731     return Py_None;
1732 #endif
1733 }
1734 
1735 #ifdef HAVE_FCHMOD
1736 PyDoc_STRVAR(posix_fchmod__doc__,
1737 "fchmod(fd, mode)\n\n\
1738 Change the access permissions of the file given by file\n\
1739 descriptor fd.");
1740 
1741 static PyObject *
1742 posix_fchmod(PyObject *self, PyObject *args)
1743 {
1744     int fd, mode, res;
1745     if (!PyArg_ParseTuple(args, "ii:fchmod", &fd, &mode))
1746         return NULL;
1747     Py_BEGIN_ALLOW_THREADS
1748     res = fchmod(fd, mode);
1749     Py_END_ALLOW_THREADS
1750     if (res < 0)
1751         return posix_error();
1752     Py_RETURN_NONE;
1753 }
1754 #endif /* HAVE_FCHMOD */
1755 
1756 #ifdef HAVE_LCHMOD
1757 PyDoc_STRVAR(posix_lchmod__doc__,
1758 "lchmod(path, mode)\n\n\
1759 Change the access permissions of a file. If path is a symlink, this\n\
1760 affects the link itself rather than the target.");
1761 
1762 static PyObject *
1763 posix_lchmod(PyObject *self, PyObject *args)
1764 {
1765     char *path = NULL;
1766     int i;
1767     int res;
1768     if (!PyArg_ParseTuple(args, "eti:lchmod", Py_FileSystemDefaultEncoding,
1769                           &path, &i))
1770         return NULL;
1771     Py_BEGIN_ALLOW_THREADS
1772     res = lchmod(path, i);
1773     Py_END_ALLOW_THREADS
1774     if (res < 0)
1775         return posix_error_with_allocated_filename(path);
1776     PyMem_Free(path);
1777     Py_RETURN_NONE;
1778 }
1779 #endif /* HAVE_LCHMOD */
1780 
1781 
1782 #ifdef HAVE_CHFLAGS
1783 PyDoc_STRVAR(posix_chflags__doc__,
1784 "chflags(path, flags)\n\n\
1785 Set file flags.");
1786 
1787 static PyObject *
1788 posix_chflags(PyObject *self, PyObject *args)
1789 {
1790     char *path;
1791     unsigned long flags;
1792     int res;
1793     if (!PyArg_ParseTuple(args, "etk:chflags",
1794                           Py_FileSystemDefaultEncoding, &path, &flags))
1795         return NULL;
1796     Py_BEGIN_ALLOW_THREADS
1797     res = chflags(path, flags);
1798     Py_END_ALLOW_THREADS
1799     if (res < 0)
1800         return posix_error_with_allocated_filename(path);
1801     PyMem_Free(path);
1802     Py_INCREF(Py_None);
1803     return Py_None;
1804 }
1805 #endif /* HAVE_CHFLAGS */
1806 
1807 #ifdef HAVE_LCHFLAGS
1808 PyDoc_STRVAR(posix_lchflags__doc__,
1809 "lchflags(path, flags)\n\n\
1810 Set file flags.\n\
1811 This function will not follow symbolic links.");
1812 
1813 static PyObject *
1814 posix_lchflags(PyObject *self, PyObject *args)
1815 {
1816     char *path;
1817     unsigned long flags;
1818     int res;
1819     if (!PyArg_ParseTuple(args, "etk:lchflags",
1820                           Py_FileSystemDefaultEncoding, &path, &flags))
1821         return NULL;
1822     Py_BEGIN_ALLOW_THREADS
1823     res = lchflags(path, flags);
1824     Py_END_ALLOW_THREADS
1825     if (res < 0)
1826         return posix_error_with_allocated_filename(path);
1827     PyMem_Free(path);
1828     Py_INCREF(Py_None);
1829     return Py_None;
1830 }
1831 #endif /* HAVE_LCHFLAGS */
1832 
1833 #ifdef HAVE_CHROOT
1834 PyDoc_STRVAR(posix_chroot__doc__,
1835 "chroot(path)\n\n\
1836 Change root directory to path.");
1837 
1838 static PyObject *
1839 posix_chroot(PyObject *self, PyObject *args)
1840 {
1841     return posix_1str(args, "et:chroot", chroot);
1842 }
1843 #endif
1844 
1845 #ifdef HAVE_FSYNC
1846 PyDoc_STRVAR(posix_fsync__doc__,
1847 "fsync(fildes)\n\n\
1848 force write of file with filedescriptor to disk.");
1849 
1850 static PyObject *
1851 posix_fsync(PyObject *self, PyObject *fdobj)
1852 {
1853     return posix_fildes(fdobj, fsync);
1854 }
1855 #endif /* HAVE_FSYNC */
1856 
1857 #ifdef HAVE_FDATASYNC
1858 
1859 #ifdef __hpux
1860 extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */
1861 #endif
1862 
1863 PyDoc_STRVAR(posix_fdatasync__doc__,
1864 "fdatasync(fildes)\n\n\
1865 force write of file with filedescriptor to disk.\n\
1866  does not force update of metadata.");
1867 
1868 static PyObject *
1869 posix_fdatasync(PyObject *self, PyObject *fdobj)
1870 {
1871     return posix_fildes(fdobj, fdatasync);
1872 }
1873 #endif /* HAVE_FDATASYNC */
1874 
1875 
1876 #ifdef HAVE_CHOWN
1877 PyDoc_STRVAR(posix_chown__doc__,
1878 "chown(path, uid, gid)\n\n\
1879 Change the owner and group id of path to the numeric uid and gid.");
1880 
1881 static PyObject *
1882 posix_chown(PyObject *self, PyObject *args)
1883 {
1884     char *path = NULL;
1885     uid_t uid;
1886     gid_t gid;
1887     int res;
1888     if (!PyArg_ParseTuple(args, "etO&O&:chown",
1889                           Py_FileSystemDefaultEncoding, &path,
1890 			  _PyArg_ParseUid, &uid,
1891 			  _PyArg_ParseGid, &gid))
1892         return NULL;
1893     Py_BEGIN_ALLOW_THREADS
1894     res = chown(path, uid, gid);
1895     Py_END_ALLOW_THREADS
1896     if (res < 0)
1897         return posix_error_with_allocated_filename(path);
1898     PyMem_Free(path);
1899     Py_INCREF(Py_None);
1900     return Py_None;
1901 }
1902 #endif /* HAVE_CHOWN */
1903 
1904 #ifdef HAVE_FCHOWN
1905 PyDoc_STRVAR(posix_fchown__doc__,
1906 "fchown(fd, uid, gid)\n\n\
1907 Change the owner and group id of the file given by file descriptor\n\
1908 fd to the numeric uid and gid.");
1909 
1910 static PyObject *
1911 posix_fchown(PyObject *self, PyObject *args)
1912 {
1913     int fd;
1914     uid_t uid;
1915     gid_t gid;
1916     int res;
1917     if (!PyArg_ParseTuple(args, "iO&O&:chown", &fd,
1918 			  _PyArg_ParseUid, &uid,
1919 			  _PyArg_ParseGid, &gid))
1920         return NULL;
1921     Py_BEGIN_ALLOW_THREADS
1922     res = fchown(fd, uid, gid);
1923     Py_END_ALLOW_THREADS
1924     if (res < 0)
1925         return posix_error();
1926     Py_RETURN_NONE;
1927 }
1928 #endif /* HAVE_FCHOWN */
1929 
1930 #ifdef HAVE_LCHOWN
1931 PyDoc_STRVAR(posix_lchown__doc__,
1932 "lchown(path, uid, gid)\n\n\
1933 Change the owner and group id of path to the numeric uid and gid.\n\
1934 This function will not follow symbolic links.");
1935 
1936 static PyObject *
1937 posix_lchown(PyObject *self, PyObject *args)
1938 {
1939     char *path = NULL;
1940     uid_t uid;
1941     gid_t gid;
1942     int res;
1943     if (!PyArg_ParseTuple(args, "etO&O&:lchown",
1944                           Py_FileSystemDefaultEncoding, &path,
1945 			  _PyArg_ParseUid, &uid,
1946 			  _PyArg_ParseGid, &gid))
1947         return NULL;
1948     Py_BEGIN_ALLOW_THREADS
1949     res = lchown(path, uid, gid);
1950     Py_END_ALLOW_THREADS
1951     if (res < 0)
1952         return posix_error_with_allocated_filename(path);
1953     PyMem_Free(path);
1954     Py_INCREF(Py_None);
1955     return Py_None;
1956 }
1957 #endif /* HAVE_LCHOWN */
1958 
1959 
1960 #ifdef HAVE_GETCWD
1961 PyDoc_STRVAR(posix_getcwd__doc__,
1962 "getcwd() -> path\n\n\
1963 Return a string representing the current working directory.");
1964 
1965 #if (defined(__sun) && defined(__SVR4)) || defined(__OpenBSD__)
1966 /* Issue 9185: getcwd() returns NULL/ERANGE indefinitely. */
1967 static PyObject *
1968 posix_getcwd(PyObject *self, PyObject *noargs)
1969 {
1970     char buf[PATH_MAX+2];
1971     char *res;
1972 
1973     Py_BEGIN_ALLOW_THREADS
1974     res = getcwd(buf, sizeof buf);
1975     Py_END_ALLOW_THREADS
1976 
1977     if (res == NULL)
1978         return posix_error();
1979 
1980     return PyString_FromString(buf);
1981 }
1982 #else
1983 static PyObject *
1984 posix_getcwd(PyObject *self, PyObject *noargs)
1985 {
1986     int bufsize_incr = 1024;
1987     int bufsize = 0;
1988     char *tmpbuf = NULL;
1989     char *res = NULL;
1990     PyObject *dynamic_return;
1991 
1992     Py_BEGIN_ALLOW_THREADS
1993     do {
1994         bufsize = bufsize + bufsize_incr;
1995         tmpbuf = malloc(bufsize);
1996         if (tmpbuf == NULL) {
1997             break;
1998         }
1999 #if defined(PYOS_OS2) && defined(PYCC_GCC)
2000         res = _getcwd2(tmpbuf, bufsize);
2001 #else
2002         res = getcwd(tmpbuf, bufsize);
2003 #endif
2004 
2005         if (res == NULL) {
2006             free(tmpbuf);
2007         }
2008     } while ((res == NULL) && (errno == ERANGE));
2009     Py_END_ALLOW_THREADS
2010 
2011     if (res == NULL)
2012         return posix_error();
2013 
2014     dynamic_return = PyString_FromString(tmpbuf);
2015     free(tmpbuf);
2016 
2017     return dynamic_return;
2018 }
2019 #endif /* getcwd() NULL/ERANGE workaround. */
2020 
2021 #ifdef Py_USING_UNICODE
2022 PyDoc_STRVAR(posix_getcwdu__doc__,
2023 "getcwdu() -> path\n\n\
2024 Return a unicode string representing the current working directory.");
2025 
2026 static PyObject *
2027 posix_getcwdu(PyObject *self, PyObject *noargs)
2028 {
2029     char buf[1026];
2030     char *res;
2031 
2032 #ifdef MS_WINDOWS
2033     DWORD len;
2034     wchar_t wbuf[1026];
2035     wchar_t *wbuf2 = wbuf;
2036     PyObject *resobj;
2037     Py_BEGIN_ALLOW_THREADS
2038     len = GetCurrentDirectoryW(sizeof wbuf/ sizeof wbuf[0], wbuf);
2039     /* If the buffer is large enough, len does not include the
2040        terminating \0. If the buffer is too small, len includes
2041        the space needed for the terminator. */
2042     if (len >= sizeof wbuf/ sizeof wbuf[0]) {
2043         wbuf2 = malloc(len * sizeof(wchar_t));
2044         if (wbuf2)
2045             len = GetCurrentDirectoryW(len, wbuf2);
2046     }
2047     Py_END_ALLOW_THREADS
2048     if (!wbuf2) {
2049         PyErr_NoMemory();
2050         return NULL;
2051     }
2052     if (!len) {
2053         if (wbuf2 != wbuf) free(wbuf2);
2054         return win32_error("getcwdu", NULL);
2055     }
2056     resobj = PyUnicode_FromWideChar(wbuf2, len);
2057     if (wbuf2 != wbuf) free(wbuf2);
2058     return resobj;
2059 #endif /* MS_WINDOWS */
2060 
2061     Py_BEGIN_ALLOW_THREADS
2062 #if defined(PYOS_OS2) && defined(PYCC_GCC)
2063     res = _getcwd2(buf, sizeof buf);
2064 #else
2065     res = getcwd(buf, sizeof buf);
2066 #endif
2067     Py_END_ALLOW_THREADS
2068     if (res == NULL)
2069         return posix_error();
2070     return PyUnicode_Decode(buf, strlen(buf), Py_FileSystemDefaultEncoding,"strict");
2071 }
2072 #endif /* Py_USING_UNICODE */
2073 #endif /* HAVE_GETCWD */
2074 
2075 
2076 #ifdef HAVE_LINK
2077 PyDoc_STRVAR(posix_link__doc__,
2078 "link(src, dst)\n\n\
2079 Create a hard link to a file.");
2080 
2081 static PyObject *
2082 posix_link(PyObject *self, PyObject *args)
2083 {
2084     return posix_2str(args, "etet:link", link);
2085 }
2086 #endif /* HAVE_LINK */
2087 
2088 
2089 PyDoc_STRVAR(posix_listdir__doc__,
2090 "listdir(path) -> list_of_strings\n\n\
2091 Return a list containing the names of the entries in the directory.\n\
2092 \n\
2093     path: path of directory to list\n\
2094 \n\
2095 The list is in arbitrary order.  It does not include the special\n\
2096 entries '.' and '..' even if they are present in the directory.");
2097 
2098 static PyObject *
2099 posix_listdir(PyObject *self, PyObject *args)
2100 {
2101     /* XXX Should redo this putting the (now four) versions of opendir
2102        in separate files instead of having them all here... */
2103 #if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
2104 
2105     PyObject *d, *v;
2106     HANDLE hFindFile;
2107     BOOL result;
2108     WIN32_FIND_DATA FileData;
2109     char namebuf[MAX_PATH+5]; /* Overallocate for \\*.*\0 */
2110     char *bufptr = namebuf;
2111     Py_ssize_t len = sizeof(namebuf)-5; /* only claim to have space for MAX_PATH */
2112 
2113     PyObject *po;
2114     if (PyArg_ParseTuple(args, "U:listdir", &po)) {
2115         WIN32_FIND_DATAW wFileData;
2116         Py_UNICODE *wnamebuf;
2117         /* Overallocate for \\*.*\0 */
2118         len = PyUnicode_GET_SIZE(po);
2119         wnamebuf = malloc((len + 5) * sizeof(wchar_t));
2120         if (!wnamebuf) {
2121             PyErr_NoMemory();
2122             return NULL;
2123         }
2124         wcscpy(wnamebuf, PyUnicode_AS_UNICODE(po));
2125         if (len > 0) {
2126             Py_UNICODE wch = wnamebuf[len-1];
2127             if (wch != L'/' && wch != L'\\' && wch != L':')
2128                 wnamebuf[len++] = L'\\';
2129             wcscpy(wnamebuf + len, L"*.*");
2130         }
2131         if ((d = PyList_New(0)) == NULL) {
2132             free(wnamebuf);
2133             return NULL;
2134         }
2135         Py_BEGIN_ALLOW_THREADS
2136         hFindFile = FindFirstFileW(wnamebuf, &wFileData);
2137         Py_END_ALLOW_THREADS
2138         if (hFindFile == INVALID_HANDLE_VALUE) {
2139             int error = GetLastError();
2140             if (error == ERROR_FILE_NOT_FOUND) {
2141                 free(wnamebuf);
2142                 return d;
2143             }
2144             Py_DECREF(d);
2145             win32_error_unicode("FindFirstFileW", wnamebuf);
2146             free(wnamebuf);
2147             return NULL;
2148         }
2149         do {
2150             /* Skip over . and .. */
2151             if (wcscmp(wFileData.cFileName, L".") != 0 &&
2152                 wcscmp(wFileData.cFileName, L"..") != 0) {
2153                 v = PyUnicode_FromUnicode(wFileData.cFileName, wcslen(wFileData.cFileName));
2154                 if (v == NULL) {
2155                     Py_DECREF(d);
2156                     d = NULL;
2157                     break;
2158                 }
2159                 if (PyList_Append(d, v) != 0) {
2160                     Py_DECREF(v);
2161                     Py_DECREF(d);
2162                     d = NULL;
2163                     break;
2164                 }
2165                 Py_DECREF(v);
2166             }
2167             Py_BEGIN_ALLOW_THREADS
2168             result = FindNextFileW(hFindFile, &wFileData);
2169             Py_END_ALLOW_THREADS
2170             /* FindNextFile sets error to ERROR_NO_MORE_FILES if
2171                it got to the end of the directory. */
2172             if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
2173                 Py_DECREF(d);
2174                 win32_error_unicode("FindNextFileW", wnamebuf);
2175                 FindClose(hFindFile);
2176                 free(wnamebuf);
2177                 return NULL;
2178             }
2179         } while (result == TRUE);
2180 
2181         if (FindClose(hFindFile) == FALSE) {
2182             Py_DECREF(d);
2183             win32_error_unicode("FindClose", wnamebuf);
2184             free(wnamebuf);
2185             return NULL;
2186         }
2187         free(wnamebuf);
2188         return d;
2189     }
2190     /* Drop the argument parsing error as narrow strings
2191        are also valid. */
2192     PyErr_Clear();
2193 
2194     if (!PyArg_ParseTuple(args, "et#:listdir",
2195                           Py_FileSystemDefaultEncoding, &bufptr, &len))
2196         return NULL;
2197     if (len > 0) {
2198         char ch = namebuf[len-1];
2199         if (ch != SEP && ch != ALTSEP && ch != ':')
2200             namebuf[len++] = '/';
2201         strcpy(namebuf + len, "*.*");
2202     }
2203 
2204     if ((d = PyList_New(0)) == NULL)
2205         return NULL;
2206 
2207     Py_BEGIN_ALLOW_THREADS
2208     hFindFile = FindFirstFile(namebuf, &FileData);
2209     Py_END_ALLOW_THREADS
2210     if (hFindFile == INVALID_HANDLE_VALUE) {
2211         int error = GetLastError();
2212         if (error == ERROR_FILE_NOT_FOUND)
2213             return d;
2214         Py_DECREF(d);
2215         return win32_error("FindFirstFile", namebuf);
2216     }
2217     do {
2218         /* Skip over . and .. */
2219         if (strcmp(FileData.cFileName, ".") != 0 &&
2220             strcmp(FileData.cFileName, "..") != 0) {
2221             v = PyString_FromString(FileData.cFileName);
2222             if (v == NULL) {
2223                 Py_DECREF(d);
2224                 d = NULL;
2225                 break;
2226             }
2227             if (PyList_Append(d, v) != 0) {
2228                 Py_DECREF(v);
2229                 Py_DECREF(d);
2230                 d = NULL;
2231                 break;
2232             }
2233             Py_DECREF(v);
2234         }
2235         Py_BEGIN_ALLOW_THREADS
2236         result = FindNextFile(hFindFile, &FileData);
2237         Py_END_ALLOW_THREADS
2238         /* FindNextFile sets error to ERROR_NO_MORE_FILES if
2239            it got to the end of the directory. */
2240         if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
2241             Py_DECREF(d);
2242             win32_error("FindNextFile", namebuf);
2243             FindClose(hFindFile);
2244             return NULL;
2245         }
2246     } while (result == TRUE);
2247 
2248     if (FindClose(hFindFile) == FALSE) {
2249         Py_DECREF(d);
2250         return win32_error("FindClose", namebuf);
2251     }
2252 
2253     return d;
2254 
2255 #elif defined(PYOS_OS2)
2256 
2257 #ifndef MAX_PATH
2258 #define MAX_PATH    CCHMAXPATH
2259 #endif
2260     char *name, *pt;
2261     Py_ssize_t len;
2262     PyObject *d, *v;
2263     char namebuf[MAX_PATH+5];
2264     HDIR  hdir = 1;
2265     ULONG srchcnt = 1;
2266     FILEFINDBUF3   ep;
2267     APIRET rc;
2268 
2269     if (!PyArg_ParseTuple(args, "t#:listdir", &name, &len))
2270         return NULL;
2271     if (len >= MAX_PATH) {
2272         PyErr_SetString(PyExc_ValueError, "path too long");
2273         return NULL;
2274     }
2275     strcpy(namebuf, name);
2276     for (pt = namebuf; *pt; pt++)
2277         if (*pt == ALTSEP)
2278             *pt = SEP;
2279     if (namebuf[len-1] != SEP)
2280         namebuf[len++] = SEP;
2281     strcpy(namebuf + len, "*.*");
2282 
2283     if ((d = PyList_New(0)) == NULL)
2284         return NULL;
2285 
2286     rc = DosFindFirst(namebuf,         /* Wildcard Pattern to Match */
2287                       &hdir,           /* Handle to Use While Search Directory */
2288                       FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY,
2289                       &ep, sizeof(ep), /* Structure to Receive Directory Entry */
2290                       &srchcnt,        /* Max and Actual Count of Entries Per Iteration */
2291                       FIL_STANDARD);   /* Format of Entry (EAs or Not) */
2292 
2293     if (rc != NO_ERROR) {
2294         errno = ENOENT;
2295         return posix_error_with_filename(name);
2296     }
2297 
2298     if (srchcnt > 0) { /* If Directory is NOT Totally Empty, */
2299         do {
2300             if (ep.achName[0] == '.'
2301             && (ep.achName[1] == '\0' || (ep.achName[1] == '.' && ep.achName[2] == '\0')))
2302                 continue; /* Skip Over "." and ".." Names */
2303 
2304             strcpy(namebuf, ep.achName);
2305 
2306             /* Leave Case of Name Alone -- In Native Form */
2307             /* (Removed Forced Lowercasing Code) */
2308 
2309             v = PyString_FromString(namebuf);
2310             if (v == NULL) {
2311                 Py_DECREF(d);
2312                 d = NULL;
2313                 break;
2314             }
2315             if (PyList_Append(d, v) != 0) {
2316                 Py_DECREF(v);
2317                 Py_DECREF(d);
2318                 d = NULL;
2319                 break;
2320             }
2321             Py_DECREF(v);
2322         } while (DosFindNext(hdir, &ep, sizeof(ep), &srchcnt) == NO_ERROR && srchcnt > 0);
2323     }
2324 
2325     return d;
2326 #else
2327 
2328     char *name = NULL;
2329     PyObject *d, *v;
2330     DIR *dirp;
2331     struct dirent *ep;
2332     int arg_is_unicode = 1;
2333 
2334     errno = 0;
2335     if (!PyArg_ParseTuple(args, "U:listdir", &v)) {
2336         arg_is_unicode = 0;
2337         PyErr_Clear();
2338     }
2339     if (!PyArg_ParseTuple(args, "et:listdir", Py_FileSystemDefaultEncoding, &name))
2340         return NULL;
2341     Py_BEGIN_ALLOW_THREADS
2342     dirp = opendir(name);
2343     Py_END_ALLOW_THREADS
2344     if (dirp == NULL) {
2345         return posix_error_with_allocated_filename(name);
2346     }
2347     if ((d = PyList_New(0)) == NULL) {
2348         Py_BEGIN_ALLOW_THREADS
2349         closedir(dirp);
2350         Py_END_ALLOW_THREADS
2351         PyMem_Free(name);
2352         return NULL;
2353     }
2354     for (;;) {
2355         errno = 0;
2356         Py_BEGIN_ALLOW_THREADS
2357         ep = readdir(dirp);
2358         Py_END_ALLOW_THREADS
2359         if (ep == NULL) {
2360             if (errno == 0) {
2361                 break;
2362             } else {
2363                 Py_BEGIN_ALLOW_THREADS
2364                 closedir(dirp);
2365                 Py_END_ALLOW_THREADS
2366                 Py_DECREF(d);
2367                 return posix_error_with_allocated_filename(name);
2368             }
2369         }
2370         if (ep->d_name[0] == '.' &&
2371             (NAMLEN(ep) == 1 ||
2372              (ep->d_name[1] == '.' && NAMLEN(ep) == 2)))
2373             continue;
2374         v = PyString_FromStringAndSize(ep->d_name, NAMLEN(ep));
2375         if (v == NULL) {
2376             Py_DECREF(d);
2377             d = NULL;
2378             break;
2379         }
2380 #ifdef Py_USING_UNICODE
2381         if (arg_is_unicode) {
2382             PyObject *w;
2383 
2384             w = PyUnicode_FromEncodedObject(v,
2385                                             Py_FileSystemDefaultEncoding,
2386                                             "strict");
2387             if (w != NULL) {
2388                 Py_DECREF(v);
2389                 v = w;
2390             }
2391             else {
2392                 /* fall back to the original byte string, as
2393                    discussed in patch #683592 */
2394                 PyErr_Clear();
2395             }
2396         }
2397 #endif
2398         if (PyList_Append(d, v) != 0) {
2399             Py_DECREF(v);
2400             Py_DECREF(d);
2401             d = NULL;
2402             break;
2403         }
2404         Py_DECREF(v);
2405     }
2406     Py_BEGIN_ALLOW_THREADS
2407     closedir(dirp);
2408     Py_END_ALLOW_THREADS
2409     PyMem_Free(name);
2410 
2411     return d;
2412 
2413 #endif /* which OS */
2414 }  /* end of posix_listdir */
2415 
2416 #ifdef MS_WINDOWS
2417 /* A helper function for abspath on win32 */
2418 static PyObject *
2419 posix__getfullpathname(PyObject *self, PyObject *args)
2420 {
2421     /* assume encoded strings won't more than double no of chars */
2422     char inbuf[MAX_PATH*2];
2423     char *inbufp = inbuf;
2424     Py_ssize_t insize = sizeof(inbuf);
2425     char outbuf[MAX_PATH*2];
2426     char *temp;
2427 
2428     PyUnicodeObject *po;
2429     if (PyArg_ParseTuple(args, "U|:_getfullpathname", &po)) {
2430         Py_UNICODE *wpath = PyUnicode_AS_UNICODE(po);
2431         Py_UNICODE woutbuf[MAX_PATH*2], *woutbufp = woutbuf;
2432         Py_UNICODE *wtemp;
2433         DWORD result;
2434         PyObject *v;
2435         result = GetFullPathNameW(wpath,
2436                                   sizeof(woutbuf)/sizeof(woutbuf[0]),
2437                                   woutbuf, &wtemp);
2438         if (result > sizeof(woutbuf)/sizeof(woutbuf[0])) {
2439             woutbufp = malloc(result * sizeof(Py_UNICODE));
2440             if (!woutbufp)
2441                 return PyErr_NoMemory();
2442             result = GetFullPathNameW(wpath, result, woutbufp, &wtemp);
2443         }
2444         if (result)
2445             v = PyUnicode_FromUnicode(woutbufp, wcslen(woutbufp));
2446         else
2447             v = win32_error_unicode("GetFullPathNameW", wpath);
2448         if (woutbufp != woutbuf)
2449             free(woutbufp);
2450         return v;
2451     }
2452     /* Drop the argument parsing error as narrow strings
2453        are also valid. */
2454     PyErr_Clear();
2455 
2456     if (!PyArg_ParseTuple (args, "et#:_getfullpathname",
2457                            Py_FileSystemDefaultEncoding, &inbufp,
2458                            &insize))
2459         return NULL;
2460     if (!GetFullPathName(inbuf, sizeof(outbuf)/sizeof(outbuf[0]),
2461                          outbuf, &temp))
2462         return win32_error("GetFullPathName", inbuf);
2463     if (PyUnicode_Check(PyTuple_GetItem(args, 0))) {
2464         return PyUnicode_Decode(outbuf, strlen(outbuf),
2465                                 Py_FileSystemDefaultEncoding, NULL);
2466     }
2467     return PyString_FromString(outbuf);
2468 } /* end of posix__getfullpathname */
2469 #endif /* MS_WINDOWS */
2470 
2471 PyDoc_STRVAR(posix_mkdir__doc__,
2472 "mkdir(path [, mode=0777])\n\n\
2473 Create a directory.");
2474 
2475 static PyObject *
2476 posix_mkdir(PyObject *self, PyObject *args)
2477 {
2478     int res;
2479     char *path = NULL;
2480     int mode = 0777;
2481 
2482 #ifdef MS_WINDOWS
2483     PyUnicodeObject *po;
2484     if (PyArg_ParseTuple(args, "U|i:mkdir", &po, &mode)) {
2485         Py_BEGIN_ALLOW_THREADS
2486         /* PyUnicode_AS_UNICODE OK without thread lock as
2487            it is a simple dereference. */
2488         res = CreateDirectoryW(PyUnicode_AS_UNICODE(po), NULL);
2489         Py_END_ALLOW_THREADS
2490         if (!res)
2491             return win32_error_unicode("mkdir", PyUnicode_AS_UNICODE(po));
2492         Py_INCREF(Py_None);
2493         return Py_None;
2494     }
2495     /* Drop the argument parsing error as narrow strings
2496        are also valid. */
2497     PyErr_Clear();
2498     if (!PyArg_ParseTuple(args, "et|i:mkdir",
2499                           Py_FileSystemDefaultEncoding, &path, &mode))
2500         return NULL;
2501     Py_BEGIN_ALLOW_THREADS
2502     /* PyUnicode_AS_UNICODE OK without thread lock as
2503        it is a simple dereference. */
2504     res = CreateDirectoryA(path, NULL);
2505     Py_END_ALLOW_THREADS
2506     if (!res) {
2507         win32_error("mkdir", path);
2508         PyMem_Free(path);
2509         return NULL;
2510     }
2511     PyMem_Free(path);
2512     Py_INCREF(Py_None);
2513     return Py_None;
2514 #else /* MS_WINDOWS */
2515 
2516     if (!PyArg_ParseTuple(args, "et|i:mkdir",
2517                           Py_FileSystemDefaultEncoding, &path, &mode))
2518         return NULL;
2519     Py_BEGIN_ALLOW_THREADS
2520 #if ( defined(__WATCOMC__) || defined(PYCC_VACPP) ) && !defined(__QNX__)
2521     res = mkdir(path);
2522 #else
2523     res = mkdir(path, mode);
2524 #endif
2525     Py_END_ALLOW_THREADS
2526     if (res < 0)
2527         return posix_error_with_allocated_filename(path);
2528     PyMem_Free(path);
2529     Py_INCREF(Py_None);
2530     return Py_None;
2531 #endif /* MS_WINDOWS */
2532 }
2533 
2534 
2535 /* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */
2536 #if defined(HAVE_SYS_RESOURCE_H)
2537 #include <sys/resource.h>
2538 #endif
2539 
2540 
2541 #ifdef HAVE_NICE
2542 PyDoc_STRVAR(posix_nice__doc__,
2543 "nice(inc) -> new_priority\n\n\
2544 Decrease the priority of process by inc and return the new priority.");
2545 
2546 static PyObject *
2547 posix_nice(PyObject *self, PyObject *args)
2548 {
2549     int increment, value;
2550 
2551     if (!PyArg_ParseTuple(args, "i:nice", &increment))
2552         return NULL;
2553 
2554     /* There are two flavours of 'nice': one that returns the new
2555        priority (as required by almost all standards out there) and the
2556        Linux/FreeBSD/BSDI one, which returns '0' on success and advices
2557        the use of getpriority() to get the new priority.
2558 
2559        If we are of the nice family that returns the new priority, we
2560        need to clear errno before the call, and check if errno is filled
2561        before calling posix_error() on a returnvalue of -1, because the
2562        -1 may be the actual new priority! */
2563 
2564     errno = 0;
2565     value = nice(increment);
2566 #if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY)
2567     if (value == 0)
2568         value = getpriority(PRIO_PROCESS, 0);
2569 #endif
2570     if (value == -1 && errno != 0)
2571         /* either nice() or getpriority() returned an error */
2572         return posix_error();
2573     return PyInt_FromLong((long) value);
2574 }
2575 #endif /* HAVE_NICE */
2576 
2577 PyDoc_STRVAR(posix_rename__doc__,
2578 "rename(old, new)\n\n\
2579 Rename a file or directory.");
2580 
2581 static PyObject *
2582 posix_rename(PyObject *self, PyObject *args)
2583 {
2584 #ifdef MS_WINDOWS
2585     PyObject *o1, *o2;
2586     char *p1, *p2;
2587     BOOL result;
2588     if (!PyArg_ParseTuple(args, "OO:rename", &o1, &o2))
2589         goto error;
2590     if (!convert_to_unicode(&o1))
2591         goto error;
2592     if (!convert_to_unicode(&o2)) {
2593         Py_DECREF(o1);
2594         goto error;
2595     }
2596     Py_BEGIN_ALLOW_THREADS
2597     result = MoveFileW(PyUnicode_AsUnicode(o1),
2598                        PyUnicode_AsUnicode(o2));
2599     Py_END_ALLOW_THREADS
2600     Py_DECREF(o1);
2601     Py_DECREF(o2);
2602     if (!result)
2603         return win32_error("rename", NULL);
2604     Py_INCREF(Py_None);
2605     return Py_None;
2606 error:
2607     PyErr_Clear();
2608     if (!PyArg_ParseTuple(args, "ss:rename", &p1, &p2))
2609         return NULL;
2610     Py_BEGIN_ALLOW_THREADS
2611     result = MoveFileA(p1, p2);
2612     Py_END_ALLOW_THREADS
2613     if (!result)
2614         return win32_error("rename", NULL);
2615     Py_INCREF(Py_None);
2616     return Py_None;
2617 #else
2618     return posix_2str(args, "etet:rename", rename);
2619 #endif
2620 }
2621 
2622 
2623 PyDoc_STRVAR(posix_rmdir__doc__,
2624 "rmdir(path)\n\n\
2625 Remove a directory.");
2626 
2627 static PyObject *
2628 posix_rmdir(PyObject *self, PyObject *args)
2629 {
2630 #ifdef MS_WINDOWS
2631     return win32_1str(args, "rmdir", "s:rmdir", RemoveDirectoryA, "U:rmdir", RemoveDirectoryW);
2632 #else
2633     return posix_1str(args, "et:rmdir", rmdir);
2634 #endif
2635 }
2636 
2637 
2638 PyDoc_STRVAR(posix_stat__doc__,
2639 "stat(path) -> stat result\n\n\
2640 Perform a stat system call on the given path.");
2641 
2642 static PyObject *
2643 posix_stat(PyObject *self, PyObject *args)
2644 {
2645 #ifdef MS_WINDOWS
2646     return posix_do_stat(self, args, "et:stat", STAT, "U:stat", win32_wstat);
2647 #else
2648     return posix_do_stat(self, args, "et:stat", STAT, NULL, NULL);
2649 #endif
2650 }
2651 
2652 
2653 #ifdef HAVE_SYSTEM
2654 PyDoc_STRVAR(posix_system__doc__,
2655 "system(command) -> exit_status\n\n\
2656 Execute the command (a string) in a subshell.");
2657 
2658 static PyObject *
2659 posix_system(PyObject *self, PyObject *args)
2660 {
2661     char *command;
2662     long sts;
2663     if (!PyArg_ParseTuple(args, "s:system", &command))
2664         return NULL;
2665     Py_BEGIN_ALLOW_THREADS
2666     sts = system(command);
2667     Py_END_ALLOW_THREADS
2668     return PyInt_FromLong(sts);
2669 }
2670 #endif
2671 
2672 
2673 PyDoc_STRVAR(posix_umask__doc__,
2674 "umask(new_mask) -> old_mask\n\n\
2675 Set the current numeric umask and return the previous umask.");
2676 
2677 static PyObject *
2678 posix_umask(PyObject *self, PyObject *args)
2679 {
2680     int i;
2681     if (!PyArg_ParseTuple(args, "i:umask", &i))
2682         return NULL;
2683     i = (int)umask(i);
2684     if (i < 0)
2685         return posix_error();
2686     return PyInt_FromLong((long)i);
2687 }
2688 
2689 
2690 PyDoc_STRVAR(posix_unlink__doc__,
2691 "unlink(path)\n\n\
2692 Remove a file (same as remove(path)).");
2693 
2694 PyDoc_STRVAR(posix_remove__doc__,
2695 "remove(path)\n\n\
2696 Remove a file (same as unlink(path)).");
2697 
2698 static PyObject *
2699 posix_unlink(PyObject *self, PyObject *args)
2700 {
2701 #ifdef MS_WINDOWS
2702     return win32_1str(args, "remove", "s:remove", DeleteFileA, "U:remove", DeleteFileW);
2703 #else
2704     return posix_1str(args, "et:remove", unlink);
2705 #endif
2706 }
2707 
2708 
2709 #ifdef HAVE_UNAME
2710 PyDoc_STRVAR(posix_uname__doc__,
2711 "uname() -> (sysname, nodename, release, version, machine)\n\n\
2712 Return a tuple identifying the current operating system.");
2713 
2714 static PyObject *
2715 posix_uname(PyObject *self, PyObject *noargs)
2716 {
2717     struct utsname u;
2718     int res;
2719 
2720     Py_BEGIN_ALLOW_THREADS
2721     res = uname(&u);
2722     Py_END_ALLOW_THREADS
2723     if (res < 0)
2724         return posix_error();
2725     return Py_BuildValue("(sssss)",
2726                          u.sysname,
2727                          u.nodename,
2728                          u.release,
2729                          u.version,
2730                          u.machine);
2731 }
2732 #endif /* HAVE_UNAME */
2733 
2734 static int
2735 extract_time(PyObject *t, time_t* sec, long* usec)
2736 {
2737     time_t intval;
2738     if (PyFloat_Check(t)) {
2739         double tval = PyFloat_AsDouble(t);
2740         PyObject *intobj = PyNumber_Long(t);
2741         if (!intobj)
2742             return -1;
2743 #if SIZEOF_TIME_T > SIZEOF_LONG
2744         intval = PyInt_AsUnsignedLongLongMask(intobj);
2745 #else
2746         intval = PyInt_AsLong(intobj);
2747 #endif
2748         Py_DECREF(intobj);
2749         if (intval == -1 && PyErr_Occurred())
2750             return -1;
2751         *sec = intval;
2752         *usec = (long)((tval - intval) * 1e6); /* can't exceed 1000000 */
2753         if (*usec < 0)
2754             /* If rounding gave us a negative number,
2755                truncate.  */
2756             *usec = 0;
2757         return 0;
2758     }
2759 #if SIZEOF_TIME_T > SIZEOF_LONG
2760     intval = PyInt_AsUnsignedLongLongMask(t);
2761 #else
2762     intval = PyInt_AsLong(t);
2763 #endif
2764     if (intval == -1 && PyErr_Occurred())
2765         return -1;
2766     *sec = intval;
2767     *usec = 0;
2768     return 0;
2769 }
2770 
2771 PyDoc_STRVAR(posix_utime__doc__,
2772 "utime(path, (atime, mtime))\n\
2773 utime(path, None)\n\n\
2774 Set the access and modified time of the file to the given values.  If the\n\
2775 second form is used, set the access and modified times to the current time.");
2776 
2777 static PyObject *
2778 posix_utime(PyObject *self, PyObject *args)
2779 {
2780 #ifdef MS_WINDOWS
2781     PyObject *arg;
2782     PyUnicodeObject *obwpath;
2783     wchar_t *wpath = NULL;
2784     char *apath = NULL;
2785     HANDLE hFile;
2786     time_t atimesec, mtimesec;
2787     long ausec, musec;
2788     FILETIME atime, mtime;
2789     PyObject *result = NULL;
2790 
2791     if (PyArg_ParseTuple(args, "UO|:utime", &obwpath, &arg)) {
2792         wpath = PyUnicode_AS_UNICODE(obwpath);
2793         Py_BEGIN_ALLOW_THREADS
2794         hFile = CreateFileW(wpath, FILE_WRITE_ATTRIBUTES, 0,
2795                             NULL, OPEN_EXISTING,
2796                             FILE_FLAG_BACKUP_SEMANTICS, NULL);
2797         Py_END_ALLOW_THREADS
2798         if (hFile == INVALID_HANDLE_VALUE)
2799             return win32_error_unicode("utime", wpath);
2800     } else
2801         /* Drop the argument parsing error as narrow strings
2802            are also valid. */
2803         PyErr_Clear();
2804 
2805     if (!wpath) {
2806         if (!PyArg_ParseTuple(args, "etO:utime",
2807                               Py_FileSystemDefaultEncoding, &apath, &arg))
2808             return NULL;
2809         Py_BEGIN_ALLOW_THREADS
2810         hFile = CreateFileA(apath, FILE_WRITE_ATTRIBUTES, 0,
2811                             NULL, OPEN_EXISTING,
2812                             FILE_FLAG_BACKUP_SEMANTICS, NULL);
2813         Py_END_ALLOW_THREADS
2814         if (hFile == INVALID_HANDLE_VALUE) {
2815             win32_error("utime", apath);
2816             PyMem_Free(apath);
2817             return NULL;
2818         }
2819         PyMem_Free(apath);
2820     }
2821 
2822     if (arg == Py_None) {
2823         SYSTEMTIME now;
2824         GetSystemTime(&now);
2825         if (!SystemTimeToFileTime(&now, &mtime) ||
2826             !SystemTimeToFileTime(&now, &atime)) {
2827             win32_error("utime", NULL);
2828             goto done;
2829         }
2830     }
2831     else if (!PyTuple_Check(arg) || PyTuple_Size(arg) != 2) {
2832         PyErr_SetString(PyExc_TypeError,
2833                         "utime() arg 2 must be a tuple (atime, mtime)");
2834         goto done;
2835     }
2836     else {
2837         if (extract_time(PyTuple_GET_ITEM(arg, 0),
2838                          &atimesec, &ausec) == -1)
2839             goto done;
2840         time_t_to_FILE_TIME(atimesec, 1000*ausec, &atime);
2841         if (extract_time(PyTuple_GET_ITEM(arg, 1),
2842                          &mtimesec, &musec) == -1)
2843             goto done;
2844         time_t_to_FILE_TIME(mtimesec, 1000*musec, &mtime);
2845     }
2846     if (!SetFileTime(hFile, NULL, &atime, &mtime)) {
2847         /* Avoid putting the file name into the error here,
2848            as that may confuse the user into believing that
2849            something is wrong with the file, when it also
2850            could be the time stamp that gives a problem. */
2851         win32_error("utime", NULL);
2852         goto done;
2853     }
2854     Py_INCREF(Py_None);
2855     result = Py_None;
2856 done:
2857     CloseHandle(hFile);
2858     return result;
2859 #else /* MS_WINDOWS */
2860 
2861     char *path = NULL;
2862     time_t atime, mtime;
2863     long ausec, musec;
2864     int res;
2865     PyObject* arg;
2866 
2867 #if defined(HAVE_UTIMES)
2868     struct timeval buf[2];
2869 #define ATIME buf[0].tv_sec
2870 #define MTIME buf[1].tv_sec
2871 #elif defined(HAVE_UTIME_H)
2872 /* XXX should define struct utimbuf instead, above */
2873     struct utimbuf buf;
2874 #define ATIME buf.actime
2875 #define MTIME buf.modtime
2876 #define UTIME_ARG &buf
2877 #else /* HAVE_UTIMES */
2878     time_t buf[2];
2879 #define ATIME buf[0]
2880 #define MTIME buf[1]
2881 #define UTIME_ARG buf
2882 #endif /* HAVE_UTIMES */
2883 
2884 
2885     if (!PyArg_ParseTuple(args, "etO:utime",
2886                           Py_FileSystemDefaultEncoding, &path, &arg))
2887         return NULL;
2888     if (arg == Py_None) {
2889         /* optional time values not given */
2890         Py_BEGIN_ALLOW_THREADS
2891         res = utime(path, NULL);
2892         Py_END_ALLOW_THREADS
2893     }
2894     else if (!PyTuple_Check(arg) || PyTuple_Size(arg) != 2) {
2895         PyErr_SetString(PyExc_TypeError,
2896                         "utime() arg 2 must be a tuple (atime, mtime)");
2897         PyMem_Free(path);
2898         return NULL;
2899     }
2900     else {
2901         if (extract_time(PyTuple_GET_ITEM(arg, 0),
2902                          &atime, &ausec) == -1) {
2903             PyMem_Free(path);
2904             return NULL;
2905         }
2906         if (extract_time(PyTuple_GET_ITEM(arg, 1),
2907                          &mtime, &musec) == -1) {
2908             PyMem_Free(path);
2909             return NULL;
2910         }
2911         ATIME = atime;
2912         MTIME = mtime;
2913 #ifdef HAVE_UTIMES
2914         buf[0].tv_usec = ausec;
2915         buf[1].tv_usec = musec;
2916         Py_BEGIN_ALLOW_THREADS
2917         res = utimes(path, buf);
2918         Py_END_ALLOW_THREADS
2919 #else
2920         Py_BEGIN_ALLOW_THREADS
2921         res = utime(path, UTIME_ARG);
2922         Py_END_ALLOW_THREADS
2923 #endif /* HAVE_UTIMES */
2924     }
2925     if (res < 0) {
2926         return posix_error_with_allocated_filename(path);
Uninitialized variable: res
(emitted by cppcheck)
Uninitialized variable: res
(emitted by cppcheck)
2927 } 2928 PyMem_Free(path); 2929 Py_INCREF(Py_None); 2930 return Py_None; 2931 #undef UTIME_ARG 2932 #undef ATIME 2933 #undef MTIME 2934 #endif /* MS_WINDOWS */ 2935 } 2936 2937 2938 /* Process operations */ 2939 2940 PyDoc_STRVAR(posix__exit__doc__, 2941 "_exit(status)\n\n\ 2942 Exit to the system with specified status, without normal exit processing."); 2943 2944 static PyObject * 2945 posix__exit(PyObject *self, PyObject *args) 2946 { 2947 int sts; 2948 if (!PyArg_ParseTuple(args, "i:_exit", &sts)) 2949 return NULL; 2950 _exit(sts); 2951 return NULL; /* Make gcc -Wall happy */ 2952 } 2953 2954 #if defined(HAVE_EXECV) || defined(HAVE_SPAWNV) 2955 static void 2956 free_string_array(char **array, Py_ssize_t count) 2957 { 2958 Py_ssize_t i; 2959 for (i = 0; i < count; i++) 2960 PyMem_Free(array[i]); 2961 PyMem_DEL(array); 2962 } 2963 #endif 2964 2965 2966 #ifdef HAVE_EXECV 2967 PyDoc_STRVAR(posix_execv__doc__, 2968 "execv(path, args)\n\n\ 2969 Execute an executable path with arguments, replacing current process.\n\ 2970 \n\ 2971 path: path of executable file\n\ 2972 args: tuple or list of strings"); 2973 2974 static PyObject * 2975 posix_execv(PyObject *self, PyObject *args) 2976 { 2977 char *path; 2978 PyObject *argv; 2979 char **argvlist; 2980 Py_ssize_t i, argc; 2981 PyObject *(*getitem)(PyObject *, Py_ssize_t); 2982 2983 /* execv has two arguments: (path, argv), where 2984 argv is a list or tuple of strings. */ 2985 2986 if (!PyArg_ParseTuple(args, "etO:execv", 2987 Py_FileSystemDefaultEncoding, 2988 &path, &argv)) 2989 return NULL; 2990 if (PyList_Check(argv)) { 2991 argc = PyList_Size(argv); 2992 getitem = PyList_GetItem; 2993 } 2994 else if (PyTuple_Check(argv)) { 2995 argc = PyTuple_Size(argv); 2996 getitem = PyTuple_GetItem; 2997 } 2998 else { 2999 PyErr_SetString(PyExc_TypeError, "execv() arg 2 must be a tuple or list"); 3000 PyMem_Free(path); 3001 return NULL; 3002 } 3003 if (argc < 1) { 3004 PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty"); 3005 PyMem_Free(path); 3006 return NULL; 3007 } 3008 3009 argvlist = PyMem_NEW(char *, argc+1); 3010 if (argvlist == NULL) { 3011 PyMem_Free(path); 3012 return PyErr_NoMemory(); 3013 } 3014 for (i = 0; i < argc; i++) { 3015 if (!PyArg_Parse((*getitem)(argv, i), "et", 3016 Py_FileSystemDefaultEncoding, 3017 &argvlist[i])) { 3018 free_string_array(argvlist, i); 3019 PyErr_SetString(PyExc_TypeError, 3020 "execv() arg 2 must contain only strings"); 3021 PyMem_Free(path); 3022 return NULL; 3023 3024 } 3025 } 3026 argvlist[argc] = NULL; 3027 3028 execv(path, argvlist); 3029 3030 /* If we get here it's definitely an error */ 3031 3032 free_string_array(argvlist, argc); 3033 PyMem_Free(path); 3034 return posix_error(); 3035 } 3036 3037 3038 PyDoc_STRVAR(posix_execve__doc__, 3039 "execve(path, args, env)\n\n\ 3040 Execute a path with arguments and environment, replacing current process.\n\ 3041 \n\ 3042 path: path of executable file\n\ 3043 args: tuple or list of arguments\n\ 3044 env: dictionary of strings mapping to strings"); 3045 3046 static PyObject * 3047 posix_execve(PyObject *self, PyObject *args) 3048 { 3049 char *path; 3050 PyObject *argv, *env; 3051 char **argvlist; 3052 char **envlist; 3053 PyObject *key, *val, *keys=NULL, *vals=NULL; 3054 Py_ssize_t i, pos, argc, envc; 3055 PyObject *(*getitem)(PyObject *, Py_ssize_t); 3056 Py_ssize_t lastarg = 0; 3057 3058 /* execve has three arguments: (path, argv, env), where 3059 argv is a list or tuple of strings and env is a dictionary 3060 like posix.environ. */ 3061 3062 if (!PyArg_ParseTuple(args, "etOO:execve", 3063 Py_FileSystemDefaultEncoding, 3064 &path, &argv, &env)) 3065 return NULL; 3066 if (PyList_Check(argv)) { 3067 argc = PyList_Size(argv); 3068 getitem = PyList_GetItem; 3069 } 3070 else if (PyTuple_Check(argv)) { 3071 argc = PyTuple_Size(argv); 3072 getitem = PyTuple_GetItem; 3073 } 3074 else { 3075 PyErr_SetString(PyExc_TypeError, 3076 "execve() arg 2 must be a tuple or list"); 3077 goto fail_0; 3078 } 3079 if (!PyMapping_Check(env)) { 3080 PyErr_SetString(PyExc_TypeError, 3081 "execve() arg 3 must be a mapping object"); 3082 goto fail_0; 3083 } 3084 3085 argvlist = PyMem_NEW(char *, argc+1); 3086 if (argvlist == NULL) { 3087 PyErr_NoMemory(); 3088 goto fail_0; 3089 } 3090 for (i = 0; i < argc; i++) { 3091 if (!PyArg_Parse((*getitem)(argv, i), 3092 "et;execve() arg 2 must contain only strings", 3093 Py_FileSystemDefaultEncoding, 3094 &argvlist[i])) 3095 { 3096 lastarg = i; 3097 goto fail_1; 3098 } 3099 } 3100 lastarg = argc; 3101 argvlist[argc] = NULL; 3102 3103 i = PyMapping_Size(env); 3104 if (i < 0) 3105 goto fail_1; 3106 envlist = PyMem_NEW(char *, i + 1); 3107 if (envlist == NULL) { 3108 PyErr_NoMemory(); 3109 goto fail_1; 3110 } 3111 envc = 0; 3112 keys = PyMapping_Keys(env); 3113 vals = PyMapping_Values(env); 3114 if (!keys || !vals) 3115 goto fail_2; 3116 if (!PyList_Check(keys) || !PyList_Check(vals)) { 3117 PyErr_SetString(PyExc_TypeError, 3118 "execve(): env.keys() or env.values() is not a list"); 3119 goto fail_2; 3120 } 3121 3122 for (pos = 0; pos < i; pos++) { 3123 char *p, *k, *v; 3124 size_t len; 3125 3126 key = PyList_GetItem(keys, pos); 3127 val = PyList_GetItem(vals, pos); 3128 if (!key || !val) 3129 goto fail_2; 3130 3131 if (!PyArg_Parse( 3132 key, 3133 "s;execve() arg 3 contains a non-string key", 3134 &k) || 3135 !PyArg_Parse( 3136 val, 3137 "s;execve() arg 3 contains a non-string value", 3138 &v)) 3139 { 3140 goto fail_2; 3141 } 3142 3143 #if defined(PYOS_OS2) 3144 /* Omit Pseudo-Env Vars that Would Confuse Programs if Passed On */ 3145 if (stricmp(k, "BEGINLIBPATH") != 0 && stricmp(k, "ENDLIBPATH") != 0) { 3146 #endif 3147 len = PyString_Size(key) + PyString_Size(val) + 2; 3148 p = PyMem_NEW(char, len); 3149 if (p == NULL) { 3150 PyErr_NoMemory(); 3151 goto fail_2; 3152 } 3153 PyOS_snprintf(p, len, "%s=%s", k, v); 3154 envlist[envc++] = p; 3155 #if defined(PYOS_OS2) 3156 } 3157 #endif 3158 } 3159 envlist[envc] = 0; 3160 3161 execve(path, argvlist, envlist); 3162 3163 /* If we get here it's definitely an error */ 3164 3165 (void) posix_error(); 3166 3167 fail_2: 3168 while (--envc >= 0) 3169 PyMem_DEL(envlist[envc]); 3170 PyMem_DEL(envlist); 3171 fail_1: 3172 free_string_array(argvlist, lastarg); 3173 Py_XDECREF(vals); 3174 Py_XDECREF(keys); 3175 fail_0: 3176 PyMem_Free(path); 3177 return NULL; 3178 } 3179 #endif /* HAVE_EXECV */ 3180 3181 3182 #ifdef HAVE_SPAWNV 3183 PyDoc_STRVAR(posix_spawnv__doc__, 3184 "spawnv(mode, path, args)\n\n\ 3185 Execute the program 'path' in a new process.\n\ 3186 \n\ 3187 mode: mode of process creation\n\ 3188 path: path of executable file\n\ 3189 args: tuple or list of strings"); 3190 3191 static PyObject * 3192 posix_spawnv(PyObject *self, PyObject *args) 3193 { 3194 char *path; 3195 PyObject *argv; 3196 char **argvlist; 3197 int mode, i; 3198 Py_ssize_t argc; 3199 Py_intptr_t spawnval; 3200 PyObject *(*getitem)(PyObject *, Py_ssize_t); 3201 3202 /* spawnv has three arguments: (mode, path, argv), where 3203 argv is a list or tuple of strings. */ 3204 3205 if (!PyArg_ParseTuple(args, "ietO:spawnv", &mode, 3206 Py_FileSystemDefaultEncoding, 3207 &path, &argv)) 3208 return NULL; 3209 if (PyList_Check(argv)) { 3210 argc = PyList_Size(argv); 3211 getitem = PyList_GetItem; 3212 } 3213 else if (PyTuple_Check(argv)) { 3214 argc = PyTuple_Size(argv); 3215 getitem = PyTuple_GetItem; 3216 } 3217 else { 3218 PyErr_SetString(PyExc_TypeError, 3219 "spawnv() arg 2 must be a tuple or list"); 3220 PyMem_Free(path); 3221 return NULL; 3222 } 3223 3224 argvlist = PyMem_NEW(char *, argc+1); 3225 if (argvlist == NULL) { 3226 PyMem_Free(path); 3227 return PyErr_NoMemory(); 3228 } 3229 for (i = 0; i < argc; i++) { 3230 if (!PyArg_Parse((*getitem)(argv, i), "et", 3231 Py_FileSystemDefaultEncoding, 3232 &argvlist[i])) { 3233 free_string_array(argvlist, i); 3234 PyErr_SetString( 3235 PyExc_TypeError, 3236 "spawnv() arg 2 must contain only strings"); 3237 PyMem_Free(path); 3238 return NULL; 3239 } 3240 } 3241 argvlist[argc] = NULL; 3242 3243 #if defined(PYOS_OS2) && defined(PYCC_GCC) 3244 Py_BEGIN_ALLOW_THREADS 3245 spawnval = spawnv(mode, path, argvlist); 3246 Py_END_ALLOW_THREADS 3247 #else 3248 if (mode == _OLD_P_OVERLAY) 3249 mode = _P_OVERLAY; 3250 3251 Py_BEGIN_ALLOW_THREADS 3252 spawnval = _spawnv(mode, path, argvlist); 3253 Py_END_ALLOW_THREADS 3254 #endif 3255 3256 free_string_array(argvlist, argc); 3257 PyMem_Free(path); 3258 3259 if (spawnval == -1) 3260 return posix_error(); 3261 else 3262 #if SIZEOF_LONG == SIZEOF_VOID_P 3263 return Py_BuildValue("l", (long) spawnval); 3264 #else 3265 return Py_BuildValue("L", (PY_LONG_LONG) spawnval); 3266 #endif 3267 } 3268 3269 3270 PyDoc_STRVAR(posix_spawnve__doc__, 3271 "spawnve(mode, path, args, env)\n\n\ 3272 Execute the program 'path' in a new process.\n\ 3273 \n\ 3274 mode: mode of process creation\n\ 3275 path: path of executable file\n\ 3276 args: tuple or list of arguments\n\ 3277 env: dictionary of strings mapping to strings"); 3278 3279 static PyObject * 3280 posix_spawnve(PyObject *self, PyObject *args) 3281 { 3282 char *path; 3283 PyObject *argv, *env; 3284 char **argvlist; 3285 char **envlist; 3286 PyObject *key, *val, *keys=NULL, *vals=NULL, *res=NULL; 3287 int mode, pos, envc; 3288 Py_ssize_t argc, i; 3289 Py_intptr_t spawnval; 3290 PyObject *(*getitem)(PyObject *, Py_ssize_t); 3291 Py_ssize_t lastarg = 0; 3292 3293 /* spawnve has four arguments: (mode, path, argv, env), where 3294 argv is a list or tuple of strings and env is a dictionary 3295 like posix.environ. */ 3296 3297 if (!PyArg_ParseTuple(args, "ietOO:spawnve", &mode, 3298 Py_FileSystemDefaultEncoding, 3299 &path, &argv, &env)) 3300 return NULL; 3301 if (PyList_Check(argv)) { 3302 argc = PyList_Size(argv); 3303 getitem = PyList_GetItem; 3304 } 3305 else if (PyTuple_Check(argv)) { 3306 argc = PyTuple_Size(argv); 3307 getitem = PyTuple_GetItem; 3308 } 3309 else { 3310 PyErr_SetString(PyExc_TypeError, 3311 "spawnve() arg 2 must be a tuple or list"); 3312 goto fail_0; 3313 } 3314 if (!PyMapping_Check(env)) { 3315 PyErr_SetString(PyExc_TypeError, 3316 "spawnve() arg 3 must be a mapping object"); 3317 goto fail_0; 3318 } 3319 3320 argvlist = PyMem_NEW(char *, argc+1); 3321 if (argvlist == NULL) { 3322 PyErr_NoMemory(); 3323 goto fail_0; 3324 } 3325 for (i = 0; i < argc; i++) { 3326 if (!PyArg_Parse((*getitem)(argv, i), 3327 "et;spawnve() arg 2 must contain only strings", 3328 Py_FileSystemDefaultEncoding, 3329 &argvlist[i])) 3330 { 3331 lastarg = i; 3332 goto fail_1; 3333 } 3334 } 3335 lastarg = argc; 3336 argvlist[argc] = NULL; 3337 3338 i = PyMapping_Size(env); 3339 if (i < 0) 3340 goto fail_1; 3341 envlist = PyMem_NEW(char *, i + 1); 3342 if (envlist == NULL) { 3343 PyErr_NoMemory(); 3344 goto fail_1; 3345 } 3346 envc = 0; 3347 keys = PyMapping_Keys(env); 3348 vals = PyMapping_Values(env); 3349 if (!keys || !vals) 3350 goto fail_2; 3351 if (!PyList_Check(keys) || !PyList_Check(vals)) { 3352 PyErr_SetString(PyExc_TypeError, 3353 "spawnve(): env.keys() or env.values() is not a list"); 3354 goto fail_2; 3355 } 3356 3357 for (pos = 0; pos < i; pos++) { 3358 char *p, *k, *v; 3359 size_t len; 3360 3361 key = PyList_GetItem(keys, pos); 3362 val = PyList_GetItem(vals, pos); 3363 if (!key || !val) 3364 goto fail_2; 3365 3366 if (!PyArg_Parse( 3367 key, 3368 "s;spawnve() arg 3 contains a non-string key", 3369 &k) || 3370 !PyArg_Parse( 3371 val, 3372 "s;spawnve() arg 3 contains a non-string value", 3373 &v)) 3374 { 3375 goto fail_2; 3376 } 3377 len = PyString_Size(key) + PyString_Size(val) + 2; 3378 p = PyMem_NEW(char, len); 3379 if (p == NULL) { 3380 PyErr_NoMemory(); 3381 goto fail_2; 3382 } 3383 PyOS_snprintf(p, len, "%s=%s", k, v); 3384 envlist[envc++] = p; 3385 } 3386 envlist[envc] = 0; 3387 3388 #if defined(PYOS_OS2) && defined(PYCC_GCC) 3389 Py_BEGIN_ALLOW_THREADS 3390 spawnval = spawnve(mode, path, argvlist, envlist); 3391 Py_END_ALLOW_THREADS 3392 #else 3393 if (mode == _OLD_P_OVERLAY) 3394 mode = _P_OVERLAY; 3395 3396 Py_BEGIN_ALLOW_THREADS 3397 spawnval = _spawnve(mode, path, argvlist, envlist); 3398 Py_END_ALLOW_THREADS 3399 #endif 3400 3401 if (spawnval == -1) 3402 (void) posix_error(); 3403 else 3404 #if SIZEOF_LONG == SIZEOF_VOID_P 3405 res = Py_BuildValue("l", (long) spawnval); 3406 #else 3407 res = Py_BuildValue("L", (PY_LONG_LONG) spawnval); 3408 #endif 3409 3410 fail_2: 3411 while (--envc >= 0) 3412 PyMem_DEL(envlist[envc]); 3413 PyMem_DEL(envlist); 3414 fail_1: 3415 free_string_array(argvlist, lastarg); 3416 Py_XDECREF(vals); 3417 Py_XDECREF(keys); 3418 fail_0: 3419 PyMem_Free(path); 3420 return res; 3421 } 3422 3423 /* OS/2 supports spawnvp & spawnvpe natively */ 3424 #if defined(PYOS_OS2) 3425 PyDoc_STRVAR(posix_spawnvp__doc__, 3426 "spawnvp(mode, file, args)\n\n\ 3427 Execute the program 'file' in a new process, using the environment\n\ 3428 search path to find the file.\n\ 3429 \n\ 3430 mode: mode of process creation\n\ 3431 file: executable file name\n\ 3432 args: tuple or list of strings"); 3433 3434 static PyObject * 3435 posix_spawnvp(PyObject *self, PyObject *args) 3436 { 3437 char *path; 3438 PyObject *argv; 3439 char **argvlist; 3440 int mode, i, argc; 3441 Py_intptr_t spawnval; 3442 PyObject *(*getitem)(PyObject *, Py_ssize_t); 3443 3444 /* spawnvp has three arguments: (mode, path, argv), where 3445 argv is a list or tuple of strings. */ 3446 3447 if (!PyArg_ParseTuple(args, "ietO:spawnvp", &mode, 3448 Py_FileSystemDefaultEncoding, 3449 &path, &argv)) 3450 return NULL; 3451 if (PyList_Check(argv)) { 3452 argc = PyList_Size(argv); 3453 getitem = PyList_GetItem; 3454 } 3455 else if (PyTuple_Check(argv)) { 3456 argc = PyTuple_Size(argv); 3457 getitem = PyTuple_GetItem; 3458 } 3459 else { 3460 PyErr_SetString(PyExc_TypeError, 3461 "spawnvp() arg 2 must be a tuple or list"); 3462 PyMem_Free(path); 3463 return NULL; 3464 } 3465 3466 argvlist = PyMem_NEW(char *, argc+1); 3467 if (argvlist == NULL) { 3468 PyMem_Free(path); 3469 return PyErr_NoMemory(); 3470 } 3471 for (i = 0; i < argc; i++) { 3472 if (!PyArg_Parse((*getitem)(argv, i), "et", 3473 Py_FileSystemDefaultEncoding, 3474 &argvlist[i])) { 3475 free_string_array(argvlist, i); 3476 PyErr_SetString( 3477 PyExc_TypeError, 3478 "spawnvp() arg 2 must contain only strings"); 3479 PyMem_Free(path); 3480 return NULL; 3481 } 3482 } 3483 argvlist[argc] = NULL; 3484 3485 Py_BEGIN_ALLOW_THREADS 3486 #if defined(PYCC_GCC) 3487 spawnval = spawnvp(mode, path, argvlist); 3488 #else 3489 spawnval = _spawnvp(mode, path, argvlist); 3490 #endif 3491 Py_END_ALLOW_THREADS 3492 3493 free_string_array(argvlist, argc); 3494 PyMem_Free(path); 3495 3496 if (spawnval == -1) 3497 return posix_error(); 3498 else 3499 return Py_BuildValue("l", (long) spawnval); 3500 } 3501 3502 3503 PyDoc_STRVAR(posix_spawnvpe__doc__, 3504 "spawnvpe(mode, file, args, env)\n\n\ 3505 Execute the program 'file' in a new process, using the environment\n\ 3506 search path to find the file.\n\ 3507 \n\ 3508 mode: mode of process creation\n\ 3509 file: executable file name\n\ 3510 args: tuple or list of arguments\n\ 3511 env: dictionary of strings mapping to strings"); 3512 3513 static PyObject * 3514 posix_spawnvpe(PyObject *self, PyObject *args) 3515 { 3516 char *path; 3517 PyObject *argv, *env; 3518 char **argvlist; 3519 char **envlist; 3520 PyObject *key, *val, *keys=NULL, *vals=NULL, *res=NULL; 3521 int mode, i, pos, argc, envc; 3522 Py_intptr_t spawnval; 3523 PyObject *(*getitem)(PyObject *, Py_ssize_t); 3524 int lastarg = 0; 3525 3526 /* spawnvpe has four arguments: (mode, path, argv, env), where 3527 argv is a list or tuple of strings and env is a dictionary 3528 like posix.environ. */ 3529 3530 if (!PyArg_ParseTuple(args, "ietOO:spawnvpe", &mode, 3531 Py_FileSystemDefaultEncoding, 3532 &path, &argv, &env)) 3533 return NULL; 3534 if (PyList_Check(argv)) { 3535 argc = PyList_Size(argv); 3536 getitem = PyList_GetItem; 3537 } 3538 else if (PyTuple_Check(argv)) { 3539 argc = PyTuple_Size(argv); 3540 getitem = PyTuple_GetItem; 3541 } 3542 else { 3543 PyErr_SetString(PyExc_TypeError, 3544 "spawnvpe() arg 2 must be a tuple or list"); 3545 goto fail_0; 3546 } 3547 if (!PyMapping_Check(env)) { 3548 PyErr_SetString(PyExc_TypeError, 3549 "spawnvpe() arg 3 must be a mapping object"); 3550 goto fail_0; 3551 } 3552 3553 argvlist = PyMem_NEW(char *, argc+1); 3554 if (argvlist == NULL) { 3555 PyErr_NoMemory(); 3556 goto fail_0; 3557 } 3558 for (i = 0; i < argc; i++) { 3559 if (!PyArg_Parse((*getitem)(argv, i), 3560 "et;spawnvpe() arg 2 must contain only strings", 3561 Py_FileSystemDefaultEncoding, 3562 &argvlist[i])) 3563 { 3564 lastarg = i; 3565 goto fail_1; 3566 } 3567 } 3568 lastarg = argc; 3569 argvlist[argc] = NULL; 3570 3571 i = PyMapping_Size(env); 3572 if (i < 0) 3573 goto fail_1; 3574 envlist = PyMem_NEW(char *, i + 1); 3575 if (envlist == NULL) { 3576 PyErr_NoMemory(); 3577 goto fail_1; 3578 } 3579 envc = 0; 3580 keys = PyMapping_Keys(env); 3581 vals = PyMapping_Values(env); 3582 if (!keys || !vals) 3583 goto fail_2; 3584 if (!PyList_Check(keys) || !PyList_Check(vals)) { 3585 PyErr_SetString(PyExc_TypeError, 3586 "spawnvpe(): env.keys() or env.values() is not a list"); 3587 goto fail_2; 3588 } 3589 3590 for (pos = 0; pos < i; pos++) { 3591 char *p, *k, *v; 3592 size_t len; 3593 3594 key = PyList_GetItem(keys, pos); 3595 val = PyList_GetItem(vals, pos); 3596 if (!key || !val) 3597 goto fail_2; 3598 3599 if (!PyArg_Parse( 3600 key, 3601 "s;spawnvpe() arg 3 contains a non-string key", 3602 &k) || 3603 !PyArg_Parse( 3604 val, 3605 "s;spawnvpe() arg 3 contains a non-string value", 3606 &v)) 3607 { 3608 goto fail_2; 3609 } 3610 len = PyString_Size(key) + PyString_Size(val) + 2; 3611 p = PyMem_NEW(char, len); 3612 if (p == NULL) { 3613 PyErr_NoMemory(); 3614 goto fail_2; 3615 } 3616 PyOS_snprintf(p, len, "%s=%s", k, v); 3617 envlist[envc++] = p; 3618 } 3619 envlist[envc] = 0; 3620 3621 Py_BEGIN_ALLOW_THREADS 3622 #if defined(PYCC_GCC) 3623 spawnval = spawnvpe(mode, path, argvlist, envlist); 3624 #else 3625 spawnval = _spawnvpe(mode, path, argvlist, envlist); 3626 #endif 3627 Py_END_ALLOW_THREADS 3628 3629 if (spawnval == -1) 3630 (void) posix_error(); 3631 else 3632 res = Py_BuildValue("l", (long) spawnval); 3633 3634 fail_2: 3635 while (--envc >= 0) 3636 PyMem_DEL(envlist[envc]); 3637 PyMem_DEL(envlist); 3638 fail_1: 3639 free_string_array(argvlist, lastarg); 3640 Py_XDECREF(vals); 3641 Py_XDECREF(keys); 3642 fail_0: 3643 PyMem_Free(path); 3644 return res; 3645 } 3646 #endif /* PYOS_OS2 */ 3647 #endif /* HAVE_SPAWNV */ 3648 3649 3650 #ifdef HAVE_FORK1 3651 PyDoc_STRVAR(posix_fork1__doc__, 3652 "fork1() -> pid\n\n\ 3653 Fork a child process with a single multiplexed (i.e., not bound) thread.\n\ 3654 \n\ 3655 Return 0 to child process and PID of child to parent process."); 3656 3657 static PyObject * 3658 posix_fork1(PyObject *self, PyObject *noargs) 3659 { 3660 pid_t pid; 3661 int result = 0; 3662 _PyImport_AcquireLock(); 3663 pid = fork1(); 3664 if (pid == 0) { 3665 /* child: this clobbers and resets the import lock. */ 3666 PyOS_AfterFork(); 3667 } else { 3668 /* parent: release the import lock. */ 3669 result = _PyImport_ReleaseLock(); 3670 } 3671 if (pid == -1) 3672 return posix_error(); 3673 if (result < 0) { 3674 /* Don't clobber the OSError if the fork failed. */ 3675 PyErr_SetString(PyExc_RuntimeError, 3676 "not holding the import lock"); 3677 return NULL; 3678 } 3679 return PyLong_FromPid(pid); 3680 } 3681 #endif 3682 3683 3684 #ifdef HAVE_FORK 3685 PyDoc_STRVAR(posix_fork__doc__, 3686 "fork() -> pid\n\n\ 3687 Fork a child process.\n\ 3688 Return 0 to child process and PID of child to parent process."); 3689 3690 static PyObject * 3691 posix_fork(PyObject *self, PyObject *noargs) 3692 { 3693 pid_t pid; 3694 int result = 0; 3695 _PyImport_AcquireLock(); 3696 pid = fork(); 3697 if (pid == 0) { 3698 /* child: this clobbers and resets the import lock. */ 3699 PyOS_AfterFork(); 3700 } else { 3701 /* parent: release the import lock. */ 3702 result = _PyImport_ReleaseLock(); 3703 } 3704 if (pid == -1) 3705 return posix_error(); 3706 if (result < 0) { 3707 /* Don't clobber the OSError if the fork failed. */ 3708 PyErr_SetString(PyExc_RuntimeError, 3709 "not holding the import lock"); 3710 return NULL; 3711 } 3712 return PyLong_FromPid(pid); 3713 } 3714 #endif 3715 3716 /* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */ 3717 /* IRIX has both /dev/ptc and /dev/ptmx, use ptmx */ 3718 #if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX) 3719 #define DEV_PTY_FILE "/dev/ptc" 3720 #define HAVE_DEV_PTMX 3721 #else 3722 #define DEV_PTY_FILE "/dev/ptmx" 3723 #endif 3724 3725 #if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX) 3726 #ifdef HAVE_PTY_H 3727 #include <pty.h> 3728 #else 3729 #ifdef HAVE_LIBUTIL_H 3730 #include <libutil.h> 3731 #else 3732 #ifdef HAVE_UTIL_H 3733 #include <util.h> 3734 #endif /* HAVE_UTIL_H */ 3735 #endif /* HAVE_LIBUTIL_H */ 3736 #endif /* HAVE_PTY_H */ 3737 #ifdef HAVE_STROPTS_H 3738 #include <stropts.h> 3739 #endif 3740 #endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX */ 3741 3742 #if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) 3743 PyDoc_STRVAR(posix_openpty__doc__, 3744 "openpty() -> (master_fd, slave_fd)\n\n\ 3745 Open a pseudo-terminal, returning open fd's for both master and slave end.\n"); 3746 3747 static PyObject * 3748 posix_openpty(PyObject *self, PyObject *noargs) 3749 { 3750 int master_fd, slave_fd; 3751 #ifndef HAVE_OPENPTY 3752 char * slave_name; 3753 #endif 3754 #if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY) 3755 PyOS_sighandler_t sig_saved; 3756 #ifdef sun 3757 extern char *ptsname(int fildes); 3758 #endif 3759 #endif 3760 3761 #ifdef HAVE_OPENPTY 3762 if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0) 3763 return posix_error(); 3764 #elif defined(HAVE__GETPTY) 3765 slave_name = _getpty(&master_fd, O_RDWR, 0666, 0); 3766 if (slave_name == NULL) 3767 return posix_error(); 3768 3769 slave_fd = open(slave_name, O_RDWR); 3770 if (slave_fd < 0) 3771 return posix_error(); 3772 #else 3773 master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */ 3774 if (master_fd < 0) 3775 return posix_error(); 3776 sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL); 3777 /* change permission of slave */ 3778 if (grantpt(master_fd) < 0) { 3779 PyOS_setsig(SIGCHLD, sig_saved); 3780 return posix_error(); 3781 } 3782 /* unlock slave */ 3783 if (unlockpt(master_fd) < 0) { 3784 PyOS_setsig(SIGCHLD, sig_saved); 3785 return posix_error(); 3786 } 3787 PyOS_setsig(SIGCHLD, sig_saved); 3788 slave_name = ptsname(master_fd); /* get name of slave */ 3789 if (slave_name == NULL) 3790 return posix_error(); 3791 slave_fd = open(slave_name, O_RDWR | O_NOCTTY); /* open slave */ 3792 if (slave_fd < 0) 3793 return posix_error(); 3794 #if !defined(__CYGWIN__) && !defined(HAVE_DEV_PTC) 3795 ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */ 3796 ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */ 3797 #ifndef __hpux 3798 ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */ 3799 #endif /* __hpux */ 3800 #endif /* HAVE_CYGWIN */ 3801 #endif /* HAVE_OPENPTY */ 3802 3803 return Py_BuildValue("(ii)", master_fd, slave_fd); 3804 3805 } 3806 #endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */ 3807 3808 #ifdef HAVE_FORKPTY 3809 PyDoc_STRVAR(posix_forkpty__doc__, 3810 "forkpty() -> (pid, master_fd)\n\n\ 3811 Fork a new process with a new pseudo-terminal as controlling tty.\n\n\ 3812 Like fork(), return 0 as pid to child process, and PID of child to parent.\n\ 3813 To both, return fd of newly opened pseudo-terminal.\n"); 3814 3815 static PyObject * 3816 posix_forkpty(PyObject *self, PyObject *noargs) 3817 { 3818 int master_fd = -1, result = 0; 3819 pid_t pid; 3820 3821 _PyImport_AcquireLock(); 3822 pid = forkpty(&master_fd, NULL, NULL, NULL); 3823 if (pid == 0) { 3824 /* child: this clobbers and resets the import lock. */ 3825 PyOS_AfterFork(); 3826 } else { 3827 /* parent: release the import lock. */ 3828 result = _PyImport_ReleaseLock(); 3829 } 3830 if (pid == -1) 3831 return posix_error(); 3832 if (result < 0) { 3833 /* Don't clobber the OSError if the fork failed. */ 3834 PyErr_SetString(PyExc_RuntimeError, 3835 "not holding the import lock"); 3836 return NULL; 3837 } 3838 return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd); 3839 } 3840 #endif 3841 3842 #ifdef HAVE_GETEGID 3843 PyDoc_STRVAR(posix_getegid__doc__, 3844 "getegid() -> egid\n\n\ 3845 Return the current process's effective group id."); 3846 3847 static PyObject * 3848 posix_getegid(PyObject *self, PyObject *noargs) 3849 { 3850 return _PyObject_FromGid(getegid()); 3851 } 3852 #endif 3853 3854 3855 #ifdef HAVE_GETEUID 3856 PyDoc_STRVAR(posix_geteuid__doc__, 3857 "geteuid() -> euid\n\n\ 3858 Return the current process's effective user id."); 3859 3860 static PyObject * 3861 posix_geteuid(PyObject *self, PyObject *noargs) 3862 { 3863 return _PyObject_FromUid(geteuid()); 3864 } 3865 #endif 3866 3867 3868 #ifdef HAVE_GETGID 3869 PyDoc_STRVAR(posix_getgid__doc__, 3870 "getgid() -> gid\n\n\ 3871 Return the current process's group id."); 3872 3873 static PyObject * 3874 posix_getgid(PyObject *self, PyObject *noargs) 3875 { 3876 return _PyObject_FromGid(getgid()); 3877 } 3878 #endif 3879 3880 3881 PyDoc_STRVAR(posix_getpid__doc__, 3882 "getpid() -> pid\n\n\ 3883 Return the current process id"); 3884 3885 static PyObject * 3886 posix_getpid(PyObject *self, PyObject *noargs) 3887 { 3888 return PyLong_FromPid(getpid()); 3889 } 3890 3891 3892 #ifdef HAVE_GETGROUPS 3893 PyDoc_STRVAR(posix_getgroups__doc__, 3894 "getgroups() -> list of group IDs\n\n\ 3895 Return list of supplemental group IDs for the process."); 3896 3897 static PyObject * 3898 posix_getgroups(PyObject *self, PyObject *noargs) 3899 { 3900 PyObject *result = NULL; 3901 3902 #ifdef NGROUPS_MAX 3903 #define MAX_GROUPS NGROUPS_MAX 3904 #else 3905 /* defined to be 16 on Solaris7, so this should be a small number */ 3906 #define MAX_GROUPS 64 3907 #endif 3908 gid_t grouplist[MAX_GROUPS]; 3909 3910 /* On MacOSX getgroups(2) can return more than MAX_GROUPS results 3911 * This is a helper variable to store the intermediate result when 3912 * that happens. 3913 * 3914 * To keep the code readable the OSX behaviour is unconditional, 3915 * according to the POSIX spec this should be safe on all unix-y 3916 * systems. 3917 */ 3918 gid_t* alt_grouplist = grouplist; 3919 int n; 3920 3921 n = getgroups(MAX_GROUPS, grouplist); 3922 if (n < 0) { 3923 if (errno == EINVAL) { 3924 n = getgroups(0, NULL); 3925 if (n == -1) { 3926 return posix_error(); 3927 } 3928 if (n == 0) { 3929 /* Avoid malloc(0) */ 3930 alt_grouplist = grouplist; 3931 } else { 3932 alt_grouplist = PyMem_Malloc(n * sizeof(gid_t)); 3933 if (alt_grouplist == NULL) { 3934 errno = EINVAL; 3935 return posix_error(); 3936 } 3937 n = getgroups(n, alt_grouplist); 3938 if (n == -1) { 3939 PyMem_Free(alt_grouplist); 3940 return posix_error(); 3941 } 3942 } 3943 } else { 3944 return posix_error(); 3945 } 3946 } 3947 result = PyList_New(n); 3948 if (result != NULL) { 3949 int i; 3950 for (i = 0; i < n; ++i) { 3951 PyObject *o = _PyObject_FromGid(alt_grouplist[i]); 3952 if (o == NULL) { 3953 Py_DECREF(result); 3954 result = NULL; 3955 break; 3956 } 3957 PyList_SET_ITEM(result, i, o); 3958 } 3959 } 3960 3961 if (alt_grouplist != grouplist) { 3962 PyMem_Free(alt_grouplist); 3963 } 3964 3965 return result; 3966 } 3967 #endif 3968 3969 #ifdef HAVE_INITGROUPS 3970 PyDoc_STRVAR(posix_initgroups__doc__, 3971 "initgroups(username, gid) -> None\n\n\ 3972 Call the system initgroups() to initialize the group access list with all of\n\ 3973 the groups of which the specified username is a member, plus the specified\n\ 3974 group id."); 3975 3976 static PyObject * 3977 posix_initgroups(PyObject *self, PyObject *args) 3978 { 3979 char *username; 3980 gid_t gid; 3981 3982 if (!PyArg_ParseTuple(args, "sO&:initgroups", &username, 3983 _PyArg_ParseGid, &gid)) 3984 return NULL; 3985 3986 if (initgroups(username, gid) == -1) 3987 return PyErr_SetFromErrno(PyExc_OSError); 3988 3989 Py_INCREF(Py_None); 3990 return Py_None; 3991 } 3992 #endif 3993 3994 #ifdef HAVE_GETPGID 3995 PyDoc_STRVAR(posix_getpgid__doc__, 3996 "getpgid(pid) -> pgid\n\n\ 3997 Call the system call getpgid()."); 3998 3999 static PyObject * 4000 posix_getpgid(PyObject *self, PyObject *args) 4001 { 4002 pid_t pid, pgid; 4003 if (!PyArg_ParseTuple(args, PARSE_PID ":getpgid", &pid)) 4004 return NULL; 4005 pgid = getpgid(pid); 4006 if (pgid < 0) 4007 return posix_error(); 4008 return PyLong_FromPid(pgid); 4009 } 4010 #endif /* HAVE_GETPGID */ 4011 4012 4013 #ifdef HAVE_GETPGRP 4014 PyDoc_STRVAR(posix_getpgrp__doc__, 4015 "getpgrp() -> pgrp\n\n\ 4016 Return the current process group id."); 4017 4018 static PyObject * 4019 posix_getpgrp(PyObject *self, PyObject *noargs) 4020 { 4021 #ifdef GETPGRP_HAVE_ARG 4022 return PyLong_FromPid(getpgrp(0)); 4023 #else /* GETPGRP_HAVE_ARG */ 4024 return PyLong_FromPid(getpgrp()); 4025 #endif /* GETPGRP_HAVE_ARG */ 4026 } 4027 #endif /* HAVE_GETPGRP */ 4028 4029 4030 #ifdef HAVE_SETPGRP 4031 PyDoc_STRVAR(posix_setpgrp__doc__, 4032 "setpgrp()\n\n\ 4033 Make this process the process group leader."); 4034 4035 static PyObject * 4036 posix_setpgrp(PyObject *self, PyObject *noargs) 4037 { 4038 #ifdef SETPGRP_HAVE_ARG 4039 if (setpgrp(0, 0) < 0) 4040 #else /* SETPGRP_HAVE_ARG */ 4041 if (setpgrp() < 0) 4042 #endif /* SETPGRP_HAVE_ARG */ 4043 return posix_error(); 4044 Py_INCREF(Py_None); 4045 return Py_None; 4046 } 4047 4048 #endif /* HAVE_SETPGRP */ 4049 4050 #ifdef HAVE_GETPPID 4051 PyDoc_STRVAR(posix_getppid__doc__, 4052 "getppid() -> ppid\n\n\ 4053 Return the parent's process id."); 4054 4055 static PyObject * 4056 posix_getppid(PyObject *self, PyObject *noargs) 4057 { 4058 return PyLong_FromPid(getppid()); 4059 } 4060 #endif 4061 4062 4063 #ifdef HAVE_GETLOGIN 4064 PyDoc_STRVAR(posix_getlogin__doc__, 4065 "getlogin() -> string\n\n\ 4066 Return the actual login name."); 4067 4068 static PyObject * 4069 posix_getlogin(PyObject *self, PyObject *noargs) 4070 { 4071 PyObject *result = NULL; 4072 char *name; 4073 int old_errno = errno; 4074 4075 errno = 0; 4076 name = getlogin(); 4077 if (name == NULL) { 4078 if (errno) 4079 posix_error(); 4080 else 4081 PyErr_SetString(PyExc_OSError, 4082 "unable to determine login name"); 4083 } 4084 else 4085 result = PyString_FromString(name); 4086 errno = old_errno; 4087 4088 return result; 4089 } 4090 #endif 4091 4092 #ifdef HAVE_GETUID 4093 PyDoc_STRVAR(posix_getuid__doc__, 4094 "getuid() -> uid\n\n\ 4095 Return the current process's user id."); 4096 4097 static PyObject * 4098 posix_getuid(PyObject *self, PyObject *noargs) 4099 { 4100 return _PyObject_FromUid(getuid()); 4101 } 4102 #endif 4103 4104 4105 #ifdef HAVE_KILL 4106 PyDoc_STRVAR(posix_kill__doc__, 4107 "kill(pid, sig)\n\n\ 4108 Kill a process with a signal."); 4109 4110 static PyObject * 4111 posix_kill(PyObject *self, PyObject *args) 4112 { 4113 pid_t pid; 4114 int sig; 4115 if (!PyArg_ParseTuple(args, PARSE_PID "i:kill", &pid, &sig)) 4116 return NULL; 4117 #if defined(PYOS_OS2) && !defined(PYCC_GCC) 4118 if (sig == XCPT_SIGNAL_INTR || sig == XCPT_SIGNAL_BREAK) { 4119 APIRET rc; 4120 if ((rc = DosSendSignalException(pid, sig)) != NO_ERROR) 4121 return os2_error(rc); 4122 4123 } else if (sig == XCPT_SIGNAL_KILLPROC) { 4124 APIRET rc; 4125 if ((rc = DosKillProcess(DKP_PROCESS, pid)) != NO_ERROR) 4126 return os2_error(rc); 4127 4128 } else 4129 return NULL; /* Unrecognized Signal Requested */ 4130 #else 4131 if (kill(pid, sig) == -1) 4132 return posix_error(); 4133 #endif 4134 Py_INCREF(Py_None); 4135 return Py_None; 4136 } 4137 #endif 4138 4139 #ifdef HAVE_KILLPG 4140 PyDoc_STRVAR(posix_killpg__doc__, 4141 "killpg(pgid, sig)\n\n\ 4142 Kill a process group with a signal."); 4143 4144 static PyObject * 4145 posix_killpg(PyObject *self, PyObject *args) 4146 { 4147 int sig; 4148 pid_t pgid; 4149 /* XXX some man pages make the `pgid` parameter an int, others 4150 a pid_t. Since getpgrp() returns a pid_t, we assume killpg should 4151 take the same type. Moreover, pid_t is always at least as wide as 4152 int (else compilation of this module fails), which is safe. */ 4153 if (!PyArg_ParseTuple(args, PARSE_PID "i:killpg", &pgid, &sig)) 4154 return NULL; 4155 if (killpg(pgid, sig) == -1) 4156 return posix_error(); 4157 Py_INCREF(Py_None); 4158 return Py_None; 4159 } 4160 #endif 4161 4162 #ifdef MS_WINDOWS 4163 PyDoc_STRVAR(win32_kill__doc__, 4164 "kill(pid, sig)\n\n\ 4165 Kill a process with a signal."); 4166 4167 static PyObject * 4168 win32_kill(PyObject *self, PyObject *args) 4169 { 4170 PyObject *result; 4171 DWORD pid, sig, err; 4172 HANDLE handle; 4173 4174 if (!PyArg_ParseTuple(args, "kk:kill", &pid, &sig)) 4175 return NULL; 4176 4177 /* Console processes which share a common console can be sent CTRL+C or 4178 CTRL+BREAK events, provided they handle said events. */ 4179 if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) { 4180 if (GenerateConsoleCtrlEvent(sig, pid) == 0) { 4181 err = GetLastError(); 4182 return PyErr_SetFromWindowsErr(err); 4183 } 4184 else 4185 Py_RETURN_NONE; 4186 } 4187 4188 /* If the signal is outside of what GenerateConsoleCtrlEvent can use, 4189 attempt to open and terminate the process. */ 4190 handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); 4191 if (handle == NULL) { 4192 err = GetLastError(); 4193 return PyErr_SetFromWindowsErr(err); 4194 } 4195 4196 if (TerminateProcess(handle, sig) == 0) { 4197 err = GetLastError(); 4198 result = PyErr_SetFromWindowsErr(err); 4199 } else { 4200 Py_INCREF(Py_None); 4201 result = Py_None; 4202 } 4203 4204 CloseHandle(handle); 4205 return result; 4206 } 4207 4208 PyDoc_STRVAR(posix__isdir__doc__, 4209 "Return true if the pathname refers to an existing directory."); 4210 4211 static PyObject * 4212 posix__isdir(PyObject *self, PyObject *args) 4213 { 4214 PyObject *opath; 4215 char *path; 4216 PyUnicodeObject *po; 4217 DWORD attributes; 4218 4219 if (PyArg_ParseTuple(args, "U|:_isdir", &po)) { 4220 Py_UNICODE *wpath = PyUnicode_AS_UNICODE(po); 4221 4222 attributes = GetFileAttributesW(wpath); 4223 if (attributes == INVALID_FILE_ATTRIBUTES) 4224 Py_RETURN_FALSE; 4225 goto check; 4226 } 4227 /* Drop the argument parsing error as narrow strings 4228 are also valid. */ 4229 PyErr_Clear(); 4230 4231 if (!PyArg_ParseTuple(args, "et:_isdir", 4232 Py_FileSystemDefaultEncoding, &path)) 4233 return NULL; 4234 4235 attributes = GetFileAttributesA(path); 4236 if (attributes == INVALID_FILE_ATTRIBUTES) 4237 Py_RETURN_FALSE; 4238 4239 check: 4240 if (attributes & FILE_ATTRIBUTE_DIRECTORY) 4241 Py_RETURN_TRUE; 4242 else 4243 Py_RETURN_FALSE; 4244 } 4245 #endif /* MS_WINDOWS */ 4246 4247 #ifdef HAVE_PLOCK 4248 4249 #ifdef HAVE_SYS_LOCK_H 4250 #include <sys/lock.h> 4251 #endif 4252 4253 PyDoc_STRVAR(posix_plock__doc__, 4254 "plock(op)\n\n\ 4255 Lock program segments into memory."); 4256 4257 static PyObject * 4258 posix_plock(PyObject *self, PyObject *args) 4259 { 4260 int op; 4261 if (!PyArg_ParseTuple(args, "i:plock", &op)) 4262 return NULL; 4263 if (plock(op) == -1) 4264 return posix_error(); 4265 Py_INCREF(Py_None); 4266 return Py_None; 4267 } 4268 #endif 4269 4270 4271 #ifdef HAVE_POPEN 4272 PyDoc_STRVAR(posix_popen__doc__, 4273 "popen(command [, mode='r' [, bufsize]]) -> pipe\n\n\ 4274 Open a pipe to/from a command returning a file object."); 4275 4276 #if defined(PYOS_OS2) 4277 #if defined(PYCC_VACPP) 4278 static int 4279 async_system(const char *command) 4280 { 4281 char errormsg[256], args[1024]; 4282 RESULTCODES rcodes; 4283 APIRET rc; 4284 4285 char *shell = getenv("COMSPEC"); 4286 if (!shell) 4287 shell = "cmd"; 4288 4289 /* avoid overflowing the argument buffer */ 4290 if (strlen(shell) + 3 + strlen(command) >= 1024) 4291 return ERROR_NOT_ENOUGH_MEMORY 4292 4293 args[0] = '\0'; 4294 strcat(args, shell); 4295 strcat(args, "/c "); 4296 strcat(args, command); 4297 4298 /* execute asynchronously, inheriting the environment */ 4299 rc = DosExecPgm(errormsg, 4300 sizeof(errormsg), 4301 EXEC_ASYNC, 4302 args, 4303 NULL, 4304 &rcodes, 4305 shell); 4306 return rc; 4307 } 4308 4309 static FILE * 4310 popen(const char *command, const char *mode, int pipesize, int *err) 4311 { 4312 int oldfd, tgtfd; 4313 HFILE pipeh[2]; 4314 APIRET rc; 4315 4316 /* mode determines which of stdin or stdout is reconnected to 4317 * the pipe to the child 4318 */ 4319 if (strchr(mode, 'r') != NULL) { 4320 tgt_fd = 1; /* stdout */ 4321 } else if (strchr(mode, 'w')) { 4322 tgt_fd = 0; /* stdin */ 4323 } else { 4324 *err = ERROR_INVALID_ACCESS; 4325 return NULL; 4326 } 4327 4328 /* setup the pipe */ 4329 if ((rc = DosCreatePipe(&pipeh[0], &pipeh[1], pipesize)) != NO_ERROR) { 4330 *err = rc; 4331 return NULL; 4332 } 4333 4334 /* prevent other threads accessing stdio */ 4335 DosEnterCritSec(); 4336 4337 /* reconnect stdio and execute child */ 4338 oldfd = dup(tgtfd); 4339 close(tgtfd); 4340 if (dup2(pipeh[tgtfd], tgtfd) == 0) { 4341 DosClose(pipeh[tgtfd]); 4342 rc = async_system(command); 4343 } 4344 4345 /* restore stdio */ 4346 dup2(oldfd, tgtfd); 4347 close(oldfd); 4348 4349 /* allow other threads access to stdio */ 4350 DosExitCritSec(); 4351 4352 /* if execution of child was successful return file stream */ 4353 if (rc == NO_ERROR) 4354 return fdopen(pipeh[1 - tgtfd], mode); 4355 else { 4356 DosClose(pipeh[1 - tgtfd]); 4357 *err = rc; 4358 return NULL; 4359 } 4360 } 4361 4362 static PyObject * 4363 posix_popen(PyObject *self, PyObject *args) 4364 { 4365 char *name; 4366 char *mode = "r"; 4367 int err, bufsize = -1; 4368 FILE *fp; 4369 PyObject *f; 4370 if (!PyArg_ParseTuple(args, "s|si:popen", &name, &mode, &bufsize)) 4371 return NULL; 4372 Py_BEGIN_ALLOW_THREADS 4373 fp = popen(name, mode, (bufsize > 0) ? bufsize : 4096, &err); 4374 Py_END_ALLOW_THREADS 4375 if (fp == NULL) 4376 return os2_error(err); 4377 4378 f = PyFile_FromFile(fp, name, mode, fclose); 4379 if (f != NULL) 4380 PyFile_SetBufSize(f, bufsize); 4381 return f; 4382 } 4383 4384 #elif defined(PYCC_GCC) 4385 4386 /* standard posix version of popen() support */ 4387 static PyObject * 4388 posix_popen(PyObject *self, PyObject *args) 4389 { 4390 char *name; 4391 char *mode = "r"; 4392 int bufsize = -1; 4393 FILE *fp; 4394 PyObject *f; 4395 if (!PyArg_ParseTuple(args, "s|si:popen", &name, &mode, &bufsize)) 4396 return NULL; 4397 Py_BEGIN_ALLOW_THREADS 4398 fp = popen(name, mode); 4399 Py_END_ALLOW_THREADS 4400 if (fp == NULL) 4401 return posix_error(); 4402 f = PyFile_FromFile(fp, name, mode, pclose); 4403 if (f != NULL) 4404 PyFile_SetBufSize(f, bufsize); 4405 return f; 4406 } 4407 4408 /* fork() under OS/2 has lots'o'warts 4409 * EMX supports pipe() and spawn*() so we can synthesize popen[234]() 4410 * most of this code is a ripoff of the win32 code, but using the 4411 * capabilities of EMX's C library routines 4412 */ 4413 4414 /* These tell _PyPopen() whether to return 1, 2, or 3 file objects. */ 4415 #define POPEN_1 1 4416 #define POPEN_2 2 4417 #define POPEN_3 3 4418 #define POPEN_4 4 4419 4420 static PyObject *_PyPopen(char *, int, int, int); 4421 static int _PyPclose(FILE *file); 4422 4423 /* 4424 * Internal dictionary mapping popen* file pointers to process handles, 4425 * for use when retrieving the process exit code. See _PyPclose() below 4426 * for more information on this dictionary's use. 4427 */ 4428 static PyObject *_PyPopenProcs = NULL; 4429 4430 /* os2emx version of popen2() 4431 * 4432 * The result of this function is a pipe (file) connected to the 4433 * process's stdin, and a pipe connected to the process's stdout. 4434 */ 4435 4436 static PyObject * 4437 os2emx_popen2(PyObject *self, PyObject *args) 4438 { 4439 PyObject *f; 4440 int tm=0; 4441 4442 char *cmdstring; 4443 char *mode = "t"; 4444 int bufsize = -1; 4445 if (!PyArg_ParseTuple(args, "s|si:popen2", &cmdstring, &mode, &bufsize)) 4446 return NULL; 4447 4448 if (*mode == 't') 4449 tm = O_TEXT; 4450 else if (*mode != 'b') { 4451 PyErr_SetString(PyExc_ValueError, &qu