posixmodule.c 237 KB
Newer Older
Guido van Rossum's avatar
Guido van Rossum committed
1

Guido van Rossum's avatar
Guido van Rossum committed
2 3
/* POSIX module implementation */

4 5 6
/* This file is also used for Windows NT/MS-Win and OS/2.  In that case the
   module actually calls itself 'nt' or 'os2', not 'posix', and a few
   functions are either unimplemented or implemented differently.  The source
7
   assumes that for Windows NT, the macro 'MS_WINDOWS' is defined independent
Guido van Rossum's avatar
Guido van Rossum committed
8
   of the compiler used.  Different compilers define their own feature
9 10 11 12
   test macro, e.g. '__BORLANDC__' or '_MSC_VER'.  For OS/2, the compiler
   independent macro PYOS_OS2 should be defined.  On OS/2 the default
   compiler is assumed to be IBM's VisualAge C++ (VACPP).  PYCC_GCC is used
   as the compiler specific macro for the EMX port of gcc to OS/2. */
Guido van Rossum's avatar
Guido van Rossum committed
13

14 15
#ifdef __APPLE__
   /*
16
    * Step 1 of support for weak-linking a number of symbols existing on
17 18 19 20 21 22 23 24 25
    * OSX 10.4 and later, see the comment in the #ifdef __APPLE__ block
    * at the end of this file for more information.
    */
#  pragma weak lchown
#  pragma weak statvfs
#  pragma weak fstatvfs

#endif /* __APPLE__ */

Thomas Wouters's avatar
Thomas Wouters committed
26 27
#define PY_SSIZE_T_CLEAN

28 29
#include "Python.h"

30 31 32 33
#if defined(__VMS)
#    include <unixio.h>
#endif /* defined(__VMS) */

34 35 36 37
#ifdef __cplusplus
extern "C" {
#endif

38
PyDoc_STRVAR(posix__doc__,
39 40 41
"This module provides access to operating system functionality that is\n\
standardized by the C Standard and the POSIX standard (a thinly\n\
disguised Unix interface).  Refer to the library manual and\n\
42
corresponding Unix manual entries for more information on calls.");
Guido van Rossum's avatar
Guido van Rossum committed
43

44

Guido van Rossum's avatar
Guido van Rossum committed
45 46 47 48 49 50
#if defined(PYOS_OS2)
#define  INCL_DOS
#define  INCL_DOSERRORS
#define  INCL_DOSPROCESS
#define  INCL_NOPMAPI
#include <os2.h>
51 52 53 54 55 56
#if defined(PYCC_GCC)
#include <ctype.h>
#include <io.h>
#include <stdio.h>
#include <process.h>
#endif
57
#include "osdefs.h"
Guido van Rossum's avatar
Guido van Rossum committed
58 59
#endif

60
#ifdef HAVE_SYS_TYPES_H
61
#include <sys/types.h>
62 63 64
#endif /* HAVE_SYS_TYPES_H */

#ifdef HAVE_SYS_STAT_H
65
#include <sys/stat.h>
66
#endif /* HAVE_SYS_STAT_H */
67

68
#ifdef HAVE_SYS_WAIT_H
69
#include <sys/wait.h>           /* For WNOHANG */
70
#endif
71

72
#ifdef HAVE_SIGNAL_H
Guido van Rossum's avatar
Guido van Rossum committed
73
#include <signal.h>
74
#endif
Guido van Rossum's avatar
Guido van Rossum committed
75

76 77
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
78
#endif /* HAVE_FCNTL_H */
79

80 81 82 83
#ifdef HAVE_GRP_H
#include <grp.h>
#endif

84 85 86 87
#ifdef HAVE_SYSEXITS_H
#include <sysexits.h>
#endif /* HAVE_SYSEXITS_H */

88 89 90 91
#ifdef HAVE_SYS_LOADAVG_H
#include <sys/loadavg.h>
#endif

92 93 94 95
#ifdef HAVE_LANGINFO_H
#include <langinfo.h>
#endif

96
/* Various compilers have only certain posix functions */
97
/* XXX Gosh I wish these were all moved into pyconfig.h */
Guido van Rossum's avatar
Guido van Rossum committed
98 99 100
#if defined(PYCC_VACPP) && defined(PYOS_OS2)
#include <process.h>
#else
101
#if defined(__WATCOMC__) && !defined(__QNX__)           /* Watcom compiler */
102 103
#define HAVE_GETCWD     1
#define HAVE_OPENDIR    1
104
#define HAVE_SYSTEM     1
105 106 107
#if defined(__OS2__)
#define HAVE_EXECV      1
#define HAVE_WAIT       1
Guido van Rossum's avatar
Guido van Rossum committed
108
#endif
109 110
#include <process.h>
#else
111
#ifdef __BORLANDC__             /* Borland compiler */
112 113 114 115
#define HAVE_EXECV      1
#define HAVE_GETCWD     1
#define HAVE_OPENDIR    1
#define HAVE_PIPE       1
116
#define HAVE_SYSTEM     1
117 118
#define HAVE_WAIT       1
#else
119
#ifdef _MSC_VER         /* Microsoft compiler */
120
#define HAVE_GETCWD     1
121
#define HAVE_GETPPID    1
122
#define HAVE_GETLOGIN   1
123
#define HAVE_SPAWNV     1
124 125
#define HAVE_EXECV      1
#define HAVE_PIPE       1
126 127 128
#define HAVE_SYSTEM     1
#define HAVE_CWAIT      1
#define HAVE_FSYNC      1
129
#define fsync _commit
130
#else
131 132
#if defined(PYOS_OS2) && defined(PYCC_GCC) || defined(__VMS)
/* Everything needed is defined in PC/os2emx/pyconfig.h or vms/pyconfig.h */
133
#else                   /* all other compilers */
134 135 136
/* Unix functions that the configure script doesn't check for */
#define HAVE_EXECV      1
#define HAVE_FORK       1
137
#if defined(__USLC__) && defined(__SCO_VERSION__)       /* SCO UDK Compiler */
138 139
#define HAVE_FORK1      1
#endif
140 141 142 143 144 145 146 147 148
#define HAVE_GETCWD     1
#define HAVE_GETEGID    1
#define HAVE_GETEUID    1
#define HAVE_GETGID     1
#define HAVE_GETPPID    1
#define HAVE_GETUID     1
#define HAVE_KILL       1
#define HAVE_OPENDIR    1
#define HAVE_PIPE       1
149
#define HAVE_SYSTEM     1
150
#define HAVE_WAIT       1
151
#define HAVE_TTYNAME    1
152
#endif  /* PYOS_OS2 && PYCC_GCC && __VMS */
153 154
#endif  /* _MSC_VER */
#endif  /* __BORLANDC__ */
155
#endif  /* ! __WATCOMC__ || __QNX__ */
Guido van Rossum's avatar
Guido van Rossum committed
156
#endif /* ! __IBMC__ */
157 158

#ifndef _MSC_VER
159

160 161 162 163 164 165
#if defined(__sgi)&&_COMPILER_VERSION>=700
/* declare ctermid_r if compiling with MIPSPro 7.x in ANSI C mode
   (default) */
extern char        *ctermid_r(char *);
#endif

166
#ifndef HAVE_UNISTD_H
Guido van Rossum's avatar
Guido van Rossum committed
167
#if defined(PYCC_VACPP)
168
extern int mkdir(char *);
Guido van Rossum's avatar
Guido van Rossum committed
169
#else
170
#if ( defined(__WATCOMC__) || defined(_MSC_VER) ) && !defined(__QNX__)
171
extern int mkdir(const char *);
172
#else
173
extern int mkdir(const char *, mode_t);
174
#endif
Guido van Rossum's avatar
Guido van Rossum committed
175 176
#endif
#if defined(__IBMC__) || defined(__IBMCPP__)
177 178
extern int chdir(char *);
extern int rmdir(char *);
Guido van Rossum's avatar
Guido van Rossum committed
179
#else
180 181 182
extern int chdir(const char *);
extern int rmdir(const char *);
#endif
183 184 185
#ifdef __BORLANDC__
extern int chmod(const char *, int);
#else
186
extern int chmod(const char *, mode_t);
187
#endif
188 189 190 191 192 193
/*#ifdef HAVE_FCHMOD
extern int fchmod(int, mode_t);
#endif*/
/*#ifdef HAVE_LCHMOD
extern int lchmod(const char *, mode_t);
#endif*/
194 195 196 197 198 199 200
extern int chown(const char *, uid_t, gid_t);
extern char *getcwd(char *, int);
extern char *strerror(int);
extern int link(const char *, const char *);
extern int rename(const char *, const char *);
extern int stat(const char *, struct stat *);
extern int unlink(const char *);
201
#ifdef HAVE_SYMLINK
202
extern int symlink(const char *, const char *);
203
#endif /* HAVE_SYMLINK */
204
#ifdef HAVE_LSTAT
205
extern int lstat(const char *, struct stat *);
206
#endif /* HAVE_LSTAT */
207
#endif /* !HAVE_UNISTD_H */
208

209
#endif /* !_MSC_VER */
210 211 212

#ifdef HAVE_UTIME_H
#include <utime.h>
213
#endif /* HAVE_UTIME_H */
214

215 216 217 218 219
#ifdef HAVE_SYS_UTIME_H
#include <sys/utime.h>
#define HAVE_UTIME_H /* pretend we do for the rest of this file */
#endif /* HAVE_SYS_UTIME_H */

220 221
#ifdef HAVE_SYS_TIMES_H
#include <sys/times.h>
222
#endif /* HAVE_SYS_TIMES_H */
223 224 225

#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
226
#endif /* HAVE_SYS_PARAM_H */
227 228 229

#ifdef HAVE_SYS_UTSNAME_H
#include <sys/utsname.h>
230
#endif /* HAVE_SYS_UTSNAME_H */
231

232
#ifdef HAVE_DIRENT_H
233
#include <dirent.h>
234 235
#define NAMLEN(dirent) strlen((dirent)->d_name)
#else
236
#if defined(__WATCOMC__) && !defined(__QNX__)
237 238 239
#include <direct.h>
#define NAMLEN(dirent) strlen((dirent)->d_name)
#else
240
#define dirent direct
241
#define NAMLEN(dirent) (dirent)->d_namlen
242
#endif
243
#ifdef HAVE_SYS_NDIR_H
244
#include <sys/ndir.h>
245 246
#endif
#ifdef HAVE_SYS_DIR_H
247
#include <sys/dir.h>
248 249
#endif
#ifdef HAVE_NDIR_H
250
#include <ndir.h>
251 252
#endif
#endif
253

254
#ifdef _MSC_VER
255
#ifdef HAVE_DIRECT_H
256
#include <direct.h>
257 258
#endif
#ifdef HAVE_IO_H
259
#include <io.h>
260 261
#endif
#ifdef HAVE_PROCESS_H
262
#include <process.h>
263
#endif
264
#ifndef VOLUME_NAME_DOS
265
#define VOLUME_NAME_DOS 0x0
266 267
#endif
#ifndef VOLUME_NAME_NT
268
#define VOLUME_NAME_NT  0x2
269 270
#endif
#ifndef IO_REPARSE_TAG_SYMLINK
271
#define IO_REPARSE_TAG_SYMLINK (0xA000000CL)
272
#endif
273
#include "osdefs.h"
274
#include <malloc.h>
275
#include <windows.h>
276
#include <shellapi.h>   /* for ShellExecute() */
277
#include <lmcons.h>     /* for UNLEN */
278 279
#ifdef SE_CREATE_SYMBOLIC_LINK_NAME /* Available starting with Vista */
#define HAVE_SYMLINK
280
static int win32_can_symlink = 0;
281
#endif
282
#endif /* _MSC_VER */
283

284
#if defined(PYCC_VACPP) && defined(PYOS_OS2)
285
#include <io.h>
286
#endif /* OS2 */
Guido van Rossum's avatar
Guido van Rossum committed
287

288
#ifndef MAXPATHLEN
289 290 291
#if defined(PATH_MAX) && PATH_MAX > 1024
#define MAXPATHLEN PATH_MAX
#else
292
#define MAXPATHLEN 1024
293
#endif
294 295
#endif /* MAXPATHLEN */

296 297 298 299 300 301 302 303 304 305 306 307 308 309 310
#ifdef UNION_WAIT
/* Emulate some macros on systems that have a union instead of macros */

#ifndef WIFEXITED
#define WIFEXITED(u_wait) (!(u_wait).w_termsig && !(u_wait).w_coredump)
#endif

#ifndef WEXITSTATUS
#define WEXITSTATUS(u_wait) (WIFEXITED(u_wait)?((u_wait).w_retcode):-1)
#endif

#ifndef WTERMSIG
#define WTERMSIG(u_wait) ((u_wait).w_termsig)
#endif

311 312 313 314 315 316
#define WAIT_TYPE union wait
#define WAIT_STATUS_INT(s) (s.w_status)

#else /* !UNION_WAIT */
#define WAIT_TYPE int
#define WAIT_STATUS_INT(s) (s)
317 318
#endif /* UNION_WAIT */

319 320 321 322 323 324
/* Don't use the "_r" form if we don't need it (also, won't have a
   prototype for it, at least on Solaris -- maybe others as well?). */
#if defined(HAVE_CTERMID_R) && defined(WITH_THREAD)
#define USE_CTERMID_R
#endif

325
/* choose the appropriate stat and fstat functions and return structs */
326
#undef STAT
327 328
#undef FSTAT
#undef STRUCT_STAT
329
#if defined(MS_WIN64) || defined(MS_WINDOWS)
330 331 332
#       define STAT win32_stat
#       define FSTAT win32_fstat
#       define STRUCT_STAT struct win32_stat
333
#else
334 335 336
#       define STAT stat
#       define FSTAT fstat
#       define STRUCT_STAT struct stat
337 338
#endif

339
#if defined(MAJOR_IN_MKDEV)
340 341 342 343 344
#include <sys/mkdev.h>
#else
#if defined(MAJOR_IN_SYSMACROS)
#include <sys/sysmacros.h>
#endif
345 346 347
#if defined(HAVE_MKNOD) && defined(HAVE_SYS_MKDEV_H)
#include <sys/mkdev.h>
#endif
348
#endif
349

350 351 352 353 354 355 356 357 358 359 360 361 362
#if defined _MSC_VER && _MSC_VER >= 1400
/* Microsoft CRT in VS2005 and higher will verify that a filehandle is
 * valid and throw an assertion if it isn't.
 * Normally, an invalid fd is likely to be a C program error and therefore
 * an assertion can be useful, but it does contradict the POSIX standard
 * which for write(2) states:
 *    "Otherwise, -1 shall be returned and errno set to indicate the error."
 *    "[EBADF] The fildes argument is not a valid file descriptor open for
 *     writing."
 * Furthermore, python allows the user to enter any old integer
 * as a fd and should merely raise a python exception on error.
 * The Microsoft CRT doesn't provide an official way to check for the
 * validity of a file descriptor, but we can emulate its internal behaviour
363
 * by using the exported __pinfo data member and knowledge of the
364 365 366 367 368 369 370
 * internal structures involved.
 * The structures below must be updated for each version of visual studio
 * according to the file internal.h in the CRT source, until MS comes
 * up with a less hacky way to do this.
 * (all of this is to avoid globally modifying the CRT behaviour using
 * _set_invalid_parameter_handler() and _CrtSetReportMode())
 */
371 372 373
/* The actual size of the structure is determined at runtime.
 * Only the first items must be present.
 */
374
typedef struct {
375 376
    intptr_t osfhnd;
    char osfile;
377 378 379
} my_ioinfo;

extern __declspec(dllimport) char * __pioinfo[];
380 381 382 383 384 385 386 387 388 389 390
#define IOINFO_L2E 5
#define IOINFO_ARRAY_ELTS   (1 << IOINFO_L2E)
#define IOINFO_ARRAYS 64
#define _NHANDLE_           (IOINFO_ARRAYS * IOINFO_ARRAY_ELTS)
#define FOPEN 0x01
#define _NO_CONSOLE_FILENO (intptr_t)-2

/* This function emulates what the windows CRT does to validate file handles */
int
_PyVerify_fd(int fd)
{
391 392 393
    const int i1 = fd >> IOINFO_L2E;
    const int i2 = fd & ((1 << IOINFO_L2E) - 1);

394
    static size_t sizeof_ioinfo = 0;
395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419

    /* Determine the actual size of the ioinfo structure,
     * as used by the CRT loaded in memory
     */
    if (sizeof_ioinfo == 0 && __pioinfo[0] != NULL) {
        sizeof_ioinfo = _msize(__pioinfo[0]) / IOINFO_ARRAY_ELTS;
    }
    if (sizeof_ioinfo == 0) {
        /* This should not happen... */
        goto fail;
    }

    /* See that it isn't a special CLEAR fileno */
    if (fd != _NO_CONSOLE_FILENO) {
        /* Microsoft CRT would check that 0<=fd<_nhandle but we can't do that.  Instead
         * we check pointer validity and other info
         */
        if (0 <= i1 && i1 < IOINFO_ARRAYS && __pioinfo[i1] != NULL) {
            /* finally, check that the file is open */
            my_ioinfo* info = (my_ioinfo*)(__pioinfo[i1] + i2 * sizeof_ioinfo);
            if (info->osfile & FOPEN) {
                return 1;
            }
        }
    }
420
  fail:
421 422
    errno = EBADF;
    return 0;
423 424 425 426 427 428
}

/* the special case of checking dup2.  The target fd must be in a sensible range */
static int
_PyVerify_fd_dup2(int fd1, int fd2)
{
429 430 431 432 433 434 435 436
    if (!_PyVerify_fd(fd1))
        return 0;
    if (fd2 == _NO_CONSOLE_FILENO)
        return 0;
    if ((unsigned)fd2 < _NHANDLE_)
        return 1;
    else
        return 0;
437 438 439 440 441 442
}
#else
/* dummy version. _PyVerify_fd() is already defined in fileobject.h */
#define _PyVerify_fd_dup2(A, B) (1)
#endif

443
#ifdef MS_WINDOWS
444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480
/* The following structure was copied from
   http://msdn.microsoft.com/en-us/library/ms791514.aspx as the required
   include doesn't seem to be present in the Windows SDK (at least as included
   with Visual Studio Express). */
typedef struct _REPARSE_DATA_BUFFER {
    ULONG ReparseTag;
    USHORT ReparseDataLength;
    USHORT Reserved;
    union {
        struct {
            USHORT SubstituteNameOffset;
            USHORT SubstituteNameLength;
            USHORT PrintNameOffset;
            USHORT PrintNameLength;
            ULONG Flags;
            WCHAR PathBuffer[1];
        } SymbolicLinkReparseBuffer;

        struct {
            USHORT SubstituteNameOffset;
            USHORT  SubstituteNameLength;
            USHORT  PrintNameOffset;
            USHORT  PrintNameLength;
            WCHAR  PathBuffer[1];
        } MountPointReparseBuffer;

        struct {
            UCHAR  DataBuffer[1];
        } GenericReparseBuffer;
    };
} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;

#define REPARSE_DATA_BUFFER_HEADER_SIZE  FIELD_OFFSET(REPARSE_DATA_BUFFER,\
                                                      GenericReparseBuffer)
#define MAXIMUM_REPARSE_DATA_BUFFER_SIZE  ( 16 * 1024 )

static int
481
win32_get_reparse_tag(HANDLE reparse_point_handle, ULONG *reparse_tag)
482 483 484 485 486 487 488 489 490 491 492 493
{
    char target_buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
    REPARSE_DATA_BUFFER *rdb = (REPARSE_DATA_BUFFER *)target_buffer;
    DWORD n_bytes_returned;

    if (0 == DeviceIoControl(
        reparse_point_handle,
        FSCTL_GET_REPARSE_POINT,
        NULL, 0, /* in buffer */
        target_buffer, sizeof(target_buffer),
        &n_bytes_returned,
        NULL)) /* we're not using OVERLAPPED_IO */
494
        return FALSE;
495 496 497 498

    if (reparse_tag)
        *reparse_tag = rdb->ReparseTag;

499
    return TRUE;
500
}
501
#endif /* MS_WINDOWS */
502

Guido van Rossum's avatar
Guido van Rossum committed
503
/* Return a dictionary corresponding to the POSIX environment table */
504 505 506 507 508 509 510
#ifdef WITH_NEXT_FRAMEWORK
/* On Darwin/MacOSX a shared library or framework has no access to
** environ directly, we must obtain it with _NSGetEnviron().
*/
#include <crt_externs.h>
static char **environ;
#elif !defined(_MSC_VER) && ( !defined(__WATCOMC__) || defined(__QNX__) )
Guido van Rossum's avatar
Guido van Rossum committed
511
extern char **environ;
512
#endif /* !_MSC_VER */
Guido van Rossum's avatar
Guido van Rossum committed
513

Barry Warsaw's avatar
Barry Warsaw committed
514
static PyObject *
515
convertenviron(void)
Guido van Rossum's avatar
Guido van Rossum committed
516
{
517
    PyObject *d;
518
#ifdef MS_WINDOWS
519
    wchar_t **e;
520
#else
521 522 523 524 525
    char **e;
#endif
#if defined(PYOS_OS2)
    APIRET rc;
    char   buffer[1024]; /* OS/2 Provides a Documented Max of 1024 Chars */
526
#endif
527 528 529 530

    d = PyDict_New();
    if (d == NULL)
        return NULL;
531
#ifdef WITH_NEXT_FRAMEWORK
532 533
    if (environ == NULL)
        environ = *_NSGetEnviron();
534
#endif
535
#ifdef MS_WINDOWS
536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565
    /* _wenviron must be initialized in this way if the program is started
       through main() instead of wmain(). */
    _wgetenv(L"");
    if (_wenviron == NULL)
        return d;
    /* This part ignores errors */
    for (e = _wenviron; *e != NULL; e++) {
        PyObject *k;
        PyObject *v;
        wchar_t *p = wcschr(*e, L'=');
        if (p == NULL)
            continue;
        k = PyUnicode_FromWideChar(*e, (Py_ssize_t)(p-*e));
        if (k == NULL) {
            PyErr_Clear();
            continue;
        }
        v = PyUnicode_FromWideChar(p+1, wcslen(p+1));
        if (v == NULL) {
            PyErr_Clear();
            Py_DECREF(k);
            continue;
        }
        if (PyDict_GetItem(d, k) == NULL) {
            if (PyDict_SetItem(d, k, v) != 0)
                PyErr_Clear();
        }
        Py_DECREF(k);
        Py_DECREF(v);
    }
566
#else
567 568 569 570 571 572 573 574 575
    if (environ == NULL)
        return d;
    /* This part ignores errors */
    for (e = environ; *e != NULL; e++) {
        PyObject *k;
        PyObject *v;
        char *p = strchr(*e, '=');
        if (p == NULL)
            continue;
576
        k = PyBytes_FromStringAndSize(*e, (int)(p-*e));
577 578 579
        if (k == NULL) {
            PyErr_Clear();
            continue;
580
        }
581
        v = PyBytes_FromStringAndSize(p+1, strlen(p+1));
582 583 584 585
        if (v == NULL) {
            PyErr_Clear();
            Py_DECREF(k);
            continue;
586
        }
587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606
        if (PyDict_GetItem(d, k) == NULL) {
            if (PyDict_SetItem(d, k, v) != 0)
                PyErr_Clear();
        }
        Py_DECREF(k);
        Py_DECREF(v);
    }
#endif
#if defined(PYOS_OS2)
    rc = DosQueryExtLIBPATH(buffer, BEGIN_LIBPATH);
    if (rc == NO_ERROR) { /* (not a type, envname is NOT 'BEGIN_LIBPATH') */
        PyObject *v = PyBytes_FromString(buffer);
        PyDict_SetItemString(d, "BEGINLIBPATH", v);
        Py_DECREF(v);
    }
    rc = DosQueryExtLIBPATH(buffer, END_LIBPATH);
    if (rc == NO_ERROR) { /* (not a typo, envname is NOT 'END_LIBPATH') */
        PyObject *v = PyBytes_FromString(buffer);
        PyDict_SetItemString(d, "ENDLIBPATH", v);
        Py_DECREF(v);
607 608
    }
#endif
609
    return d;
Guido van Rossum's avatar
Guido van Rossum committed
610 611 612 613
}

/* Set a POSIX-specific error from errno, and return NULL */

614
static PyObject *
615
posix_error(void)
Guido van Rossum's avatar
Guido van Rossum committed
616
{
617
    return PyErr_SetFromErrno(PyExc_OSError);
Guido van Rossum's avatar
Guido van Rossum committed
618
}
619
static PyObject *
620
posix_error_with_filename(char* name)
621
{
622
    return PyErr_SetFromErrnoWithFilename(PyExc_OSError, name);
623 624
}

625

626
static PyObject *
627
posix_error_with_allocated_filename(PyObject* name)
628
{
629 630 631
    PyObject *name_str, *rc;
    name_str = PyUnicode_DecodeFSDefaultAndSize(PyBytes_AsString(name),
                                                PyBytes_GET_SIZE(name));
632
    Py_DECREF(name);
633 634 635
    rc = PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError,
                                              name_str);
    Py_XDECREF(name_str);
636
    return rc;
637 638
}

639
#ifdef MS_WINDOWS
640
static PyObject *
641
win32_error(char* function, const char* filename)
642
{
643 644 645 646 647 648 649 650 651 652
    /* XXX We should pass the function name along in the future.
       (winreg.c also wants to pass the function name.)
       This would however require an additional param to the
       Windows error object, which is non-trivial.
    */
    errno = GetLastError();
    if (filename)
        return PyErr_SetFromWindowsErrWithFilename(errno, filename);
    else
        return PyErr_SetFromWindowsErr(errno);
653
}
654 655 656 657

static PyObject *
win32_error_unicode(char* function, Py_UNICODE* filename)
{
658 659 660 661 662 663
    /* XXX - see win32_error for comments on 'function' */
    errno = GetLastError();
    if (filename)
        return PyErr_SetFromWindowsErrWithUnicodeFilename(errno, filename);
    else
        return PyErr_SetFromWindowsErr(errno);
664 665
}

666
static int
667
convert_to_unicode(PyObject **param)
668
{
669 670 671 672 673 674 675 676 677 678 679 680
    if (PyUnicode_CheckExact(*param))
        Py_INCREF(*param);
    else if (PyUnicode_Check(*param))
        /* For a Unicode subtype that's not a Unicode object,
           return a true Unicode object with the same data. */
        *param = PyUnicode_FromUnicode(PyUnicode_AS_UNICODE(*param),
                                       PyUnicode_GET_SIZE(*param));
    else
        *param = PyUnicode_FromEncodedObject(*param,
                                             Py_FileSystemDefaultEncoding,
                                             "strict");
    return (*param) != NULL;
681 682
}

683
#endif /* MS_WINDOWS */
Guido van Rossum's avatar
Guido van Rossum committed
684

685 686 687 688
#if defined(PYOS_OS2)
/**********************************************************************
 *         Helper Function to Trim and Format OS/2 Messages
 **********************************************************************/
689
static void
690 691 692 693 694 695 696
os2_formatmsg(char *msgbuf, int msglen, char *reason)
{
    msgbuf[msglen] = '\0'; /* OS/2 Doesn't Guarantee a Terminator */

    if (strlen(msgbuf) > 0) { /* If Non-Empty Msg, Trim CRLF */
        char *lastc = &msgbuf[ strlen(msgbuf)-1 ];

697
        while (lastc > msgbuf && isspace(Py_CHARMASK(*lastc)))
698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718
            *lastc-- = '\0'; /* Trim Trailing Whitespace (CRLF) */
    }

    /* Add Optional Reason Text */
    if (reason) {
        strcat(msgbuf, " : ");
        strcat(msgbuf, reason);
    }
}

/**********************************************************************
 *             Decode an OS/2 Operating System Error Code
 *
 * A convenience function to lookup an OS/2 error code and return a
 * text message we can use to raise a Python exception.
 *
 * Notes:
 *   The messages for errors returned from the OS/2 kernel reside in
 *   the file OSO001.MSG in the \OS2 directory hierarchy.
 *
 **********************************************************************/
719
static char *
720 721 722 723 724 725 726 727 728 729 730 731 732 733
os2_strerror(char *msgbuf, int msgbuflen, int errorcode, char *reason)
{
    APIRET rc;
    ULONG  msglen;

    /* Retrieve Kernel-Related Error Message from OSO001.MSG File */
    Py_BEGIN_ALLOW_THREADS
    rc = DosGetMessage(NULL, 0, msgbuf, msgbuflen,
                       errorcode, "oso001.msg", &msglen);
    Py_END_ALLOW_THREADS

    if (rc == NO_ERROR)
        os2_formatmsg(msgbuf, msglen, reason);
    else
734
        PyOS_snprintf(msgbuf, msgbuflen,
735
                      "unknown OS error #%d", errorcode);
736 737 738 739 740 741 742 743

    return msgbuf;
}

/* Set an OS/2-specific error and return NULL.  OS/2 kernel
   errors are not in a global variable e.g. 'errno' nor are
   they congruent with posix error numbers. */

744 745
static PyObject *
os2_error(int code)
746 747 748 749 750 751 752 753
{
    char text[1024];
    PyObject *v;

    os2_strerror(text, sizeof(text), code, "");

    v = Py_BuildValue("(is)", code, text);
    if (v != NULL) {
754
        PyErr_SetObject(PyExc_OSError, v);
755 756 757 758 759 760
        Py_DECREF(v);
    }
    return NULL; /* Signal to Python that an Exception is Pending */
}

#endif /* OS2 */
Guido van Rossum's avatar
Guido van Rossum committed
761 762 763

/* POSIX generic methods */

764 765 766
static PyObject *
posix_fildes(PyObject *fdobj, int (*func)(int))
{
767 768 769 770 771 772 773 774 775 776 777 778 779 780
    int fd;
    int res;
    fd = PyObject_AsFileDescriptor(fdobj);
    if (fd < 0)
        return NULL;
    if (!_PyVerify_fd(fd))
        return posix_error();
    Py_BEGIN_ALLOW_THREADS
    res = (*func)(fd);
    Py_END_ALLOW_THREADS
    if (res < 0)
        return posix_error();
    Py_INCREF(Py_None);
    return Py_None;
781
}
782

Barry Warsaw's avatar
Barry Warsaw committed
783
static PyObject *
784
posix_1str(PyObject *args, char *format, int (*func)(const char*))
Guido van Rossum's avatar
Guido van Rossum committed
785
{
786 787 788 789 790 791 792 793 794 795 796 797 798 799 800
    PyObject *opath1 = NULL;
    char *path1;
    int res;
    if (!PyArg_ParseTuple(args, format,
                          PyUnicode_FSConverter, &opath1))
        return NULL;
    path1 = PyBytes_AsString(opath1);
    Py_BEGIN_ALLOW_THREADS
    res = (*func)(path1);
    Py_END_ALLOW_THREADS
    if (res < 0)
        return posix_error_with_allocated_filename(opath1);
    Py_DECREF(opath1);
    Py_INCREF(Py_None);
    return Py_None;
Guido van Rossum's avatar
Guido van Rossum committed
801 802
}

Barry Warsaw's avatar
Barry Warsaw committed
803
static PyObject *
804
posix_2str(PyObject *args,
805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827
           char *format,
           int (*func)(const char *, const char *))
{
    PyObject *opath1 = NULL, *opath2 = NULL;
    char *path1, *path2;
    int res;
    if (!PyArg_ParseTuple(args, format,
                          PyUnicode_FSConverter, &opath1,
                          PyUnicode_FSConverter, &opath2)) {
        return NULL;
    }
    path1 = PyBytes_AsString(opath1);
    path2 = PyBytes_AsString(opath2);
    Py_BEGIN_ALLOW_THREADS
    res = (*func)(path1, path2);
    Py_END_ALLOW_THREADS
    Py_DECREF(opath1);
    Py_DECREF(opath2);
    if (res != 0)
        /* XXX how to report both path1 and path2??? */
        return posix_error();
    Py_INCREF(Py_None);
    return Py_None;
Guido van Rossum's avatar
Guido van Rossum committed
828 829
}

830
#ifdef MS_WINDOWS
831
static PyObject*
832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859
win32_1str(PyObject* args, char* func,
           char* format, BOOL (__stdcall *funcA)(LPCSTR),
           char* wformat, BOOL (__stdcall *funcW)(LPWSTR))
{
    PyObject *uni;
    char *ansi;
    BOOL result;

    if (!PyArg_ParseTuple(args, wformat, &uni))
        PyErr_Clear();
    else {
        Py_BEGIN_ALLOW_THREADS
        result = funcW(PyUnicode_AsUnicode(uni));
        Py_END_ALLOW_THREADS
        if (!result)
            return win32_error_unicode(func, PyUnicode_AsUnicode(uni));
        Py_INCREF(Py_None);
        return Py_None;
    }
    if (!PyArg_ParseTuple(args, format, &ansi))
        return NULL;
    Py_BEGIN_ALLOW_THREADS
    result = funcA(ansi);
    Py_END_ALLOW_THREADS
    if (!result)
        return win32_error(func, ansi);
    Py_INCREF(Py_None);
    return Py_None;
860 861 862 863 864 865 866 867

}

/* This is a reimplementation of the C library's chdir function,
   but one that produces Win32 errors instead of DOS error codes.
   chdir is essentially a wrapper around SetCurrentDirectory; however,
   it also needs to set "magic" environment variables indicating
   the per-drive current directory, which are of the form =<drive>: */
Benjamin Peterson's avatar
Benjamin Peterson committed
868
static BOOL __stdcall
869 870
win32_chdir(LPCSTR path)
{
871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888
    char new_path[MAX_PATH+1];
    int result;
    char env[4] = "=x:";

    if(!SetCurrentDirectoryA(path))
        return FALSE;
    result = GetCurrentDirectoryA(MAX_PATH+1, new_path);
    if (!result)
        return FALSE;
    /* In the ANSI API, there should not be any paths longer
       than MAX_PATH. */
    assert(result <= MAX_PATH+1);
    if (strncmp(new_path, "\\\\", 2) == 0 ||
        strncmp(new_path, "//", 2) == 0)
        /* UNC path, nothing to do. */
        return TRUE;
    env[1] = new_path[0];
    return SetEnvironmentVariableA(env, new_path);
889 890 891 892
}

/* The Unicode version differs from the ANSI version
   since the current directory might exceed MAX_PATH characters */
Benjamin Peterson's avatar
Benjamin Peterson committed
893
static BOOL __stdcall
894 895
win32_wchdir(LPCWSTR path)
{
896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925
    wchar_t _new_path[MAX_PATH+1], *new_path = _new_path;
    int result;
    wchar_t env[4] = L"=x:";

    if(!SetCurrentDirectoryW(path))
        return FALSE;
    result = GetCurrentDirectoryW(MAX_PATH+1, new_path);
    if (!result)
        return FALSE;
    if (result > MAX_PATH+1) {
        new_path = malloc(result * sizeof(wchar_t));
        if (!new_path) {
            SetLastError(ERROR_OUTOFMEMORY);
            return FALSE;
        }
        result = GetCurrentDirectoryW(result, new_path);
        if (!result) {
            free(new_path);
            return FALSE;
        }
    }
    if (wcsncmp(new_path, L"\\\\", 2) == 0 ||
        wcsncmp(new_path, L"//", 2) == 0)
        /* UNC path, nothing to do. */
        return TRUE;
    env[1] = new_path[0];
    result = SetEnvironmentVariableW(env, new_path);
    if (new_path != _new_path)
        free(new_path);
    return result;
926 927 928
}
#endif

929 930 931 932 933 934 935
#ifdef MS_WINDOWS
/* The CRT of Windows has a number of flaws wrt. its stat() implementation:
   - time stamps are restricted to second resolution
   - file modification times suffer from forth-and-back conversions between
     UTC and local time
   Therefore, we implement our own stat, based on the Win32 API directly.
*/
936
#define HAVE_STAT_NSEC 1
937 938 939 940 941 942 943 944 945 946

struct win32_stat{
    int st_dev;
    __int64 st_ino;
    unsigned short st_mode;
    int st_nlink;
    int st_uid;
    int st_gid;
    int st_rdev;
    __int64 st_size;
947
    time_t st_atime;
948
    int st_atime_nsec;
949
    time_t st_mtime;
950
    int st_mtime_nsec;
951
    time_t st_ctime;
952 953 954 955 956 957
    int st_ctime_nsec;
};

static __int64 secs_between_epochs = 11644473600; /* Seconds between 1.1.1601 and 1.1.1970 */

static void
958
FILE_TIME_to_time_t_nsec(FILETIME *in_ptr, time_t *time_out, int* nsec_out)
959
{
960 961 962 963 964 965
    /* XXX endianness. Shouldn't matter, as all Windows implementations are little-endian */
    /* Cannot simply cast and dereference in_ptr,
       since it might not be aligned properly */
    __int64 in;
    memcpy(&in, in_ptr, sizeof(in));
    *nsec_out = (int)(in % 10000000) * 100; /* FILETIME is in units of 100 nsec. */
966
    *time_out = Py_SAFE_DOWNCAST((in / 10000000) - secs_between_epochs, __int64, time_t);
967 968
}

969
static void
970
time_t_to_FILE_TIME(time_t time_in, int nsec_in, FILETIME *out_ptr)
971
{
972 973 974 975 976
    /* XXX endianness */
    __int64 out;
    out = time_in + secs_between_epochs;
    out = out * 10000000 + nsec_in / 100;
    memcpy(out_ptr, &out, sizeof(out));
977 978
}

979 980 981 982 983 984 985
/* Below, we *know* that ugo+r is 0444 */
#if _S_IREAD != 0400
#error Unsupported C library
#endif
static int
attributes_to_mode(DWORD attr)
{
986 987 988 989 990 991 992 993 994 995
    int m = 0;
    if (attr & FILE_ATTRIBUTE_DIRECTORY)
        m |= _S_IFDIR | 0111; /* IFEXEC for user,group,other */
    else
        m |= _S_IFREG;
    if (attr & FILE_ATTRIBUTE_READONLY)
        m |= 0444;
    else
        m |= 0666;
    return m;
996 997 998
}

static int
999
attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *info, ULONG reparse_tag, struct win32_stat *result)
1000
{
1001 1002 1003 1004 1005 1006
    memset(result, 0, sizeof(*result));
    result->st_mode = attributes_to_mode(info->dwFileAttributes);
    result->st_size = (((__int64)info->nFileSizeHigh)<<32) + info->nFileSizeLow;
    FILE_TIME_to_time_t_nsec(&info->ftCreationTime, &result->st_ctime, &result->st_ctime_nsec);
    FILE_TIME_to_time_t_nsec(&info->ftLastWriteTime, &result->st_mtime, &result->st_mtime_nsec);
    FILE_TIME_to_time_t_nsec(&info->ftLastAccessTime, &result->st_atime, &result->st_atime_nsec);
1007
    result->st_nlink = info->nNumberOfLinks;
1008
    result->st_ino = (((__int64)info->nFileIndexHigh)<<32) + info->nFileIndexLow;
1009 1010 1011 1012 1013 1014
    if (reparse_tag == IO_REPARSE_TAG_SYMLINK) {
        /* first clear the S_IFMT bits */
        result->st_mode ^= (result->st_mode & 0170000);
        /* now set the bits that make this a symlink */
        result->st_mode |= 0120000;
    }
1015

1016
    return 0;
1017 1018
}

1019
static BOOL
1020
attributes_from_dir(LPCSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag)
1021
{
1022 1023 1024 1025 1026 1027
    HANDLE hFindFile;
    WIN32_FIND_DATAA FileData;
    hFindFile = FindFirstFileA(pszFile, &FileData);
    if (hFindFile == INVALID_HANDLE_VALUE)
        return FALSE;
    FindClose(hFindFile);
1028
    memset(info, 0, sizeof(*info));
1029
    *reparse_tag = 0;
1030 1031 1032 1033 1034 1035 1036
    info->dwFileAttributes = FileData.dwFileAttributes;
    info->ftCreationTime   = FileData.ftCreationTime;
    info->ftLastAccessTime = FileData.ftLastAccessTime;
    info->ftLastWriteTime  = FileData.ftLastWriteTime;
    info->nFileSizeHigh    = FileData.nFileSizeHigh;
    info->nFileSizeLow     = FileData.nFileSizeLow;
/*  info->nNumberOfLinks   = 1; */
1037 1038
    if (FileData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
        *reparse_tag = FileData.dwReserved0;
1039
    return TRUE;
1040 1041 1042
}

static BOOL
1043
attributes_from_dir_w(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag)
1044
{
1045 1046 1047 1048 1049 1050
    HANDLE hFindFile;
    WIN32_FIND_DATAW FileData;
    hFindFile = FindFirstFileW(pszFile, &FileData);
    if (hFindFile == INVALID_HANDLE_VALUE)
        return FALSE;
    FindClose(hFindFile);
1051
    memset(info, 0, sizeof(*info));
1052
    *reparse_tag = 0;
1053 1054 1055 1056 1057 1058 1059
    info->dwFileAttributes = FileData.dwFileAttributes;
    info->ftCreationTime   = FileData.ftCreationTime;
    info->ftLastAccessTime = FileData.ftLastAccessTime;
    info->ftLastWriteTime  = FileData.ftLastWriteTime;
    info->nFileSizeHigh    = FileData.nFileSizeHigh;
    info->nFileSizeLow     = FileData.nFileSizeLow;
/*  info->nNumberOfLinks   = 1; */
1060 1061
    if (FileData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
        *reparse_tag = FileData.dwReserved0;
1062 1063 1064
    return TRUE;
}

1065 1066 1067 1068 1069 1070
/* Grab GetFinalPathNameByHandle dynamically from kernel32 */
static int has_GetFinalPathNameByHandle = 0;
static DWORD (CALLBACK *Py_GetFinalPathNameByHandleA)(HANDLE, LPSTR, DWORD,
                                                      DWORD);
static DWORD (CALLBACK *Py_GetFinalPathNameByHandleW)(HANDLE, LPWSTR, DWORD,
                                                      DWORD);
1071
static int
1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102
check_GetFinalPathNameByHandle()
{
    HINSTANCE hKernel32;
    /* only recheck */
    if (!has_GetFinalPathNameByHandle)
    {
        hKernel32 = GetModuleHandle("KERNEL32");
        *(FARPROC*)&Py_GetFinalPathNameByHandleA = GetProcAddress(hKernel32,
                                                "GetFinalPathNameByHandleA");
        *(FARPROC*)&Py_GetFinalPathNameByHandleW = GetProcAddress(hKernel32,
                                                "GetFinalPathNameByHandleW");
        has_GetFinalPathNameByHandle = Py_GetFinalPathNameByHandleA &&
                                       Py_GetFinalPathNameByHandleW;
    }
    return has_GetFinalPathNameByHandle;
}

static BOOL
get_target_path(HANDLE hdl, wchar_t **target_path)
{
    int buf_size, result_length;
    wchar_t *buf;

    /* We have a good handle to the target, use it to determine
       the target path name (then we'll call lstat on it). */
    buf_size = Py_GetFinalPathNameByHandleW(hdl, 0, 0,
                                            VOLUME_NAME_DOS);
    if(!buf_size)
        return FALSE;

    buf = (wchar_t *)malloc((buf_size+1)*sizeof(wchar_t));
1103 1104 1105 1106 1107
    if (!buf) {
        SetLastError(ERROR_OUTOFMEMORY);
        return FALSE;
    }

1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125
    result_length = Py_GetFinalPathNameByHandleW(hdl,
                       buf, buf_size, VOLUME_NAME_DOS);

    if(!result_length) {
        free(buf);
        return FALSE;
    }

    if(!CloseHandle(hdl)) {
        free(buf);
        return FALSE;
    }

    buf[result_length] = 0;

    *target_path = buf;
    return TRUE;
}
1126

1127
static int
1128 1129 1130 1131 1132
win32_xstat_impl_w(const wchar_t *path, struct win32_stat *result,
                   BOOL traverse);
static int
win32_xstat_impl(const char *path, struct win32_stat *result,
                 BOOL traverse)
1133
{
1134
    int code;
1135
    HANDLE hFile, hFile2;
1136
    BY_HANDLE_FILE_INFORMATION info;
1137
    ULONG reparse_tag = 0;
1138
    wchar_t *target_path;
1139 1140
    const char *dot;

1141
    if(!check_GetFinalPathNameByHandle()) {
1142 1143 1144
        /* If the OS doesn't have GetFinalPathNameByHandle, don't
           traverse reparse point. */
        traverse = FALSE;
1145 1146
    }

1147 1148
    hFile = CreateFileA(
        path,
1149
        FILE_READ_ATTRIBUTES, /* desired access */
1150 1151 1152 1153
        0, /* share mode */
        NULL, /* security attributes */
        OPEN_EXISTING,
        /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
1154 1155 1156 1157 1158
        /* FILE_FLAG_OPEN_REPARSE_POINT does not follow the symlink.
           Because of this, calls like GetFinalPathNameByHandle will return
           the symlink path agin and not the actual final path. */
        FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS|
            FILE_FLAG_OPEN_REPARSE_POINT,
1159 1160
        NULL);

1161
    if (hFile == INVALID_HANDLE_VALUE) {
1162 1163 1164 1165
        /* Either the target doesn't exist, or we don't have access to
           get a handle to it. If the former, we need to return an error.
           If the latter, we can use attributes_from_dir. */
        if (GetLastError() != ERROR_SHARING_VIOLATION)
1166 1167 1168 1169 1170 1171 1172 1173 1174
            return -1;
        /* Could not get attributes on open file. Fall back to
           reading the directory. */
        if (!attributes_from_dir(path, &info, &reparse_tag))
            /* Very strange. This should not fail now */
            return -1;
        if (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
            if (traverse) {
                /* Should traverse, but could not open reparse point handle */
1175
                SetLastError(ERROR_SHARING_VIOLATION);
1176 1177 1178 1179 1180 1181
                return -1;
            }
        }
    } else {
        if (!GetFileInformationByHandle(hFile, &info)) {
            CloseHandle(hFile);
1182
            return -1;
1183 1184
        }
        if (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
1185 1186 1187 1188 1189 1190 1191 1192
            if (!win32_get_reparse_tag(hFile, &reparse_tag))
                return -1;

            /* Close the outer open file handle now that we're about to
               reopen it with different flags. */
            if (!CloseHandle(hFile))
                return -1;

1193
            if (traverse) {
1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207
                /* In order to call GetFinalPathNameByHandle we need to open
                   the file without the reparse handling flag set. */
                hFile2 = CreateFileA(
                           path, FILE_READ_ATTRIBUTES, FILE_SHARE_READ,
                           NULL, OPEN_EXISTING,
                           FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS,
                           NULL);
                if (hFile2 == INVALID_HANDLE_VALUE)
                    return -1;

                if (!get_target_path(hFile2, &target_path))
                    return -1;

                code = win32_xstat_impl_w(target_path, result, FALSE);
1208 1209
                free(target_path);
                return code;
1210
            }
1211 1212
        } else
            CloseHandle(hFile);
1213
    }
1214
    attribute_data_to_stat(&info, reparse_tag, result);
1215

1216
    /* Set S_IEXEC if it is an .exe, .bat, ... */
1217 1218
    dot = strrchr(path, '.');
    if (dot) {
1219 1220
        if (stricmp(dot, ".bat") == 0 || stricmp(dot, ".cmd") == 0 ||
            stricmp(dot, ".exe") == 0 || stricmp(dot, ".com") == 0)
1221 1222
            result->st_mode |= 0111;
    }
1223
    return 0;
1224 1225 1226
}

static int
1227 1228
win32_xstat_impl_w(const wchar_t *path, struct win32_stat *result,
                   BOOL traverse)
1229 1230
{
    int code;
1231
    HANDLE hFile, hFile2;
1232
    BY_HANDLE_FILE_INFORMATION info;
1233
    ULONG reparse_tag = 0;
1234
    wchar_t *target_path;
1235
    const wchar_t *dot;
1236

1237
    if(!check_GetFinalPathNameByHandle()) {
1238 1239 1240
        /* If the OS doesn't have GetFinalPathNameByHandle, don't
           traverse reparse point. */
        traverse = FALSE;
1241 1242
    }

1243
    hFile = CreateFileW(
1244
        path,
1245
        FILE_READ_ATTRIBUTES, /* desired access */
1246 1247 1248 1249
        0, /* share mode */
        NULL, /* security attributes */
        OPEN_EXISTING,
        /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
1250 1251 1252
        /* FILE_FLAG_OPEN_REPARSE_POINT does not follow the symlink.
           Because of this, calls like GetFinalPathNameByHandle will return
           the symlink path agin and not the actual final path. */
1253
        FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS|
1254
            FILE_FLAG_OPEN_REPARSE_POINT,
1255
        NULL);
1256

1257
    if (hFile == INVALID_HANDLE_VALUE) {
1258 1259 1260
        /* Either the target doesn't exist, or we don't have access to
           get a handle to it. If the former, we need to return an error.
           If the latter, we can use attributes_from_dir. */
1261
        if (GetLastError() != ERROR_SHARING_VIOLATION)
1262 1263 1264 1265 1266 1267 1268 1269 1270
            return -1;
        /* Could not get attributes on open file. Fall back to
           reading the directory. */
        if (!attributes_from_dir_w(path, &info, &reparse_tag))
            /* Very strange. This should not fail now */
            return -1;
        if (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
            if (traverse) {
                /* Should traverse, but could not open reparse point handle */
1271
                SetLastError(ERROR_SHARING_VIOLATION);
1272 1273 1274 1275 1276 1277
                return -1;
            }
        }
    } else {
        if (!GetFileInformationByHandle(hFile, &info)) {
            CloseHandle(hFile);
1278
            return -1;
1279 1280
        }
        if (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
1281 1282 1283 1284 1285 1286 1287 1288
            if (!win32_get_reparse_tag(hFile, &reparse_tag))
                return -1;

            /* Close the outer open file handle now that we're about to
               reopen it with different flags. */
            if (!CloseHandle(hFile))
                return -1;

1289
            if (traverse) {
1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303
                /* In order to call GetFinalPathNameByHandle we need to open
                   the file without the reparse handling flag set. */
                hFile2 = CreateFileW(
                           path, FILE_READ_ATTRIBUTES, FILE_SHARE_READ,
                           NULL, OPEN_EXISTING,
                           FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS,
                           NULL);
                if (hFile2 == INVALID_HANDLE_VALUE)
                    return -1;

                if (!get_target_path(hFile2, &target_path))
                    return -1;

                code = win32_xstat_impl_w(target_path, result, FALSE);
1304 1305
                free(target_path);
                return code;
1306
            }
1307 1308
        } else
            CloseHandle(hFile);
1309
    }
1310
    attribute_data_to_stat(&info, reparse_tag, result);
1311

1312 1313 1314 1315 1316 1317
    /* Set S_IEXEC if it is an .exe, .bat, ... */
    dot = wcsrchr(path, '.');
    if (dot) {
        if (_wcsicmp(dot, L".bat") == 0 || _wcsicmp(dot, L".cmd") == 0 ||
            _wcsicmp(dot, L".exe") == 0 || _wcsicmp(dot, L".com") == 0)
            result->st_mode |= 0111;
1318
    }
1319
    return 0;
1320
}
1321

1322 1323 1324
static int
win32_xstat(const char *path, struct win32_stat *result, BOOL traverse)
{
1325 1326
    /* Protocol violation: we explicitly clear errno, instead of
       setting it to a POSIX error. Callers should use GetLastError. */
1327
    int code = win32_xstat_impl(path, result, traverse);
1328
    errno = 0;
1329
    return code;
1330 1331
}

1332
static int
1333
win32_xstat_w(const wchar_t *path, struct win32_stat *result, BOOL traverse)
1334
{
1335 1336
    /* Protocol violation: we explicitly clear errno, instead of
       setting it to a POSIX error. Callers should use GetLastError. */
1337
    int code = win32_xstat_impl_w(path, result, traverse);
1338 1339
    errno = 0;
    return code;
1340
}
1341
/* About the following functions: win32_lstat_w, win32_stat, win32_stat_w
1342

1343 1344 1345 1346
   In Posix, stat automatically traverses symlinks and returns the stat
   structure for the target.  In Windows, the equivalent GetFileAttributes by
   default does not traverse symlinks and instead returns attributes for
   the symlink.
1347

1348 1349 1350 1351
   Therefore, win32_lstat will get the attributes traditionally, and
   win32_stat will first explicitly resolve the symlink target and then will
   call win32_lstat on that result.

Ezio Melotti's avatar
Ezio Melotti committed
1352
   The _w represent Unicode equivalents of the aforementioned ANSI functions. */
1353

1354
static int
1355 1356
win32_lstat(const char* path, struct win32_stat *result)
{
1357
    return win32_xstat(path, result, FALSE);
1358 1359 1360 1361 1362
}

static int
win32_lstat_w(const wchar_t* path, struct win32_stat *result)
{
1363
    return win32_xstat_w(path, result, FALSE);
1364 1365 1366 1367 1368
}

static int
win32_stat(const char* path, struct win32_stat *result)
{
1369
    return win32_xstat(path, result, TRUE);
1370 1371
}

1372
static int
1373 1374
win32_stat_w(const wchar_t* path, struct win32_stat *result)
{
1375
    return win32_xstat_w(path, result, TRUE);
1376 1377
}

1378 1379 1380
static int
win32_fstat(int file_number, struct win32_stat *result)
{
1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402
    BY_HANDLE_FILE_INFORMATION info;
    HANDLE h;
    int type;

    h = (HANDLE)_get_osfhandle(file_number);

    /* Protocol violation: we explicitly clear errno, instead of
       setting it to a POSIX error. Callers should use GetLastError. */
    errno = 0;

    if (h == INVALID_HANDLE_VALUE) {
        /* This is really a C library error (invalid file handle).
           We set the Win32 error to the closes one matching. */
        SetLastError(ERROR_INVALID_HANDLE);
        return -1;
    }
    memset(result, 0, sizeof(*result));

    type = GetFileType(h);
    if (type == FILE_TYPE_UNKNOWN) {
        DWORD error = GetLastError();
        if (error != 0) {
1403
            return -1;
1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419
        }
        /* else: valid but unknown file */
    }

    if (type != FILE_TYPE_DISK) {
        if (type == FILE_TYPE_CHAR)
            result->st_mode = _S_IFCHR;
        else if (type == FILE_TYPE_PIPE)
            result->st_mode = _S_IFIFO;
        return 0;
    }

    if (!GetFileInformationByHandle(h, &info)) {
        return -1;
    }

1420
    attribute_data_to_stat(&info, 0, result);
1421 1422 1423
    /* specific to fstat() */
    result->st_ino = (((__int64)info.nFileIndexHigh)<<32) + info.nFileIndexLow;
    return 0;
1424 1425 1426 1427
}

#endif /* MS_WINDOWS */

1428
PyDoc_STRVAR(stat_result__doc__,
1429 1430
"stat_result: Result from stat or lstat.\n\n\
This object may be accessed either as a tuple of\n\
Fred Drake's avatar
Fred Drake committed
1431
  (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\
1432 1433
or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\
\n\
1434 1435
Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\
or st_flags, they are available as attributes only.\n\
1436
\n\
1437
See os.stat for more information.");
1438 1439

static PyStructSequence_Field stat_result_fields[] = {
1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453
    {"st_mode",    "protection bits"},
    {"st_ino",     "inode"},
    {"st_dev",     "device"},
    {"st_nlink",   "number of hard links"},
    {"st_uid",     "user ID of owner"},
    {"st_gid",     "group ID of owner"},
    {"st_size",    "total size, in bytes"},
    /* The NULL is replaced with PyStructSequence_UnnamedField later. */
    {NULL,   "integer time of last access"},
    {NULL,   "integer time of last modification"},
    {NULL,   "integer time of last change"},
    {"st_atime",   "time of last access"},
    {"st_mtime",   "time of last modification"},
    {"st_ctime",   "time of last change"},
1454
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
1455
    {"st_blksize", "blocksize for filesystem I/O"},
1456
#endif
1457
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
1458
    {"st_blocks",  "number of blocks allocated"},
1459
#endif
1460
#ifdef HAVE_STRUCT_STAT_ST_RDEV
1461
    {"st_rdev",    "device type (if inode device)"},
1462 1463
#endif
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
1464
    {"st_flags",   "user defined flags for file"},
1465 1466
#endif
#ifdef HAVE_STRUCT_STAT_ST_GEN
1467
    {"st_gen",    "generation number"},
1468 1469
#endif
#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
1470
    {"st_birthtime",   "time of creation"},
1471
#endif
1472
    {0}
1473 1474
};

1475
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
1476
#define ST_BLKSIZE_IDX 13
1477
#else
1478
#define ST_BLKSIZE_IDX 12
1479 1480
#endif

1481
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
1482 1483 1484 1485 1486
#define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1)
#else
#define ST_BLOCKS_IDX ST_BLKSIZE_IDX
#endif

1487
#ifdef HAVE_STRUCT_STAT_ST_RDEV
1488 1489 1490 1491 1492
#define ST_RDEV_IDX (ST_BLOCKS_IDX+1)
#else
#define ST_RDEV_IDX ST_BLOCKS_IDX
#endif

1493 1494 1495 1496 1497 1498
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
#define ST_FLAGS_IDX (ST_RDEV_IDX+1)
#else
#define ST_FLAGS_IDX ST_RDEV_IDX
#endif

1499
#ifdef HAVE_STRUCT_STAT_ST_GEN
1500
#define ST_GEN_IDX (ST_FLAGS_IDX+1)
1501
#else
1502
#define ST_GEN_IDX ST_FLAGS_IDX
1503 1504 1505 1506 1507 1508 1509 1510
#endif

#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
#define ST_BIRTHTIME_IDX (ST_GEN_IDX+1)
#else
#define ST_BIRTHTIME_IDX ST_GEN_IDX
#endif

1511
static PyStructSequence_Desc stat_result_desc = {
1512 1513 1514 1515
    "stat_result", /* name */
    stat_result__doc__, /* doc */
    stat_result_fields,
    10
1516 1517
};

1518
PyDoc_STRVAR(statvfs_result__doc__,
1519 1520
"statvfs_result: Result from statvfs or fstatvfs.\n\n\
This object may be accessed either as a tuple of\n\
Fred Drake's avatar
Fred Drake committed
1521
  (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\
1522
or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\
1523
\n\
1524
See os.statvfs for more information.");
1525 1526

static PyStructSequence_Field statvfs_result_fields[] = {
1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537
    {"f_bsize",  },
    {"f_frsize", },
    {"f_blocks", },
    {"f_bfree",  },
    {"f_bavail", },
    {"f_files",  },
    {"f_ffree",  },
    {"f_favail", },
    {"f_flag",   },
    {"f_namemax",},
    {0}
1538 1539 1540
};

static PyStructSequence_Desc statvfs_result_desc = {
1541 1542 1543 1544
    "statvfs_result", /* name */
    statvfs_result__doc__, /* doc */
    statvfs_result_fields,
    10
1545 1546
};

1547
static int initialized;
1548 1549
static PyTypeObject StatResultType;
static PyTypeObject StatVFSResultType;
1550 1551 1552 1553 1554
static newfunc structseq_new;

static PyObject *
statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
1555 1556
    PyStructSequence *result;
    int i;
1557

1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571
    result = (PyStructSequence*)structseq_new(type, args, kwds);
    if (!result)
        return NULL;
    /* If we have been initialized from a tuple,
       st_?time might be set to None. Initialize it
       from the int slots.  */
    for (i = 7; i <= 9; i++) {
        if (result->ob_item[i+3] == Py_None) {
            Py_DECREF(Py_None);
            Py_INCREF(result->ob_item[i]);
            result->ob_item[i+3] = result->ob_item[i];
        }
    }
    return (PyObject*)result;
1572 1573 1574 1575 1576
}



/* If true, st_?time is float. */
1577
static int _stat_float_times = 1;
1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588

PyDoc_STRVAR(stat_float_times__doc__,
"stat_float_times([newval]) -> oldval\n\n\
Determine whether os.[lf]stat represents time stamps as float objects.\n\
If newval is True, future calls to stat() return floats, if it is False,\n\
future calls return ints. \n\
If newval is omitted, return the current setting.\n");

static PyObject*
stat_float_times(PyObject* self, PyObject *args)
{
1589 1590 1591 1592 1593 1594 1595 1596 1597
    int newval = -1;
    if (!PyArg_ParseTuple(args, "|i:stat_float_times", &newval))
        return NULL;
    if (newval == -1)
        /* Return old value */
        return PyBool_FromLong(_stat_float_times);
    _stat_float_times = newval;
    Py_INCREF(Py_None);
    return Py_None;
1598
}
1599

1600 1601 1602
static void
fill_time(PyObject *v, int index, time_t sec, unsigned long nsec)
{
1603
    PyObject *fval,*ival;
1604
#if SIZEOF_TIME_T > SIZEOF_LONG
1605
    ival = PyLong_FromLongLong((PY_LONG_LONG)sec);
1606
#else
1607
    ival = PyLong_FromLong((long)sec);
1608
#endif
1609 1610 1611 1612 1613 1614 1615 1616 1617 1618
    if (!ival)
        return;
    if (_stat_float_times) {
        fval = PyFloat_FromDouble(sec + 1e-9*nsec);
    } else {
        fval = ival;
        Py_INCREF(fval);
    }
    PyStructSequence_SET_ITEM(v, index, ival);
    PyStructSequence_SET_ITEM(v, index+3, fval);
1619 1620
}

1621
/* pack a system stat C structure into the Python stat tuple
1622 1623
   (used by posix_stat() and posix_fstat()) */
static PyObject*
1624
_pystat_fromstructstat(STRUCT_STAT *st)
1625
{
1626 1627 1628 1629
    unsigned long ansec, mnsec, cnsec;
    PyObject *v = PyStructSequence_New(&StatResultType);
    if (v == NULL)
        return NULL;
1630

1631
    PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long)st->st_mode));
1632
#ifdef HAVE_LARGEFILE_SUPPORT
1633 1634
    PyStructSequence_SET_ITEM(v, 1,
                              PyLong_FromLongLong((PY_LONG_LONG)st->st_ino));
1635
#else
1636
    PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long)st->st_ino));
1637 1638
#endif
#if defined(HAVE_LONG_LONG) && !defined(MS_WINDOWS)
1639 1640
    PyStructSequence_SET_ITEM(v, 2,
                              PyLong_FromLongLong((PY_LONG_LONG)st->st_dev));
1641
#else
1642
    PyStructSequence_SET_ITEM(v, 2, PyLong_FromLong((long)st->st_dev));
1643
#endif
1644 1645 1646
    PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long)st->st_nlink));
    PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong((long)st->st_uid));
    PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong((long)st->st_gid));
1647
#ifdef HAVE_LARGEFILE_SUPPORT
1648 1649
    PyStructSequence_SET_ITEM(v, 6,
                              PyLong_FromLongLong((PY_LONG_LONG)st->st_size));
1650
#else
1651
    PyStructSequence_SET_ITEM(v, 6, PyLong_FromLong(st->st_size));
1652 1653 1654
#endif

#if defined(HAVE_STAT_TV_NSEC)
1655 1656 1657
    ansec = st->st_atim.tv_nsec;
    mnsec = st->st_mtim.tv_nsec;
    cnsec = st->st_ctim.tv_nsec;
1658
#elif defined(HAVE_STAT_TV_NSEC2)
1659 1660 1661
    ansec = st->st_atimespec.tv_nsec;
    mnsec = st->st_mtimespec.tv_nsec;
    cnsec = st->st_ctimespec.tv_nsec;
1662
#elif defined(HAVE_STAT_NSEC)
1663 1664 1665
    ansec = st->st_atime_nsec;
    mnsec = st->st_mtime_nsec;
    cnsec = st->st_ctime_nsec;
1666
#else
1667
    ansec = mnsec = cnsec = 0;
1668
#endif
1669 1670 1671
    fill_time(v, 7, st->st_atime, ansec);
    fill_time(v, 8, st->st_mtime, mnsec);
    fill_time(v, 9, st->st_ctime, cnsec);
1672

1673
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
1674 1675
    PyStructSequence_SET_ITEM(v, ST_BLKSIZE_IDX,
                              PyLong_FromLong((long)st->st_blksize));
1676
#endif
1677
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
1678 1679
    PyStructSequence_SET_ITEM(v, ST_BLOCKS_IDX,
                              PyLong_FromLong((long)st->st_blocks));
1680
#endif
1681
#ifdef HAVE_STRUCT_STAT_ST_RDEV
1682 1683
    PyStructSequence_SET_ITEM(v, ST_RDEV_IDX,
                              PyLong_FromLong((long)st->st_rdev));
1684
#endif
1685
#ifdef HAVE_STRUCT_STAT_ST_GEN
1686 1687
    PyStructSequence_SET_ITEM(v, ST_GEN_IDX,
                              PyLong_FromLong((long)st->st_gen));
1688 1689
#endif
#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME
1690 1691 1692 1693
    {
      PyObject *val;
      unsigned long bsec,bnsec;
      bsec = (long)st->st_birthtime;
1694
#ifdef HAVE_STAT_TV_NSEC2
1695
      bnsec = st->st_birthtimespec.tv_nsec;
1696
#else
1697 1698 1699 1700 1701 1702 1703 1704 1705 1706
      bnsec = 0;
#endif
      if (_stat_float_times) {
        val = PyFloat_FromDouble(bsec + 1e-9*bnsec);
      } else {
        val = PyLong_FromLong((long)bsec);
      }
      PyStructSequence_SET_ITEM(v, ST_BIRTHTIME_IDX,
                                val);
    }
1707
#endif
1708
#ifdef HAVE_STRUCT_STAT_ST_FLAGS
1709 1710
    PyStructSequence_SET_ITEM(v, ST_FLAGS_IDX,
                              PyLong_FromLong((long)st->st_flags));
1711
#endif
1712

1713 1714 1715 1716
    if (PyErr_Occurred()) {
        Py_DECREF(v);
        return NULL;
    }
1717

1718
    return v;
1719 1720
}

Barry Warsaw's avatar
Barry Warsaw committed
1721
static PyObject *
1722
posix_do_stat(PyObject *self, PyObject *args,
1723
              char *format,
1724
#ifdef __VMS
1725
              int (*statfunc)(const char *, STRUCT_STAT *, ...),
1726
#else
1727
              int (*statfunc)(const char *, STRUCT_STAT *),
1728
#endif
1729 1730
              char *wformat,
              int (*wstatfunc)(const Py_UNICODE *, STRUCT_STAT *))
Guido van Rossum's avatar
Guido van Rossum committed
1731
{
1732 1733 1734 1735 1736
    STRUCT_STAT st;
    PyObject *opath;
    char *path;
    int res;
    PyObject *result;
1737

1738
#ifdef MS_WINDOWS
1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766
    PyUnicodeObject *po;
    if (PyArg_ParseTuple(args, wformat, &po)) {
        Py_UNICODE *wpath = PyUnicode_AS_UNICODE(po);

        Py_BEGIN_ALLOW_THREADS
            /* PyUnicode_AS_UNICODE result OK without
               thread lock as it is a simple dereference. */
        res = wstatfunc(wpath, &st);
        Py_END_ALLOW_THREADS

        if (res != 0)
            return win32_error_unicode("stat", wpath);
        return _pystat_fromstructstat(&st);
    }
    /* Drop the argument parsing error as narrow strings
       are also valid. */
    PyErr_Clear();
#endif

    if (!PyArg_ParseTuple(args, format,
                          PyUnicode_FSConverter, &opath))
        return NULL;
    path = PyBytes_AsString(opath);
    Py_BEGIN_ALLOW_THREADS
    res = (*statfunc)(path, &st);
    Py_END_ALLOW_THREADS

    if (res != 0) {
1767
#ifdef MS_WINDOWS
1768
        result = win32_error("stat", path);
1769
#else
1770
        result = posix_error_with_filename(path);
1771
#endif
1772 1773 1774
    }
    else
        result = _pystat_fromstructstat(&st);
1775

1776 1777
    Py_DECREF(opath);
    return result;
Guido van Rossum's avatar
Guido van Rossum committed
1778 1779 1780 1781
}

/* POSIX methods */

1782
PyDoc_STRVAR(posix_access__doc__,
1783
"access(path, mode) -> True if granted, False otherwise\n\n\
1784 1785 1786 1787 1788
Use the real uid/gid to test for access to a path.  Note that most\n\
operations will use the effective uid/gid, therefore this routine can\n\
be used in a suid/sgid environment to test if the invoking user has the\n\
specified access to the path.  The mode argument can be F_OK to test\n\
existence, or the inclusive-OR of R_OK, W_OK, and X_OK.");
1789 1790

static PyObject *
1791
posix_access(PyObject *self, PyObject *args)
1792
{
1793 1794 1795 1796
    PyObject *opath;
    char *path;
    int mode;

1797
#ifdef MS_WINDOWS
1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818
    DWORD attr;
    PyUnicodeObject *po;
    if (PyArg_ParseTuple(args, "Ui:access", &po, &mode)) {
        Py_BEGIN_ALLOW_THREADS
        /* PyUnicode_AS_UNICODE OK without thread lock as
           it is a simple dereference. */
        attr = GetFileAttributesW(PyUnicode_AS_UNICODE(po));
        Py_END_ALLOW_THREADS
        goto finish;
    }
    /* Drop the argument parsing error as narrow strings
       are also valid. */
    PyErr_Clear();
    if (!PyArg_ParseTuple(args, "O&i:access",
                          PyUnicode_FSConverter, &opath, &mode))
        return NULL;
    path = PyBytes_AsString(opath);
    Py_BEGIN_ALLOW_THREADS
    attr = GetFileAttributesA(path);
    Py_END_ALLOW_THREADS
    Py_DECREF(opath);
1819
finish:
1820 1821 1822 1823 1824 1825 1826 1827 1828
    if (attr == 0xFFFFFFFF)
        /* File does not exist, or cannot read attributes */
        return PyBool_FromLong(0);
    /* Access is possible if either write access wasn't requested, or
       the file isn't read-only, or if it's a directory, as there are
       no read-only directories on Windows. */
    return PyBool_FromLong(!(mode & 2)
                           || !(attr & FILE_ATTRIBUTE_READONLY)
                           || (attr & FILE_ATTRIBUTE_DIRECTORY));
1829
#else
1830 1831 1832 1833 1834 1835 1836 1837 1838 1839
    int res;
    if (!PyArg_ParseTuple(args, "O&i:access",
                          PyUnicode_FSConverter, &opath, &mode))
        return NULL;
    path = PyBytes_AsString(opath);
    Py_BEGIN_ALLOW_THREADS
    res = access(path, mode);
    Py_END_ALLOW_THREADS
    Py_DECREF(opath);
    return PyBool_FromLong(res == 0);
1840
#endif
1841 1842
}

1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856
#ifndef F_OK
#define F_OK 0
#endif
#ifndef R_OK
#define R_OK 4
#endif
#ifndef W_OK
#define W_OK 2
#endif
#ifndef X_OK
#define X_OK 1
#endif

#ifdef HAVE_TTYNAME
1857
PyDoc_STRVAR(posix_ttyname__doc__,
Fred Drake's avatar
Fred Drake committed
1858
"ttyname(fd) -> string\n\n\
1859
Return the name of the terminal device connected to 'fd'.");
1860 1861

static PyObject *
1862
posix_ttyname(PyObject *self, PyObject *args)
1863
{
1864 1865
    int id;
    char *ret;
1866

1867 1868
    if (!PyArg_ParseTuple(args, "i:ttyname", &id))
        return NULL;
1869

1870
#if defined(__VMS)
1871 1872 1873 1874 1875 1876 1877
    /* file descriptor 0 only, the default input device (stdin) */
    if (id == 0) {
        ret = ttyname();
    }
    else {
        ret = NULL;
    }
1878
#else
1879
    ret = ttyname(id);
1880
#endif
1881 1882
    if (ret == NULL)
        return posix_error();
1883
    return PyUnicode_DecodeFSDefault(ret);
1884
}
1885
#endif
1886

1887
#ifdef HAVE_CTERMID
1888
PyDoc_STRVAR(posix_ctermid__doc__,
Fred Drake's avatar
Fred Drake committed
1889
"ctermid() -> string\n\n\
1890
Return the name of the controlling terminal for this process.");
1891 1892

static PyObject *
1893
posix_ctermid(PyObject *self, PyObject *noargs)
1894
{
1895 1896
    char *ret;
    char buffer[L_ctermid];
1897

1898
#ifdef USE_CTERMID_R
1899
    ret = ctermid_r(buffer);
1900
#else
1901
    ret = ctermid(buffer);
1902
#endif
1903 1904
    if (ret == NULL)
        return posix_error();
1905
    return PyUnicode_DecodeFSDefault(buffer);
1906 1907 1908
}
#endif

1909
PyDoc_STRVAR(posix_chdir__doc__,
Fred Drake's avatar
Fred Drake committed
1910
"chdir(path)\n\n\
1911
Change the current working directory to the specified path.");
1912

Barry Warsaw's avatar
Barry Warsaw committed
1913
static PyObject *
1914
posix_chdir(PyObject *self, PyObject *args)
Guido van Rossum's avatar
Guido van Rossum committed
1915
{
1916
#ifdef MS_WINDOWS
1917
    return win32_1str(args, "chdir", "y:chdir", win32_chdir, "U:chdir", win32_wchdir);
1918
#elif defined(PYOS_OS2) && defined(PYCC_GCC)
1919
    return posix_1str(args, "O&:chdir", _chdir2);
1920
#elif defined(__VMS)
1921
    return posix_1str(args, "O&:chdir", (int (*)(const char *))chdir);
1922
#else
1923
    return posix_1str(args, "O&:chdir", chdir);
1924
#endif
Guido van Rossum's avatar
Guido van Rossum committed
1925 1926
}

1927
#ifdef HAVE_FCHDIR
1928
PyDoc_STRVAR(posix_fchdir__doc__,
Fred Drake's avatar
Fred Drake committed
1929
"fchdir(fildes)\n\n\
1930
Change to the directory of the given file descriptor.  fildes must be\n\
1931
opened on a directory, not a file.");
1932 1933 1934 1935

static PyObject *
posix_fchdir(PyObject *self, PyObject *fdobj)
{
1936
    return posix_fildes(fdobj, fchdir);
1937 1938 1939
}
#endif /* HAVE_FCHDIR */

1940

1941
PyDoc_STRVAR(posix_chmod__doc__,
Fred Drake's avatar
Fred Drake committed
1942
"chmod(path, mode)\n\n\
1943
Change the access permissions of a file.");
1944

Barry Warsaw's avatar
Barry Warsaw committed
1945
static PyObject *
1946
posix_chmod(PyObject *self, PyObject *args)
Guido van Rossum's avatar
Guido van Rossum committed
1947
{
1948 1949 1950 1951
    PyObject *opath = NULL;
    char *path = NULL;
    int i;
    int res;
1952
#ifdef MS_WINDOWS
1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001
    DWORD attr;
    PyUnicodeObject *po;
    if (PyArg_ParseTuple(args, "Ui|:chmod", &po, &i)) {
        Py_BEGIN_ALLOW_THREADS
        attr = GetFileAttributesW(PyUnicode_AS_UNICODE(po));
        if (attr != 0xFFFFFFFF) {
            if (i & _S_IWRITE)
                attr &= ~FILE_ATTRIBUTE_READONLY;
            else
                attr |= FILE_ATTRIBUTE_READONLY;
            res = SetFileAttributesW(PyUnicode_AS_UNICODE(po), attr);
        }
        else
            res = 0;
        Py_END_ALLOW_THREADS
        if (!res)
            return win32_error_unicode("chmod",
                                       PyUnicode_AS_UNICODE(po));
        Py_INCREF(Py_None);
        return Py_None;
    }
    /* Drop the argument parsing error as narrow strings
       are also valid. */
    PyErr_Clear();

    if (!PyArg_ParseTuple(args, "O&i:chmod", PyUnicode_FSConverter,
                          &opath, &i))
        return NULL;
    path = PyBytes_AsString(opath);
    Py_BEGIN_ALLOW_THREADS
    attr = GetFileAttributesA(path);
    if (attr != 0xFFFFFFFF) {
        if (i & _S_IWRITE)
            attr &= ~FILE_ATTRIBUTE_READONLY;
        else
            attr |= FILE_ATTRIBUTE_READONLY;
        res = SetFileAttributesA(path, attr);
    }
    else
        res = 0;
    Py_END_ALLOW_THREADS
    if (!res) {
        win32_error("chmod", path);
        Py_DECREF(opath);
        return NULL;
    }
    Py_DECREF(opath);
    Py_INCREF(Py_None);
    return Py_None;
2002
#else /* MS_WINDOWS */
2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014
    if (!PyArg_ParseTuple(args, "O&i:chmod", PyUnicode_FSConverter,
                          &opath, &i))
        return NULL;
    path = PyBytes_AsString(opath);
    Py_BEGIN_ALLOW_THREADS
    res = chmod(path, i);
    Py_END_ALLOW_THREADS
    if (res < 0)
        return posix_error_with_allocated_filename(opath);
    Py_DECREF(opath);
    Py_INCREF(Py_None);
    return Py_None;
2015
#endif
Guido van Rossum's avatar
Guido van Rossum committed
2016 2017
}

2018 2019 2020 2021 2022 2023 2024 2025 2026
#ifdef HAVE_FCHMOD
PyDoc_STRVAR(posix_fchmod__doc__,
"fchmod(fd, mode)\n\n\
Change the access permissions of the file given by file\n\
descriptor fd.");

static PyObject *
posix_fchmod(PyObject *self, PyObject *args)
{
2027 2028 2029 2030 2031 2032 2033 2034 2035
    int fd, mode, res;
    if (!PyArg_ParseTuple(args, "ii:fchmod", &fd, &mode))
        return NULL;
    Py_BEGIN_ALLOW_THREADS
    res = fchmod(fd, mode);
    Py_END_ALLOW_THREADS
    if (res < 0)
        return posix_error();
    Py_RETURN_NONE;
2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047
}
#endif /* HAVE_FCHMOD */

#ifdef HAVE_LCHMOD
PyDoc_STRVAR(posix_lchmod__doc__,
"lchmod(path, mode)\n\n\
Change the access permissions of a file. If path is a symlink, this\n\
affects the link itself rather than the target.");

static PyObject *
posix_lchmod(PyObject *self, PyObject *args)
{
2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062
    PyObject *opath;
    char *path;
    int i;
    int res;
    if (!PyArg_ParseTuple(args, "O&i:lchmod", PyUnicode_FSConverter,
                          &opath, &i))
        return NULL;
    path = PyBytes_AsString(opath);
    Py_BEGIN_ALLOW_THREADS
    res = lchmod(path, i);
    Py_END_ALLOW_THREADS
    if (res < 0)
        return posix_error_with_allocated_filename(opath);
    Py_DECREF(opath);
    Py_RETURN_NONE;
2063 2064 2065
}
#endif /* HAVE_LCHMOD */

2066

2067 2068 2069 2070 2071 2072 2073 2074
#ifdef HAVE_CHFLAGS
PyDoc_STRVAR(posix_chflags__doc__,
"chflags(path, flags)\n\n\
Set file flags.");

static PyObject *
posix_chflags(PyObject *self, PyObject *args)
{
2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090
    PyObject *opath;
    char *path;
    unsigned long flags;
    int res;
    if (!PyArg_ParseTuple(args, "O&k:chflags",
                          PyUnicode_FSConverter, &opath, &flags))
        return NULL;
    path = PyBytes_AsString(opath);
    Py_BEGIN_ALLOW_THREADS
    res = chflags(path, flags);
    Py_END_ALLOW_THREADS
    if (res < 0)
        return posix_error_with_allocated_filename(opath);
    Py_DECREF(opath);
    Py_INCREF(Py_None);
    return Py_None;
2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102
}
#endif /* HAVE_CHFLAGS */

#ifdef HAVE_LCHFLAGS
PyDoc_STRVAR(posix_lchflags__doc__,
"lchflags(path, flags)\n\n\
Set file flags.\n\
This function will not follow symbolic links.");

static PyObject *
posix_lchflags(PyObject *self, PyObject *args)
{
2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118
    PyObject *opath;
    char *path;
    unsigned long flags;
    int res;
    if (!PyArg_ParseTuple(args, "O&k:lchflags",
                          PyUnicode_FSConverter, &opath, &flags))
        return NULL;
    path = PyBytes_AsString(opath);
    Py_BEGIN_ALLOW_THREADS
    res = lchflags(path, flags);
    Py_END_ALLOW_THREADS
    if (res < 0)
        return posix_error_with_allocated_filename(opath);
    Py_DECREF(opath);
    Py_INCREF(Py_None);
    return Py_None;
2119 2120 2121
}
#endif /* HAVE_LCHFLAGS */

2122
#ifdef HAVE_CHROOT
2123
PyDoc_STRVAR(posix_chroot__doc__,
Fred Drake's avatar
Fred Drake committed
2124
"chroot(path)\n\n\
2125
Change root directory to path.");
2126 2127 2128 2129

static PyObject *
posix_chroot(PyObject *self, PyObject *args)
{
2130
    return posix_1str(args, "O&:chroot", chroot);
2131 2132 2133
}
#endif

2134
#ifdef HAVE_FSYNC
2135
PyDoc_STRVAR(posix_fsync__doc__,
Fred Drake's avatar
Fred Drake committed
2136
"fsync(fildes)\n\n\
2137
force write of file with filedescriptor to disk.");
2138 2139

static PyObject *
2140
posix_fsync(PyObject *self, PyObject *fdobj)
2141
{
Stefan Krah's avatar
Stefan Krah committed
2142
    return posix_fildes(fdobj, fsync);
2143 2144 2145 2146
}
#endif /* HAVE_FSYNC */

#ifdef HAVE_FDATASYNC
2147

2148
#ifdef __hpux
2149 2150 2151
extern int fdatasync(int); /* On HP-UX, in libc but not in unistd.h */
#endif

2152
PyDoc_STRVAR(posix_fdatasync__doc__,
Fred Drake's avatar
Fred Drake committed
2153
"fdatasync(fildes)\n\n\
2154
force write of file with filedescriptor to disk.\n\
2155
 does not force update of metadata.");
2156 2157

static PyObject *
2158
posix_fdatasync(PyObject *self, PyObject *fdobj)
2159
{
Stefan Krah's avatar
Stefan Krah committed
2160
    return posix_fildes(fdobj, fdatasync);
2161 2162 2163 2164
}
#endif /* HAVE_FDATASYNC */


Fredrik Lundh's avatar
Fredrik Lundh committed
2165
#ifdef HAVE_CHOWN
2166
PyDoc_STRVAR(posix_chown__doc__,
Fred Drake's avatar
Fred Drake committed
2167
"chown(path, uid, gid)\n\n\
2168
Change the owner and group id of path to the numeric uid and gid.");
2169

Barry Warsaw's avatar
Barry Warsaw committed
2170
static PyObject *
2171
posix_chown(PyObject *self, PyObject *args)
2172
{
2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189
    PyObject *opath;
    char *path;
    long uid, gid;
    int res;
    if (!PyArg_ParseTuple(args, "O&ll:chown",
                          PyUnicode_FSConverter, &opath,
                          &uid, &gid))
        return NULL;
    path = PyBytes_AsString(opath);
    Py_BEGIN_ALLOW_THREADS
    res = chown(path, (uid_t) uid, (gid_t) gid);
    Py_END_ALLOW_THREADS
    if (res < 0)
        return posix_error_with_allocated_filename(opath);
    Py_DECREF(opath);
    Py_INCREF(Py_None);
    return Py_None;
2190
}
2191
#endif /* HAVE_CHOWN */
2192

2193 2194 2195 2196 2197 2198 2199 2200 2201
#ifdef HAVE_FCHOWN
PyDoc_STRVAR(posix_fchown__doc__,
"fchown(fd, uid, gid)\n\n\
Change the owner and group id of the file given by file descriptor\n\
fd to the numeric uid and gid.");

static PyObject *
posix_fchown(PyObject *self, PyObject *args)
{
2202 2203 2204
    int fd;
    long uid, gid;
    int res;
2205
    if (!PyArg_ParseTuple(args, "ill:fchown", &fd, &uid, &gid))
2206 2207 2208 2209 2210 2211 2212
        return NULL;
    Py_BEGIN_ALLOW_THREADS
    res = fchown(fd, (uid_t) uid, (gid_t) gid);
    Py_END_ALLOW_THREADS
    if (res < 0)
        return posix_error();
    Py_RETURN_NONE;
2213 2214 2215
}
#endif /* HAVE_FCHOWN */

2216 2217 2218 2219 2220 2221 2222 2223 2224
#ifdef HAVE_LCHOWN
PyDoc_STRVAR(posix_lchown__doc__,
"lchown(path, uid, gid)\n\n\
Change the owner and group id of path to the numeric uid and gid.\n\
This function will not follow symbolic links.");

static PyObject *
posix_lchown(PyObject *self, PyObject *args)
{
2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241
    PyObject *opath;
    char *path;
    long uid, gid;
    int res;
    if (!PyArg_ParseTuple(args, "O&ll:lchown",
                          PyUnicode_FSConverter, &opath,
                          &uid, &gid))
        return NULL;
    path = PyBytes_AsString(opath);
    Py_BEGIN_ALLOW_THREADS
    res = lchown(path, (uid_t) uid, (gid_t) gid);
    Py_END_ALLOW_THREADS
    if (res < 0)
        return posix_error_with_allocated_filename(opath);
    Py_DECREF(opath);
    Py_INCREF(Py_None);
    return Py_None;
2242 2243 2244
}
#endif /* HAVE_LCHOWN */

2245

2246
#ifdef HAVE_GETCWD
Barry Warsaw's avatar
Barry Warsaw committed
2247
static PyObject *
2248
posix_getcwd(int use_bytes)
2249
{
2250 2251
    char buf[1026];
    char *res;
2252

2253
#ifdef MS_WINDOWS
2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284
    if (!use_bytes) {
        wchar_t wbuf[1026];
        wchar_t *wbuf2 = wbuf;
        PyObject *resobj;
        DWORD len;
        Py_BEGIN_ALLOW_THREADS
        len = GetCurrentDirectoryW(sizeof wbuf/ sizeof wbuf[0], wbuf);
        /* If the buffer is large enough, len does not include the
           terminating \0. If the buffer is too small, len includes
           the space needed for the terminator. */
        if (len >= sizeof wbuf/ sizeof wbuf[0]) {
            wbuf2 = malloc(len * sizeof(wchar_t));
            if (wbuf2)
                len = GetCurrentDirectoryW(len, wbuf2);
        }
        Py_END_ALLOW_THREADS
        if (!wbuf2) {
            PyErr_NoMemory();
            return NULL;
        }
        if (!len) {
            if (wbuf2 != wbuf) free(wbuf2);
            return win32_error("getcwdu", NULL);
        }
        resobj = PyUnicode_FromWideChar(wbuf2, len);
        if (wbuf2 != wbuf) free(wbuf2);
        return resobj;
    }
#endif

    Py_BEGIN_ALLOW_THREADS
2285
#if defined(PYOS_OS2) && defined(PYCC_GCC)
2286
    res = _getcwd2(buf, sizeof buf);
2287
#else
2288
    res = getcwd(buf, sizeof buf);
2289
#endif
2290 2291 2292 2293 2294
    Py_END_ALLOW_THREADS
    if (res == NULL)
        return posix_error();
    if (use_bytes)
        return PyBytes_FromStringAndSize(buf, strlen(buf));
2295
    return PyUnicode_DecodeFSDefault(buf);
2296
}
2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316

PyDoc_STRVAR(posix_getcwd__doc__,
"getcwd() -> path\n\n\
Return a unicode string representing the current working directory.");

static PyObject *
posix_getcwd_unicode(PyObject *self)
{
    return posix_getcwd(0);
}

PyDoc_STRVAR(posix_getcwdb__doc__,
"getcwdb() -> path\n\n\
Return a bytes string representing the current working directory.");

static PyObject *
posix_getcwd_bytes(PyObject *self)
{
    return posix_getcwd(1);
}
2317
#endif
Guido van Rossum's avatar
Guido van Rossum committed
2318

2319

2320
#ifdef HAVE_LINK
2321
PyDoc_STRVAR(posix_link__doc__,
Fred Drake's avatar
Fred Drake committed
2322
"link(src, dst)\n\n\
2323
Create a hard link to a file.");
2324

Barry Warsaw's avatar
Barry Warsaw committed
2325
static PyObject *
2326
posix_link(PyObject *self, PyObject *args)
Guido van Rossum's avatar
Guido van Rossum committed
2327
{
2328
    return posix_2str(args, "O&O&:link", link);
Guido van Rossum's avatar
Guido van Rossum committed
2329
}
2330
#endif /* HAVE_LINK */
2331

2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343
#ifdef MS_WINDOWS
PyDoc_STRVAR(win32_link__doc__,
"link(src, dst)\n\n\
Create a hard link to a file.");

static PyObject *
win32_link(PyObject *self, PyObject *args)
{
    PyObject *osrc, *odst;
    char *src, *dst;
    BOOL rslt;

Brian Curtin's avatar
Brian Curtin committed
2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359
    PyUnicodeObject *usrc, *udst;
    if (PyArg_ParseTuple(args, "UU:link", &usrc, &udst)) {
        Py_BEGIN_ALLOW_THREADS
        rslt = CreateHardLinkW(PyUnicode_AS_UNICODE(udst),
                               PyUnicode_AS_UNICODE(usrc), NULL);
        Py_END_ALLOW_THREADS

        if (rslt == 0)
            return win32_error("link", NULL);

        Py_RETURN_NONE;
    }

    /* Narrow strings also valid. */
    PyErr_Clear();

2360 2361 2362 2363 2364 2365 2366 2367
    if (!PyArg_ParseTuple(args, "O&O&:link", PyUnicode_FSConverter, &osrc,
                          PyUnicode_FSConverter, &odst))
        return NULL;

    src = PyBytes_AsString(osrc);
    dst = PyBytes_AsString(odst);

    Py_BEGIN_ALLOW_THREADS
Brian Curtin's avatar
Brian Curtin committed
2368
    rslt = CreateHardLinkA(dst, src, NULL);
2369 2370
    Py_END_ALLOW_THREADS

Stefan Krah's avatar
Stefan Krah committed
2371 2372
    Py_DECREF(osrc);
    Py_DECREF(odst);
2373
    if (rslt == 0)
Brian Curtin's avatar
Brian Curtin committed
2374
        return win32_error("link", NULL);
2375 2376 2377 2378 2379

    Py_RETURN_NONE;
}
#endif /* MS_WINDOWS */

2380

2381
PyDoc_STRVAR(posix_listdir__doc__,
2382
"listdir([path]) -> list_of_strings\n\n\
2383 2384
Return a list containing the names of the entries in the directory.\n\
\n\
2385
    path: path of directory to list (default: '.')\n\
2386 2387
\n\
The list is in arbitrary order.  It does not include the special\n\
2388
entries '.' and '..' even if they are present in the directory.");
2389

Barry Warsaw's avatar
Barry Warsaw committed
2390
static PyObject *
2391
posix_listdir(PyObject *self, PyObject *args)
2392
{
2393 2394
    /* XXX Should redo this putting the (now four) versions of opendir
       in separate files instead of having them all here... */
2395
#if defined(MS_WINDOWS) && !defined(HAVE_OPENDIR)
2396

2397 2398 2399 2400 2401 2402 2403 2404 2405
    PyObject *d, *v;
    HANDLE hFindFile;
    BOOL result;
    WIN32_FIND_DATA FileData;
    PyObject *opath;
    char namebuf[MAX_PATH+5]; /* Overallocate for \\*.*\0 */
    char *bufptr = namebuf;
    Py_ssize_t len = sizeof(namebuf)-5; /* only claim to have space for MAX_PATH */

2406 2407
    PyObject *po = NULL;
    if (PyArg_ParseTuple(args, "|U:listdir", &po)) {
2408
        WIN32_FIND_DATAW wFileData;
2409
        Py_UNICODE *wnamebuf, *po_wchars;
2410

Antoine Pitrou's avatar
Antoine Pitrou committed
2411
        if (po == NULL) { /* Default arg: "." */
2412 2413 2414 2415 2416 2417
            po_wchars = L".";
            len = 1;
        } else {
            po_wchars = PyUnicode_AS_UNICODE(po);
            len = PyUnicode_GET_SIZE(po);
        }
2418 2419 2420 2421 2422 2423
        /* Overallocate for \\*.*\0 */
        wnamebuf = malloc((len + 5) * sizeof(wchar_t));
        if (!wnamebuf) {
            PyErr_NoMemory();
            return NULL;
        }
2424
        wcscpy(wnamebuf, po_wchars);
2425 2426 2427 2428 2429 2430 2431 2432 2433 2434
        if (len > 0) {
            Py_UNICODE wch = wnamebuf[len-1];
            if (wch != L'/' && wch != L'\\' && wch != L':')
                wnamebuf[len++] = L'\\';
            wcscpy(wnamebuf + len, L"*.*");
        }
        if ((d = PyList_New(0)) == NULL) {
            free(wnamebuf);
            return NULL;
        }
2435
        Py_BEGIN_ALLOW_THREADS
2436
        hFindFile = FindFirstFileW(wnamebuf, &wFileData);
2437
        Py_END_ALLOW_THREADS
2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503
        if (hFindFile == INVALID_HANDLE_VALUE) {
            int error = GetLastError();
            if (error == ERROR_FILE_NOT_FOUND) {
                free(wnamebuf);
                return d;
            }
            Py_DECREF(d);
            win32_error_unicode("FindFirstFileW", wnamebuf);
            free(wnamebuf);
            return NULL;
        }
        do {
            /* Skip over . and .. */
            if (wcscmp(wFileData.cFileName, L".") != 0 &&
                wcscmp(wFileData.cFileName, L"..") != 0) {
                v = PyUnicode_FromUnicode(wFileData.cFileName, wcslen(wFileData.cFileName));
                if (v == NULL) {
                    Py_DECREF(d);
                    d = NULL;
                    break;
                }
                if (PyList_Append(d, v) != 0) {
                    Py_DECREF(v);
                    Py_DECREF(d);
                    d = NULL;
                    break;
                }
                Py_DECREF(v);
            }
            Py_BEGIN_ALLOW_THREADS
            result = FindNextFileW(hFindFile, &wFileData);
            Py_END_ALLOW_THREADS
            /* FindNextFile sets error to ERROR_NO_MORE_FILES if
               it got to the end of the directory. */
            if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
                Py_DECREF(d);
                win32_error_unicode("FindNextFileW", wnamebuf);
                FindClose(hFindFile);
                free(wnamebuf);
                return NULL;
            }
        } while (result == TRUE);

        if (FindClose(hFindFile) == FALSE) {
            Py_DECREF(d);
            win32_error_unicode("FindClose", wnamebuf);
            free(wnamebuf);
            return NULL;
        }
        free(wnamebuf);
        return d;
    }
    /* Drop the argument parsing error as narrow strings
       are also valid. */
    PyErr_Clear();

    if (!PyArg_ParseTuple(args, "O&:listdir",
                          PyUnicode_FSConverter, &opath))
        return NULL;
    if (PyBytes_GET_SIZE(opath)+1 > MAX_PATH) {
        PyErr_SetString(PyExc_ValueError, "path too long");
        Py_DECREF(opath);
        return NULL;
    }
    strcpy(namebuf, PyBytes_AsString(opath));
    len = PyObject_Size(opath);
2504
    Py_DECREF(opath);
2505 2506 2507 2508 2509 2510 2511 2512 2513 2514
    if (len > 0) {
        char ch = namebuf[len-1];
        if (ch != SEP && ch != ALTSEP && ch != ':')
            namebuf[len++] = '/';
        strcpy(namebuf + len, "*.*");
    }

    if ((d = PyList_New(0)) == NULL)
        return NULL;

2515
    Py_BEGIN_ALLOW_THREADS
2516
    hFindFile = FindFirstFile(namebuf, &FileData);
2517
    Py_END_ALLOW_THREADS
2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561
    if (hFindFile == INVALID_HANDLE_VALUE) {
        int error = GetLastError();
        if (error == ERROR_FILE_NOT_FOUND)
            return d;
        Py_DECREF(d);
        return win32_error("FindFirstFile", namebuf);
    }
    do {
        /* Skip over . and .. */
        if (strcmp(FileData.cFileName, ".") != 0 &&
            strcmp(FileData.cFileName, "..") != 0) {
            v = PyBytes_FromString(FileData.cFileName);
            if (v == NULL) {
                Py_DECREF(d);
                d = NULL;
                break;
            }
            if (PyList_Append(d, v) != 0) {
                Py_DECREF(v);
                Py_DECREF(d);
                d = NULL;
                break;
            }
            Py_DECREF(v);
        }
        Py_BEGIN_ALLOW_THREADS
        result = FindNextFile(hFindFile, &FileData);
        Py_END_ALLOW_THREADS
        /* FindNextFile sets error to ERROR_NO_MORE_FILES if
           it got to the end of the directory. */
        if (!result && GetLastError() != ERROR_NO_MORE_FILES) {
            Py_DECREF(d);
            win32_error("FindNextFile", namebuf);
            FindClose(hFindFile);
            return NULL;
        }
    } while (result == TRUE);

    if (FindClose(hFindFile) == FALSE) {
        Py_DECREF(d);
        return win32_error("FindClose", namebuf);
    }

    return d;
2562

2563
#elif defined(PYOS_OS2)
Guido van Rossum's avatar
Guido van Rossum committed
2564 2565 2566 2567

#ifndef MAX_PATH
#define MAX_PATH    CCHMAXPATH
#endif
2568
    PyObject *oname;
Guido van Rossum's avatar
Guido van Rossum committed
2569
    char *name, *pt;
Thomas Wouters's avatar
Thomas Wouters committed
2570
    Py_ssize_t len;
Guido van Rossum's avatar
Guido van Rossum committed
2571 2572 2573 2574 2575 2576 2577
    PyObject *d, *v;
    char namebuf[MAX_PATH+5];
    HDIR  hdir = 1;
    ULONG srchcnt = 1;
    FILEFINDBUF3   ep;
    APIRET rc;

2578
    if (!PyArg_ParseTuple(args, "O&:listdir",
2579
                          PyUnicode_FSConverter, &oname))
Guido van Rossum's avatar
Guido van Rossum committed
2580
        return NULL;
2581 2582
    name = PyBytes_AsString(oname);
    len = PyBytes_GET_SIZE(oname);
Guido van Rossum's avatar
Guido van Rossum committed
2583
    if (len >= MAX_PATH) {
2584
        Py_DECREF(oname);
2585
        PyErr_SetString(PyExc_ValueError, "path too long");
Guido van Rossum's avatar
Guido van Rossum committed
2586 2587 2588 2589
        return NULL;
    }
    strcpy(namebuf, name);
    for (pt = namebuf; *pt; pt++)
2590 2591 2592 2593
        if (*pt == ALTSEP)
            *pt = SEP;
    if (namebuf[len-1] != SEP)
        namebuf[len++] = SEP;
Guido van Rossum's avatar
Guido van Rossum committed
2594 2595
    strcpy(namebuf + len, "*.*");

2596
    if ((d = PyList_New(0)) == NULL) {
2597
        Py_DECREF(oname);
Guido van Rossum's avatar
Guido van Rossum committed
2598
        return NULL;
2599
    }
Guido van Rossum's avatar
Guido van Rossum committed
2600

2601 2602
    rc = DosFindFirst(namebuf,         /* Wildcard Pattern to Match */
                      &hdir,           /* Handle to Use While Search Directory */
Guido van Rossum's avatar
Guido van Rossum committed
2603
                      FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY,
2604 2605 2606
                      &ep, sizeof(ep), /* Structure to Receive Directory Entry */
                      &srchcnt,        /* Max and Actual Count of Entries Per Iteration */
                      FIL_STANDARD);   /* Format of Entry (EAs or Not) */
Guido van Rossum's avatar
Guido van Rossum committed
2607 2608 2609

    if (rc != NO_ERROR) {
        errno = ENOENT;
2610
        return posix_error_with_allocated_filename(oname);
Guido van Rossum's avatar
Guido van Rossum committed
2611 2612
    }

2613
    if (srchcnt > 0) { /* If Directory is NOT Totally Empty, */
Guido van Rossum's avatar
Guido van Rossum committed
2614 2615
        do {
            if (ep.achName[0] == '.'
2616
            && (ep.achName[1] == '\0' || (ep.achName[1] == '.' && ep.achName[2] == '\0')))
2617
                continue; /* Skip Over "." and ".." Names */
Guido van Rossum's avatar
Guido van Rossum committed
2618 2619 2620

            strcpy(namebuf, ep.achName);

2621 2622
            /* Leave Case of Name Alone -- In Native Form */
            /* (Removed Forced Lowercasing Code) */
Guido van Rossum's avatar
Guido van Rossum committed
2623

2624
            v = PyBytes_FromString(namebuf);
Guido van Rossum's avatar
Guido van Rossum committed
2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639
            if (v == NULL) {
                Py_DECREF(d);
                d = NULL;
                break;
            }
            if (PyList_Append(d, v) != 0) {
                Py_DECREF(v);
                Py_DECREF(d);
                d = NULL;
                break;
            }
            Py_DECREF(v);
        } while (DosFindNext(hdir, &ep, sizeof(ep), &srchcnt) == NO_ERROR && srchcnt > 0);
    }

2640
    Py_DECREF(oname);
Guido van Rossum's avatar
Guido van Rossum committed
2641
    return d;
2642
#else
2643 2644 2645 2646 2647 2648 2649 2650
    PyObject *oname;
    char *name;
    PyObject *d, *v;
    DIR *dirp;
    struct dirent *ep;
    int arg_is_unicode = 1;

    errno = 0;
2651 2652
    /* v is never read, so it does not need to be initialized yet. */
    if (!PyArg_ParseTuple(args, "|U:listdir", &v)) {
2653 2654 2655
        arg_is_unicode = 0;
        PyErr_Clear();
    }
2656 2657
    oname = NULL;
    if (!PyArg_ParseTuple(args, "|O&:listdir", PyUnicode_FSConverter, &oname))
2658
        return NULL;
Antoine Pitrou's avatar
Antoine Pitrou committed
2659
    if (oname == NULL) { /* Default arg: "." */
Stefan Krah's avatar
Stefan Krah committed
2660
        oname = PyBytes_FromString(".");
2661
    }
2662
    name = PyBytes_AsString(oname);
2663 2664 2665 2666
    Py_BEGIN_ALLOW_THREADS
    dirp = opendir(name);
    Py_END_ALLOW_THREADS
    if (dirp == NULL) {
2667 2668 2669
        return posix_error_with_allocated_filename(oname);
    }
    if ((d = PyList_New(0)) == NULL) {
2670
        Py_BEGIN_ALLOW_THREADS
2671
        closedir(dirp);
2672
        Py_END_ALLOW_THREADS
2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684
        Py_DECREF(oname);
        return NULL;
    }
    for (;;) {
        errno = 0;
        Py_BEGIN_ALLOW_THREADS
        ep = readdir(dirp);
        Py_END_ALLOW_THREADS
        if (ep == NULL) {
            if (errno == 0) {
                break;
            } else {
2685
                Py_BEGIN_ALLOW_THREADS
2686
                closedir(dirp);
2687
                Py_END_ALLOW_THREADS
2688 2689 2690 2691 2692 2693 2694 2695
                Py_DECREF(d);
                return posix_error_with_allocated_filename(oname);
            }
        }
        if (ep->d_name[0] == '.' &&
            (NAMLEN(ep) == 1 ||
             (ep->d_name[1] == '.' && NAMLEN(ep) == 2)))
            continue;
2696 2697 2698 2699
        if (arg_is_unicode)
            v = PyUnicode_DecodeFSDefaultAndSize(ep->d_name, NAMLEN(ep));
        else
            v = PyBytes_FromStringAndSize(ep->d_name, NAMLEN(ep));
2700
        if (v == NULL) {
2701
            Py_CLEAR(d);
2702 2703 2704 2705
            break;
        }
        if (PyList_Append(d, v) != 0) {
            Py_DECREF(v);
2706
            Py_CLEAR(d);
2707 2708 2709 2710
            break;
        }
        Py_DECREF(v);
    }
2711
    Py_BEGIN_ALLOW_THREADS
2712
    closedir(dirp);
2713
    Py_END_ALLOW_THREADS
2714 2715 2716
    Py_DECREF(oname);

    return d;
2717

2718 2719
#endif /* which OS */
}  /* end of posix_listdir */
Guido van Rossum's avatar
Guido van Rossum committed
2720

2721
#ifdef MS_WINDOWS
2722 2723 2724 2725
/* A helper function for abspath on win32 */
static PyObject *
posix__getfullpathname(PyObject *self, PyObject *args)
{
2726 2727 2728 2729
    PyObject *opath;
    char *path;
    char outbuf[MAX_PATH*2];
    char *temp;
2730
#ifdef MS_WINDOWS
2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775
    PyUnicodeObject *po;
    if (PyArg_ParseTuple(args, "U|:_getfullpathname", &po)) {
        Py_UNICODE *wpath = PyUnicode_AS_UNICODE(po);
        Py_UNICODE woutbuf[MAX_PATH*2], *woutbufp = woutbuf;
        Py_UNICODE *wtemp;
        DWORD result;
        PyObject *v;
        result = GetFullPathNameW(wpath,
                                  sizeof(woutbuf)/sizeof(woutbuf[0]),
                                  woutbuf, &wtemp);
        if (result > sizeof(woutbuf)/sizeof(woutbuf[0])) {
            woutbufp = malloc(result * sizeof(Py_UNICODE));
            if (!woutbufp)
                return PyErr_NoMemory();
            result = GetFullPathNameW(wpath, result, woutbufp, &wtemp);
        }
        if (result)
            v = PyUnicode_FromUnicode(woutbufp, wcslen(woutbufp));
        else
            v = win32_error_unicode("GetFullPathNameW", wpath);
        if (woutbufp != woutbuf)
            free(woutbufp);
        return v;
    }
    /* Drop the argument parsing error as narrow strings
       are also valid. */
    PyErr_Clear();

#endif
    if (!PyArg_ParseTuple (args, "O&:_getfullpathname",
                           PyUnicode_FSConverter, &opath))
        return NULL;
    path = PyBytes_AsString(opath);
    if (!GetFullPathName(path, sizeof(outbuf)/sizeof(outbuf[0]),
                         outbuf, &temp)) {
        win32_error("GetFullPathName", path);
        Py_DECREF(opath);
        return NULL;
    }
    Py_DECREF(opath);
    if (PyUnicode_Check(PyTuple_GetItem(args, 0))) {
        return PyUnicode_Decode(outbuf, strlen(outbuf),
                                Py_FileSystemDefaultEncoding, NULL);
    }
    return PyBytes_FromString(outbuf);
2776
} /* end of posix__getfullpathname */
2777

2778

2779

2780 2781 2782 2783 2784 2785 2786 2787 2788 2789
/* A helper function for samepath on windows */
static PyObject *
posix__getfinalpathname(PyObject *self, PyObject *args)
{
    HANDLE hFile;
    int buf_size;
    wchar_t *target_path;
    int result_length;
    PyObject *result;
    wchar_t *path;
2790

Brian Curtin's avatar
Brian Curtin committed
2791
    if (!PyArg_ParseTuple(args, "u|:_getfinalpathname", &path)) {
2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810
        return NULL;
    }

    if(!check_GetFinalPathNameByHandle()) {
        /* If the OS doesn't have GetFinalPathNameByHandle, return a
           NotImplementedError. */
        return PyErr_Format(PyExc_NotImplementedError,
            "GetFinalPathNameByHandle not available on this platform");
    }

    hFile = CreateFileW(
        path,
        0, /* desired access */
        0, /* share mode */
        NULL, /* security attributes */
        OPEN_EXISTING,
        /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */
        FILE_FLAG_BACKUP_SEMANTICS,
        NULL);
2811

2812 2813
    if(hFile == INVALID_HANDLE_VALUE) {
        return win32_error_unicode("GetFinalPathNamyByHandle", path);
2814 2815
        return PyErr_Format(PyExc_RuntimeError,
                            "Could not get a handle to file.");
2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842
    }

    /* We have a good handle to the target, use it to determine the
       target path name. */
    buf_size = Py_GetFinalPathNameByHandleW(hFile, 0, 0, VOLUME_NAME_NT);

    if(!buf_size)
        return win32_error_unicode("GetFinalPathNameByHandle", path);

    target_path = (wchar_t *)malloc((buf_size+1)*sizeof(wchar_t));
    if(!target_path)
        return PyErr_NoMemory();

    result_length = Py_GetFinalPathNameByHandleW(hFile, target_path,
                                                 buf_size, VOLUME_NAME_DOS);
    if(!result_length)
        return win32_error_unicode("GetFinalPathNamyByHandle", path);

    if(!CloseHandle(hFile))
        return win32_error_unicode("GetFinalPathNameByHandle", path);

    target_path[result_length] = 0;
    result = PyUnicode_FromUnicode(target_path, result_length);
    free(target_path);
    return result;

} /* end of posix__getfinalpathname */
2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853

static PyObject *
posix__getfileinformation(PyObject *self, PyObject *args)
{
    HANDLE hFile;
    BY_HANDLE_FILE_INFORMATION info;
    int fd;

    if (!PyArg_ParseTuple(args, "i:_getfileinformation", &fd))
        return NULL;

2854 2855
    if (!_PyVerify_fd(fd))
        return posix_error();
2856 2857 2858

    hFile = (HANDLE)_get_osfhandle(fd);
    if (hFile == INVALID_HANDLE_VALUE)
2859
        return posix_error();
2860 2861 2862 2863 2864 2865 2866 2867

    if (!GetFileInformationByHandle(hFile, &info))
        return win32_error("_getfileinformation", NULL);

    return Py_BuildValue("iii", info.dwVolumeSerialNumber,
                                info.nFileIndexHigh,
                                info.nFileIndexLow);
}
2868

2869 2870 2871
PyDoc_STRVAR(posix__isdir__doc__,
"Return true if the pathname refers to an existing directory.");

2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906
static PyObject *
posix__isdir(PyObject *self, PyObject *args)
{
    PyObject *opath;
    char *path;
    PyUnicodeObject *po;
    DWORD attributes;

    if (PyArg_ParseTuple(args, "U|:_isdir", &po)) {
        Py_UNICODE *wpath = PyUnicode_AS_UNICODE(po);

        attributes = GetFileAttributesW(wpath);
        if (attributes == INVALID_FILE_ATTRIBUTES)
            Py_RETURN_FALSE;
        goto check;
    }
    /* Drop the argument parsing error as narrow strings
       are also valid. */
    PyErr_Clear();

    if (!PyArg_ParseTuple(args, "O&:_isdir",
                          PyUnicode_FSConverter, &opath))
        return NULL;

    path = PyBytes_AsString(opath);
    attributes = GetFileAttributesA(path);
    if (attributes == INVALID_FILE_ATTRIBUTES)
        Py_RETURN_FALSE;

check:
    if (attributes & FILE_ATTRIBUTE_DIRECTORY)
        Py_RETURN_TRUE;
    else
        Py_RETURN_FALSE;
}
2907
#endif /* MS_WINDOWS */
2908

2909
PyDoc_STRVAR(posix_mkdir__doc__,
Fred Drake's avatar
Fred Drake committed
2910
"mkdir(path [, mode=0777])\n\n\
2911
Create a directory.");
2912

Barry Warsaw's avatar
Barry Warsaw committed
2913
static PyObject *
2914
posix_mkdir(PyObject *self, PyObject *args)
Guido van Rossum's avatar
Guido van Rossum committed
2915
{
2916 2917 2918 2919
    int res;
    PyObject *opath;
    char *path;
    int mode = 0777;
2920

2921
#ifdef MS_WINDOWS
2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953
    PyUnicodeObject *po;
    if (PyArg_ParseTuple(args, "U|i:mkdir", &po, &mode)) {
        Py_BEGIN_ALLOW_THREADS
        /* PyUnicode_AS_UNICODE OK without thread lock as
           it is a simple dereference. */
        res = CreateDirectoryW(PyUnicode_AS_UNICODE(po), NULL);
        Py_END_ALLOW_THREADS
        if (!res)
            return win32_error_unicode("mkdir", PyUnicode_AS_UNICODE(po));
        Py_INCREF(Py_None);
        return Py_None;
    }
    /* Drop the argument parsing error as narrow strings
       are also valid. */
    PyErr_Clear();
    if (!PyArg_ParseTuple(args, "O&|i:mkdir",
                          PyUnicode_FSConverter, &opath, &mode))
        return NULL;
    path = PyBytes_AsString(opath);
    Py_BEGIN_ALLOW_THREADS
    /* PyUnicode_AS_UNICODE OK without thread lock as
       it is a simple dereference. */
    res = CreateDirectoryA(path, NULL);
    Py_END_ALLOW_THREADS
    if (!res) {
        win32_error("mkdir", path);
        Py_DECREF(opath);
        return NULL;
    }
    Py_DECREF(opath);
    Py_INCREF(Py_None);
    return Py_None;
2954
#else
2955

2956 2957 2958 2959 2960
    if (!PyArg_ParseTuple(args, "O&|i:mkdir",
                          PyUnicode_FSConverter, &opath, &mode))
        return NULL;
    path = PyBytes_AsString(opath);
    Py_BEGIN_ALLOW_THREADS
2961
#if ( defined(__WATCOMC__) || defined(PYCC_VACPP) ) && !defined(__QNX__)
2962
    res = mkdir(path);
2963
#else
2964
    res = mkdir(path, mode);
2965
#endif
2966 2967 2968 2969 2970 2971
    Py_END_ALLOW_THREADS
    if (res < 0)
        return posix_error_with_allocated_filename(opath);
    Py_DECREF(opath);
    Py_INCREF(Py_None);
    return Py_None;
2972
#endif
Guido van Rossum's avatar
Guido van Rossum committed
2973 2974
}

2975

2976 2977
/* sys/resource.h is needed for at least: wait3(), wait4(), broken nice. */
#if defined(HAVE_SYS_RESOURCE_H)
2978 2979 2980
#include <sys/resource.h>
#endif

2981 2982

#ifdef HAVE_NICE
2983
PyDoc_STRVAR(posix_nice__doc__,
Fred Drake's avatar
Fred Drake committed
2984 2985
"nice(inc) -> new_priority\n\n\
Decrease the priority of process by inc and return the new priority.");
2986

Barry Warsaw's avatar
Barry Warsaw committed
2987
static PyObject *
2988
posix_nice(PyObject *self, PyObject *args)
2989
{
2990
    int increment, value;
2991

2992 2993
    if (!PyArg_ParseTuple(args, "i:nice", &increment))
        return NULL;
2994

2995 2996 2997 2998
    /* There are two flavours of 'nice': one that returns the new
       priority (as required by almost all standards out there) and the
       Linux/FreeBSD/BSDI one, which returns '0' on success and advices
       the use of getpriority() to get the new priority.
2999

3000 3001 3002 3003
       If we are of the nice family that returns the new priority, we
       need to clear errno before the call, and check if errno is filled
       before calling posix_error() on a returnvalue of -1, because the
       -1 may be the actual new priority! */
3004

3005 3006
    errno = 0;
    value = nice(increment);
3007
#if defined(HAVE_BROKEN_NICE) && defined(HAVE_GETPRIORITY)
3008 3009
    if (value == 0)
        value = getpriority(PRIO_PROCESS, 0);
3010
#endif
3011 3012 3013 3014
    if (value == -1 && errno != 0)
        /* either nice() or getpriority() returned an error */
        return posix_error();
    return PyLong_FromLong((long) value);
3015
}
3016
#endif /* HAVE_NICE */
3017

3018
PyDoc_STRVAR(posix_rename__doc__,
Fred Drake's avatar
Fred Drake committed
3019
"rename(old, new)\n\n\
3020
Rename a file or directory.");
3021

Barry Warsaw's avatar
Barry Warsaw committed
3022
static PyObject *
3023
posix_rename(PyObject *self, PyObject *args)
Guido van Rossum's avatar
Guido van Rossum committed
3024
{
3025
#ifdef MS_WINDOWS
3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046
    PyObject *o1, *o2;
    char *p1, *p2;
    BOOL result;
    if (!PyArg_ParseTuple(args, "OO:rename", &o1, &o2))
        goto error;
    if (!convert_to_unicode(&o1))
        goto error;
    if (!convert_to_unicode(&o2)) {
        Py_DECREF(o1);
        goto error;
    }
    Py_BEGIN_ALLOW_THREADS
    result = MoveFileW(PyUnicode_AsUnicode(o1),
                       PyUnicode_AsUnicode(o2));
    Py_END_ALLOW_THREADS
    Py_DECREF(o1);
    Py_DECREF(o2);
    if (!result)
        return win32_error("rename", NULL);
    Py_INCREF(Py_None);
    return Py_None;
3047
error:
3048 3049 3050 3051 3052 3053 3054 3055 3056 3057
    PyErr_Clear();
    if (!PyArg_ParseTuple(args, "ss:rename", &p1, &p2))
        return NULL;
    Py_BEGIN_ALLOW_THREADS
    result = MoveFileA(p1, p2);
    Py_END_ALLOW_THREADS
    if (!result)
        return win32_error("rename", NULL);
    Py_INCREF(Py_None);
    return Py_None;
3058
#else
3059
    return posix_2str(args, "O&O&:rename", rename);
3060
#endif
Guido van Rossum's avatar
Guido van Rossum committed
3061 3062
}

3063

3064
PyDoc_STRVAR(posix_rmdir__doc__,
Fred Drake's avatar
Fred Drake committed
3065
"rmdir(path)\n\n\
3066
Remove a directory.");
3067

Barry Warsaw's avatar
Barry Warsaw committed
3068
static PyObject *
3069
posix_rmdir(PyObject *self, PyObject *args)
Guido van Rossum's avatar
Guido van Rossum committed
3070
{
3071
#ifdef MS_WINDOWS
3072
    return win32_1str(args, "rmdir", "y:rmdir", RemoveDirectoryA, "U:rmdir", RemoveDirectoryW);
3073
#else
3074
    return posix_1str(args, "O&:rmdir", rmdir);
3075
#endif
Guido van Rossum's avatar
Guido van Rossum committed
3076 3077
}

3078

3079
PyDoc_STRVAR(posix_stat__doc__,
Fred Drake's avatar
Fred Drake committed
3080
"stat(path) -> stat result\n\n\
3081
Perform a stat system call on the given path.");
3082

Barry Warsaw's avatar
Barry Warsaw committed
3083
static PyObject *
3084
posix_stat(PyObject *self, PyObject *args)
Guido van Rossum's avatar
Guido van Rossum committed
3085
{
3086
#ifdef MS_WINDOWS
3087
    return posix_do_stat(self, args, "O&:stat", STAT, "U:stat", win32_stat_w);
3088
#else
3089
    return posix_do_stat(self, args, "O&:stat", STAT, NULL, NULL);
3090
#endif
Guido van Rossum's avatar
Guido van Rossum committed
3091 3092
}

3093

3094
#ifdef HAVE_SYSTEM
3095
PyDoc_STRVAR(posix_system__doc__,
Fred Drake's avatar
Fred Drake committed
3096
"system(command) -> exit_status\n\n\
3097
Execute the command (a string) in a subshell.");
3098

Barry Warsaw's avatar
Barry Warsaw committed
3099
static PyObject *
3100
posix_system(PyObject *self, PyObject *args)
Guido van Rossum's avatar
Guido van Rossum committed
3101
{
3102
    long sts;
3103
#ifdef MS_WINDOWS
3104 3105 3106
    wchar_t *command;
    if (!PyArg_ParseTuple(args, "u:system", &command))
        return NULL;
3107

3108 3109 3110
    Py_BEGIN_ALLOW_THREADS
    sts = _wsystem(command);
    Py_END_ALLOW_THREADS
3111
#else
3112 3113 3114 3115 3116
    PyObject *command_obj;
    char *command;
    if (!PyArg_ParseTuple(args, "O&:system",
                          PyUnicode_FSConverter, &command_obj))
        return NULL;
3117

3118 3119 3120 3121 3122
    command = PyBytes_AsString(command_obj);
    Py_BEGIN_ALLOW_THREADS
    sts = system(command);
    Py_END_ALLOW_THREADS
    Py_DECREF(command_obj);
3123
#endif
3124
    return PyLong_FromLong(sts);
Guido van Rossum's avatar
Guido van Rossum committed
3125
}
3126
#endif
Guido van Rossum's avatar
Guido van Rossum committed
3127

3128

3129
PyDoc_STRVAR(posix_umask__doc__,
Fred Drake's avatar
Fred Drake committed
3130
"umask(new_mask) -> old_mask\n\n\
3131
Set the current numeric umask and return the previous umask.");
3132

Barry Warsaw's avatar
Barry Warsaw committed
3133
static PyObject *
3134
posix_umask(PyObject *self, PyObject *args)
Guido van Rossum's avatar
Guido van Rossum committed
3135
{
3136 3137 3138 3139 3140 3141 3142
    int i;
    if (!PyArg_ParseTuple(args, "i:umask", &i))
        return NULL;
    i = (int)umask(i);
    if (i < 0)
        return posix_error();
    return PyLong_FromLong((long)i);
Guido van Rossum's avatar
Guido van Rossum committed
3143 3144
}

3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159
#ifdef MS_WINDOWS

/* override the default DeleteFileW behavior so that directory
symlinks can be removed with this function, the same as with
Unix symlinks */
BOOL WINAPI Py_DeleteFileW(LPCWSTR lpFileName)
{
    WIN32_FILE_ATTRIBUTE_DATA info;
    WIN32_FIND_DATAW find_data;
    HANDLE find_data_handle;
    int is_directory = 0;
    int is_link = 0;

    if (GetFileAttributesExW(lpFileName, GetFileExInfoStandard, &info)) {
        is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
3160

3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179
        /* Get WIN32_FIND_DATA structure for the path to determine if
           it is a symlink */
        if(is_directory &&
           info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
            find_data_handle = FindFirstFileW(lpFileName, &find_data);

            if(find_data_handle != INVALID_HANDLE_VALUE) {
                is_link = find_data.dwReserved0 == IO_REPARSE_TAG_SYMLINK;
                FindClose(find_data_handle);
            }
        }
    }

    if (is_directory && is_link)
        return RemoveDirectoryW(lpFileName);

    return DeleteFileW(lpFileName);
}
#endif /* MS_WINDOWS */
3180

3181
PyDoc_STRVAR(posix_unlink__doc__,
Fred Drake's avatar
Fred Drake committed
3182
"unlink(path)\n\n\
3183
Remove a file (same as remove(path)).");
3184

3185
PyDoc_STRVAR(posix_remove__doc__,
Fred Drake's avatar
Fred Drake committed
3186
"remove(path)\n\n\
3187
Remove a file (same as unlink(path)).");
3188

Barry Warsaw's avatar
Barry Warsaw committed
3189
static PyObject *
3190
posix_unlink(PyObject *self, PyObject *args)
Guido van Rossum's avatar
Guido van Rossum committed
3191
{
3192
#ifdef MS_WINDOWS
3193 3194
    return win32_1str(args, "remove", "y:remove", DeleteFileA,
                      "U:remove", Py_DeleteFileW);
3195
#else
3196
    return posix_1str(args, "O&:remove", unlink);
3197
#endif
Guido van Rossum's avatar
Guido van Rossum committed
3198 3199
}

3200

3201
#ifdef HAVE_UNAME
3202
PyDoc_STRVAR(posix_uname__doc__,
Fred Drake's avatar
Fred Drake committed
3203
"uname() -> (sysname, nodename, release, version, machine)\n\n\
3204
Return a tuple identifying the current operating system.");
3205

Barry Warsaw's avatar
Barry Warsaw committed
3206
static PyObject *
3207
posix_uname(PyObject *self, PyObject *noargs)
3208
{
3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222
    struct utsname u;
    int res;

    Py_BEGIN_ALLOW_THREADS
    res = uname(&u);
    Py_END_ALLOW_THREADS
    if (res < 0)
        return posix_error();
    return Py_BuildValue("(sssss)",
                         u.sysname,
                         u.nodename,
                         u.release,
                         u.version,
                         u.machine);
3223
}
3224
#endif /* HAVE_UNAME */
3225

3226
static int
3227
extract_time(PyObject *t, time_t* sec, long* usec)
3228
{
3229
    time_t intval;
3230 3231
    if (PyFloat_Check(t)) {
        double tval = PyFloat_AsDouble(t);
3232
        PyObject *intobj = PyNumber_Long(t);
3233 3234
        if (!intobj)
            return -1;
3235 3236 3237
#if SIZEOF_TIME_T > SIZEOF_LONG
        intval = PyLong_AsUnsignedLongLongMask(intobj);
#else
3238
        intval = PyLong_AsLong(intobj);
3239
#endif
3240 3241 3242 3243 3244 3245 3246 3247 3248
        Py_DECREF(intobj);
        if (intval == -1 && PyErr_Occurred())
            return -1;
        *sec = intval;
        *usec = (long)((tval - intval) * 1e6); /* can't exceed 1000000 */
        if (*usec < 0)
            /* If rounding gave us a negative number,
               truncate.  */
            *usec = 0;
3249
        return 0;
3250
    }
3251 3252 3253
#if SIZEOF_TIME_T > SIZEOF_LONG
    intval = PyLong_AsUnsignedLongLongMask(t);
#else
3254
    intval = PyLong_AsLong(t);
3255
#endif
3256 3257 3258 3259 3260
    if (intval == -1 && PyErr_Occurred())
        return -1;
    *sec = intval;
    *usec = 0;
    return 0;
3261
}
3262

3263
PyDoc_STRVAR(posix_utime__doc__,
3264
"utime(path, (atime, mtime))\n\
Fred Drake's avatar
Fred Drake committed
3265
utime(path, None)\n\n\
3266
Set the access and modified time of the file to the given values.  If the\n\
3267
second form is used, set the access and modified times to the current time.");
3268

Barry Warsaw's avatar
Barry Warsaw committed
3269
static PyObject *
3270
posix_utime(PyObject *self, PyObject *args)
Guido van Rossum's avatar
Guido van Rossum committed
3271
{
3272
#ifdef MS_WINDOWS
3273 3274 3275 3276 3277 3278
    PyObject *arg;
    PyUnicodeObject *obwpath;
    wchar_t *wpath = NULL;
    PyObject *oapath;
    char *apath;
    HANDLE hFile;
3279 3280
    time_t atimesec, mtimesec;
    long ausec, musec;
3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322
    FILETIME atime, mtime;
    PyObject *result = NULL;

    if (PyArg_ParseTuple(args, "UO|:utime", &obwpath, &arg)) {
        wpath = PyUnicode_AS_UNICODE(obwpath);
        Py_BEGIN_ALLOW_THREADS
        hFile = CreateFileW(wpath, FILE_WRITE_ATTRIBUTES, 0,
                            NULL, OPEN_EXISTING,
                            FILE_FLAG_BACKUP_SEMANTICS, NULL);
        Py_END_ALLOW_THREADS
        if (hFile == INVALID_HANDLE_VALUE)
            return win32_error_unicode("utime", wpath);
    } else
        /* Drop the argument parsing error as narrow strings
           are also valid. */
        PyErr_Clear();

    if (!wpath) {
        if (!PyArg_ParseTuple(args, "O&O:utime",
                        PyUnicode_FSConverter, &oapath, &arg))
            return NULL;
        apath = PyBytes_AsString(oapath);
        Py_BEGIN_ALLOW_THREADS
        hFile = CreateFileA(apath, FILE_WRITE_ATTRIBUTES, 0,
                            NULL, OPEN_EXISTING,
                            FILE_FLAG_BACKUP_SEMANTICS, NULL);
        Py_END_ALLOW_THREADS
        if (hFile == INVALID_HANDLE_VALUE) {
            win32_error("utime", apath);
            Py_DECREF(oapath);
            return NULL;
        }
        Py_DECREF(oapath);
    }

    if (arg == Py_None) {
        SYSTEMTIME now;
        GetSystemTime(&now);
        if (!SystemTimeToFileTime(&now, &mtime) ||
            !SystemTimeToFileTime(&now, &atime)) {
            win32_error("utime", NULL);
            goto done;
Stefan Krah's avatar
Stefan Krah committed
3323
        }
3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345
    }
    else if (!PyTuple_Check(arg) || PyTuple_Size(arg) != 2) {
        PyErr_SetString(PyExc_TypeError,
                        "utime() arg 2 must be a tuple (atime, mtime)");
        goto done;
    }
    else {
        if (extract_time(PyTuple_GET_ITEM(arg, 0),
                         &atimesec, &ausec) == -1)
            goto done;
        time_t_to_FILE_TIME(atimesec, 1000*ausec, &atime);
        if (extract_time(PyTuple_GET_ITEM(arg, 1),
                         &mtimesec, &musec) == -1)
            goto done;
        time_t_to_FILE_TIME(mtimesec, 1000*musec, &mtime);
    }
    if (!SetFileTime(hFile, NULL, &atime, &mtime)) {
        /* Avoid putting the file name into the error here,
           as that may confuse the user into believing that
           something is wrong with the file, when it also
           could be the time stamp that gives a problem. */
        win32_error("utime", NULL);
3346
        goto done;
3347 3348 3349
    }
    Py_INCREF(Py_None);
    result = Py_None;
3350
done:
3351 3352
    CloseHandle(hFile);
    return result;
3353
#else /* MS_WINDOWS */
3354

3355 3356
    PyObject *opath;
    char *path;
3357 3358
    time_t atime, mtime;
    long ausec, musec;
3359 3360
    int res;
    PyObject* arg;
3361

3362
#if defined(HAVE_UTIMES)
3363
    struct timeval buf[2];
3364 3365 3366
#define ATIME buf[0].tv_sec
#define MTIME buf[1].tv_sec
#elif defined(HAVE_UTIME_H)
3367
/* XXX should define struct utimbuf instead, above */
3368
    struct utimbuf buf;
3369 3370 3371
#define ATIME buf.actime
#define MTIME buf.modtime
#define UTIME_ARG &buf
3372
#else /* HAVE_UTIMES */
3373
    time_t buf[2];
3374 3375 3376
#define ATIME buf[0]
#define MTIME buf[1]
#define UTIME_ARG buf
3377
#endif /* HAVE_UTIMES */
3378

3379

3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408
    if (!PyArg_ParseTuple(args, "O&O:utime",
                          PyUnicode_FSConverter, &opath, &arg))
        return NULL;
    path = PyBytes_AsString(opath);
    if (arg == Py_None) {
        /* optional time values not given */
        Py_BEGIN_ALLOW_THREADS
        res = utime(path, NULL);
        Py_END_ALLOW_THREADS
    }
    else if (!PyTuple_Check(arg) || PyTuple_Size(arg) != 2) {
        PyErr_SetString(PyExc_TypeError,
                        "utime() arg 2 must be a tuple (atime, mtime)");
        Py_DECREF(opath);
        return NULL;
    }
    else {
        if (extract_time(PyTuple_GET_ITEM(arg, 0),
                         &atime, &ausec) == -1) {
            Py_DECREF(opath);
            return NULL;
        }
        if (extract_time(PyTuple_GET_ITEM(arg, 1),
                         &mtime, &musec) == -1) {
            Py_DECREF(opath);
            return NULL;
        }
        ATIME = atime;
        MTIME = mtime;
3409
#ifdef HAVE_UTIMES
3410 3411 3412 3413 3414
        buf[0].tv_usec = ausec;
        buf[1].tv_usec = musec;
        Py_BEGIN_ALLOW_THREADS
        res = utimes(path, buf);
        Py_END_ALLOW_THREADS
3415
#else
3416 3417 3418
        Py_BEGIN_ALLOW_THREADS
        res = utime(path, UTIME_ARG);
        Py_END_ALLOW_THREADS
3419
#endif /* HAVE_UTIMES */
3420 3421 3422 3423 3424 3425 3426
    }
    if (res < 0) {
        return posix_error_with_allocated_filename(opath);
    }
    Py_DECREF(opath);
    Py_INCREF(Py_None);
    return Py_None;
3427 3428 3429
#undef UTIME_ARG
#undef ATIME
#undef MTIME
3430
#endif /* MS_WINDOWS */
Guido van Rossum's avatar
Guido van Rossum committed
3431 3432
}

3433

Guido van Rossum's avatar
Guido van Rossum committed
3434
/* Process operations */
3435

3436
PyDoc_STRVAR(posix__exit__doc__,
Fred Drake's avatar
Fred Drake committed
3437
"_exit(status)\n\n\
3438
Exit to the system with specified status, without normal exit processing.");
3439

Barry Warsaw's avatar
Barry Warsaw committed
3440
static PyObject *
3441
posix__exit(PyObject *self, PyObject *args)
3442
{
3443 3444 3445 3446 3447
    int sts;
    if (!PyArg_ParseTuple(args, "i:_exit", &sts))
        return NULL;
    _exit(sts);
    return NULL; /* Make gcc -Wall happy */
3448 3449
}

3450 3451
#if defined(HAVE_EXECV) || defined(HAVE_SPAWNV)
static void
3452
free_string_array(char **array, Py_ssize_t count)
3453
{
3454 3455 3456 3457
    Py_ssize_t i;
    for (i = 0; i < count; i++)
        PyMem_Free(array[i]);
    PyMem_DEL(array);
3458
}
3459

3460
static
3461 3462
int fsconvert_strdup(PyObject *o, char**out)
{
3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473
    PyObject *bytes;
    Py_ssize_t size;
    if (!PyUnicode_FSConverter(o, &bytes))
        return 0;
    size = PyBytes_GET_SIZE(bytes);
    *out = PyMem_Malloc(size+1);
    if (!*out)
        return 0;
    memcpy(*out, PyBytes_AsString(bytes), size+1);
    Py_DECREF(bytes);
    return 1;
3474
}
3475 3476
#endif

3477

3478
#ifdef HAVE_EXECV
3479
PyDoc_STRVAR(posix_execv__doc__,
Fred Drake's avatar
Fred Drake committed
3480
"execv(path, args)\n\n\
3481 3482
Execute an executable path with arguments, replacing current process.\n\
\n\
3483 3484
    path: path of executable file\n\
    args: tuple or list of strings");
3485

Barry Warsaw's avatar
Barry Warsaw committed
3486
static PyObject *
3487
posix_execv(PyObject *self, PyObject *args)
3488
{
3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547
    PyObject *opath;
    char *path;
    PyObject *argv;
    char **argvlist;
    Py_ssize_t i, argc;
    PyObject *(*getitem)(PyObject *, Py_ssize_t);

    /* execv has two arguments: (path, argv), where
       argv is a list or tuple of strings. */

    if (!PyArg_ParseTuple(args, "O&O:execv",
                          PyUnicode_FSConverter,
                          &opath, &argv))
        return NULL;
    path = PyBytes_AsString(opath);
    if (PyList_Check(argv)) {
        argc = PyList_Size(argv);
        getitem = PyList_GetItem;
    }
    else if (PyTuple_Check(argv)) {
        argc = PyTuple_Size(argv);
        getitem = PyTuple_GetItem;
    }
    else {
        PyErr_SetString(PyExc_TypeError, "execv() arg 2 must be a tuple or list");
        Py_DECREF(opath);
        return NULL;
    }
    if (argc < 1) {
        PyErr_SetString(PyExc_ValueError, "execv() arg 2 must not be empty");
        Py_DECREF(opath);
        return NULL;
    }

    argvlist = PyMem_NEW(char *, argc+1);
    if (argvlist == NULL) {
        Py_DECREF(opath);
        return PyErr_NoMemory();
    }
    for (i = 0; i < argc; i++) {
        if (!fsconvert_strdup((*getitem)(argv, i),
                              &argvlist[i])) {
            free_string_array(argvlist, i);
            PyErr_SetString(PyExc_TypeError,
                            "execv() arg 2 must contain only strings");
            Py_DECREF(opath);
            return NULL;

        }
    }
    argvlist[argc] = NULL;

    execv(path, argvlist);

    /* If we get here it's definitely an error */

    free_string_array(argvlist, argc);
    Py_DECREF(opath);
    return posix_error();
3548 3549
}

3550 3551 3552
static char**
parse_envlist(PyObject* env, Py_ssize_t *envc_ptr)
{
3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590
    char **envlist;
    Py_ssize_t i, pos, envc;
    PyObject *keys=NULL, *vals=NULL;
    PyObject *key, *val, *key2, *val2;
    char *p, *k, *v;
    size_t len;

    i = PyMapping_Size(env);
    if (i < 0)
        return NULL;
    envlist = PyMem_NEW(char *, i + 1);
    if (envlist == NULL) {
        PyErr_NoMemory();
        return NULL;
    }
    envc = 0;
    keys = PyMapping_Keys(env);
    vals = PyMapping_Values(env);
    if (!keys || !vals)
        goto error;
    if (!PyList_Check(keys) || !PyList_Check(vals)) {
        PyErr_Format(PyExc_TypeError,
                     "env.keys() or env.values() is not a list");
        goto error;
    }

    for (pos = 0; pos < i; pos++) {
        key = PyList_GetItem(keys, pos);
        val = PyList_GetItem(vals, pos);
        if (!key || !val)
            goto error;

        if (PyUnicode_FSConverter(key, &key2) == 0)
            goto error;
        if (PyUnicode_FSConverter(val, &val2) == 0) {
            Py_DECREF(key2);
            goto error;
        }
3591 3592

#if defined(PYOS_OS2)
3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610
        /* Omit Pseudo-Env Vars that Would Confuse Programs if Passed On */
        if (stricmp(k, "BEGINLIBPATH") != 0 && stricmp(k, "ENDLIBPATH") != 0) {
#endif
        k = PyBytes_AsString(key2);
        v = PyBytes_AsString(val2);
        len = PyBytes_GET_SIZE(key2) + PyBytes_GET_SIZE(val2) + 2;

        p = PyMem_NEW(char, len);
        if (p == NULL) {
            PyErr_NoMemory();
            Py_DECREF(key2);
            Py_DECREF(val2);
            goto error;
        }
        PyOS_snprintf(p, len, "%s=%s", k, v);
        envlist[envc++] = p;
        Py_DECREF(key2);
        Py_DECREF(val2);
3611
#if defined(PYOS_OS2)
3612
        }
3613
#endif
3614 3615 3616
    }
    Py_DECREF(vals);
    Py_DECREF(keys);
3617

3618 3619 3620
    envlist[envc] = 0;
    *envc_ptr = envc;
    return envlist;
3621 3622

error:
3623 3624 3625 3626 3627 3628
    Py_XDECREF(keys);
    Py_XDECREF(vals);
    while (--envc >= 0)
        PyMem_DEL(envlist[envc]);
    PyMem_DEL(envlist);
    return NULL;
3629
}
3630

3631
PyDoc_STRVAR(posix_execve__doc__,
Fred Drake's avatar
Fred Drake committed
3632
"execve(path, args, env)\n\n\
3633 3634
Execute a path with arguments and environment, replacing current process.\n\
\n\
3635 3636 3637
    path: path of executable file\n\
    args: tuple or list of arguments\n\
    env: dictionary of strings mapping to strings");
3638

Barry Warsaw's avatar
Barry Warsaw committed
3639
static PyObject *
3640
posix_execve(PyObject *self, PyObject *args)
3641
{
3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707
    PyObject *opath;
    char *path;
    PyObject *argv, *env;
    char **argvlist;
    char **envlist;
    Py_ssize_t i, argc, envc;
    PyObject *(*getitem)(PyObject *, Py_ssize_t);
    Py_ssize_t lastarg = 0;

    /* execve has three arguments: (path, argv, env), where
       argv is a list or tuple of strings and env is a dictionary
       like posix.environ. */

    if (!PyArg_ParseTuple(args, "O&OO:execve",
                          PyUnicode_FSConverter,
                          &opath, &argv, &env))
        return NULL;
    path = PyBytes_AsString(opath);
    if (PyList_Check(argv)) {
        argc = PyList_Size(argv);
        getitem = PyList_GetItem;
    }
    else if (PyTuple_Check(argv)) {
        argc = PyTuple_Size(argv);
        getitem = PyTuple_GetItem;
    }
    else {
        PyErr_SetString(PyExc_TypeError,
                        "execve() arg 2 must be a tuple or list");
        goto fail_0;
    }
    if (!PyMapping_Check(env)) {
        PyErr_SetString(PyExc_TypeError,
                        "execve() arg 3 must be a mapping object");
        goto fail_0;
    }

    argvlist = PyMem_NEW(char *, argc+1);
    if (argvlist == NULL) {
        PyErr_NoMemory();
        goto fail_0;
    }
    for (i = 0; i < argc; i++) {
        if (!fsconvert_strdup((*getitem)(argv, i),
                              &argvlist[i]))
        {
            lastarg = i;
            goto fail_1;
        }
    }
    lastarg = argc;
    argvlist[argc] = NULL;

    envlist = parse_envlist(env, &envc);
    if (envlist == NULL)
        goto fail_1;

    execve(path, argvlist, envlist);

    /* If we get here it's definitely an error */

    (void) posix_error();

    while (--envc >= 0)
        PyMem_DEL(envlist[envc]);
    PyMem_DEL(envlist);
3708
  fail_1:
3709
    free_string_array(argvlist, lastarg);
3710
  fail_0:
3711 3712
    Py_DECREF(opath);
    return NULL;
3713
}
3714
#endif /* HAVE_EXECV */
3715

3716

3717
#ifdef HAVE_SPAWNV
3718
PyDoc_STRVAR(posix_spawnv__doc__,
Fred Drake's avatar
Fred Drake committed
3719
"spawnv(mode, path, args)\n\n\
3720
Execute the program 'path' in a new process.\n\
3721
\n\
3722 3723 3724
    mode: mode of process creation\n\
    path: path of executable file\n\
    args: tuple or list of strings");
3725 3726

static PyObject *
3727
posix_spawnv(PyObject *self, PyObject *args)
3728
{
3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777
    PyObject *opath;
    char *path;
    PyObject *argv;
    char **argvlist;
    int mode, i;
    Py_ssize_t argc;
    Py_intptr_t spawnval;
    PyObject *(*getitem)(PyObject *, Py_ssize_t);

    /* spawnv has three arguments: (mode, path, argv), where
       argv is a list or tuple of strings. */

    if (!PyArg_ParseTuple(args, "iO&O:spawnv", &mode,
                          PyUnicode_FSConverter,
                          &opath, &argv))
        return NULL;
    path = PyBytes_AsString(opath);
    if (PyList_Check(argv)) {
        argc = PyList_Size(argv);
        getitem = PyList_GetItem;
    }
    else if (PyTuple_Check(argv)) {
        argc = PyTuple_Size(argv);
        getitem = PyTuple_GetItem;
    }
    else {
        PyErr_SetString(PyExc_TypeError,
                        "spawnv() arg 2 must be a tuple or list");
        Py_DECREF(opath);
        return NULL;
    }

    argvlist = PyMem_NEW(char *, argc+1);
    if (argvlist == NULL) {
        Py_DECREF(opath);
        return PyErr_NoMemory();
    }
    for (i = 0; i < argc; i++) {
        if (!fsconvert_strdup((*getitem)(argv, i),
                              &argvlist[i])) {
            free_string_array(argvlist, i);
            PyErr_SetString(
                PyExc_TypeError,
                "spawnv() arg 2 must contain only strings");
            Py_DECREF(opath);
            return NULL;
        }
    }
    argvlist[argc] = NULL;
3778

3779
#if defined(PYOS_OS2) && defined(PYCC_GCC)
3780 3781 3782
    Py_BEGIN_ALLOW_THREADS
    spawnval = spawnv(mode, path, argvlist);
    Py_END_ALLOW_THREADS
3783
#else
3784 3785
    if (mode == _OLD_P_OVERLAY)
        mode = _P_OVERLAY;
3786

3787 3788 3789
    Py_BEGIN_ALLOW_THREADS
    spawnval = _spawnv(mode, path, argvlist);
    Py_END_ALLOW_THREADS
3790
#endif
3791

3792 3793
    free_string_array(argvlist, argc);
    Py_DECREF(opath);
3794

3795 3796 3797
    if (spawnval == -1)
        return posix_error();
    else
3798
#if SIZEOF_LONG == SIZEOF_VOID_P
3799
        return Py_BuildValue("l", (long) spawnval);
3800
#else
3801
        return Py_BuildValue("L", (PY_LONG_LONG) spawnval);
3802
#endif
3803 3804 3805
}


3806
PyDoc_STRVAR(posix_spawnve__doc__,
Fred Drake's avatar
Fred Drake committed
3807
"spawnve(mode, path, args, env)\n\n\
3808
Execute the program 'path' in a new process.\n\
3809
\n\
3810 3811 3812 3813
    mode: mode of process creation\n\
    path: path of executable file\n\
    args: tuple or list of arguments\n\
    env: dictionary of strings mapping to strings");
3814 3815

static PyObject *
3816
posix_spawnve(PyObject *self, PyObject *args)
3817
{
3818 3819 3820 3821 3822 3823
    PyObject *opath;
    char *path;
    PyObject *argv, *env;
    char **argvlist;
    char **envlist;
    PyObject *res = NULL;
3824 3825
    int mode;
    Py_ssize_t argc, i, envc;
3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876
    Py_intptr_t spawnval;
    PyObject *(*getitem)(PyObject *, Py_ssize_t);
    Py_ssize_t lastarg = 0;

    /* spawnve has four arguments: (mode, path, argv, env), where
       argv is a list or tuple of strings and env is a dictionary
       like posix.environ. */

    if (!PyArg_ParseTuple(args, "iO&OO:spawnve", &mode,
                          PyUnicode_FSConverter,
                          &opath, &argv, &env))
        return NULL;
    path = PyBytes_AsString(opath);
    if (PyList_Check(argv)) {
        argc = PyList_Size(argv);
        getitem = PyList_GetItem;
    }
    else if (PyTuple_Check(argv)) {
        argc = PyTuple_Size(argv);
        getitem = PyTuple_GetItem;
    }
    else {
        PyErr_SetString(PyExc_TypeError,
                        "spawnve() arg 2 must be a tuple or list");
        goto fail_0;
    }
    if (!PyMapping_Check(env)) {
        PyErr_SetString(PyExc_TypeError,
                        "spawnve() arg 3 must be a mapping object");
        goto fail_0;
    }

    argvlist = PyMem_NEW(char *, argc+1);
    if (argvlist == NULL) {
        PyErr_NoMemory();
        goto fail_0;
    }
    for (i = 0; i < argc; i++) {
        if (!fsconvert_strdup((*getitem)(argv, i),
                              &argvlist[i]))
        {
            lastarg = i;
            goto fail_1;
        }
    }
    lastarg = argc;
    argvlist[argc] = NULL;

    envlist = parse_envlist(env, &envc);
    if (envlist == NULL)
        goto fail_1;
3877

3878
#if defined(PYOS_OS2) && defined(PYCC_GCC)
3879 3880 3881
    Py_BEGIN_ALLOW_THREADS
    spawnval = spawnve(mode, path, argvlist, envlist);
    Py_END_ALLOW_THREADS
3882
#else
3883 3884
    if (mode == _OLD_P_OVERLAY)
        mode = _P_OVERLAY;
3885

3886 3887 3888
    Py_BEGIN_ALLOW_THREADS
    spawnval = _spawnve(mode, path, argvlist, envlist);
    Py_END_ALLOW_THREADS
3889
#endif
3890

3891 3892 3893
    if (spawnval == -1)
        (void) posix_error();
    else
3894
#if SIZEOF_LONG == SIZEOF_VOID_P
3895
        res = Py_BuildValue("l", (long) spawnval);
3896
#else
3897
        res = Py_BuildValue("L", (PY_LONG_LONG) spawnval);
3898
#endif
3899

3900 3901 3902
    while (--envc >= 0)
        PyMem_DEL(envlist[envc]);
    PyMem_DEL(envlist);
3903
  fail_1:
3904
    free_string_array(argvlist, lastarg);
3905
  fail_0:
3906 3907
    Py_DECREF(opath);
    return res;
3908
}
3909 3910 3911 3912 3913 3914 3915 3916

/* OS/2 supports spawnvp & spawnvpe natively */
#if defined(PYOS_OS2)
PyDoc_STRVAR(posix_spawnvp__doc__,
"spawnvp(mode, file, args)\n\n\
Execute the program 'file' in a new process, using the environment\n\
search path to find the file.\n\
\n\
3917 3918 3919
    mode: mode of process creation\n\
    file: executable file name\n\
    args: tuple or list of strings");
3920 3921 3922 3923

static PyObject *
posix_spawnvp(PyObject *self, PyObject *args)
{
3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973
    PyObject *opath;
    char *path;
    PyObject *argv;
    char **argvlist;
    int mode, i, argc;
    Py_intptr_t spawnval;
    PyObject *(*getitem)(PyObject *, Py_ssize_t);

    /* spawnvp has three arguments: (mode, path, argv), where
       argv is a list or tuple of strings. */

    if (!PyArg_ParseTuple(args, "iO&O:spawnvp", &mode,
                          PyUnicode_FSConverter,
                          &opath, &argv))
        return NULL;
    path = PyBytes_AsString(opath);
    if (PyList_Check(argv)) {
        argc = PyList_Size(argv);
        getitem = PyList_GetItem;
    }
    else if (PyTuple_Check(argv)) {
        argc = PyTuple_Size(argv);
        getitem = PyTuple_GetItem;
    }
    else {
        PyErr_SetString(PyExc_TypeError,
                        "spawnvp() arg 2 must be a tuple or list");
        Py_DECREF(opath);
        return NULL;
    }

    argvlist = PyMem_NEW(char *, argc+1);
    if (argvlist == NULL) {
        Py_DECREF(opath);
        return PyErr_NoMemory();
    }
    for (i = 0; i < argc; i++) {
        if (!fsconvert_strdup((*getitem)(argv, i),
                              &argvlist[i])) {
            free_string_array(argvlist, i);
            PyErr_SetString(
                PyExc_TypeError,
                "spawnvp() arg 2 must contain only strings");
            Py_DECREF(opath);
            return NULL;
        }
    }
    argvlist[argc] = NULL;

    Py_BEGIN_ALLOW_THREADS
3974
#if defined(PYCC_GCC)
3975
    spawnval = spawnvp(mode, path, argvlist);
3976
#else
3977
    spawnval = _spawnvp(mode, path, argvlist);
3978
#endif
3979
    Py_END_ALLOW_THREADS
3980

3981 3982
    free_string_array(argvlist, argc);
    Py_DECREF(opath);
3983

3984 3985 3986 3987
    if (spawnval == -1)
        return posix_error();
    else
        return Py_BuildValue("l", (long) spawnval);
3988 3989 3990 3991 3992 3993 3994 3995
}


PyDoc_STRVAR(posix_spawnvpe__doc__,
"spawnvpe(mode, file, args, env)\n\n\
Execute the program 'file' in a new process, using the environment\n\
search path to find the file.\n\
\n\
3996 3997 3998 3999
    mode: mode of process creation\n\
    file: executable file name\n\
    args: tuple or list of arguments\n\
    env: dictionary of strings mapping to strings");
4000 4001 4002 4003

static PyObject *
posix_spawnvpe(PyObject *self, PyObject *args)
{
4004 4005 4006 4007 4008 4009
    PyObject *opath
    char *path;
    PyObject *argv, *env;
    char **argvlist;
    char **envlist;
    PyObject *res=NULL;
4010 4011
    int mode;
    Py_ssize_t argc, i, envc;
4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064
    Py_intptr_t spawnval;
    PyObject *(*getitem)(PyObject *, Py_ssize_t);
    int lastarg = 0;

    /* spawnvpe has four arguments: (mode, path, argv, env), where
       argv is a list or tuple of strings and env is a dictionary
       like posix.environ. */

    if (!PyArg_ParseTuple(args, "ietOO:spawnvpe", &mode,
                          PyUnicode_FSConverter,
                          &opath, &argv, &env))
        return NULL;
    path = PyBytes_AsString(opath);
    if (PyList_Check(argv)) {
        argc = PyList_Size(argv);
        getitem = PyList_GetItem;
    }
    else if (PyTuple_Check(argv)) {
        argc = PyTuple_Size(argv);
        getitem = PyTuple_GetItem;
    }
    else {
        PyErr_SetString(PyExc_TypeError,
                        "spawnvpe() arg 2 must be a tuple or list");
        goto fail_0;
    }
    if (!PyMapping_Check(env)) {
        PyErr_SetString(PyExc_TypeError,
                        "spawnvpe() arg 3 must be a mapping object");
        goto fail_0;
    }

    argvlist = PyMem_NEW(char *, argc+1);
    if (argvlist == NULL) {
        PyErr_NoMemory();
        goto fail_0;
    }
    for (i = 0; i < argc; i++) {
        if (!fsconvert_strdup((*getitem)(argv, i),
                              &argvlist[i]))
        {
            lastarg = i;
            goto fail_1;
        }
    }
    lastarg = argc;
    argvlist[argc] = NULL;

    envlist = parse_envlist(env, &envc);
    if (envlist == NULL)
        goto fail_1;

    Py_BEGIN_ALLOW_THREADS
4065
#if defined(PYCC_GCC)
4066
    spawnval = spawnvpe(mode, path, argvlist, envlist);
4067
#else
4068
    spawnval = _spawnvpe(mode, path, argvlist, envlist);
4069
#endif
4070
    Py_END_ALLOW_THREADS
4071

4072 4073 4074 4075
    if (spawnval == -1)
        (void) posix_error();
    else
        res = Py_BuildValue("l", (long) spawnval);
4076

4077 4078 4079
    while (--envc >= 0)
        PyMem_DEL(envlist[envc]);
    PyMem_DEL(envlist);
4080
  fail_1:
4081
    free_string_array(argvlist, lastarg);
4082
  fail_0:
4083 4084
    Py_DECREF(opath);
    return res;
4085 4086
}
#endif /* PYOS_OS2 */
4087 4088 4089
#endif /* HAVE_SPAWNV */


4090
#ifdef HAVE_FORK1
4091
PyDoc_STRVAR(posix_fork1__doc__,
Fred Drake's avatar
Fred Drake committed
4092
"fork1() -> pid\n\n\
4093 4094
Fork a child process with a single multiplexed (i.e., not bound) thread.\n\
\n\
4095
Return 0 to child process and PID of child to parent process.");
4096 4097

static PyObject *
4098
posix_fork1(PyObject *self, PyObject *noargs)
4099
{
4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119
    pid_t pid;
    int result = 0;
    _PyImport_AcquireLock();
    pid = fork1();
    if (pid == 0) {
        /* child: this clobbers and resets the import lock. */
        PyOS_AfterFork();
    } else {
        /* parent: release the import lock. */
        result = _PyImport_ReleaseLock();
    }
    if (pid == -1)
        return posix_error();
    if (result < 0) {
        /* Don't clobber the OSError if the fork failed. */
        PyErr_SetString(PyExc_RuntimeError,
                        "not holding the import lock");
        return NULL;
    }
    return PyLong_FromPid(pid);
4120 4121 4122 4123
}
#endif


Guido van Rossum's avatar
Guido van Rossum committed
4124
#ifdef HAVE_FORK
4125
PyDoc_STRVAR(posix_fork__doc__,
Fred Drake's avatar
Fred Drake committed
4126
"fork() -> pid\n\n\
4127
Fork a child process.\n\
4128
Return 0 to child process and PID of child to parent process.");
4129

Barry Warsaw's avatar
Barry Warsaw committed
4130
static PyObject *
4131
posix_fork(PyObject *self, PyObject *noargs)
4132
{
4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152
    pid_t pid;
    int result = 0;
    _PyImport_AcquireLock();
    pid = fork();
    if (pid == 0) {
        /* child: this clobbers and resets the import lock. */
        PyOS_AfterFork();
    } else {
        /* parent: release the import lock. */
        result = _PyImport_ReleaseLock();
    }
    if (pid == -1)
        return posix_error();
    if (result < 0) {
        /* Don't clobber the OSError if the fork failed. */
        PyErr_SetString(PyExc_RuntimeError,
                        "not holding the import lock");
        return NULL;
    }
    return PyLong_FromPid(pid);
4153
}
Guido van Rossum's avatar
Guido van Rossum committed
4154
#endif
4155

4156
/* AIX uses /dev/ptc but is otherwise the same as /dev/ptmx */
Neal Norwitz's avatar
Neal Norwitz committed
4157 4158
/* IRIX has both /dev/ptc and /dev/ptmx, use ptmx */
#if defined(HAVE_DEV_PTC) && !defined(HAVE_DEV_PTMX)
4159 4160 4161 4162 4163 4164
#define DEV_PTY_FILE "/dev/ptc"
#define HAVE_DEV_PTMX
#else
#define DEV_PTY_FILE "/dev/ptmx"
#endif

4165
#if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX)
4166 4167 4168 4169 4170
#ifdef HAVE_PTY_H
#include <pty.h>
#else
#ifdef HAVE_LIBUTIL_H
#include <libutil.h>
4171 4172 4173 4174
#else
#ifdef HAVE_UTIL_H
#include <util.h>
#endif /* HAVE_UTIL_H */
4175 4176
#endif /* HAVE_LIBUTIL_H */
#endif /* HAVE_PTY_H */
4177 4178
#ifdef HAVE_STROPTS_H
#include <stropts.h>
4179 4180
#endif
#endif /* defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) || defined(HAVE_DEV_PTMX */
4181

4182
#if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
4183
PyDoc_STRVAR(posix_openpty__doc__,
Fred Drake's avatar
Fred Drake committed
4184
"openpty() -> (master_fd, slave_fd)\n\n\
4185
Open a pseudo-terminal, returning open fd's for both master and slave end.\n");
4186 4187

static PyObject *
4188
posix_openpty(PyObject *self, PyObject *noargs)
4189
{
4190
    int master_fd, slave_fd;
4191
#ifndef HAVE_OPENPTY
4192
    char * slave_name;
4193 4194
#endif
#if defined(HAVE_DEV_PTMX) && !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
4195
    PyOS_sighandler_t sig_saved;
4196
#ifdef sun
4197
    extern char *ptsname(int fildes);
4198
#endif
4199 4200 4201
#endif

#ifdef HAVE_OPENPTY
4202 4203
    if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0)
        return posix_error();
4204
#elif defined(HAVE__GETPTY)
4205 4206 4207
    slave_name = _getpty(&master_fd, O_RDWR, 0666, 0);
    if (slave_name == NULL)
        return posix_error();
4208

4209 4210 4211
    slave_fd = open(slave_name, O_RDWR);
    if (slave_fd < 0)
        return posix_error();
4212
#else
4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233
    master_fd = open(DEV_PTY_FILE, O_RDWR | O_NOCTTY); /* open master */
    if (master_fd < 0)
        return posix_error();
    sig_saved = PyOS_setsig(SIGCHLD, SIG_DFL);
    /* change permission of slave */
    if (grantpt(master_fd) < 0) {
        PyOS_setsig(SIGCHLD, sig_saved);
        return posix_error();
    }
    /* unlock slave */
    if (unlockpt(master_fd) < 0) {
        PyOS_setsig(SIGCHLD, sig_saved);
        return posix_error();
    }
    PyOS_setsig(SIGCHLD, sig_saved);
    slave_name = ptsname(master_fd); /* get name of slave */
    if (slave_name == NULL)
        return posix_error();
    slave_fd = open(slave_name, O_RDWR | O_NOCTTY); /* open slave */
    if (slave_fd < 0)
        return posix_error();
4234
#if !defined(__CYGWIN__) && !defined(HAVE_DEV_PTC)
4235 4236
    ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */
    ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */
4237
#ifndef __hpux
4238
    ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */
4239
#endif /* __hpux */
4240
#endif /* HAVE_CYGWIN */
4241
#endif /* HAVE_OPENPTY */
4242

4243
    return Py_BuildValue("(ii)", master_fd, slave_fd);
4244

4245
}
4246
#endif /* defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX) */
4247 4248

#ifdef HAVE_FORKPTY
4249
PyDoc_STRVAR(posix_forkpty__doc__,
Fred Drake's avatar
Fred Drake committed
4250
"forkpty() -> (pid, master_fd)\n\n\
4251 4252
Fork a new process with a new pseudo-terminal as controlling tty.\n\n\
Like fork(), return 0 as pid to child process, and PID of child to parent.\n\
4253
To both, return fd of newly opened pseudo-terminal.\n");
4254 4255

static PyObject *
4256
posix_forkpty(PyObject *self, PyObject *noargs)
4257
{
4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278
    int master_fd = -1, result = 0;
    pid_t pid;

    _PyImport_AcquireLock();
    pid = forkpty(&master_fd, NULL, NULL, NULL);
    if (pid == 0) {
        /* child: this clobbers and resets the import lock. */
        PyOS_AfterFork();
    } else {
        /* parent: release the import lock. */
        result = _PyImport_ReleaseLock();
    }
    if (pid == -1)
        return posix_error();
    if (result < 0) {
        /* Don't clobber the OSError if the fork failed. */
        PyErr_SetString(PyExc_RuntimeError,
                        "not holding the import lock");
        return NULL;
    }
    return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd);
4279 4280
}
#endif
4281

Guido van Rossum's avatar
Guido van Rossum committed
4282
#ifdef HAVE_GETEGID
4283
PyDoc_STRVAR(posix_getegid__doc__,
Fred Drake's avatar
Fred Drake committed
4284
"getegid() -> egid\n\n\
4285
Return the current process's effective group id.");
4286

Barry Warsaw's avatar
Barry Warsaw committed
4287
static PyObject *
4288
posix_getegid(PyObject *self, PyObject *noargs)
4289
{
4290
    return PyLong_FromLong((long)getegid());
4291
}
Guido van Rossum's avatar
Guido van Rossum committed
4292
#endif
4293

4294

Guido van Rossum's avatar
Guido van Rossum committed
4295
#ifdef HAVE_GETEUID
4296
PyDoc_STRVAR(posix_geteuid__doc__,
Fred Drake's avatar
Fred Drake committed
4297
"geteuid() -> euid\n\n\
4298
Return the current process's effective user id.");
4299

Barry Warsaw's avatar
Barry Warsaw committed
4300
static PyObject *
4301
posix_geteuid(PyObject *self, PyObject *noargs)
4302
{
4303
    return PyLong_FromLong((long)geteuid());
4304
}
Guido van Rossum's avatar
Guido van Rossum committed
4305
#endif
4306

4307

Guido van Rossum's avatar
Guido van Rossum committed
4308
#ifdef HAVE_GETGID
4309
PyDoc_STRVAR(posix_getgid__doc__,
Fred Drake's avatar
Fred Drake committed
4310
"getgid() -> gid\n\n\
4311
Return the current process's group id.");
4312

Barry Warsaw's avatar
Barry Warsaw committed
4313
static PyObject *
4314
posix_getgid(PyObject *self, PyObject *noargs)
4315
{
4316
    return PyLong_FromLong((long)getgid());
4317
}
Guido van Rossum's avatar
Guido van Rossum committed
4318
#endif
4319

4320

4321
PyDoc_STRVAR(posix_getpid__doc__,
Fred Drake's avatar
Fred Drake committed
4322
"getpid() -> pid\n\n\
4323
Return the current process id");
4324

Barry Warsaw's avatar
Barry Warsaw committed
4325
static PyObject *
4326
posix_getpid(PyObject *self, PyObject *noargs)
4327
{
4328
    return PyLong_FromPid(getpid());
4329 4330
}

4331

4332
#ifdef HAVE_GETGROUPS
4333
PyDoc_STRVAR(posix_getgroups__doc__,
Fred Drake's avatar
Fred Drake committed
4334
"getgroups() -> list of group IDs\n\n\
4335
Return list of supplemental group IDs for the process.");
4336 4337

static PyObject *
4338
posix_getgroups(PyObject *self, PyObject *noargs)
4339 4340 4341 4342 4343 4344
{
    PyObject *result = NULL;

#ifdef NGROUPS_MAX
#define MAX_GROUPS NGROUPS_MAX
#else
4345
    /* defined to be 16 on Solaris7, so this should be a small number */
4346 4347
#define MAX_GROUPS 64
#endif
4348
    gid_t grouplist[MAX_GROUPS];
4349

4350
    /* On MacOSX getgroups(2) can return more than MAX_GROUPS results
4351 4352 4353 4354 4355 4356 4357 4358
     * This is a helper variable to store the intermediate result when
     * that happens.
     *
     * To keep the code readable the OSX behaviour is unconditional,
     * according to the POSIX spec this should be safe on all unix-y
     * systems.
     */
    gid_t* alt_grouplist = grouplist;
4359
    int n;
4360

4361
    n = getgroups(MAX_GROUPS, grouplist);
4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388
    if (n < 0) {
        if (errno == EINVAL) {
            n = getgroups(0, NULL);
            if (n == -1) {
                return posix_error();
            }
            if (n == 0) {
                /* Avoid malloc(0) */
                alt_grouplist = grouplist;
            } else {
                alt_grouplist = PyMem_Malloc(n * sizeof(gid_t));
                if (alt_grouplist == NULL) {
                    errno = EINVAL;
                    return posix_error();
                }
                n = getgroups(n, alt_grouplist);
                if (n == -1) {
                    PyMem_Free(alt_grouplist);
                    return posix_error();
                }
            }
        } else {
            return posix_error();
        }
    }
    result = PyList_New(n);
    if (result != NULL) {
4389 4390
        int i;
        for (i = 0; i < n; ++i) {
4391
            PyObject *o = PyLong_FromLong((long)alt_grouplist[i]);
4392
            if (o == NULL) {
Stefan Krah's avatar
Stefan Krah committed
4393 4394 4395
                Py_DECREF(result);
                result = NULL;
                break;
4396
            }
4397
            PyList_SET_ITEM(result, i, o);
4398
        }
4399 4400 4401 4402
    }

    if (alt_grouplist != grouplist) {
        PyMem_Free(alt_grouplist);
4403
    }
4404

4405 4406 4407 4408
    return result;
}
#endif

4409 4410 4411 4412 4413 4414 4415 4416 4417 4418
#ifdef HAVE_INITGROUPS
PyDoc_STRVAR(posix_initgroups__doc__,
"initgroups(username, gid) -> None\n\n\
Call the system initgroups() to initialize the group access list with all of\n\
the groups of which the specified username is a member, plus the specified\n\
group id.");

static PyObject *
posix_initgroups(PyObject *self, PyObject *args)
{
4419
    PyObject *oname;
4420
    char *username;
4421
    int res;
4422
    long gid;
4423

4424 4425
    if (!PyArg_ParseTuple(args, "O&l:initgroups",
                          PyUnicode_FSConverter, &oname, &gid))
4426
        return NULL;
4427
    username = PyBytes_AS_STRING(oname);
4428

4429 4430 4431
    res = initgroups(username, (gid_t) gid);
    Py_DECREF(oname);
    if (res == -1)
4432
        return PyErr_SetFromErrno(PyExc_OSError);
4433

4434 4435
    Py_INCREF(Py_None);
    return Py_None;
4436 4437 4438
}
#endif

4439
#ifdef HAVE_GETPGID
Neal Norwitz's avatar
Neal Norwitz committed
4440
PyDoc_STRVAR(posix_getpgid__doc__,
Fred Drake's avatar
Fred Drake committed
4441
"getpgid(pid) -> pgid\n\n\
Neal Norwitz's avatar
Neal Norwitz committed
4442
Call the system call getpgid().");
4443 4444 4445 4446

static PyObject *
posix_getpgid(PyObject *self, PyObject *args)
{
4447 4448 4449 4450 4451 4452 4453
    pid_t pid, pgid;
    if (!PyArg_ParseTuple(args, _Py_PARSE_PID ":getpgid", &pid))
        return NULL;
    pgid = getpgid(pid);
    if (pgid < 0)
        return posix_error();
    return PyLong_FromPid(pgid);
4454 4455 4456 4457
}
#endif /* HAVE_GETPGID */


4458
#ifdef HAVE_GETPGRP
4459
PyDoc_STRVAR(posix_getpgrp__doc__,
Fred Drake's avatar
Fred Drake committed
4460
"getpgrp() -> pgrp\n\n\
4461
Return the current process group id.");
4462

Barry Warsaw's avatar
Barry Warsaw committed
4463
static PyObject *
4464
posix_getpgrp(PyObject *self, PyObject *noargs)
4465
{
4466
#ifdef GETPGRP_HAVE_ARG
4467
    return PyLong_FromPid(getpgrp(0));
4468
#else /* GETPGRP_HAVE_ARG */
4469
    return PyLong_FromPid(getpgrp());
4470
#endif /* GETPGRP_HAVE_ARG */
4471
}
4472
#endif /* HAVE_GETPGRP */
4473

4474

4475
#ifdef HAVE_SETPGRP
4476
PyDoc_STRVAR(posix_setpgrp__doc__,
Fred Drake's avatar
Fred Drake committed
4477
"setpgrp()\n\n\
4478
Make this process the process group leader.");
4479

Barry Warsaw's avatar
Barry Warsaw committed
4480
static PyObject *
4481
posix_setpgrp(PyObject *self, PyObject *noargs)
4482
{
4483
#ifdef SETPGRP_HAVE_ARG
4484
    if (setpgrp(0, 0) < 0)
4485
#else /* SETPGRP_HAVE_ARG */
4486
    if (setpgrp() < 0)
4487
#endif /* SETPGRP_HAVE_ARG */
4488 4489 4490
        return posix_error();
    Py_INCREF(Py_None);
    return Py_None;
4491 4492
}

4493 4494
#endif /* HAVE_SETPGRP */

Guido van Rossum's avatar
Guido van Rossum committed
4495
#ifdef HAVE_GETPPID
4496 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 4537 4538

#ifdef MS_WINDOWS
#include <tlhelp32.h>

static PyObject*
win32_getppid()
{
    HANDLE snapshot;
    pid_t mypid;
    PyObject* result = NULL;
    BOOL have_record;
    PROCESSENTRY32 pe;

    mypid = getpid(); /* This function never fails */

    snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (snapshot == INVALID_HANDLE_VALUE)
        return PyErr_SetFromWindowsErr(GetLastError());

    pe.dwSize = sizeof(pe);
    have_record = Process32First(snapshot, &pe);
    while (have_record) {
        if (mypid == (pid_t)pe.th32ProcessID) {
            /* We could cache the ulong value in a static variable. */
            result = PyLong_FromPid((pid_t)pe.th32ParentProcessID);
            break;
        }

        have_record = Process32Next(snapshot, &pe);
    }

    /* If our loop exits and our pid was not found (result will be NULL)
     * then GetLastError will return ERROR_NO_MORE_FILES. This is an
     * error anyway, so let's raise it. */
    if (!result)
        result = PyErr_SetFromWindowsErr(GetLastError());

    CloseHandle(snapshot);

    return result;
}
#endif /*MS_WINDOWS*/

4539
PyDoc_STRVAR(posix_getppid__doc__,
Fred Drake's avatar
Fred Drake committed
4540
"getppid() -> ppid\n\n\
4541 4542 4543
Return the parent's process id.  If the parent process has already exited,\n\
Windows machines will still return its id; others systems will return the id\n\
of the 'init' process (1).");
4544

Barry Warsaw's avatar
Barry Warsaw committed
4545
static PyObject *
4546
posix_getppid(PyObject *self, PyObject *noargs)
4547
{
4548 4549 4550
#ifdef MS_WINDOWS
    return win32_getppid();
#else
4551
    return PyLong_FromPid(getppid());
Guido van Rossum's avatar
Guido van Rossum committed
4552
#endif
4553 4554
}
#endif /* HAVE_GETPPID */
4555

4556

4557
#ifdef HAVE_GETLOGIN
4558
PyDoc_STRVAR(posix_getlogin__doc__,
Fred Drake's avatar
Fred Drake committed
4559
"getlogin() -> string\n\n\
4560
Return the actual login name.");
4561 4562

static PyObject *
4563
posix_getlogin(PyObject *self, PyObject *noargs)
4564
{
4565
    PyObject *result = NULL;
4566
#ifdef MS_WINDOWS
4567 4568 4569 4570 4571 4572
    wchar_t user_name[UNLEN + 1];
    DWORD num_chars = sizeof(user_name)/sizeof(user_name[0]);

    if (GetUserNameW(user_name, &num_chars)) {
        /* num_chars is the number of unicode chars plus null terminator */
        result = PyUnicode_FromWideChar(user_name, num_chars - 1);
4573 4574
    }
    else
4575 4576
        result = PyErr_SetFromWindowsErr(GetLastError());
#else
4577 4578
    char *name;
    int old_errno = errno;
4579

4580 4581 4582 4583
    errno = 0;
    name = getlogin();
    if (name == NULL) {
        if (errno)
4584
            posix_error();
4585
        else
4586
            PyErr_SetString(PyExc_OSError, "unable to determine login name");
4587 4588
    }
    else
4589
        result = PyUnicode_DecodeFSDefault(name);
4590
    errno = old_errno;
4591
#endif
4592 4593
    return result;
}
4594
#endif /* HAVE_GETLOGIN */
4595

Guido van Rossum's avatar
Guido van Rossum committed
4596
#ifdef HAVE_GETUID
4597
PyDoc_STRVAR(posix_getuid__doc__,
Fred Drake's avatar
Fred Drake committed
4598
"getuid() -> uid\n\n\
4599
Return the current process's user id.");
4600

Barry Warsaw's avatar
Barry Warsaw committed
4601
static PyObject *
4602
posix_getuid(PyObject *self, PyObject *noargs)
4603
{
4604
    return PyLong_FromLong((long)getuid());
4605
}
Guido van Rossum's avatar
Guido van Rossum committed
4606
#endif
4607

4608

Guido van Rossum's avatar
Guido van Rossum committed
4609
#ifdef HAVE_KILL
4610
PyDoc_STRVAR(posix_kill__doc__,
Fred Drake's avatar
Fred Drake committed
4611
"kill(pid, sig)\n\n\
4612
Kill a process with a signal.");
4613

Barry Warsaw's avatar
Barry Warsaw committed
4614
static PyObject *
4615
posix_kill(PyObject *self, PyObject *args)
4616
{
4617 4618 4619 4620
    pid_t pid;
    int sig;
    if (!PyArg_ParseTuple(args, _Py_PARSE_PID "i:kill", &pid, &sig))
        return NULL;
4621
#if defined(PYOS_OS2) && !defined(PYCC_GCC)
Guido van Rossum's avatar
Guido van Rossum committed
4622 4623 4624
    if (sig == XCPT_SIGNAL_INTR || sig == XCPT_SIGNAL_BREAK) {
        APIRET rc;
        if ((rc = DosSendSignalException(pid, sig)) != NO_ERROR)
4625
            return os2_error(rc);
Guido van Rossum's avatar
Guido van Rossum committed
4626 4627 4628 4629

    } else if (sig == XCPT_SIGNAL_KILLPROC) {
        APIRET rc;
        if ((rc = DosKillProcess(DKP_PROCESS, pid)) != NO_ERROR)
4630
            return os2_error(rc);
Guido van Rossum's avatar
Guido van Rossum committed
4631 4632

    } else
4633
        return NULL; /* Unrecognized Signal Requested */
Guido van Rossum's avatar
Guido van Rossum committed
4634
#else
4635 4636
    if (kill(pid, sig) == -1)
        return posix_error();
Guido van Rossum's avatar
Guido van Rossum committed
4637
#endif
4638 4639
    Py_INCREF(Py_None);
    return Py_None;
4640
}
Guido van Rossum's avatar
Guido van Rossum committed
4641
#endif
4642

4643
#ifdef HAVE_KILLPG
4644
PyDoc_STRVAR(posix_killpg__doc__,
Fred Drake's avatar
Fred Drake committed
4645
"killpg(pgid, sig)\n\n\
4646
Kill a process group with a signal.");
4647 4648 4649 4650

static PyObject *
posix_killpg(PyObject *self, PyObject *args)
{
4651 4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662
    int sig;
    pid_t pgid;
    /* XXX some man pages make the `pgid` parameter an int, others
       a pid_t. Since getpgrp() returns a pid_t, we assume killpg should
       take the same type. Moreover, pid_t is always at least as wide as
       int (else compilation of this module fails), which is safe. */
    if (!PyArg_ParseTuple(args, _Py_PARSE_PID "i:killpg", &pgid, &sig))
        return NULL;
    if (killpg(pgid, sig) == -1)
        return posix_error();
    Py_INCREF(Py_None);
    return Py_None;
4663 4664 4665
}
#endif

4666 4667 4668 4669 4670 4671 4672 4673
#ifdef MS_WINDOWS
PyDoc_STRVAR(win32_kill__doc__,
"kill(pid, sig)\n\n\
Kill a process with a signal.");

static PyObject *
win32_kill(PyObject *self, PyObject *args)
{
4674
    PyObject *result;
4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690 4691 4692 4693 4694 4695 4696 4697 4698 4699 4700 4701 4702 4703 4704 4705 4706 4707 4708 4709
    DWORD pid, sig, err;
    HANDLE handle;

    if (!PyArg_ParseTuple(args, "kk:kill", &pid, &sig))
        return NULL;

    /* Console processes which share a common console can be sent CTRL+C or
       CTRL+BREAK events, provided they handle said events. */
    if (sig == CTRL_C_EVENT || sig == CTRL_BREAK_EVENT) {
        if (GenerateConsoleCtrlEvent(sig, pid) == 0) {
            err = GetLastError();
            PyErr_SetFromWindowsErr(err);
        }
        else
            Py_RETURN_NONE;
    }

    /* If the signal is outside of what GenerateConsoleCtrlEvent can use,
       attempt to open and terminate the process. */
    handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
    if (handle == NULL) {
        err = GetLastError();
        return PyErr_SetFromWindowsErr(err);
    }

    if (TerminateProcess(handle, sig) == 0) {
        err = GetLastError();
        result = PyErr_SetFromWindowsErr(err);
    } else {
        Py_INCREF(Py_None);
        result = Py_None;
    }

    CloseHandle(handle);
    return result;
4710 4711 4712
}
#endif /* MS_WINDOWS */

4713 4714 4715 4716 4717 4718
#ifdef HAVE_PLOCK

#ifdef HAVE_SYS_LOCK_H
#include <sys/lock.h>
#endif

4719
PyDoc_STRVAR(posix_plock__doc__,
Fred Drake's avatar
Fred Drake committed
4720
"plock(op)\n\n\
4721
Lock program segments into memory.");
4722

Barry Warsaw's avatar
Barry Warsaw committed
4723
static PyObject *
4724
posix_plock(PyObject *self, PyObject *args)
4725
{
4726 4727 4728 4729 4730 4731 4732
    int op;
    if (!PyArg_ParseTuple(args, "i:plock", &op))
        return NULL;
    if (plock(op) == -1)
        return posix_error();
    Py_INCREF(Py_None);
    return Py_None;
4733 4734 4735
}
#endif

4736
#ifdef HAVE_SETUID
4737
PyDoc_STRVAR(posix_setuid__doc__,
Fred Drake's avatar
Fred Drake committed
4738
"setuid(uid)\n\n\
4739 4740
Set the current process's user id.");

Barry Warsaw's avatar
Barry Warsaw committed
4741
static PyObject *
4742
posix_setuid(PyObject *self, PyObject *args)
4743
{
4744 4745 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756
    long uid_arg;
    uid_t uid;
    if (!PyArg_ParseTuple(args, "l:setuid", &uid_arg))
        return NULL;
    uid = uid_arg;
    if (uid != uid_arg) {
        PyErr_SetString(PyExc_OverflowError, "user id too big");
        return NULL;
    }
    if (setuid(uid) < 0)
        return posix_error();
    Py_INCREF(Py_None);
    return Py_None;
4757
}
4758
#endif /* HAVE_SETUID */
4759

4760

4761
#ifdef HAVE_SETEUID
4762
PyDoc_STRVAR(posix_seteuid__doc__,
Fred Drake's avatar
Fred Drake committed
4763
"seteuid(uid)\n\n\
4764 4765
Set the current process's effective user id.");

4766 4767 4768
static PyObject *
posix_seteuid (PyObject *self, PyObject *args)
{
4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 4780 4781 4782 4783
    long euid_arg;
    uid_t euid;
    if (!PyArg_ParseTuple(args, "l", &euid_arg))
        return NULL;
    euid = euid_arg;
    if (euid != euid_arg) {
        PyErr_SetString(PyExc_OverflowError, "user id too big");
        return NULL;
    }
    if (seteuid(euid) < 0) {
        return posix_error();
    } else {
        Py_INCREF(Py_None);
        return Py_None;
    }
4784 4785 4786 4787
}
#endif /* HAVE_SETEUID */

#ifdef HAVE_SETEGID
4788
PyDoc_STRVAR(posix_setegid__doc__,
Fred Drake's avatar
Fred Drake committed
4789
"setegid(gid)\n\n\
4790 4791
Set the current process's effective group id.");

4792 4793 4794
static PyObject *
posix_setegid (PyObject *self, PyObject *args)
{
4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809
    long egid_arg;
    gid_t egid;
    if (!PyArg_ParseTuple(args, "l", &egid_arg))
        return NULL;
    egid = egid_arg;
    if (egid != egid_arg) {
        PyErr_SetString(PyExc_OverflowError, "group id too big");
        return NULL;
    }
    if (setegid(egid) < 0) {
        return posix_error();
    } else {
        Py_INCREF(Py_None);
        return Py_None;
    }
4810 4811 4812 4813
}
#endif /* HAVE_SETEGID */

#ifdef HAVE_SETREUID
4814
PyDoc_STRVAR(posix_setreuid__doc__,
4815
"setreuid(ruid, euid)\n\n\
4816 4817
Set the current process's real and effective user ids.");

4818 4819 4820
static PyObject *
posix_setreuid (PyObject *self, PyObject *args)
{
4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836 4837 4838 4839 4840 4841 4842 4843
    long ruid_arg, euid_arg;
    uid_t ruid, euid;
    if (!PyArg_ParseTuple(args, "ll", &ruid_arg, &euid_arg))
        return NULL;
    if (ruid_arg == -1)
        ruid = (uid_t)-1;  /* let the compiler choose how -1 fits */
    else
        ruid = ruid_arg;  /* otherwise, assign from our long */
    if (euid_arg == -1)
        euid = (uid_t)-1;
    else
        euid = euid_arg;
    if ((euid_arg != -1 && euid != euid_arg) ||
        (ruid_arg != -1 && ruid != ruid_arg)) {
        PyErr_SetString(PyExc_OverflowError, "user id too big");
        return NULL;
    }
    if (setreuid(ruid, euid) < 0) {
        return posix_error();
    } else {
        Py_INCREF(Py_None);
        return Py_None;
    }
4844 4845 4846 4847
}
#endif /* HAVE_SETREUID */

#ifdef HAVE_SETREGID
4848
PyDoc_STRVAR(posix_setregid__doc__,
4849
"setregid(rgid, egid)\n\n\
4850 4851
Set the current process's real and effective group ids.");

4852 4853 4854
static PyObject *
posix_setregid (PyObject *self, PyObject *args)
{
4855 4856 4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 4867 4868 4869 4870 4871 4872 4873 4874 4875 4876 4877
    long rgid_arg, egid_arg;
    gid_t rgid, egid;
    if (!PyArg_ParseTuple(args, "ll", &rgid_arg, &egid_arg))
        return NULL;
    if (rgid_arg == -1)
        rgid = (gid_t)-1;  /* let the compiler choose how -1 fits */
    else
        rgid = rgid_arg;  /* otherwise, assign from our long */
    if (egid_arg == -1)
        egid = (gid_t)-1;
    else
        egid = egid_arg;
    if ((egid_arg != -1 && egid != egid_arg) ||
        (rgid_arg != -1 && rgid != rgid_arg)) {
        PyErr_SetString(PyExc_OverflowError, "group id too big");
        return NULL;
    }
    if (setregid(rgid, egid) < 0) {
        return posix_error();
    } else {
        Py_INCREF(Py_None);
        return Py_None;
    }
4878 4879 4880
}
#endif /* HAVE_SETREGID */

4881
#ifdef HAVE_SETGID
4882
PyDoc_STRVAR(posix_setgid__doc__,
Fred Drake's avatar
Fred Drake committed
4883
"setgid(gid)\n\n\
4884
Set the current process's group id.");
4885

Barry Warsaw's avatar
Barry Warsaw committed
4886
static PyObject *
4887
posix_setgid(PyObject *self, PyObject *args)
4888
{
4889 4890 4891 4892 4893 4894 4895 4896 4897 4898 4899 4900 4901
    long gid_arg;
    gid_t gid;
    if (!PyArg_ParseTuple(args, "l:setgid", &gid_arg))
        return NULL;
    gid = gid_arg;
    if (gid != gid_arg) {
        PyErr_SetString(PyExc_OverflowError, "group id too big");
        return NULL;
    }
    if (setgid(gid) < 0)
        return posix_error();
    Py_INCREF(Py_None);
    return Py_None;
4902
}
4903
#endif /* HAVE_SETGID */
4904

4905
#ifdef HAVE_SETGROUPS
4906
PyDoc_STRVAR(posix_setgroups__doc__,
Fred Drake's avatar
Fred Drake committed
4907
"setgroups(list)\n\n\
4908
Set the groups of the current process to list.");
4909 4910

static PyObject *
4911
posix_setgroups(PyObject *self, PyObject *groups)
4912
{
4913 4914 4915 4916 4917 4918 4919 4920 4921 4922 4923 4924 4925 4926 4927 4928 4929 4930 4931 4932 4933 4934 4935 4936 4937 4938 4939 4940 4941 4942 4943 4944 4945 4946 4947 4948 4949 4950 4951 4952 4953 4954 4955 4956 4957 4958
    int i, len;
    gid_t grouplist[MAX_GROUPS];

    if (!PySequence_Check(groups)) {
        PyErr_SetString(PyExc_TypeError, "setgroups argument must be a sequence");
        return NULL;
    }
    len = PySequence_Size(groups);
    if (len > MAX_GROUPS) {
        PyErr_SetString(PyExc_ValueError, "too many groups");
        return NULL;
    }
    for(i = 0; i < len; i++) {
        PyObject *elem;
        elem = PySequence_GetItem(groups, i);
        if (!elem)
            return NULL;
        if (!PyLong_Check(elem)) {
            PyErr_SetString(PyExc_TypeError,
                            "groups must be integers");
            Py_DECREF(elem);
            return NULL;
        } else {
            unsigned long x = PyLong_AsUnsignedLong(elem);
            if (PyErr_Occurred()) {
                PyErr_SetString(PyExc_TypeError,
                                "group id too big");
                Py_DECREF(elem);
                return NULL;
            }
            grouplist[i] = x;
            /* read back the value to see if it fitted in gid_t */
            if (grouplist[i] != x) {
                PyErr_SetString(PyExc_TypeError,
                                "group id too big");
                Py_DECREF(elem);
                return NULL;
            }
        }
        Py_DECREF(elem);
    }

    if (setgroups(len, grouplist) < 0)
        return posix_error();
    Py_INCREF(Py_None);
    return Py_None;
4959 4960
}
#endif /* HAVE_SETGROUPS */
4961

4962 4963
#if defined(HAVE_WAIT3) || defined(HAVE_WAIT4)
static PyObject *
Christian Heimes's avatar
Christian Heimes committed
4964
wait_helper(pid_t pid, int status, struct rusage *ru)
4965
{
4966 4967
    PyObject *result;
    static PyObject *struct_rusage;
4968

4969 4970
    if (pid == -1)
        return posix_error();
4971

4972 4973 4974 4975 4976 4977 4978 4979 4980
    if (struct_rusage == NULL) {
        PyObject *m = PyImport_ImportModuleNoBlock("resource");
        if (m == NULL)
            return NULL;
        struct_rusage = PyObject_GetAttrString(m, "struct_rusage");
        Py_DECREF(m);
        if (struct_rusage == NULL)
            return NULL;
    }
4981

4982 4983 4984 4985
    /* XXX(nnorwitz): Copied (w/mods) from resource.c, there should be only one. */
    result = PyStructSequence_New((PyTypeObject*) struct_rusage);
    if (!result)
        return NULL;
4986 4987 4988 4989 4990

#ifndef doubletime
#define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001)
#endif

4991 4992 4993 4994
    PyStructSequence_SET_ITEM(result, 0,
                              PyFloat_FromDouble(doubletime(ru->ru_utime)));
    PyStructSequence_SET_ITEM(result, 1,
                              PyFloat_FromDouble(doubletime(ru->ru_stime)));
4995
#define SET_INT(result, index, value)\
4996 4997 4998 4999 5000 5001 5002 5003 5004 5005 5006 5007 5008 5009 5010
        PyStructSequence_SET_ITEM(result, index, PyLong_FromLong(value))
    SET_INT(result, 2, ru->ru_maxrss);
    SET_INT(result, 3, ru->ru_ixrss);
    SET_INT(result, 4, ru->ru_idrss);
    SET_INT(result, 5, ru->ru_isrss);
    SET_INT(result, 6, ru->ru_minflt);
    SET_INT(result, 7, ru->ru_majflt);
    SET_INT(result, 8, ru->ru_nswap);
    SET_INT(result, 9, ru->ru_inblock);
    SET_INT(result, 10, ru->ru_oublock);
    SET_INT(result, 11, ru->ru_msgsnd);
    SET_INT(result, 12, ru->ru_msgrcv);
    SET_INT(result, 13, ru->ru_nsignals);
    SET_INT(result, 14, ru->ru_nvcsw);
    SET_INT(result, 15, ru->ru_nivcsw);
5011 5012
#undef SET_INT

5013 5014 5015 5016
    if (PyErr_Occurred()) {
        Py_DECREF(result);
        return NULL;
    }
5017

5018
    return Py_BuildValue("NiN", PyLong_FromPid(pid), status, result);
5019 5020 5021 5022 5023 5024 5025 5026 5027 5028 5029
}
#endif /* HAVE_WAIT3 || HAVE_WAIT4 */

#ifdef HAVE_WAIT3
PyDoc_STRVAR(posix_wait3__doc__,
"wait3(options) -> (pid, status, rusage)\n\n\
Wait for completion of a child process.");

static PyObject *
posix_wait3(PyObject *self, PyObject *args)
{
5030 5031 5032 5033 5034
    pid_t pid;
    int options;
    struct rusage ru;
    WAIT_TYPE status;
    WAIT_STATUS_INT(status) = 0;
5035

5036 5037
    if (!PyArg_ParseTuple(args, "i:wait3", &options))
        return NULL;
5038

5039 5040 5041
    Py_BEGIN_ALLOW_THREADS
    pid = wait3(&status, options, &ru);
    Py_END_ALLOW_THREADS
5042

5043
    return wait_helper(pid, WAIT_STATUS_INT(status), &ru);
5044 5045 5046 5047 5048 5049 5050 5051 5052 5053 5054
}
#endif /* HAVE_WAIT3 */

#ifdef HAVE_WAIT4
PyDoc_STRVAR(posix_wait4__doc__,
"wait4(pid, options) -> (pid, status, rusage)\n\n\
Wait for completion of a given child process.");

static PyObject *
posix_wait4(PyObject *self, PyObject *args)
{
5055 5056 5057 5058 5059
    pid_t pid;
    int options;
    struct rusage ru;
    WAIT_TYPE status;
    WAIT_STATUS_INT(status) = 0;
5060

5061 5062
    if (!PyArg_ParseTuple(args, _Py_PARSE_PID "i:wait4", &pid, &options))
        return NULL;
5063

5064 5065 5066
    Py_BEGIN_ALLOW_THREADS
    pid = wait4(pid, &status, options, &ru);
    Py_END_ALLOW_THREADS
5067

5068
    return wait_helper(pid, WAIT_STATUS_INT(status), &ru);
5069 5070 5071
}
#endif /* HAVE_WAIT4 */

5072
#ifdef HAVE_WAITPID
5073
PyDoc_STRVAR(posix_waitpid__doc__,
Fred Drake's avatar
Fred Drake committed
5074
"waitpid(pid, options) -> (pid, status)\n\n\
5075
Wait for completion of a given child process.");
5076

Barry Warsaw's avatar
Barry Warsaw committed
5077
static PyObject *
5078
posix_waitpid(PyObject *self, PyObject *args)
5079
{
5080 5081 5082 5083
    pid_t pid;
    int options;
    WAIT_TYPE status;
    WAIT_STATUS_INT(status) = 0;
5084

5085 5086 5087 5088 5089 5090 5091
    if (!PyArg_ParseTuple(args, _Py_PARSE_PID "i:waitpid", &pid, &options))
        return NULL;
    Py_BEGIN_ALLOW_THREADS
    pid = waitpid(pid, &status, options);
    Py_END_ALLOW_THREADS
    if (pid == -1)
        return posix_error();
5092

5093
    return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
5094 5095
}

5096 5097 5098
#elif defined(HAVE_CWAIT)

/* MS C has a variant of waitpid() that's usable for most purposes. */
5099
PyDoc_STRVAR(posix_waitpid__doc__,
Fred Drake's avatar
Fred Drake committed
5100
"waitpid(pid, options) -> (pid, status << 8)\n\n"
5101
"Wait for completion of a given process.  options is ignored on Windows.");
5102 5103 5104 5105

static PyObject *
posix_waitpid(PyObject *self, PyObject *args)
{
5106 5107
    Py_intptr_t pid;
    int status, options;
5108

5109 5110 5111 5112 5113 5114 5115
    if (!PyArg_ParseTuple(args, _Py_PARSE_PID "i:waitpid", &pid, &options))
        return NULL;
    Py_BEGIN_ALLOW_THREADS
    pid = _cwait(&status, pid, options);
    Py_END_ALLOW_THREADS
    if (pid == -1)
        return posix_error();
5116

5117 5118
    /* shift the status left a byte so this is more like the POSIX waitpid */
    return Py_BuildValue("Ni", PyLong_FromPid(pid), status << 8);
5119 5120
}
#endif /* HAVE_WAITPID || HAVE_CWAIT */
5121

Guido van Rossum's avatar
Guido van Rossum committed
5122
#ifdef HAVE_WAIT
5123
PyDoc_STRVAR(posix_wait__doc__,
Fred Drake's avatar
Fred Drake committed
5124
"wait() -> (pid, status)\n\n\
5125
Wait for completion of a child process.");
5126

Barry Warsaw's avatar
Barry Warsaw committed
5127
static PyObject *
5128
posix_wait(PyObject *self, PyObject *noargs)
5129
{
5130 5131 5132
    pid_t pid;
    WAIT_TYPE status;
    WAIT_STATUS_INT(status) = 0;
5133

5134 5135 5136 5137 5138
    Py_BEGIN_ALLOW_THREADS
    pid = wait(&status);
    Py_END_ALLOW_THREADS
    if (pid == -1)
        return posix_error();
5139

5140
    return Py_BuildValue("Ni", PyLong_FromPid(pid), WAIT_STATUS_INT(status));
5141
}
Guido van Rossum's avatar
Guido van Rossum committed
5142
#endif
5143

5144

5145
PyDoc_STRVAR(posix_lstat__doc__,
Fred Drake's avatar
Fred Drake committed
5146
"lstat(path) -> stat result\n\n\
5147
Like stat(path), but do not follow symbolic links.");
5148

Barry Warsaw's avatar
Barry Warsaw committed
5149
static PyObject *
5150
posix_lstat(PyObject *self, PyObject *args)
Guido van Rossum's avatar
Guido van Rossum committed
5151
{
5152
#ifdef HAVE_LSTAT
5153
    return posix_do_stat(self, args, "O&:lstat", lstat, NULL, NULL);
5154
#else /* !HAVE_LSTAT */
5155
#ifdef MS_WINDOWS
5156
    return posix_do_stat(self, args, "O&:lstat", win32_lstat, "U:lstat",
5157
                         win32_lstat_w);
5158
#else
5159
    return posix_do_stat(self, args, "O&:lstat", STAT, NULL, NULL);
5160
#endif
5161
#endif /* !HAVE_LSTAT */
Guido van Rossum's avatar
Guido van Rossum committed
5162 5163
}

5164

5165
#ifdef HAVE_READLINK
5166
PyDoc_STRVAR(posix_readlink__doc__,
Fred Drake's avatar
Fred Drake committed
5167
"readlink(path) -> path\n\n\
5168
Return a string representing the path to which the symbolic link points.");
5169

Barry Warsaw's avatar
Barry Warsaw committed
5170
static PyObject *
5171
posix_readlink(PyObject *self, PyObject *args)
Guido van Rossum's avatar
Guido van Rossum committed
5172
{
5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 5189 5190 5191 5192 5193 5194 5195 5196 5197 5198 5199 5200 5201
    PyObject* v;
    char buf[MAXPATHLEN];
    PyObject *opath;
    char *path;
    int n;
    int arg_is_unicode = 0;

    if (!PyArg_ParseTuple(args, "O&:readlink",
                          PyUnicode_FSConverter, &opath))
        return NULL;
    path = PyBytes_AsString(opath);
    v = PySequence_GetItem(args, 0);
    if (v == NULL) {
        Py_DECREF(opath);
        return NULL;
    }

    if (PyUnicode_Check(v)) {
        arg_is_unicode = 1;
    }
    Py_DECREF(v);

    Py_BEGIN_ALLOW_THREADS
    n = readlink(path, buf, (int) sizeof buf);
    Py_END_ALLOW_THREADS
    if (n < 0)
        return posix_error_with_allocated_filename(opath);

    Py_DECREF(opath);
5202 5203 5204 5205
    if (arg_is_unicode)
        return PyUnicode_DecodeFSDefaultAndSize(buf, n);
    else
        return PyBytes_FromStringAndSize(buf, n);
Guido van Rossum's avatar
Guido van Rossum committed
5206
}
5207
#endif /* HAVE_READLINK */
Guido van Rossum's avatar
Guido van Rossum committed
5208

5209

5210
#if defined(HAVE_SYMLINK) && !defined(MS_WINDOWS)
5211
PyDoc_STRVAR(posix_symlink__doc__,
Fred Drake's avatar
Fred Drake committed
5212
"symlink(src, dst)\n\n\
5213
Create a symbolic link pointing to src named dst.");
5214

5215
static PyObject *
5216
posix_symlink(PyObject *self, PyObject *args)
5217
{
5218
    return posix_2str(args, "O&O&:symlink", symlink);
5219 5220 5221
}
#endif /* HAVE_SYMLINK */

5222 5223 5224 5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243 5244 5245 5246 5247 5248 5249 5250 5251 5252 5253 5254 5255 5256 5257
#if !defined(HAVE_READLINK) && defined(MS_WINDOWS)

PyDoc_STRVAR(win_readlink__doc__,
"readlink(path) -> path\n\n\
Return a string representing the path to which the symbolic link points.");

/* Windows readlink implementation */
static PyObject *
win_readlink(PyObject *self, PyObject *args)
{
    wchar_t *path;
    DWORD n_bytes_returned;
    DWORD io_result;
    PyObject *result;
    HANDLE reparse_point_handle;

    char target_buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
    REPARSE_DATA_BUFFER *rdb = (REPARSE_DATA_BUFFER *)target_buffer;
    wchar_t *print_name;

    if (!PyArg_ParseTuple(args,
                  "u:readlink",
                  &path))
        return NULL;

    /* First get a handle to the reparse point */
    Py_BEGIN_ALLOW_THREADS
    reparse_point_handle = CreateFileW(
        path,
        0,
        0,
        0,
        OPEN_EXISTING,
        FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS,
        0);
    Py_END_ALLOW_THREADS
5258

5259 5260 5261 5262
    if (reparse_point_handle==INVALID_HANDLE_VALUE)
    {
        return win32_error_unicode("readlink", path);
    }
5263

5264 5265 5266 5267 5268 5269 5270 5271 5272 5273 5274 5275 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286 5287
    Py_BEGIN_ALLOW_THREADS
    /* New call DeviceIoControl to read the reparse point */
    io_result = DeviceIoControl(
        reparse_point_handle,
        FSCTL_GET_REPARSE_POINT,
        0, 0, /* in buffer */
        target_buffer, sizeof(target_buffer),
        &n_bytes_returned,
        0 /* we're not using OVERLAPPED_IO */
        );
    CloseHandle(reparse_point_handle);
    Py_END_ALLOW_THREADS

    if (io_result==0)
    {
        return win32_error_unicode("readlink", path);
    }

    if (rdb->ReparseTag != IO_REPARSE_TAG_SYMLINK)
    {
        PyErr_SetString(PyExc_ValueError,
                "not a symbolic link");
        return NULL;
    }
5288 5289 5290 5291 5292
    print_name = rdb->SymbolicLinkReparseBuffer.PathBuffer +
                 rdb->SymbolicLinkReparseBuffer.PrintNameOffset;

    result = PyUnicode_FromWideChar(print_name,
                    rdb->SymbolicLinkReparseBuffer.PrintNameLength/2);
5293 5294 5295 5296 5297
    return result;
}

#endif /* !defined(HAVE_READLINK) && defined(MS_WINDOWS) */

5298
#if defined(HAVE_SYMLINK) && defined(MS_WINDOWS)
5299 5300 5301 5302 5303 5304 5305 5306 5307 5308 5309 5310

/* Grab CreateSymbolicLinkW dynamically from kernel32 */
static int has_CreateSymbolicLinkW = 0;
static DWORD (CALLBACK *Py_CreateSymbolicLinkW)(LPWSTR, LPWSTR, DWORD);
static int
check_CreateSymbolicLinkW()
{
    HINSTANCE hKernel32;
    /* only recheck */
    if (has_CreateSymbolicLinkW)
        return has_CreateSymbolicLinkW;
    hKernel32 = GetModuleHandle("KERNEL32");
5311 5312
    *(FARPROC*)&Py_CreateSymbolicLinkW = GetProcAddress(hKernel32,
                                                        "CreateSymbolicLinkW");
5313 5314 5315 5316 5317 5318 5319 5320 5321 5322 5323 5324 5325 5326 5327 5328 5329 5330 5331 5332 5333
    if (Py_CreateSymbolicLinkW)
        has_CreateSymbolicLinkW = 1;
    return has_CreateSymbolicLinkW;
}

PyDoc_STRVAR(win_symlink__doc__,
"symlink(src, dst, target_is_directory=False)\n\n\
Create a symbolic link pointing to src named dst.\n\
target_is_directory is required if the target is to be interpreted as\n\
a directory.\n\
This function requires Windows 6.0 or greater, and raises a\n\
NotImplementedError otherwise.");

static PyObject *
win_symlink(PyObject *self, PyObject *args, PyObject *kwargs)
{
    static char *kwlist[] = {"src", "dest", "target_is_directory", NULL};
    PyObject *src, *dest;
    int target_is_directory = 0;
    DWORD res;
    WIN32_FILE_ATTRIBUTE_DATA src_info;
5334

5335 5336 5337 5338 5339 5340 5341 5342 5343
    if (!check_CreateSymbolicLinkW())
    {
        /* raise NotImplementedError */
        return PyErr_Format(PyExc_NotImplementedError,
            "CreateSymbolicLinkW not found");
    }
    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|i:symlink",
        kwlist, &src, &dest, &target_is_directory))
        return NULL;
5344 5345 5346 5347

    if (win32_can_symlink == 0)
        return PyErr_Format(PyExc_OSError, "symbolic link privilege not held");

5348 5349 5350 5351 5352
    if (!convert_to_unicode(&src)) { return NULL; }
    if (!convert_to_unicode(&dest)) {
        Py_DECREF(src);
        return NULL;
    }
5353

5354 5355 5356 5357 5358 5359 5360 5361 5362 5363 5364 5365 5366 5367 5368 5369 5370 5371 5372 5373 5374 5375
    /* if src is a directory, ensure target_is_directory==1 */
    if(
        GetFileAttributesExW(
            PyUnicode_AsUnicode(src), GetFileExInfoStandard, &src_info
        ))
    {
        target_is_directory = target_is_directory ||
            (src_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
    }

    Py_BEGIN_ALLOW_THREADS
    res = Py_CreateSymbolicLinkW(
        PyUnicode_AsUnicode(dest),
        PyUnicode_AsUnicode(src),
        target_is_directory);
    Py_END_ALLOW_THREADS
    Py_DECREF(src);
    Py_DECREF(dest);
    if (!res)
    {
        return win32_error_unicode("symlink", PyUnicode_AsUnicode(src));
    }
5376

5377 5378 5379
    Py_INCREF(Py_None);
    return Py_None;
}
5380
#endif /* defined(HAVE_SYMLINK) && defined(MS_WINDOWS) */
5381 5382

#ifdef HAVE_TIMES
5383 5384
#if defined(PYCC_VACPP) && defined(PYOS_OS2)
static long
5385
system_uptime(void)
5386 5387 5388 5389 5390 5391 5392 5393 5394 5395 5396
{
    ULONG     value = 0;

    Py_BEGIN_ALLOW_THREADS
    DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT, &value, sizeof(value));
    Py_END_ALLOW_THREADS

    return value;
}

static PyObject *
5397
posix_times(PyObject *self, PyObject *noargs)
5398 5399
{
    /* Currently Only Uptime is Provided -- Others Later */
5400 5401 5402 5403 5404 5405
    return Py_BuildValue("ddddd",
                         (double)0 /* t.tms_utime / HZ */,
                         (double)0 /* t.tms_stime / HZ */,
                         (double)0 /* t.tms_cutime / HZ */,
                         (double)0 /* t.tms_cstime / HZ */,
                         (double)system_uptime() / 1000);
5406
}
5407
#else /* not OS2 */
5408 5409
#define NEED_TICKS_PER_SECOND
static long ticks_per_second = -1;
Barry Warsaw's avatar
Barry Warsaw committed
5410
static PyObject *
5411
posix_times(PyObject *self, PyObject *noargs)
Guido van Rossum's avatar
Guido van Rossum committed
5412
{
5413 5414 5415 5416 5417 5418 5419 5420 5421 5422 5423 5424
    struct tms t;
    clock_t c;
    errno = 0;
    c = times(&t);
    if (c == (clock_t) -1)
        return posix_error();
    return Py_BuildValue("ddddd",
                         (double)t.tms_utime / ticks_per_second,
                         (double)t.tms_stime / ticks_per_second,
                         (double)t.tms_cutime / ticks_per_second,
                         (double)t.tms_cstime / ticks_per_second,
                         (double)c / ticks_per_second);
Guido van Rossum's avatar
Guido van Rossum committed
5425
}
5426
#endif /* not OS2 */
5427
#endif /* HAVE_TIMES */
5428 5429


5430
#ifdef MS_WINDOWS
5431
#define HAVE_TIMES      /* so the method table will pick it up */
Barry Warsaw's avatar
Barry Warsaw committed
5432
static PyObject *
5433
posix_times(PyObject *self, PyObject *noargs)
5434
{
5435 5436 5437 5438 5439 5440 5441 5442 5443 5444 5445 5446 5447 5448 5449 5450 5451 5452
    FILETIME create, exit, kernel, user;
    HANDLE hProc;
    hProc = GetCurrentProcess();
    GetProcessTimes(hProc, &create, &exit, &kernel, &user);
    /* The fields of a FILETIME structure are the hi and lo part
       of a 64-bit value expressed in 100 nanosecond units.
       1e7 is one second in such units; 1e-7 the inverse.
       429.4967296 is 2**32 / 1e7 or 2**32 * 1e-7.
    */
    return Py_BuildValue(
        "ddddd",
        (double)(user.dwHighDateTime*429.4967296 +
                 user.dwLowDateTime*1e-7),
        (double)(kernel.dwHighDateTime*429.4967296 +
                 kernel.dwLowDateTime*1e-7),
        (double)0,
        (double)0,
        (double)0);
5453
}
5454
#endif /* MS_WINDOWS */
5455 5456

#ifdef HAVE_TIMES
5457
PyDoc_STRVAR(posix_times__doc__,
Fred Drake's avatar
Fred Drake committed
5458
"times() -> (utime, stime, cutime, cstime, elapsed_time)\n\n\
5459
Return a tuple of floating point numbers indicating process times.");
5460
#endif
Guido van Rossum's avatar
Guido van Rossum committed
5461

5462

5463 5464 5465 5466 5467 5468 5469 5470
#ifdef HAVE_GETSID
PyDoc_STRVAR(posix_getsid__doc__,
"getsid(pid) -> sid\n\n\
Call the system call getsid().");

static PyObject *
posix_getsid(PyObject *self, PyObject *args)
{
5471 5472 5473 5474 5475 5476 5477 5478
    pid_t pid;
    int sid;
    if (!PyArg_ParseTuple(args, _Py_PARSE_PID ":getsid", &pid))
        return NULL;
    sid = getsid(pid);
    if (sid < 0)
        return posix_error();
    return PyLong_FromLong((long)sid);
5479 5480 5481 5482
}
#endif /* HAVE_GETSID */


5483
#ifdef HAVE_SETSID
5484
PyDoc_STRVAR(posix_setsid__doc__,
Fred Drake's avatar
Fred Drake committed
5485
"setsid()\n\n\
5486
Call the system call setsid().");
5487

Barry Warsaw's avatar
Barry Warsaw committed
5488
static PyObject *
5489
posix_setsid(PyObject *self, PyObject *noargs)
5490
{
5491 5492 5493 5494
    if (setsid() < 0)
        return posix_error();
    Py_INCREF(Py_None);
    return Py_None;
5495
}
5496
#endif /* HAVE_SETSID */
5497

5498
#ifdef HAVE_SETPGID
5499
PyDoc_STRVAR(posix_setpgid__doc__,
Fred Drake's avatar
Fred Drake committed
5500
"setpgid(pid, pgrp)\n\n\
5501
Call the system call setpgid().");
5502

Barry Warsaw's avatar
Barry Warsaw committed
5503
static PyObject *
5504
posix_setpgid(PyObject *self, PyObject *args)
5505
{
5506 5507 5508 5509 5510 5511 5512 5513
    pid_t pid;
    int pgrp;
    if (!PyArg_ParseTuple(args, _Py_PARSE_PID "i:setpgid", &pid, &pgrp))
        return NULL;
    if (setpgid(pid, pgrp) < 0)
        return posix_error();
    Py_INCREF(Py_None);
    return Py_None;
5514
}
5515
#endif /* HAVE_SETPGID */
5516

5517

5518
#ifdef HAVE_TCGETPGRP
5519
PyDoc_STRVAR(posix_tcgetpgrp__doc__,
Fred Drake's avatar
Fred Drake committed
5520
"tcgetpgrp(fd) -> pgid\n\n\
5521
Return the process group associated with the terminal given by a fd.");
5522

Barry Warsaw's avatar
Barry Warsaw committed
5523
static PyObject *
5524
posix_tcgetpgrp(PyObject *self, PyObject *args)
5525
{
5526 5527 5528 5529 5530 5531 5532 5533
    int fd;
    pid_t pgid;
    if (!PyArg_ParseTuple(args, "i:tcgetpgrp", &fd))
        return NULL;
    pgid = tcgetpgrp(fd);
    if (pgid < 0)
        return posix_error();
    return PyLong_FromPid(pgid);
5534
}
5535
#endif /* HAVE_TCGETPGRP */
5536

5537

5538
#ifdef HAVE_TCSETPGRP
5539
PyDoc_STRVAR(posix_tcsetpgrp__doc__,
Fred Drake's avatar
Fred Drake committed
5540
"tcsetpgrp(fd, pgid)\n\n\
5541
Set the process group associated with the terminal given by a fd.");
5542

Barry Warsaw's avatar
Barry Warsaw committed
5543
static PyObject *
5544
posix_tcsetpgrp(PyObject *self, PyObject *args)
5545
{
5546 5547 5548 5549 5550 5551 5552 5553
    int fd;
    pid_t pgid;
    if (!PyArg_ParseTuple(args, "i" _Py_PARSE_PID ":tcsetpgrp", &fd, &pgid))
        return NULL;
    if (tcsetpgrp(fd, pgid) < 0)
        return posix_error();
    Py_INCREF(Py_None);
    return Py_None;
5554
}
5555
#endif /* HAVE_TCSETPGRP */
Guido van Rossum's avatar
Guido van Rossum committed
5556

5557 5558
/* Functions acting on file descriptors */

5559
PyDoc_STRVAR(posix_open__doc__,
Fred Drake's avatar
Fred Drake committed
5560
"open(filename, flag [, mode=0777]) -> fd\n\n\
5561
Open a file (for low level IO).");
5562

Barry Warsaw's avatar
Barry Warsaw committed
5563
static PyObject *
5564
posix_open(PyObject *self, PyObject *args)
5565
{
5566 5567 5568 5569 5570
    PyObject *ofile;
    char *file;
    int flag;
    int mode = 0777;
    int fd;
5571 5572

#ifdef MS_WINDOWS
5573
    PyUnicodeObject *po;
5574
    if (PyArg_ParseTuple(args, "Ui|i:open", &po, &flag, &mode)) {
5575 5576 5577 5578 5579 5580 5581 5582 5583 5584 5585 5586 5587 5588
        Py_BEGIN_ALLOW_THREADS
        /* PyUnicode_AS_UNICODE OK without thread
           lock as it is a simple dereference. */
        fd = _wopen(PyUnicode_AS_UNICODE(po), flag, mode);
        Py_END_ALLOW_THREADS
        if (fd < 0)
            return posix_error();
        return PyLong_FromLong((long)fd);
    }
    /* Drop the argument parsing error as narrow strings
       are also valid. */
    PyErr_Clear();
#endif

5589
    if (!PyArg_ParseTuple(args, "O&i|i:open",
5590 5591 5592 5593 5594 5595 5596 5597 5598 5599 5600
                          PyUnicode_FSConverter, &ofile,
                          &flag, &mode))
        return NULL;
    file = PyBytes_AsString(ofile);
    Py_BEGIN_ALLOW_THREADS
    fd = open(file, flag, mode);
    Py_END_ALLOW_THREADS
    if (fd < 0)
        return posix_error_with_allocated_filename(ofile);
    Py_DECREF(ofile);
    return PyLong_FromLong((long)fd);
5601 5602
}

5603

5604
PyDoc_STRVAR(posix_close__doc__,
Fred Drake's avatar
Fred Drake committed
5605
"close(fd)\n\n\
5606
Close a file descriptor (for low level IO).");
5607

Barry Warsaw's avatar
Barry Warsaw committed
5608
static PyObject *
5609
posix_close(PyObject *self, PyObject *args)
5610
{
5611 5612 5613 5614 5615 5616 5617 5618 5619 5620 5621 5622
    int fd, res;
    if (!PyArg_ParseTuple(args, "i:close", &fd))
        return NULL;
    if (!_PyVerify_fd(fd))
        return posix_error();
    Py_BEGIN_ALLOW_THREADS
    res = close(fd);
    Py_END_ALLOW_THREADS
    if (res < 0)
        return posix_error();
    Py_INCREF(Py_None);
    return Py_None;
5623 5624
}

5625

5626
PyDoc_STRVAR(posix_closerange__doc__,
5627 5628 5629 5630 5631 5632
"closerange(fd_low, fd_high)\n\n\
Closes all file descriptors in [fd_low, fd_high), ignoring errors.");

static PyObject *
posix_closerange(PyObject *self, PyObject *args)
{
5633 5634 5635 5636 5637 5638 5639 5640 5641
    int fd_from, fd_to, i;
    if (!PyArg_ParseTuple(args, "ii:closerange", &fd_from, &fd_to))
        return NULL;
    Py_BEGIN_ALLOW_THREADS
    for (i = fd_from; i < fd_to; i++)
        if (_PyVerify_fd(i))
            close(i);
    Py_END_ALLOW_THREADS
    Py_RETURN_NONE;
5642 5643 5644
}


5645
PyDoc_STRVAR(posix_dup__doc__,
Fred Drake's avatar
Fred Drake committed
5646
"dup(fd) -> fd2\n\n\
5647
Return a duplicate of a file descriptor.");
5648

Barry Warsaw's avatar
Barry Warsaw committed
5649
static PyObject *
5650
posix_dup(PyObject *self, PyObject *args)
5651
{
5652 5653 5654 5655 5656 5657 5658 5659 5660 5661 5662
    int fd;
    if (!PyArg_ParseTuple(args, "i:dup", &fd))
        return NULL;
    if (!_PyVerify_fd(fd))
        return posix_error();
    Py_BEGIN_ALLOW_THREADS
    fd = dup(fd);
    Py_END_ALLOW_THREADS
    if (fd < 0)
        return posix_error();
    return PyLong_FromLong((long)fd);
5663 5664
}

5665

5666
PyDoc_STRVAR(posix_dup2__doc__,
5667
"dup2(old_fd, new_fd)\n\n\
5668
Duplicate file descriptor.");
5669

Barry Warsaw's avatar
Barry Warsaw committed
5670
static PyObject *
5671
posix_dup2(PyObject *self, PyObject *args)
5672
{
5673 5674 5675 5676 5677 5678 5679 5680 5681 5682 5683 5684
    int fd, fd2, res;
    if (!PyArg_ParseTuple(args, "ii:dup2", &fd, &fd2))
        return NULL;
    if (!_PyVerify_fd_dup2(fd, fd2))
        return posix_error();
    Py_BEGIN_ALLOW_THREADS
    res = dup2(fd, fd2);
    Py_END_ALLOW_THREADS
    if (res < 0)
        return posix_error();
    Py_INCREF(Py_None);
    return Py_None;
5685 5686
}

5687

5688
PyDoc_STRVAR(posix_lseek__doc__,
Fred Drake's avatar
Fred Drake committed
5689
"lseek(fd, pos, how) -> newpos\n\n\
5690
Set the current position of a file descriptor.");
5691

Barry Warsaw's avatar
Barry Warsaw committed
5692
static PyObject *
5693
posix_lseek(PyObject *self, PyObject *args)
5694
{
5695
    int fd, how;
5696
#if defined(MS_WIN64) || defined(MS_WINDOWS)
5697
    PY_LONG_LONG pos, res;
5698
#else
5699
    off_t pos, res;
5700
#endif
5701 5702 5703
    PyObject *posobj;
    if (!PyArg_ParseTuple(args, "iOi:lseek", &fd, &posobj, &how))
        return NULL;
5704
#ifdef SEEK_SET
5705 5706 5707 5708 5709 5710
    /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
    switch (how) {
    case 0: how = SEEK_SET; break;
    case 1: how = SEEK_CUR; break;
    case 2: how = SEEK_END; break;
    }
5711
#endif /* SEEK_END */
5712 5713

#if !defined(HAVE_LARGEFILE_SUPPORT)
5714
    pos = PyLong_AsLong(posobj);
5715
#else
5716 5717
    pos = PyLong_Check(posobj) ?
        PyLong_AsLongLong(posobj) : PyLong_AsLong(posobj);
5718
#endif
5719 5720
    if (PyErr_Occurred())
        return NULL;
5721

5722 5723 5724
    if (!_PyVerify_fd(fd))
        return posix_error();
    Py_BEGIN_ALLOW_THREADS
5725
#if defined(MS_WIN64) || defined(MS_WINDOWS)
5726
    res = _lseeki64(fd, pos, how);
5727
#else
5728
    res = lseek(fd, pos, how);
5729
#endif
5730 5731 5732
    Py_END_ALLOW_THREADS
    if (res < 0)
        return posix_error();
5733 5734

#if !defined(HAVE_LARGEFILE_SUPPORT)
5735
    return PyLong_FromLong(res);
5736
#else
5737
    return PyLong_FromLongLong(res);
5738
#endif
5739 5740
}

5741

5742
PyDoc_STRVAR(posix_read__doc__,
Fred Drake's avatar
Fred Drake committed
5743
"read(fd, buffersize) -> string\n\n\
5744
Read a file descriptor.");
5745

Barry Warsaw's avatar
Barry Warsaw committed
5746
static PyObject *
5747
posix_read(PyObject *self, PyObject *args)
5748
{
5749 5750 5751 5752 5753 5754 5755 5756 5757 5758 5759 5760
    int fd, size;
    Py_ssize_t n;
    PyObject *buffer;
    if (!PyArg_ParseTuple(args, "ii:read", &fd, &size))
        return NULL;
    if (size < 0) {
        errno = EINVAL;
        return posix_error();
    }
    buffer = PyBytes_FromStringAndSize((char *)NULL, size);
    if (buffer == NULL)
        return NULL;
Stefan Krah's avatar
Stefan Krah committed
5761 5762
    if (!_PyVerify_fd(fd)) {
        Py_DECREF(buffer);
5763
        return posix_error();
Stefan Krah's avatar
Stefan Krah committed
5764
    }
5765 5766 5767 5768 5769 5770 5771 5772 5773 5774
    Py_BEGIN_ALLOW_THREADS
    n = read(fd, PyBytes_AS_STRING(buffer), size);
    Py_END_ALLOW_THREADS
    if (n < 0) {
        Py_DECREF(buffer);
        return posix_error();
    }
    if (n != size)
        _PyBytes_Resize(&buffer, n);
    return buffer;
5775 5776
}

5777

5778
PyDoc_STRVAR(posix_write__doc__,
Fred Drake's avatar
Fred Drake committed
5779
"write(fd, string) -> byteswritten\n\n\
5780
Write a string to a file descriptor.");
5781

Barry Warsaw's avatar
Barry Warsaw committed
5782
static PyObject *
5783
posix_write(PyObject *self, PyObject *args)
5784
{
5785 5786
    Py_buffer pbuf;
    int fd;
5787
    Py_ssize_t size, len;
Thomas Wouters's avatar
Thomas Wouters committed
5788

5789 5790
    if (!PyArg_ParseTuple(args, "iy*:write", &fd, &pbuf))
        return NULL;
Stefan Krah's avatar
Stefan Krah committed
5791 5792
    if (!_PyVerify_fd(fd)) {
        PyBuffer_Release(&pbuf);
5793
        return posix_error();
Stefan Krah's avatar
Stefan Krah committed
5794
    }
5795
    len = pbuf.len;
5796
    Py_BEGIN_ALLOW_THREADS
5797 5798 5799 5800 5801
#if defined(MS_WIN64) || defined(MS_WINDOWS)
    if (len > INT_MAX)
        len = INT_MAX;
    size = write(fd, pbuf.buf, (int)len);
#else
5802
    size = write(fd, pbuf.buf, len);
5803
#endif
5804
    Py_END_ALLOW_THREADS
Stefan Krah's avatar
Stefan Krah committed
5805
    PyBuffer_Release(&pbuf);
5806 5807 5808
    if (size < 0)
        return posix_error();
    return PyLong_FromSsize_t(size);
5809 5810
}

5811

5812
PyDoc_STRVAR(posix_fstat__doc__,
Fred Drake's avatar
Fred Drake committed
5813
"fstat(fd) -> stat result\n\n\
5814
Like stat(), but for an open file descriptor.");
5815

Barry Warsaw's avatar
Barry Warsaw committed
5816
static PyObject *
5817
posix_fstat(PyObject *self, PyObject *args)
5818
{
5819 5820 5821 5822 5823
    int fd;
    STRUCT_STAT st;
    int res;
    if (!PyArg_ParseTuple(args, "i:fstat", &fd))
        return NULL;
5824
#ifdef __VMS
5825 5826 5827 5828 5829 5830 5831 5832 5833
    /* on OpenVMS we must ensure that all bytes are written to the file */
    fsync(fd);
#endif
    if (!_PyVerify_fd(fd))
        return posix_error();
    Py_BEGIN_ALLOW_THREADS
    res = FSTAT(fd, &st);
    Py_END_ALLOW_THREADS
    if (res != 0) {
5834
#ifdef MS_WINDOWS
5835
        return win32_error("fstat", NULL);
5836
#else
5837
        return posix_error();
5838
#endif
5839
    }
5840

5841
    return _pystat_fromstructstat(&st);
5842 5843
}

5844
PyDoc_STRVAR(posix_isatty__doc__,
Fred Drake's avatar
Fred Drake committed
5845
"isatty(fd) -> bool\n\n\
5846
Return True if the file descriptor 'fd' is an open file descriptor\n\
5847
connected to the slave end of a terminal.");
5848 5849

static PyObject *
5850
posix_isatty(PyObject *self, PyObject *args)
5851
{
5852 5853 5854 5855 5856 5857
    int fd;
    if (!PyArg_ParseTuple(args, "i:isatty", &fd))
        return NULL;
    if (!_PyVerify_fd(fd))
        return PyBool_FromLong(0);
    return PyBool_FromLong(isatty(fd));
5858
}
5859

5860
#ifdef HAVE_PIPE
5861
PyDoc_STRVAR(posix_pipe__doc__,
Fred Drake's avatar
Fred Drake committed
5862
"pipe() -> (read_end, write_end)\n\n\
5863
Create a pipe.");
5864

Barry Warsaw's avatar
Barry Warsaw committed
5865
static PyObject *
5866
posix_pipe(PyObject *self, PyObject *noargs)
5867
{
Guido van Rossum's avatar
Guido van Rossum committed
5868 5869 5870 5871
#if defined(PYOS_OS2)
    HFILE read, write;
    APIRET rc;

5872
    Py_BEGIN_ALLOW_THREADS
Guido van Rossum's avatar
Guido van Rossum committed
5873
    rc = DosCreatePipe( &read, &write, 4096);
5874
    Py_END_ALLOW_THREADS
Guido van Rossum's avatar
Guido van Rossum committed
5875
    if (rc != NO_ERROR)
5876
        return os2_error(rc);
Guido van Rossum's avatar
Guido van Rossum committed
5877 5878 5879

    return Py_BuildValue("(ii)", read, write);
#else
5880
#if !defined(MS_WINDOWS)
5881 5882 5883 5884 5885 5886 5887 5888
    int fds[2];
    int res;
    Py_BEGIN_ALLOW_THREADS
    res = pipe(fds);
    Py_END_ALLOW_THREADS
    if (res != 0)
        return posix_error();
    return Py_BuildValue("(ii)", fds[0], fds[1]);
5889
#else /* MS_WINDOWS */
5890 5891 5892 5893 5894 5895 5896 5897 5898 5899 5900
    HANDLE read, write;
    int read_fd, write_fd;
    BOOL ok;
    Py_BEGIN_ALLOW_THREADS
    ok = CreatePipe(&read, &write, NULL, 0);
    Py_END_ALLOW_THREADS
    if (!ok)
        return win32_error("CreatePipe", NULL);
    read_fd = _open_osfhandle((Py_intptr_t)read, 0);
    write_fd = _open_osfhandle((Py_intptr_t)write, 1);
    return Py_BuildValue("(ii)", read_fd, write_fd);
5901
#endif /* MS_WINDOWS */
Guido van Rossum's avatar
Guido van Rossum committed
5902
#endif
5903
}
5904 5905
#endif  /* HAVE_PIPE */

5906

5907
#ifdef HAVE_MKFIFO
5908
PyDoc_STRVAR(posix_mkfifo__doc__,
5909
"mkfifo(filename [, mode=0666])\n\n\
5910
Create a FIFO (a POSIX named pipe).");
5911

Barry Warsaw's avatar
Barry Warsaw committed
5912
static PyObject *
5913
posix_mkfifo(PyObject *self, PyObject *args)
5914
{
5915
    PyObject *opath;
5916 5917 5918
    char *filename;
    int mode = 0666;
    int res;
5919 5920
    if (!PyArg_ParseTuple(args, "O&|i:mkfifo", PyUnicode_FSConverter, &opath,
                          &mode))
5921
        return NULL;
5922
    filename = PyBytes_AS_STRING(opath);
5923 5924 5925
    Py_BEGIN_ALLOW_THREADS
    res = mkfifo(filename, mode);
    Py_END_ALLOW_THREADS
5926
    Py_DECREF(opath);
5927 5928 5929 5930
    if (res < 0)
        return posix_error();
    Py_INCREF(Py_None);
    return Py_None;
5931 5932 5933 5934
}
#endif


5935
#if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
5936
PyDoc_STRVAR(posix_mknod__doc__,
5937
"mknod(filename [, mode=0600, device])\n\n\
5938 5939 5940 5941
Create a filesystem node (file, device special file or named pipe)\n\
named filename. mode specifies both the permissions to use and the\n\
type of node to be created, being combined (bitwise OR) with one of\n\
S_IFREG, S_IFCHR, S_IFBLK, and S_IFIFO. For S_IFCHR and S_IFBLK,\n\
5942 5943
device defines the newly created device special file (probably using\n\
os.makedev()), otherwise it is ignored.");
5944 5945 5946 5947 5948


static PyObject *
posix_mknod(PyObject *self, PyObject *args)
{
5949
    PyObject *opath;
5950 5951 5952 5953
    char *filename;
    int mode = 0600;
    int device = 0;
    int res;
5954 5955
    if (!PyArg_ParseTuple(args, "O&|ii:mknod", PyUnicode_FSConverter, &opath,
                          &mode, &device))
5956
        return NULL;
5957
    filename = PyBytes_AS_STRING(opath);
5958 5959 5960
    Py_BEGIN_ALLOW_THREADS
    res = mknod(filename, mode, device);
    Py_END_ALLOW_THREADS
5961
    Py_DECREF(opath);
5962 5963 5964 5965
    if (res < 0)
        return posix_error();
    Py_INCREF(Py_None);
    return Py_None;
5966 5967 5968
}
#endif

5969 5970 5971 5972 5973 5974 5975 5976
#ifdef HAVE_DEVICE_MACROS
PyDoc_STRVAR(posix_major__doc__,
"major(device) -> major number\n\
Extracts a device major number from a raw device number.");

static PyObject *
posix_major(PyObject *self, PyObject *args)
{
5977 5978 5979 5980
    int device;
    if (!PyArg_ParseTuple(args, "i:major", &device))
        return NULL;
    return PyLong_FromLong((long)major(device));
5981 5982 5983 5984 5985 5986 5987 5988 5989
}

PyDoc_STRVAR(posix_minor__doc__,
"minor(device) -> minor number\n\
Extracts a device minor number from a raw device number.");

static PyObject *
posix_minor(PyObject *self, PyObject *args)
{
5990 5991 5992 5993
    int device;
    if (!PyArg_ParseTuple(args, "i:minor", &device))
        return NULL;
    return PyLong_FromLong((long)minor(device));
5994 5995 5996 5997 5998 5999 6000 6001 6002
}

PyDoc_STRVAR(posix_makedev__doc__,
"makedev(major, minor) -> device number\n\
Composes a raw device number from the major and minor device numbers.");

static PyObject *
posix_makedev(PyObject *self, PyObject *args)
{
6003 6004 6005 6006
    int major, minor;
    if (!PyArg_ParseTuple(args, "ii:makedev", &major, &minor))
        return NULL;
    return PyLong_FromLong((long)makedev(major, minor));
6007 6008 6009
}
#endif /* device macros */

6010

6011
#ifdef HAVE_FTRUNCATE
6012
PyDoc_STRVAR(posix_ftruncate__doc__,
Fred Drake's avatar
Fred Drake committed
6013
"ftruncate(fd, length)\n\n\
6014
Truncate a file to a specified length.");
6015

Barry Warsaw's avatar
Barry Warsaw committed
6016
static PyObject *
6017
posix_ftruncate(PyObject *self, PyObject *args)
6018
{
6019 6020 6021 6022
    int fd;
    off_t length;
    int res;
    PyObject *lenobj;
6023

6024 6025
    if (!PyArg_ParseTuple(args, "iO:ftruncate", &fd, &lenobj))
        return NULL;
6026 6027

#if !defined(HAVE_LARGEFILE_SUPPORT)
6028
    length = PyLong_AsLong(lenobj);
6029
#else
6030 6031
    length = PyLong_Check(lenobj) ?
        PyLong_AsLongLong(lenobj) : PyLong_AsLong(lenobj);
6032
#endif
6033 6034
    if (PyErr_Occurred())
        return NULL;
6035

6036 6037 6038 6039 6040 6041 6042
    Py_BEGIN_ALLOW_THREADS
    res = ftruncate(fd, length);
    Py_END_ALLOW_THREADS
    if (res < 0)
        return posix_error();
    Py_INCREF(Py_None);
    return Py_None;
6043 6044
}
#endif
Guido van Rossum's avatar
Guido van Rossum committed
6045

6046
#ifdef HAVE_PUTENV
6047
PyDoc_STRVAR(posix_putenv__doc__,
Fred Drake's avatar
Fred Drake committed
6048
"putenv(key, value)\n\n\
6049
Change or add an environment variable.");
6050

6051 6052 6053 6054
/* Save putenv() parameters as values here, so we can collect them when they
 * get re-set with another call for the same key. */
static PyObject *posix_putenv_garbage;

6055
static PyObject *
6056
posix_putenv(PyObject *self, PyObject *args)
6057
{
6058
#ifdef MS_WINDOWS
6059 6060
    wchar_t *s1, *s2;
    wchar_t *newenv;
6061
#else
6062 6063 6064
    PyObject *os1, *os2;
    char *s1, *s2;
    char *newenv;
6065
#endif
6066
    PyObject *newstr = NULL;
6067
    size_t len;
6068

6069
#ifdef MS_WINDOWS
6070 6071 6072 6073
    if (!PyArg_ParseTuple(args,
                          "uu:putenv",
                          &s1, &s2))
        return NULL;
6074
#else
6075 6076 6077 6078 6079 6080 6081
    if (!PyArg_ParseTuple(args,
                          "O&O&:putenv",
                          PyUnicode_FSConverter, &os1,
                          PyUnicode_FSConverter, &os2))
        return NULL;
    s1 = PyBytes_AsString(os1);
    s2 = PyBytes_AsString(os2);
6082
#endif
6083 6084 6085 6086 6087 6088

#if defined(PYOS_OS2)
    if (stricmp(s1, "BEGINLIBPATH") == 0) {
        APIRET rc;

        rc = DosSetExtLIBPATH(s2, BEGIN_LIBPATH);
6089 6090 6091 6092
        if (rc != NO_ERROR) {
            os2_error(rc);
            goto error;
        }
6093 6094 6095 6096 6097

    } else if (stricmp(s1, "ENDLIBPATH") == 0) {
        APIRET rc;

        rc = DosSetExtLIBPATH(s2, END_LIBPATH);
6098 6099 6100 6101
        if (rc != NO_ERROR) {
            os2_error(rc);
            goto error;
        }
6102 6103
    } else {
#endif
6104 6105 6106
    /* XXX This can leak memory -- not easy to fix :-( */
    /* len includes space for a trailing \0; the size arg to
       PyBytes_FromStringAndSize does not count that */
6107
#ifdef MS_WINDOWS
6108 6109
    len = wcslen(s1) + wcslen(s2) + 2;
    newstr = PyUnicode_FromUnicode(NULL, (int)len - 1);
6110
#else
6111
    len = PyBytes_GET_SIZE(os1) + PyBytes_GET_SIZE(os2) + 2;
6112
    newstr = PyBytes_FromStringAndSize(NULL, (int)len - 1);
6113
#endif
6114 6115 6116 6117
    if (newstr == NULL) {
        PyErr_NoMemory();
        goto error;
    }
6118
#ifdef MS_WINDOWS
6119 6120 6121 6122
    newenv = PyUnicode_AsUnicode(newstr);
    _snwprintf(newenv, len, L"%s=%s", s1, s2);
    if (_wputenv(newenv)) {
        posix_error();
6123
        goto error;
6124
    }
6125
#else
6126 6127 6128 6129
    newenv = PyBytes_AS_STRING(newstr);
    PyOS_snprintf(newenv, len, "%s=%s", s1, s2);
    if (putenv(newenv)) {
        posix_error();
6130
        goto error;
6131 6132
    }
#endif
6133

6134 6135 6136 6137 6138
    /* Install the first arg and newstr in posix_putenv_garbage;
     * this will cause previous value to be collected.  This has to
     * happen after the real putenv() call because the old value
     * was still accessible until then. */
    if (PyDict_SetItem(posix_putenv_garbage,
6139 6140 6141 6142 6143 6144
#ifdef MS_WINDOWS
                       PyTuple_GET_ITEM(args, 0),
#else
                       os1,
#endif
                       newstr)) {
6145 6146 6147 6148 6149 6150
        /* really not much we can do; just leak */
        PyErr_Clear();
    }
    else {
        Py_DECREF(newstr);
    }
6151 6152 6153

#if defined(PYOS_OS2)
    }
6154
#endif
6155

6156
#ifndef MS_WINDOWS
6157 6158
    Py_DECREF(os1);
    Py_DECREF(os2);
6159
#endif
6160 6161 6162 6163 6164 6165 6166 6167 6168
    Py_RETURN_NONE;

error:
#ifndef MS_WINDOWS
    Py_DECREF(os1);
    Py_DECREF(os2);
#endif
    Py_XDECREF(newstr);
    return NULL;
6169
}
Guido van Rossum's avatar
Guido van Rossum committed
6170 6171
#endif /* putenv */

6172
#ifdef HAVE_UNSETENV
6173
PyDoc_STRVAR(posix_unsetenv__doc__,
Fred Drake's avatar
Fred Drake committed
6174
"unsetenv(key)\n\n\
6175
Delete an environment variable.");
6176 6177 6178 6179

static PyObject *
posix_unsetenv(PyObject *self, PyObject *args)
{
6180
#ifdef MS_WINDOWS
6181
    char *s1;
6182

6183 6184
    if (!PyArg_ParseTuple(args, "s:unsetenv", &s1))
        return NULL;
6185 6186 6187 6188 6189 6190 6191 6192 6193
#else
    PyObject *os1;
    char *s1;

    if (!PyArg_ParseTuple(args, "O&:unsetenv",
                          PyUnicode_FSConverter, &os1))
        return NULL;
    s1 = PyBytes_AsString(os1);
#endif
6194

6195 6196 6197 6198 6199 6200 6201 6202
    unsetenv(s1);

    /* Remove the key from posix_putenv_garbage;
     * this will cause it to be collected.  This has to
     * happen after the real unsetenv() call because the
     * old value was still accessible until then.
     */
    if (PyDict_DelItem(posix_putenv_garbage,
6203 6204 6205 6206 6207 6208
#ifdef MS_WINDOWS
                       PyTuple_GET_ITEM(args, 0)
#else
                       os1
#endif
                       )) {
6209 6210 6211
        /* really not much we can do; just leak */
        PyErr_Clear();
    }
6212

6213 6214 6215 6216
#ifndef MS_WINDOWS
    Py_DECREF(os1);
#endif
    Py_RETURN_NONE;
6217 6218 6219
}
#endif /* unsetenv */

6220
PyDoc_STRVAR(posix_strerror__doc__,
Fred Drake's avatar
Fred Drake committed
6221
"strerror(code) -> string\n\n\
6222
Translate an error code to a message string.");
Guido van Rossum's avatar
Guido van Rossum committed
6223

6224
static PyObject *
6225
posix_strerror(PyObject *self, PyObject *args)
Guido van Rossum's avatar
Guido van Rossum committed
6226
{
6227 6228 6229 6230 6231 6232 6233 6234 6235 6236 6237
    int code;
    char *message;
    if (!PyArg_ParseTuple(args, "i:strerror", &code))
        return NULL;
    message = strerror(code);
    if (message == NULL) {
        PyErr_SetString(PyExc_ValueError,
                        "strerror() argument out of range");
        return NULL;
    }
    return PyUnicode_FromString(message);
Guido van Rossum's avatar
Guido van Rossum committed
6238 6239
}

6240

6241 6242
#ifdef HAVE_SYS_WAIT_H

6243
#ifdef WCOREDUMP
6244
PyDoc_STRVAR(posix_WCOREDUMP__doc__,
Fred Drake's avatar
Fred Drake committed
6245
"WCOREDUMP(status) -> bool\n\n\
6246
Return True if the process returning 'status' was dumped to a core file.");
6247 6248 6249 6250

static PyObject *
posix_WCOREDUMP(PyObject *self, PyObject *args)
{
6251 6252
    WAIT_TYPE status;
    WAIT_STATUS_INT(status) = 0;
6253

6254 6255
    if (!PyArg_ParseTuple(args, "i:WCOREDUMP", &WAIT_STATUS_INT(status)))
        return NULL;
6256

6257
    return PyBool_FromLong(WCOREDUMP(status));
6258 6259 6260 6261
}
#endif /* WCOREDUMP */

#ifdef WIFCONTINUED
6262
PyDoc_STRVAR(posix_WIFCONTINUED__doc__,
Fred Drake's avatar
Fred Drake committed
6263
"WIFCONTINUED(status) -> bool\n\n\
6264
Return True if the process returning 'status' was continued from a\n\
6265
job control stop.");
6266 6267

static PyObject *
6268
posix_WIFCONTINUED(PyObject *self, PyObject *args)
6269
{
6270 6271
    WAIT_TYPE status;
    WAIT_STATUS_INT(status) = 0;
6272

6273 6274
    if (!PyArg_ParseTuple(args, "i:WCONTINUED", &WAIT_STATUS_INT(status)))
        return NULL;
6275

6276
    return PyBool_FromLong(WIFCONTINUED(status));
6277 6278 6279
}
#endif /* WIFCONTINUED */

6280
#ifdef WIFSTOPPED
6281
PyDoc_STRVAR(posix_WIFSTOPPED__doc__,
Fred Drake's avatar
Fred Drake committed
6282
"WIFSTOPPED(status) -> bool\n\n\
6283
Return True if the process returning 'status' was stopped.");
6284 6285

static PyObject *
6286
posix_WIFSTOPPED(PyObject *self, PyObject *args)
6287
{
6288 6289
    WAIT_TYPE status;
    WAIT_STATUS_INT(status) = 0;
6290

6291 6292
    if (!PyArg_ParseTuple(args, "i:WIFSTOPPED", &WAIT_STATUS_INT(status)))
        return NULL;
6293

6294
    return PyBool_FromLong(WIFSTOPPED(status));
6295 6296 6297 6298
}
#endif /* WIFSTOPPED */

#ifdef WIFSIGNALED
6299
PyDoc_STRVAR(posix_WIFSIGNALED__doc__,
Fred Drake's avatar
Fred Drake committed
6300
"WIFSIGNALED(status) -> bool\n\n\
6301
Return True if the process returning 'status' was terminated by a signal.");
6302 6303

static PyObject *
6304
posix_WIFSIGNALED(PyObject *self, PyObject *args)
6305
{
6306 6307
    WAIT_TYPE status;
    WAIT_STATUS_INT(status) = 0;
6308

6309 6310
    if (!PyArg_ParseTuple(args, "i:WIFSIGNALED", &WAIT_STATUS_INT(status)))
        return NULL;
6311

6312
    return PyBool_FromLong(WIFSIGNALED(status));
6313 6314 6315 6316
}
#endif /* WIFSIGNALED */

#ifdef WIFEXITED
6317
PyDoc_STRVAR(posix_WIFEXITED__doc__,
Fred Drake's avatar
Fred Drake committed
6318
"WIFEXITED(status) -> bool\n\n\
6319
Return true if the process returning 'status' exited using the exit()\n\
6320
system call.");
6321 6322

static PyObject *
6323
posix_WIFEXITED(PyObject *self, PyObject *args)
6324
{
6325 6326
    WAIT_TYPE status;
    WAIT_STATUS_INT(status) = 0;
6327

6328 6329
    if (!PyArg_ParseTuple(args, "i:WIFEXITED", &WAIT_STATUS_INT(status)))
        return NULL;
6330

6331
    return PyBool_FromLong(WIFEXITED(status));
6332 6333 6334
}
#endif /* WIFEXITED */

6335
#ifdef WEXITSTATUS
6336
PyDoc_STRVAR(posix_WEXITSTATUS__doc__,
Fred Drake's avatar
Fred Drake committed
6337
"WEXITSTATUS(status) -> integer\n\n\
6338
Return the process return code from 'status'.");
6339 6340

static PyObject *
6341
posix_WEXITSTATUS(PyObject *self, PyObject *args)
6342
{
6343 6344
    WAIT_TYPE status;
    WAIT_STATUS_INT(status) = 0;
6345

6346 6347
    if (!PyArg_ParseTuple(args, "i:WEXITSTATUS", &WAIT_STATUS_INT(status)))
        return NULL;
6348

6349
    return Py_BuildValue("i", WEXITSTATUS(status));
6350 6351 6352 6353
}
#endif /* WEXITSTATUS */

#ifdef WTERMSIG
6354
PyDoc_STRVAR(posix_WTERMSIG__doc__,
Fred Drake's avatar
Fred Drake committed
6355
"WTERMSIG(status) -> integer\n\n\
6356
Return the signal that terminated the process that provided the 'status'\n\
6357
value.");
6358 6359

static PyObject *
6360
posix_WTERMSIG(PyObject *self, PyObject *args)
6361
{
6362 6363
    WAIT_TYPE status;
    WAIT_STATUS_INT(status) = 0;
6364

6365 6366
    if (!PyArg_ParseTuple(args, "i:WTERMSIG", &WAIT_STATUS_INT(status)))
        return NULL;
6367

6368
    return Py_BuildValue("i", WTERMSIG(status));
6369 6370 6371 6372
}
#endif /* WTERMSIG */

#ifdef WSTOPSIG
6373
PyDoc_STRVAR(posix_WSTOPSIG__doc__,
Fred Drake's avatar
Fred Drake committed
6374
"WSTOPSIG(status) -> integer\n\n\
6375 6376
Return the signal that stopped the process that provided\n\
the 'status' value.");
6377 6378

static PyObject *
6379
posix_WSTOPSIG(PyObject *self, PyObject *args)
6380
{
6381 6382
    WAIT_TYPE status;
    WAIT_STATUS_INT(status) = 0;
6383

6384 6385
    if (!PyArg_ParseTuple(args, "i:WSTOPSIG", &WAIT_STATUS_INT(status)))
        return NULL;
6386

6387
    return Py_BuildValue("i", WSTOPSIG(status));
6388 6389 6390 6391 6392 6393
}
#endif /* WSTOPSIG */

#endif /* HAVE_SYS_WAIT_H */


6394
#if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
6395 6396 6397 6398 6399
#ifdef _SCO_DS
/* SCO OpenServer 5.0 and later requires _SVID3 before it reveals the
   needed definitions in sys/statvfs.h */
#define _SVID3
#endif
6400 6401
#include <sys/statvfs.h>

6402 6403
static PyObject*
_pystatvfs_fromstructstatvfs(struct statvfs st) {
6404 6405 6406
    PyObject *v = PyStructSequence_New(&StatVFSResultType);
    if (v == NULL)
        return NULL;
6407 6408

#if !defined(HAVE_LARGEFILE_SUPPORT)
6409 6410 6411 6412 6413 6414 6415 6416 6417 6418
    PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
    PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
    PyStructSequence_SET_ITEM(v, 2, PyLong_FromLong((long) st.f_blocks));
    PyStructSequence_SET_ITEM(v, 3, PyLong_FromLong((long) st.f_bfree));
    PyStructSequence_SET_ITEM(v, 4, PyLong_FromLong((long) st.f_bavail));
    PyStructSequence_SET_ITEM(v, 5, PyLong_FromLong((long) st.f_files));
    PyStructSequence_SET_ITEM(v, 6, PyLong_FromLong((long) st.f_ffree));
    PyStructSequence_SET_ITEM(v, 7, PyLong_FromLong((long) st.f_favail));
    PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
    PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
6419
#else
6420 6421 6422 6423 6424 6425 6426 6427 6428 6429 6430 6431 6432 6433 6434 6435 6436 6437 6438
    PyStructSequence_SET_ITEM(v, 0, PyLong_FromLong((long) st.f_bsize));
    PyStructSequence_SET_ITEM(v, 1, PyLong_FromLong((long) st.f_frsize));
    PyStructSequence_SET_ITEM(v, 2,
                              PyLong_FromLongLong((PY_LONG_LONG) st.f_blocks));
    PyStructSequence_SET_ITEM(v, 3,
                              PyLong_FromLongLong((PY_LONG_LONG) st.f_bfree));
    PyStructSequence_SET_ITEM(v, 4,
                              PyLong_FromLongLong((PY_LONG_LONG) st.f_bavail));
    PyStructSequence_SET_ITEM(v, 5,
                              PyLong_FromLongLong((PY_LONG_LONG) st.f_files));
    PyStructSequence_SET_ITEM(v, 6,
                              PyLong_FromLongLong((PY_LONG_LONG) st.f_ffree));
    PyStructSequence_SET_ITEM(v, 7,
                              PyLong_FromLongLong((PY_LONG_LONG) st.f_favail));
    PyStructSequence_SET_ITEM(v, 8, PyLong_FromLong((long) st.f_flag));
    PyStructSequence_SET_ITEM(v, 9, PyLong_FromLong((long) st.f_namemax));
#endif

    return v;
6439 6440
}

6441
PyDoc_STRVAR(posix_fstatvfs__doc__,
Fred Drake's avatar
Fred Drake committed
6442
"fstatvfs(fd) -> statvfs result\n\n\
6443
Perform an fstatvfs system call on the given fd.");
6444 6445

static PyObject *
6446
posix_fstatvfs(PyObject *self, PyObject *args)
6447
{
6448 6449
    int fd, res;
    struct statvfs st;
6450

6451 6452 6453 6454 6455 6456 6457
    if (!PyArg_ParseTuple(args, "i:fstatvfs", &fd))
        return NULL;
    Py_BEGIN_ALLOW_THREADS
    res = fstatvfs(fd, &st);
    Py_END_ALLOW_THREADS
    if (res != 0)
        return posix_error();
6458

6459
    return _pystatvfs_fromstructstatvfs(st);
6460
}
6461
#endif /* HAVE_FSTATVFS && HAVE_SYS_STATVFS_H */
6462 6463


6464
#if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
6465 6466
#include <sys/statvfs.h>

6467
PyDoc_STRVAR(posix_statvfs__doc__,
Fred Drake's avatar
Fred Drake committed
6468
"statvfs(path) -> statvfs result\n\n\
6469
Perform a statvfs system call on the given path.");
6470 6471

static PyObject *
6472
posix_statvfs(PyObject *self, PyObject *args)
6473
{
6474 6475 6476 6477 6478 6479 6480 6481 6482 6483
    char *path;
    int res;
    struct statvfs st;
    if (!PyArg_ParseTuple(args, "s:statvfs", &path))
        return NULL;
    Py_BEGIN_ALLOW_THREADS
    res = statvfs(path, &st);
    Py_END_ALLOW_THREADS
    if (res != 0)
        return posix_error_with_filename(path);
6484

6485
    return _pystatvfs_fromstructstatvfs(st);
6486 6487 6488
}
#endif /* HAVE_STATVFS */

6489 6490 6491
/* This is used for fpathconf(), pathconf(), confstr() and sysconf().
 * It maps strings representing configuration variable names to
 * integer values, allowing those functions to be called with the
6492
 * magic names instead of polluting the module's namespace with tons of
6493 6494
 * rarely-used constants.  There are three separate tables that use
 * these definitions.
6495 6496 6497 6498
 *
 * This code is always included, even if none of the interfaces that
 * need it are included.  The #if hackery needed to avoid it would be
 * sufficiently pervasive that it's not worth the loss of readability.
6499 6500 6501 6502 6503 6504
 */
struct constdef {
    char *name;
    long value;
};

6505
static int
6506
conv_confname(PyObject *arg, int *valuep, struct constdef *table,
6507
              size_t tablesize)
6508
{
6509
    if (PyLong_Check(arg)) {
Stefan Krah's avatar
Stefan Krah committed
6510 6511
        *valuep = PyLong_AS_LONG(arg);
        return 1;
6512
    }
6513
    else {
Stefan Krah's avatar
Stefan Krah committed
6514 6515 6516 6517 6518 6519 6520 6521 6522 6523
        /* look up the value in the table using a binary search */
        size_t lo = 0;
        size_t mid;
        size_t hi = tablesize;
        int cmp;
        const char *confname;
        if (!PyUnicode_Check(arg)) {
            PyErr_SetString(PyExc_TypeError,
                "configuration names must be strings or integers");
            return 0;
6524
        }
Stefan Krah's avatar
Stefan Krah committed
6525 6526 6527 6528 6529 6530 6531 6532 6533 6534 6535 6536 6537 6538 6539 6540 6541
        confname = _PyUnicode_AsString(arg);
        if (confname == NULL)
            return 0;
        while (lo < hi) {
            mid = (lo + hi) / 2;
            cmp = strcmp(confname, table[mid].name);
            if (cmp < 0)
                hi = mid;
            else if (cmp > 0)
                lo = mid + 1;
            else {
                *valuep = table[mid].value;
                return 1;
            }
        }
        PyErr_SetString(PyExc_ValueError, "unrecognized configuration name");
        return 0;
6542
    }
6543 6544 6545 6546 6547
}


#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
static struct constdef  posix_constants_pathconf[] = {
6548
#ifdef _PC_ABI_AIO_XFER_MAX
6549
    {"PC_ABI_AIO_XFER_MAX",     _PC_ABI_AIO_XFER_MAX},
6550 6551
#endif
#ifdef _PC_ABI_ASYNC_IO
6552
    {"PC_ABI_ASYNC_IO", _PC_ABI_ASYNC_IO},
6553
#endif
6554
#ifdef _PC_ASYNC_IO
6555
    {"PC_ASYNC_IO",     _PC_ASYNC_IO},
6556 6557
#endif
#ifdef _PC_CHOWN_RESTRICTED
6558
    {"PC_CHOWN_RESTRICTED",     _PC_CHOWN_RESTRICTED},
6559 6560
#endif
#ifdef _PC_FILESIZEBITS
6561
    {"PC_FILESIZEBITS", _PC_FILESIZEBITS},
6562 6563
#endif
#ifdef _PC_LAST
6564
    {"PC_LAST", _PC_LAST},
6565 6566
#endif
#ifdef _PC_LINK_MAX
6567
    {"PC_LINK_MAX",     _PC_LINK_MAX},
6568 6569
#endif
#ifdef _PC_MAX_CANON
6570
    {"PC_MAX_CANON",    _PC_MAX_CANON},
6571 6572
#endif
#ifdef _PC_MAX_INPUT
6573
    {"PC_MAX_INPUT",    _PC_MAX_INPUT},
6574 6575
#endif
#ifdef _PC_NAME_MAX
6576
    {"PC_NAME_MAX",     _PC_NAME_MAX},
6577 6578
#endif
#ifdef _PC_NO_TRUNC
6579
    {"PC_NO_TRUNC",     _PC_NO_TRUNC},
6580 6581
#endif
#ifdef _PC_PATH_MAX
6582
    {"PC_PATH_MAX",     _PC_PATH_MAX},
6583 6584
#endif
#ifdef _PC_PIPE_BUF
6585
    {"PC_PIPE_BUF",     _PC_PIPE_BUF},
6586 6587
#endif
#ifdef _PC_PRIO_IO
6588
    {"PC_PRIO_IO",      _PC_PRIO_IO},
6589 6590
#endif
#ifdef _PC_SOCK_MAXBUF
6591
    {"PC_SOCK_MAXBUF",  _PC_SOCK_MAXBUF},
6592 6593
#endif
#ifdef _PC_SYNC_IO
6594
    {"PC_SYNC_IO",      _PC_SYNC_IO},
6595 6596
#endif
#ifdef _PC_VDISABLE
6597
    {"PC_VDISABLE",     _PC_VDISABLE},
6598
#endif
6599 6600 6601 6602 6603 6604 6605 6606 6607 6608 6609 6610 6611 6612 6613 6614 6615 6616 6617 6618 6619 6620 6621 6622 6623 6624 6625 6626 6627 6628 6629 6630 6631
#ifdef _PC_ACL_ENABLED
    {"PC_ACL_ENABLED",  _PC_ACL_ENABLED},
#endif
#ifdef _PC_MIN_HOLE_SIZE
    {"PC_MIN_HOLE_SIZE",    _PC_MIN_HOLE_SIZE},
#endif
#ifdef _PC_ALLOC_SIZE_MIN
    {"PC_ALLOC_SIZE_MIN",   _PC_ALLOC_SIZE_MIN},
#endif
#ifdef _PC_REC_INCR_XFER_SIZE
    {"PC_REC_INCR_XFER_SIZE",   _PC_REC_INCR_XFER_SIZE},
#endif
#ifdef _PC_REC_MAX_XFER_SIZE
    {"PC_REC_MAX_XFER_SIZE",    _PC_REC_MAX_XFER_SIZE},
#endif
#ifdef _PC_REC_MIN_XFER_SIZE
    {"PC_REC_MIN_XFER_SIZE",    _PC_REC_MIN_XFER_SIZE},
#endif
#ifdef _PC_REC_XFER_ALIGN
    {"PC_REC_XFER_ALIGN",   _PC_REC_XFER_ALIGN},
#endif
#ifdef _PC_SYMLINK_MAX
    {"PC_SYMLINK_MAX",  _PC_SYMLINK_MAX},
#endif
#ifdef _PC_XATTR_ENABLED
    {"PC_XATTR_ENABLED",    _PC_XATTR_ENABLED},
#endif
#ifdef _PC_XATTR_EXISTS
    {"PC_XATTR_EXISTS", _PC_XATTR_EXISTS},
#endif
#ifdef _PC_TIMESTAMP_RESOLUTION
    {"PC_TIMESTAMP_RESOLUTION", _PC_TIMESTAMP_RESOLUTION},
#endif
6632 6633 6634
};

static int
6635
conv_path_confname(PyObject *arg, int *valuep)
6636 6637 6638 6639 6640 6641 6642 6643
{
    return conv_confname(arg, valuep, posix_constants_pathconf,
                         sizeof(posix_constants_pathconf)
                           / sizeof(struct constdef));
}
#endif

#ifdef HAVE_FPATHCONF
6644
PyDoc_STRVAR(posix_fpathconf__doc__,
Fred Drake's avatar
Fred Drake committed
6645
"fpathconf(fd, name) -> integer\n\n\
6646
Return the configuration limit name for the file descriptor fd.\n\
6647
If there is no limit, return -1.");
6648 6649

static PyObject *
6650
posix_fpathconf(PyObject *self, PyObject *args)
6651 6652 6653 6654
{
    PyObject *result = NULL;
    int name, fd;

6655 6656
    if (PyArg_ParseTuple(args, "iO&:fpathconf", &fd,
                         conv_path_confname, &name)) {
Stefan Krah's avatar
Stefan Krah committed
6657
        long limit;
6658

Stefan Krah's avatar
Stefan Krah committed
6659 6660 6661 6662 6663 6664
        errno = 0;
        limit = fpathconf(fd, name);
        if (limit == -1 && errno != 0)
            posix_error();
        else
            result = PyLong_FromLong(limit);
6665 6666 6667 6668 6669 6670 6671
    }
    return result;
}
#endif


#ifdef HAVE_PATHCONF
6672
PyDoc_STRVAR(posix_pathconf__doc__,
Fred Drake's avatar
Fred Drake committed
6673
"pathconf(path, name) -> integer\n\n\
6674
Return the configuration limit name for the file or directory path.\n\
6675
If there is no limit, return -1.");
6676 6677

static PyObject *
6678
posix_pathconf(PyObject *self, PyObject *args)
6679 6680 6681 6682 6683 6684 6685
{
    PyObject *result = NULL;
    int name;
    char *path;

    if (PyArg_ParseTuple(args, "sO&:pathconf", &path,
                         conv_path_confname, &name)) {
6686 6687 6688 6689 6690 6691
    long limit;

    errno = 0;
    limit = pathconf(path, name);
    if (limit == -1 && errno != 0) {
        if (errno == EINVAL)
Stefan Krah's avatar
Stefan Krah committed
6692 6693
            /* could be a path or name problem */
            posix_error();
6694
        else
Stefan Krah's avatar
Stefan Krah committed
6695
            posix_error_with_filename(path);
6696 6697 6698
    }
    else
        result = PyLong_FromLong(limit);
6699 6700 6701 6702 6703 6704 6705
    }
    return result;
}
#endif

#ifdef HAVE_CONFSTR
static struct constdef posix_constants_confstr[] = {
6706
#ifdef _CS_ARCHITECTURE
6707
    {"CS_ARCHITECTURE", _CS_ARCHITECTURE},
6708
#endif
6709
#ifdef _CS_GNU_LIBC_VERSION
6710
    {"CS_GNU_LIBC_VERSION",     _CS_GNU_LIBC_VERSION},
6711 6712
#endif
#ifdef _CS_GNU_LIBPTHREAD_VERSION
6713
    {"CS_GNU_LIBPTHREAD_VERSION",       _CS_GNU_LIBPTHREAD_VERSION},
6714
#endif
6715
#ifdef _CS_HOSTNAME
6716
    {"CS_HOSTNAME",     _CS_HOSTNAME},
6717 6718
#endif
#ifdef _CS_HW_PROVIDER
6719
    {"CS_HW_PROVIDER",  _CS_HW_PROVIDER},
6720 6721
#endif
#ifdef _CS_HW_SERIAL
6722
    {"CS_HW_SERIAL",    _CS_HW_SERIAL},
6723 6724
#endif
#ifdef _CS_INITTAB_NAME
6725
    {"CS_INITTAB_NAME", _CS_INITTAB_NAME},
6726
#endif
6727
#ifdef _CS_LFS64_CFLAGS
6728
    {"CS_LFS64_CFLAGS", _CS_LFS64_CFLAGS},
6729 6730
#endif
#ifdef _CS_LFS64_LDFLAGS
6731
    {"CS_LFS64_LDFLAGS",        _CS_LFS64_LDFLAGS},
6732 6733
#endif
#ifdef _CS_LFS64_LIBS
6734
    {"CS_LFS64_LIBS",   _CS_LFS64_LIBS},
6735 6736
#endif
#ifdef _CS_LFS64_LINTFLAGS
6737
    {"CS_LFS64_LINTFLAGS",      _CS_LFS64_LINTFLAGS},
6738 6739
#endif
#ifdef _CS_LFS_CFLAGS
6740
    {"CS_LFS_CFLAGS",   _CS_LFS_CFLAGS},
6741 6742
#endif
#ifdef _CS_LFS_LDFLAGS
6743
    {"CS_LFS_LDFLAGS",  _CS_LFS_LDFLAGS},
6744 6745
#endif
#ifdef _CS_LFS_LIBS
6746
    {"CS_LFS_LIBS",     _CS_LFS_LIBS},
6747 6748
#endif
#ifdef _CS_LFS_LINTFLAGS
6749
    {"CS_LFS_LINTFLAGS",        _CS_LFS_LINTFLAGS},
6750
#endif
6751
#ifdef _CS_MACHINE
6752
    {"CS_MACHINE",      _CS_MACHINE},
6753
#endif
6754
#ifdef _CS_PATH
6755
    {"CS_PATH", _CS_PATH},
6756
#endif
6757
#ifdef _CS_RELEASE
6758
    {"CS_RELEASE",      _CS_RELEASE},
6759 6760
#endif
#ifdef _CS_SRPC_DOMAIN
6761
    {"CS_SRPC_DOMAIN",  _CS_SRPC_DOMAIN},
6762 6763
#endif
#ifdef _CS_SYSNAME
6764
    {"CS_SYSNAME",      _CS_SYSNAME},
6765 6766
#endif
#ifdef _CS_VERSION
6767
    {"CS_VERSION",      _CS_VERSION},
6768
#endif
6769
#ifdef _CS_XBS5_ILP32_OFF32_CFLAGS
6770
    {"CS_XBS5_ILP32_OFF32_CFLAGS",      _CS_XBS5_ILP32_OFF32_CFLAGS},
6771 6772
#endif
#ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS
6773
    {"CS_XBS5_ILP32_OFF32_LDFLAGS",     _CS_XBS5_ILP32_OFF32_LDFLAGS},
6774 6775
#endif
#ifdef _CS_XBS5_ILP32_OFF32_LIBS
6776
    {"CS_XBS5_ILP32_OFF32_LIBS",        _CS_XBS5_ILP32_OFF32_LIBS},
6777 6778
#endif
#ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS
6779
    {"CS_XBS5_ILP32_OFF32_LINTFLAGS",   _CS_XBS5_ILP32_OFF32_LINTFLAGS},
6780 6781
#endif
#ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS
6782
    {"CS_XBS5_ILP32_OFFBIG_CFLAGS",     _CS_XBS5_ILP32_OFFBIG_CFLAGS},
6783 6784
#endif
#ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS
6785
    {"CS_XBS5_ILP32_OFFBIG_LDFLAGS",    _CS_XBS5_ILP32_OFFBIG_LDFLAGS},
6786 6787
#endif
#ifdef _CS_XBS5_ILP32_OFFBIG_LIBS
6788
    {"CS_XBS5_ILP32_OFFBIG_LIBS",       _CS_XBS5_ILP32_OFFBIG_LIBS},
6789 6790
#endif
#ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS
6791
    {"CS_XBS5_ILP32_OFFBIG_LINTFLAGS",  _CS_XBS5_ILP32_OFFBIG_LINTFLAGS},
6792 6793
#endif
#ifdef _CS_XBS5_LP64_OFF64_CFLAGS
6794
    {"CS_XBS5_LP64_OFF64_CFLAGS",       _CS_XBS5_LP64_OFF64_CFLAGS},
6795 6796
#endif
#ifdef _CS_XBS5_LP64_OFF64_LDFLAGS
6797
    {"CS_XBS5_LP64_OFF64_LDFLAGS",      _CS_XBS5_LP64_OFF64_LDFLAGS},
6798 6799
#endif
#ifdef _CS_XBS5_LP64_OFF64_LIBS
6800
    {"CS_XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS},
6801 6802
#endif
#ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS
6803
    {"CS_XBS5_LP64_OFF64_LINTFLAGS",    _CS_XBS5_LP64_OFF64_LINTFLAGS},
6804 6805
#endif
#ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS
6806
    {"CS_XBS5_LPBIG_OFFBIG_CFLAGS",     _CS_XBS5_LPBIG_OFFBIG_CFLAGS},
6807 6808
#endif
#ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS
6809
    {"CS_XBS5_LPBIG_OFFBIG_LDFLAGS",    _CS_XBS5_LPBIG_OFFBIG_LDFLAGS},
6810 6811
#endif
#ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS
6812
    {"CS_XBS5_LPBIG_OFFBIG_LIBS",       _CS_XBS5_LPBIG_OFFBIG_LIBS},
6813 6814
#endif
#ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS
6815
    {"CS_XBS5_LPBIG_OFFBIG_LINTFLAGS",  _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS},
6816
#endif
6817
#ifdef _MIPS_CS_AVAIL_PROCESSORS
6818
    {"MIPS_CS_AVAIL_PROCESSORS",        _MIPS_CS_AVAIL_PROCESSORS},
6819 6820
#endif
#ifdef _MIPS_CS_BASE
6821
    {"MIPS_CS_BASE",    _MIPS_CS_BASE},
6822 6823
#endif
#ifdef _MIPS_CS_HOSTID
6824
    {"MIPS_CS_HOSTID",  _MIPS_CS_HOSTID},
6825 6826
#endif
#ifdef _MIPS_CS_HW_NAME
6827
    {"MIPS_CS_HW_NAME", _MIPS_CS_HW_NAME},
6828 6829
#endif
#ifdef _MIPS_CS_NUM_PROCESSORS
6830
    {"MIPS_CS_NUM_PROCESSORS",  _MIPS_CS_NUM_PROCESSORS},
6831 6832
#endif
#ifdef _MIPS_CS_OSREL_MAJ
6833
    {"MIPS_CS_OSREL_MAJ",       _MIPS_CS_OSREL_MAJ},
6834 6835
#endif
#ifdef _MIPS_CS_OSREL_MIN
6836
    {"MIPS_CS_OSREL_MIN",       _MIPS_CS_OSREL_MIN},
6837 6838
#endif
#ifdef _MIPS_CS_OSREL_PATCH
6839
    {"MIPS_CS_OSREL_PATCH",     _MIPS_CS_OSREL_PATCH},
6840 6841
#endif
#ifdef _MIPS_CS_OS_NAME
6842
    {"MIPS_CS_OS_NAME", _MIPS_CS_OS_NAME},
6843 6844
#endif
#ifdef _MIPS_CS_OS_PROVIDER
6845
    {"MIPS_CS_OS_PROVIDER",     _MIPS_CS_OS_PROVIDER},
6846 6847
#endif
#ifdef _MIPS_CS_PROCESSORS
6848
    {"MIPS_CS_PROCESSORS",      _MIPS_CS_PROCESSORS},
6849 6850
#endif
#ifdef _MIPS_CS_SERIAL
6851
    {"MIPS_CS_SERIAL",  _MIPS_CS_SERIAL},
6852 6853
#endif
#ifdef _MIPS_CS_VENDOR
6854
    {"MIPS_CS_VENDOR",  _MIPS_CS_VENDOR},
6855
#endif
6856 6857 6858
};

static int
6859
conv_confstr_confname(PyObject *arg, int *valuep)
6860 6861 6862 6863 6864 6865
{
    return conv_confname(arg, valuep, posix_constants_confstr,
                         sizeof(posix_constants_confstr)
                           / sizeof(struct constdef));
}

6866
PyDoc_STRVAR(posix_confstr__doc__,
Fred Drake's avatar
Fred Drake committed
6867
"confstr(name) -> string\n\n\
6868
Return a string-valued system configuration variable.");
6869 6870

static PyObject *
6871
posix_confstr(PyObject *self, PyObject *args)
6872 6873 6874
{
    PyObject *result = NULL;
    int name;
6875
    char buffer[255];
Stefan Krah's avatar
Stefan Krah committed
6876
    int len;
6877

6878 6879 6880 6881 6882 6883 6884 6885 6886
    if (!PyArg_ParseTuple(args, "O&:confstr", conv_confstr_confname, &name))
        return NULL;

    errno = 0;
    len = confstr(name, buffer, sizeof(buffer));
    if (len == 0) {
        if (errno) {
            posix_error();
            return NULL;
6887 6888
        }
        else {
6889
            Py_RETURN_NONE;
6890 6891
        }
    }
6892 6893 6894 6895 6896 6897 6898 6899 6900 6901 6902

    if ((unsigned int)len >= sizeof(buffer)) {
        char *buf = PyMem_Malloc(len);
        if (buf == NULL)
            return PyErr_NoMemory();
        confstr(name, buf, len);
        result = PyUnicode_DecodeFSDefaultAndSize(buf, len-1);
        PyMem_Free(buf);
    }
    else
        result = PyUnicode_DecodeFSDefaultAndSize(buffer, len-1);
6903 6904 6905 6906 6907 6908 6909 6910
    return result;
}
#endif


#ifdef HAVE_SYSCONF
static struct constdef posix_constants_sysconf[] = {
#ifdef _SC_2_CHAR_TERM
6911
    {"SC_2_CHAR_TERM",  _SC_2_CHAR_TERM},
6912 6913
#endif
#ifdef _SC_2_C_BIND
6914
    {"SC_2_C_BIND",     _SC_2_C_BIND},
6915 6916
#endif
#ifdef _SC_2_C_DEV
6917
    {"SC_2_C_DEV",      _SC_2_C_DEV},
6918 6919
#endif
#ifdef _SC_2_C_VERSION
6920
    {"SC_2_C_VERSION",  _SC_2_C_VERSION},
6921 6922
#endif
#ifdef _SC_2_FORT_DEV
6923
    {"SC_2_FORT_DEV",   _SC_2_FORT_DEV},
6924 6925
#endif
#ifdef _SC_2_FORT_RUN
6926
    {"SC_2_FORT_RUN",   _SC_2_FORT_RUN},
6927 6928
#endif
#ifdef _SC_2_LOCALEDEF
6929
    {"SC_2_LOCALEDEF",  _SC_2_LOCALEDEF},
6930 6931
#endif
#ifdef _SC_2_SW_DEV
6932
    {"SC_2_SW_DEV",     _SC_2_SW_DEV},
6933 6934
#endif
#ifdef _SC_2_UPE
6935
    {"SC_2_UPE",        _SC_2_UPE},
6936 6937
#endif
#ifdef _SC_2_VERSION
6938
    {"SC_2_VERSION",    _SC_2_VERSION},
6939
#endif
6940
#ifdef _SC_ABI_ASYNCHRONOUS_IO
6941
    {"SC_ABI_ASYNCHRONOUS_IO",  _SC_ABI_ASYNCHRONOUS_IO},
6942 6943
#endif
#ifdef _SC_ACL
6944
    {"SC_ACL",  _SC_ACL},
6945
#endif
6946
#ifdef _SC_AIO_LISTIO_MAX
6947
    {"SC_AIO_LISTIO_MAX",       _SC_AIO_LISTIO_MAX},
6948 6949
#endif
#ifdef _SC_AIO_MAX
6950
    {"SC_AIO_MAX",      _SC_AIO_MAX},
6951 6952
#endif
#ifdef _SC_AIO_PRIO_DELTA_MAX
6953
    {"SC_AIO_PRIO_DELTA_MAX",   _SC_AIO_PRIO_DELTA_MAX},
6954 6955
#endif
#ifdef _SC_ARG_MAX
6956
    {"SC_ARG_MAX",      _SC_ARG_MAX},
6957 6958
#endif
#ifdef _SC_ASYNCHRONOUS_IO
6959
    {"SC_ASYNCHRONOUS_IO",      _SC_ASYNCHRONOUS_IO},
6960 6961
#endif
#ifdef _SC_ATEXIT_MAX
6962
    {"SC_ATEXIT_MAX",   _SC_ATEXIT_MAX},
6963
#endif
6964
#ifdef _SC_AUDIT
6965
    {"SC_AUDIT",        _SC_AUDIT},
6966
#endif
6967
#ifdef _SC_AVPHYS_PAGES
6968
    {"SC_AVPHYS_PAGES", _SC_AVPHYS_PAGES},
6969 6970
#endif
#ifdef _SC_BC_BASE_MAX
6971
    {"SC_BC_BASE_MAX",  _SC_BC_BASE_MAX},
6972 6973
#endif
#ifdef _SC_BC_DIM_MAX
6974
    {"SC_BC_DIM_MAX",   _SC_BC_DIM_MAX},
6975 6976
#endif
#ifdef _SC_BC_SCALE_MAX
6977
    {"SC_BC_SCALE_MAX", _SC_BC_SCALE_MAX},
6978 6979
#endif
#ifdef _SC_BC_STRING_MAX
6980
    {"SC_BC_STRING_MAX",        _SC_BC_STRING_MAX},
6981
#endif
6982
#ifdef _SC_CAP
6983
    {"SC_CAP",  _SC_CAP},
6984
#endif
6985
#ifdef _SC_CHARCLASS_NAME_MAX
6986
    {"SC_CHARCLASS_NAME_MAX",   _SC_CHARCLASS_NAME_MAX},
6987 6988
#endif
#ifdef _SC_CHAR_BIT
6989
    {"SC_CHAR_BIT",     _SC_CHAR_BIT},
6990 6991
#endif
#ifdef _SC_CHAR_MAX
6992
    {"SC_CHAR_MAX",     _SC_CHAR_MAX},
6993 6994
#endif
#ifdef _SC_CHAR_MIN
6995
    {"SC_CHAR_MIN",     _SC_CHAR_MIN},
6996 6997
#endif
#ifdef _SC_CHILD_MAX
6998
    {"SC_CHILD_MAX",    _SC_CHILD_MAX},
6999 7000
#endif
#ifdef _SC_CLK_TCK
7001
    {"SC_CLK_TCK",      _SC_CLK_TCK},
7002 7003
#endif
#ifdef _SC_COHER_BLKSZ
7004
    {"SC_COHER_BLKSZ",  _SC_COHER_BLKSZ},
7005 7006
#endif
#ifdef _SC_COLL_WEIGHTS_MAX
7007
    {"SC_COLL_WEIGHTS_MAX",     _SC_COLL_WEIGHTS_MAX},
7008 7009
#endif
#ifdef _SC_DCACHE_ASSOC
7010
    {"SC_DCACHE_ASSOC", _SC_DCACHE_ASSOC},
7011 7012
#endif
#ifdef _SC_DCACHE_BLKSZ
7013
    {"SC_DCACHE_BLKSZ", _SC_DCACHE_BLKSZ},
7014 7015
#endif
#ifdef _SC_DCACHE_LINESZ
7016
    {"SC_DCACHE_LINESZ",        _SC_DCACHE_LINESZ},
7017 7018
#endif
#ifdef _SC_DCACHE_SZ
7019
    {"SC_DCACHE_SZ",    _SC_DCACHE_SZ},
7020 7021
#endif
#ifdef _SC_DCACHE_TBLKSZ
7022
    {"SC_DCACHE_TBLKSZ",        _SC_DCACHE_TBLKSZ},
7023 7024
#endif
#ifdef _SC_DELAYTIMER_MAX
7025
    {"SC_DELAYTIMER_MAX",       _SC_DELAYTIMER_MAX},
7026 7027
#endif
#ifdef _SC_EQUIV_CLASS_MAX
7028
    {"SC_EQUIV_CLASS_MAX",      _SC_EQUIV_CLASS_MAX},
7029 7030
#endif
#ifdef _SC_EXPR_NEST_MAX
7031
    {"SC_EXPR_NEST_MAX",        _SC_EXPR_NEST_MAX},
7032 7033
#endif
#ifdef _SC_FSYNC
7034
    {"SC_FSYNC",        _SC_FSYNC},
7035 7036
#endif
#ifdef _SC_GETGR_R_SIZE_MAX
7037
    {"SC_GETGR_R_SIZE_MAX",     _SC_GETGR_R_SIZE_MAX},
7038 7039
#endif
#ifdef _SC_GETPW_R_SIZE_MAX
7040
    {"SC_GETPW_R_SIZE_MAX",     _SC_GETPW_R_SIZE_MAX},
7041 7042
#endif
#ifdef _SC_ICACHE_ASSOC
7043
    {"SC_ICACHE_ASSOC", _SC_ICACHE_ASSOC},
7044 7045
#endif
#ifdef _SC_ICACHE_BLKSZ
7046
    {"SC_ICACHE_BLKSZ", _SC_ICACHE_BLKSZ},
7047 7048
#endif
#ifdef _SC_ICACHE_LINESZ
7049
    {"SC_ICACHE_LINESZ",        _SC_ICACHE_LINESZ},
7050 7051
#endif
#ifdef _SC_ICACHE_SZ
7052
    {"SC_ICACHE_SZ",    _SC_ICACHE_SZ},
7053
#endif
7054
#ifdef _SC_INF
7055
    {"SC_INF",  _SC_INF},
7056
#endif
7057
#ifdef _SC_INT_MAX
7058
    {"SC_INT_MAX",      _SC_INT_MAX},
7059 7060
#endif
#ifdef _SC_INT_MIN
7061
    {"SC_INT_MIN",      _SC_INT_MIN},
7062 7063
#endif
#ifdef _SC_IOV_MAX
7064
    {"SC_IOV_MAX",      _SC_IOV_MAX},
7065
#endif
7066
#ifdef _SC_IP_SECOPTS
7067
    {"SC_IP_SECOPTS",   _SC_IP_SECOPTS},
7068
#endif
7069
#ifdef _SC_JOB_CONTROL
7070
    {"SC_JOB_CONTROL",  _SC_JOB_CONTROL},
7071
#endif
7072
#ifdef _SC_KERN_POINTERS
7073
    {"SC_KERN_POINTERS",        _SC_KERN_POINTERS},
7074 7075
#endif
#ifdef _SC_KERN_SIM
7076
    {"SC_KERN_SIM",     _SC_KERN_SIM},
7077
#endif
7078
#ifdef _SC_LINE_MAX
7079
    {"SC_LINE_MAX",     _SC_LINE_MAX},
7080 7081
#endif
#ifdef _SC_LOGIN_NAME_MAX
7082
    {"SC_LOGIN_NAME_MAX",       _SC_LOGIN_NAME_MAX},
7083 7084
#endif
#ifdef _SC_LOGNAME_MAX
7085
    {"SC_LOGNAME_MAX",  _SC_LOGNAME_MAX},
7086 7087
#endif
#ifdef _SC_LONG_BIT
7088
    {"SC_LONG_BIT",     _SC_LONG_BIT},
7089
#endif
7090
#ifdef _SC_MAC
7091
    {"SC_MAC",  _SC_MAC},
7092
#endif
7093
#ifdef _SC_MAPPED_FILES
7094
    {"SC_MAPPED_FILES", _SC_MAPPED_FILES},
7095 7096
#endif
#ifdef _SC_MAXPID
7097
    {"SC_MAXPID",       _SC_MAXPID},
7098 7099
#endif
#ifdef _SC_MB_LEN_MAX
7100
    {"SC_MB_LEN_MAX",   _SC_MB_LEN_MAX},
7101 7102
#endif
#ifdef _SC_MEMLOCK
7103
    {"SC_MEMLOCK",      _SC_MEMLOCK},
7104 7105
#endif
#ifdef _SC_MEMLOCK_RANGE
7106
    {"SC_MEMLOCK_RANGE",        _SC_MEMLOCK_RANGE},
7107 7108
#endif
#ifdef _SC_MEMORY_PROTECTION
7109
    {"SC_MEMORY_PROTECTION",    _SC_MEMORY_PROTECTION},
7110 7111
#endif
#ifdef _SC_MESSAGE_PASSING
7112
    {"SC_MESSAGE_PASSING",      _SC_MESSAGE_PASSING},
7113
#endif
7114
#ifdef _SC_MMAP_FIXED_ALIGNMENT
7115
    {"SC_MMAP_FIXED_ALIGNMENT", _SC_MMAP_FIXED_ALIGNMENT},
7116
#endif
7117
#ifdef _SC_MQ_OPEN_MAX
7118
    {"SC_MQ_OPEN_MAX",  _SC_MQ_OPEN_MAX},
7119 7120
#endif
#ifdef _SC_MQ_PRIO_MAX
7121
    {"SC_MQ_PRIO_MAX",  _SC_MQ_PRIO_MAX},
7122
#endif
7123
#ifdef _SC_NACLS_MAX
7124
    {"SC_NACLS_MAX",    _SC_NACLS_MAX},
7125
#endif
7126
#ifdef _SC_NGROUPS_MAX
7127
    {"SC_NGROUPS_MAX",  _SC_NGROUPS_MAX},
7128 7129
#endif
#ifdef _SC_NL_ARGMAX
7130
    {"SC_NL_ARGMAX",    _SC_NL_ARGMAX},
7131 7132
#endif
#ifdef _SC_NL_LANGMAX
7133
    {"SC_NL_LANGMAX",   _SC_NL_LANGMAX},
7134 7135
#endif
#ifdef _SC_NL_MSGMAX
7136
    {"SC_NL_MSGMAX",    _SC_NL_MSGMAX},
7137 7138
#endif
#ifdef _SC_NL_NMAX
7139
    {"SC_NL_NMAX",      _SC_NL_NMAX},
7140 7141
#endif
#ifdef _SC_NL_SETMAX
7142
    {"SC_NL_SETMAX",    _SC_NL_SETMAX},
7143 7144
#endif
#ifdef _SC_NL_TEXTMAX
7145
    {"SC_NL_TEXTMAX",   _SC_NL_TEXTMAX},
7146 7147
#endif
#ifdef _SC_NPROCESSORS_CONF
7148
    {"SC_NPROCESSORS_CONF",     _SC_NPROCESSORS_CONF},
7149 7150
#endif
#ifdef _SC_NPROCESSORS_ONLN
7151
    {"SC_NPROCESSORS_ONLN",     _SC_NPROCESSORS_ONLN},
7152
#endif
7153
#ifdef _SC_NPROC_CONF
7154
    {"SC_NPROC_CONF",   _SC_NPROC_CONF},
7155 7156
#endif
#ifdef _SC_NPROC_ONLN
7157
    {"SC_NPROC_ONLN",   _SC_NPROC_ONLN},
7158
#endif
7159
#ifdef _SC_NZERO
7160
    {"SC_NZERO",        _SC_NZERO},
7161 7162
#endif
#ifdef _SC_OPEN_MAX
7163
    {"SC_OPEN_MAX",     _SC_OPEN_MAX},
7164 7165
#endif
#ifdef _SC_PAGESIZE
7166
    {"SC_PAGESIZE",     _SC_PAGESIZE},
7167 7168
#endif
#ifdef _SC_PAGE_SIZE
7169
    {"SC_PAGE_SIZE",    _SC_PAGE_SIZE},
7170 7171
#endif
#ifdef _SC_PASS_MAX
7172
    {"SC_PASS_MAX",     _SC_PASS_MAX},
7173 7174
#endif
#ifdef _SC_PHYS_PAGES
7175
    {"SC_PHYS_PAGES",   _SC_PHYS_PAGES},
7176 7177
#endif
#ifdef _SC_PII
7178
    {"SC_PII",  _SC_PII},
7179 7180
#endif
#ifdef _SC_PII_INTERNET
7181
    {"SC_PII_INTERNET", _SC_PII_INTERNET},
7182 7183
#endif
#ifdef _SC_PII_INTERNET_DGRAM
7184
    {"SC_PII_INTERNET_DGRAM",   _SC_PII_INTERNET_DGRAM},
7185 7186
#endif
#ifdef _SC_PII_INTERNET_STREAM
7187
    {"SC_PII_INTERNET_STREAM",  _SC_PII_INTERNET_STREAM},
7188 7189
#endif
#ifdef _SC_PII_OSI
7190
    {"SC_PII_OSI",      _SC_PII_OSI},
7191 7192
#endif
#ifdef _SC_PII_OSI_CLTS
7193
    {"SC_PII_OSI_CLTS", _SC_PII_OSI_CLTS},
7194 7195
#endif
#ifdef _SC_PII_OSI_COTS
7196
    {"SC_PII_OSI_COTS", _SC_PII_OSI_COTS},
7197 7198
#endif
#ifdef _SC_PII_OSI_M
7199
    {"SC_PII_OSI_M",    _SC_PII_OSI_M},
7200 7201
#endif
#ifdef _SC_PII_SOCKET
7202
    {"SC_PII_SOCKET",   _SC_PII_SOCKET},
7203 7204
#endif
#ifdef _SC_PII_XTI
7205
    {"SC_PII_XTI",      _SC_PII_XTI},
7206 7207
#endif
#ifdef _SC_POLL
7208
    {"SC_POLL", _SC_POLL},
7209 7210
#endif
#ifdef _SC_PRIORITIZED_IO
7211
    {"SC_PRIORITIZED_IO",       _SC_PRIORITIZED_IO},
7212 7213
#endif
#ifdef _SC_PRIORITY_SCHEDULING
7214
    {"SC_PRIORITY_SCHEDULING",  _SC_PRIORITY_SCHEDULING},
7215 7216
#endif
#ifdef _SC_REALTIME_SIGNALS
7217
    {"SC_REALTIME_SIGNALS",     _SC_REALTIME_SIGNALS},
7218 7219
#endif
#ifdef _SC_RE_DUP_MAX
7220
    {"SC_RE_DUP_MAX",   _SC_RE_DUP_MAX},
7221 7222
#endif
#ifdef _SC_RTSIG_MAX
7223
    {"SC_RTSIG_MAX",    _SC_RTSIG_MAX},
7224 7225
#endif
#ifdef _SC_SAVED_IDS
7226
    {"SC_SAVED_IDS",    _SC_SAVED_IDS},
7227 7228
#endif
#ifdef _SC_SCHAR_MAX
7229
    {"SC_SCHAR_MAX",    _SC_SCHAR_MAX},
7230 7231
#endif
#ifdef _SC_SCHAR_MIN
7232
    {"SC_SCHAR_MIN",    _SC_SCHAR_MIN},
7233 7234
#endif
#ifdef _SC_SELECT
7235
    {"SC_SELECT",       _SC_SELECT},
7236 7237
#endif
#ifdef _SC_SEMAPHORES
7238
    {"SC_SEMAPHORES",   _SC_SEMAPHORES},
7239 7240
#endif
#ifdef _SC_SEM_NSEMS_MAX
7241
    {"SC_SEM_NSEMS_MAX",        _SC_SEM_NSEMS_MAX},
7242 7243
#endif
#ifdef _SC_SEM_VALUE_MAX
7244
    {"SC_SEM_VALUE_MAX",        _SC_SEM_VALUE_MAX},
7245 7246
#endif
#ifdef _SC_SHARED_MEMORY_OBJECTS
7247
    {"SC_SHARED_MEMORY_OBJECTS",        _SC_SHARED_MEMORY_OBJECTS},
7248 7249
#endif
#ifdef _SC_SHRT_MAX
7250
    {"SC_SHRT_MAX",     _SC_SHRT_MAX},
7251 7252
#endif
#ifdef _SC_SHRT_MIN
7253
    {"SC_SHRT_MIN",     _SC_SHRT_MIN},
7254 7255
#endif
#ifdef _SC_SIGQUEUE_MAX
7256
    {"SC_SIGQUEUE_MAX", _SC_SIGQUEUE_MAX},
7257 7258
#endif
#ifdef _SC_SIGRT_MAX
7259
    {"SC_SIGRT_MAX",    _SC_SIGRT_MAX},
7260 7261
#endif
#ifdef _SC_SIGRT_MIN
7262
    {"SC_SIGRT_MIN",    _SC_SIGRT_MIN},
7263
#endif
7264
#ifdef _SC_SOFTPOWER
7265
    {"SC_SOFTPOWER",    _SC_SOFTPOWER},
7266
#endif
7267
#ifdef _SC_SPLIT_CACHE
7268
    {"SC_SPLIT_CACHE",  _SC_SPLIT_CACHE},
7269 7270
#endif
#ifdef _SC_SSIZE_MAX
7271
    {"SC_SSIZE_MAX",    _SC_SSIZE_MAX},
7272 7273
#endif
#ifdef _SC_STACK_PROT
7274
    {"SC_STACK_PROT",   _SC_STACK_PROT},
7275 7276
#endif
#ifdef _SC_STREAM_MAX
7277
    {"SC_STREAM_MAX",   _SC_STREAM_MAX},
7278 7279
#endif
#ifdef _SC_SYNCHRONIZED_IO
7280
    {"SC_SYNCHRONIZED_IO",      _SC_SYNCHRONIZED_IO},
7281 7282
#endif
#ifdef _SC_THREADS
7283
    {"SC_THREADS",      _SC_THREADS},
7284 7285
#endif
#ifdef _SC_THREAD_ATTR_STACKADDR
7286
    {"SC_THREAD_ATTR_STACKADDR",        _SC_THREAD_ATTR_STACKADDR},
7287 7288
#endif
#ifdef _SC_THREAD_ATTR_STACKSIZE
7289
    {"SC_THREAD_ATTR_STACKSIZE",        _SC_THREAD_ATTR_STACKSIZE},
7290 7291
#endif
#ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS
7292
    {"SC_THREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS},
7293 7294
#endif
#ifdef _SC_THREAD_KEYS_MAX
7295
    {"SC_THREAD_KEYS_MAX",      _SC_THREAD_KEYS_MAX},
7296 7297
#endif
#ifdef _SC_THREAD_PRIORITY_SCHEDULING
7298
    {"SC_THREAD_PRIORITY_SCHEDULING",   _SC_THREAD_PRIORITY_SCHEDULING},
7299 7300
#endif
#ifdef _SC_THREAD_PRIO_INHERIT
7301
    {"SC_THREAD_PRIO_INHERIT",  _SC_THREAD_PRIO_INHERIT},
7302 7303
#endif
#ifdef _SC_THREAD_PRIO_PROTECT
7304
    {"SC_THREAD_PRIO_PROTECT",  _SC_THREAD_PRIO_PROTECT},
7305 7306
#endif
#ifdef _SC_THREAD_PROCESS_SHARED
7307
    {"SC_THREAD_PROCESS_SHARED",        _SC_THREAD_PROCESS_SHARED},
7308 7309
#endif
#ifdef _SC_THREAD_SAFE_FUNCTIONS
7310
    {"SC_THREAD_SAFE_FUNCTIONS",        _SC_THREAD_SAFE_FUNCTIONS},
7311 7312
#endif
#ifdef _SC_THREAD_STACK_MIN
7313
    {"SC_THREAD_STACK_MIN",     _SC_THREAD_STACK_MIN},
7314 7315
#endif
#ifdef _SC_THREAD_THREADS_MAX
7316
    {"SC_THREAD_THREADS_MAX",   _SC_THREAD_THREADS_MAX},
7317 7318
#endif
#ifdef _SC_TIMERS
7319
    {"SC_TIMERS",       _SC_TIMERS},
7320 7321
#endif
#ifdef _SC_TIMER_MAX
7322
    {"SC_TIMER_MAX",    _SC_TIMER_MAX},
7323 7324
#endif
#ifdef _SC_TTY_NAME_MAX
7325
    {"SC_TTY_NAME_MAX", _SC_TTY_NAME_MAX},
7326 7327
#endif
#ifdef _SC_TZNAME_MAX
7328
    {"SC_TZNAME_MAX",   _SC_TZNAME_MAX},
7329 7330
#endif
#ifdef _SC_T_IOV_MAX
7331
    {"SC_T_IOV_MAX",    _SC_T_IOV_MAX},
7332 7333
#endif
#ifdef _SC_UCHAR_MAX
7334
    {"SC_UCHAR_MAX",    _SC_UCHAR_MAX},
7335 7336
#endif
#ifdef _SC_UINT_MAX
7337
    {"SC_UINT_MAX",     _SC_UINT_MAX},
7338 7339
#endif
#ifdef _SC_UIO_MAXIOV
7340
    {"SC_UIO_MAXIOV",   _SC_UIO_MAXIOV},
7341 7342
#endif
#ifdef _SC_ULONG_MAX
7343
    {"SC_ULONG_MAX",    _SC_ULONG_MAX},
7344 7345
#endif
#ifdef _SC_USHRT_MAX
7346
    {"SC_USHRT_MAX",    _SC_USHRT_MAX},
7347 7348
#endif
#ifdef _SC_VERSION
7349
    {"SC_VERSION",      _SC_VERSION},
7350 7351
#endif
#ifdef _SC_WORD_BIT
7352
    {"SC_WORD_BIT",     _SC_WORD_BIT},
7353 7354
#endif
#ifdef _SC_XBS5_ILP32_OFF32
7355
    {"SC_XBS5_ILP32_OFF32",     _SC_XBS5_ILP32_OFF32},
7356 7357
#endif
#ifdef _SC_XBS5_ILP32_OFFBIG
7358
    {"SC_XBS5_ILP32_OFFBIG",    _SC_XBS5_ILP32_OFFBIG},
7359 7360
#endif
#ifdef _SC_XBS5_LP64_OFF64
7361
    {"SC_XBS5_LP64_OFF64",      _SC_XBS5_LP64_OFF64},
7362 7363
#endif
#ifdef _SC_XBS5_LPBIG_OFFBIG
7364
    {"SC_XBS5_LPBIG_OFFBIG",    _SC_XBS5_LPBIG_OFFBIG},
7365 7366
#endif
#ifdef _SC_XOPEN_CRYPT
7367
    {"SC_XOPEN_CRYPT",  _SC_XOPEN_CRYPT},
7368 7369
#endif
#ifdef _SC_XOPEN_ENH_I18N
7370
    {"SC_XOPEN_ENH_I18N",       _SC_XOPEN_ENH_I18N},
7371 7372
#endif
#ifdef _SC_XOPEN_LEGACY
7373
    {"SC_XOPEN_LEGACY", _SC_XOPEN_LEGACY},
7374 7375
#endif
#ifdef _SC_XOPEN_REALTIME
7376
    {"SC_XOPEN_REALTIME",       _SC_XOPEN_REALTIME},
7377 7378
#endif
#ifdef _SC_XOPEN_REALTIME_THREADS
7379
    {"SC_XOPEN_REALTIME_THREADS",       _SC_XOPEN_REALTIME_THREADS},
7380 7381
#endif
#ifdef _SC_XOPEN_SHM
7382
    {"SC_XOPEN_SHM",    _SC_XOPEN_SHM},
7383 7384
#endif
#ifdef _SC_XOPEN_UNIX
7385
    {"SC_XOPEN_UNIX",   _SC_XOPEN_UNIX},
7386 7387
#endif
#ifdef _SC_XOPEN_VERSION
7388
    {"SC_XOPEN_VERSION",        _SC_XOPEN_VERSION},
7389 7390
#endif
#ifdef _SC_XOPEN_XCU_VERSION
7391
    {"SC_XOPEN_XCU_VERSION",    _SC_XOPEN_XCU_VERSION},
7392 7393
#endif
#ifdef _SC_XOPEN_XPG2
7394
    {"SC_XOPEN_XPG2",   _SC_XOPEN_XPG2},
7395 7396
#endif
#ifdef _SC_XOPEN_XPG3
7397
    {"SC_XOPEN_XPG3",   _SC_XOPEN_XPG3},
7398 7399
#endif
#ifdef _SC_XOPEN_XPG4
7400
    {"SC_XOPEN_XPG4",   _SC_XOPEN_XPG4},
7401 7402 7403 7404
#endif
};

static int
7405
conv_sysconf_confname(PyObject *arg, int *valuep)
7406 7407 7408 7409 7410 7411
{
    return conv_confname(arg, valuep, posix_constants_sysconf,
                         sizeof(posix_constants_sysconf)
                           / sizeof(struct constdef));
}

7412
PyDoc_STRVAR(posix_sysconf__doc__,
Fred Drake's avatar
Fred Drake committed
7413
"sysconf(name) -> integer\n\n\
7414
Return an integer-valued system configuration variable.");
7415 7416

static PyObject *
7417
posix_sysconf(PyObject *self, PyObject *args)
7418 7419 7420 7421 7422 7423 7424 7425 7426 7427 7428 7429
{
    PyObject *result = NULL;
    int name;

    if (PyArg_ParseTuple(args, "O&:sysconf", conv_sysconf_confname, &name)) {
        int value;

        errno = 0;
        value = sysconf(name);
        if (value == -1 && errno != 0)
            posix_error();
        else
7430
            result = PyLong_FromLong(value);
7431 7432 7433 7434 7435 7436
    }
    return result;
}
#endif


7437 7438 7439 7440 7441 7442 7443 7444
/* This code is used to ensure that the tables of configuration value names
 * are in sorted order as required by conv_confname(), and also to build the
 * the exported dictionaries that are used to publish information about the
 * names available on the host platform.
 *
 * Sorting the table at runtime ensures that the table is properly ordered
 * when used, even for platforms we're not able to test on.  It also makes
 * it easier to add additional entries to the tables.
7445
 */
7446 7447

static int
7448
cmp_constdefs(const void *v1,  const void *v2)
7449 7450
{
    const struct constdef *c1 =
7451
    (const struct constdef *) v1;
7452
    const struct constdef *c2 =
7453
    (const struct constdef *) v2;
7454 7455 7456 7457 7458

    return strcmp(c1->name, c2->name);
}

static int
7459
setup_confname_table(struct constdef *table, size_t tablesize,
7460
                     char *tablename, PyObject *module)
7461
{
7462
    PyObject *d = NULL;
7463
    size_t i;
7464

7465 7466
    qsort(table, tablesize, sizeof(struct constdef), cmp_constdefs);
    d = PyDict_New();
7467
    if (d == NULL)
7468
        return -1;
7469 7470

    for (i=0; i < tablesize; ++i) {
7471 7472 7473 7474 7475 7476 7477
        PyObject *o = PyLong_FromLong(table[i].value);
        if (o == NULL || PyDict_SetItemString(d, table[i].name, o) == -1) {
            Py_XDECREF(o);
            Py_DECREF(d);
            return -1;
        }
        Py_DECREF(o);
7478
    }
7479
    return PyModule_AddObject(module, tablename, d);
7480 7481
}

7482 7483
/* Return -1 on failure, 0 on success. */
static int
7484
setup_confname_tables(PyObject *module)
7485 7486
{
#if defined(HAVE_FPATHCONF) || defined(HAVE_PATHCONF)
7487
    if (setup_confname_table(posix_constants_pathconf,
7488 7489
                             sizeof(posix_constants_pathconf)
                               / sizeof(struct constdef),
7490
                             "pathconf_names", module))
Stefan Krah's avatar
Stefan Krah committed
7491
        return -1;
7492 7493
#endif
#ifdef HAVE_CONFSTR
7494
    if (setup_confname_table(posix_constants_confstr,
7495 7496
                             sizeof(posix_constants_confstr)
                               / sizeof(struct constdef),
7497
                             "confstr_names", module))
Stefan Krah's avatar
Stefan Krah committed
7498
        return -1;
7499 7500
#endif
#ifdef HAVE_SYSCONF
7501
    if (setup_confname_table(posix_constants_sysconf,
7502 7503
                             sizeof(posix_constants_sysconf)
                               / sizeof(struct constdef),
7504
                             "sysconf_names", module))
Stefan Krah's avatar
Stefan Krah committed
7505
        return -1;
7506
#endif
7507
    return 0;
7508 7509 7510
}


7511
PyDoc_STRVAR(posix_abort__doc__,
Fred Drake's avatar
Fred Drake committed
7512
"abort() -> does not return!\n\n\
7513
Abort the interpreter immediately.  This 'dumps core' or otherwise fails\n\
7514
in the hardest way possible on the hosting operating system.");
7515 7516

static PyObject *
7517
posix_abort(PyObject *self, PyObject *noargs)
7518 7519 7520 7521 7522 7523
{
    abort();
    /*NOTREACHED*/
    Py_FatalError("abort() called from Python code didn't abort!");
    return NULL;
}
7524

7525
#ifdef MS_WINDOWS
7526
PyDoc_STRVAR(win32_startfile__doc__,
7527 7528
"startfile(filepath [, operation]) - Start a file with its associated\n\
application.\n\
7529
\n\
7530 7531 7532 7533 7534 7535
When \"operation\" is not specified or \"open\", this acts like\n\
double-clicking the file in Explorer, or giving the file name as an\n\
argument to the DOS \"start\" command: the file is opened with whatever\n\
application (if any) its extension is associated.\n\
When another \"operation\" is given, it specifies what should be done with\n\
the file.  A typical operation is \"print\".\n\
7536 7537 7538 7539 7540 7541 7542
\n\
startfile returns as soon as the associated application is launched.\n\
There is no option to wait for the application to close, and no way\n\
to retrieve the application's exit status.\n\
\n\
The filepath is relative to the current directory.  If you want to use\n\
an absolute path, make sure the first character is not a slash (\"/\");\n\
7543
the underlying Win32 ShellExecute function doesn't work if it is.");
7544 7545 7546 7547

static PyObject *
win32_startfile(PyObject *self, PyObject *args)
{
7548 7549 7550 7551 7552 7553 7554 7555 7556 7557 7558 7559 7560 7561 7562 7563 7564 7565 7566 7567 7568 7569 7570 7571 7572 7573 7574 7575 7576 7577 7578 7579 7580 7581 7582 7583
    PyObject *ofilepath;
    char *filepath;
    char *operation = NULL;
    HINSTANCE rc;

    PyObject *unipath, *woperation = NULL;
    if (!PyArg_ParseTuple(args, "U|s:startfile",
                          &unipath, &operation)) {
        PyErr_Clear();
        goto normal;
    }

    if (operation) {
        woperation = PyUnicode_DecodeASCII(operation,
                                           strlen(operation), NULL);
        if (!woperation) {
            PyErr_Clear();
            operation = NULL;
            goto normal;
        }
    }

    Py_BEGIN_ALLOW_THREADS
    rc = ShellExecuteW((HWND)0, woperation ? PyUnicode_AS_UNICODE(woperation) : 0,
        PyUnicode_AS_UNICODE(unipath),
        NULL, NULL, SW_SHOWNORMAL);
    Py_END_ALLOW_THREADS

    Py_XDECREF(woperation);
    if (rc <= (HINSTANCE)32) {
        PyObject *errval = win32_error_unicode("startfile",
                                               PyUnicode_AS_UNICODE(unipath));
        return errval;
    }
    Py_INCREF(Py_None);
    return Py_None;
7584 7585

normal:
7586 7587 7588 7589 7590 7591 7592 7593 7594 7595 7596 7597 7598 7599 7600 7601 7602
    if (!PyArg_ParseTuple(args, "O&|s:startfile",
                          PyUnicode_FSConverter, &ofilepath,
                          &operation))
        return NULL;
    filepath = PyBytes_AsString(ofilepath);
    Py_BEGIN_ALLOW_THREADS
    rc = ShellExecute((HWND)0, operation, filepath,
                      NULL, NULL, SW_SHOWNORMAL);
    Py_END_ALLOW_THREADS
    if (rc <= (HINSTANCE)32) {
        PyObject *errval = win32_error("startfile", filepath);
        Py_DECREF(ofilepath);
        return errval;
    }
    Py_DECREF(ofilepath);
    Py_INCREF(Py_None);
    return Py_None;
7603 7604
}
#endif
7605

7606 7607 7608 7609 7610 7611 7612 7613
#ifdef HAVE_GETLOADAVG
PyDoc_STRVAR(posix_getloadavg__doc__,
"getloadavg() -> (float, float, float)\n\n\
Return the number of processes in the system run queue averaged over\n\
the last 1, 5, and 15 minutes or raises OSError if the load average\n\
was unobtainable");

static PyObject *
7614
posix_getloadavg(PyObject *self, PyObject *noargs)
7615 7616 7617
{
    double loadavg[3];
    if (getloadavg(loadavg, 3)!=3) {
Stefan Krah's avatar
Stefan Krah committed
7618 7619
        PyErr_SetString(PyExc_OSError, "Load averages are unobtainable");
        return NULL;
7620
    } else
Stefan Krah's avatar
Stefan Krah committed
7621
        return Py_BuildValue("ddd", loadavg[0], loadavg[1], loadavg[2]);
7622 7623 7624
}
#endif

7625 7626 7627 7628
#ifdef MS_WINDOWS

PyDoc_STRVAR(win32_urandom__doc__,
"urandom(n) -> str\n\n\
7629
Return n random bytes suitable for cryptographic use.");
7630 7631 7632 7633 7634 7635 7636 7637

typedef BOOL (WINAPI *CRYPTACQUIRECONTEXTA)(HCRYPTPROV *phProv,\
              LPCSTR pszContainer, LPCSTR pszProvider, DWORD dwProvType,\
              DWORD dwFlags );
typedef BOOL (WINAPI *CRYPTGENRANDOM)(HCRYPTPROV hProv, DWORD dwLen,\
              BYTE *pbBuffer );

static CRYPTGENRANDOM pCryptGenRandom = NULL;
7638 7639
/* This handle is never explicitly released. Instead, the operating
   system will release it when the process terminates. */
7640 7641
static HCRYPTPROV hCryptProv = 0;

7642 7643
static PyObject*
win32_urandom(PyObject *self, PyObject *args)
7644
{
7645 7646 7647 7648 7649 7650 7651 7652 7653 7654 7655 7656 7657 7658 7659 7660 7661 7662 7663 7664 7665 7666 7667 7668 7669 7670 7671 7672 7673 7674 7675 7676 7677 7678 7679 7680 7681 7682 7683 7684 7685 7686 7687 7688 7689 7690 7691 7692 7693 7694 7695 7696 7697
    int howMany;
    PyObject* result;

    /* Read arguments */
    if (! PyArg_ParseTuple(args, "i:urandom", &howMany))
        return NULL;
    if (howMany < 0)
        return PyErr_Format(PyExc_ValueError,
                            "negative argument not allowed");

    if (hCryptProv == 0) {
        HINSTANCE hAdvAPI32 = NULL;
        CRYPTACQUIRECONTEXTA pCryptAcquireContext = NULL;

        /* Obtain handle to the DLL containing CryptoAPI
           This should not fail         */
        hAdvAPI32 = GetModuleHandle("advapi32.dll");
        if(hAdvAPI32 == NULL)
            return win32_error("GetModuleHandle", NULL);

        /* Obtain pointers to the CryptoAPI functions
           This will fail on some early versions of Win95 */
        pCryptAcquireContext = (CRYPTACQUIRECONTEXTA)GetProcAddress(
                                        hAdvAPI32,
                                        "CryptAcquireContextA");
        if (pCryptAcquireContext == NULL)
            return PyErr_Format(PyExc_NotImplementedError,
                                "CryptAcquireContextA not found");

        pCryptGenRandom = (CRYPTGENRANDOM)GetProcAddress(
                                        hAdvAPI32, "CryptGenRandom");
        if (pCryptGenRandom == NULL)
            return PyErr_Format(PyExc_NotImplementedError,
                                "CryptGenRandom not found");

        /* Acquire context */
        if (! pCryptAcquireContext(&hCryptProv, NULL, NULL,
                                   PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
            return win32_error("CryptAcquireContext", NULL);
    }

    /* Allocate bytes */
    result = PyBytes_FromStringAndSize(NULL, howMany);
    if (result != NULL) {
        /* Get random data */
        memset(PyBytes_AS_STRING(result), 0, howMany); /* zero seed */
        if (! pCryptGenRandom(hCryptProv, howMany, (unsigned char*)
                              PyBytes_AS_STRING(result))) {
            Py_DECREF(result);
            return win32_error("CryptGenRandom", NULL);
        }
    }
    return result;
7698 7699
}
#endif
7700

7701 7702 7703 7704 7705 7706 7707 7708
PyDoc_STRVAR(device_encoding__doc__,
"device_encoding(fd) -> str\n\n\
Return a string describing the encoding of the device\n\
if the output is a terminal; else return None.");

static PyObject *
device_encoding(PyObject *self, PyObject *args)
{
7709 7710 7711 7712 7713 7714 7715
    int fd;
    if (!PyArg_ParseTuple(args, "i:device_encoding", &fd))
        return NULL;
    if (!_PyVerify_fd(fd) || !isatty(fd)) {
        Py_INCREF(Py_None);
        return Py_None;
    }
7716
#if defined(MS_WINDOWS) || defined(MS_WIN64)
7717 7718 7719 7720 7721 7722 7723 7724 7725 7726
    if (fd == 0) {
        char buf[100];
        sprintf(buf, "cp%d", GetConsoleCP());
        return PyUnicode_FromString(buf);
    }
    if (fd == 1 || fd == 2) {
        char buf[100];
        sprintf(buf, "cp%d", GetConsoleOutputCP());
        return PyUnicode_FromString(buf);
    }
7727
#elif defined(CODESET)
7728 7729 7730 7731 7732
    {
        char *codeset = nl_langinfo(CODESET);
        if (codeset != NULL && codeset[0] != 0)
            return PyUnicode_FromString(codeset);
    }
7733
#endif
7734 7735
    Py_INCREF(Py_None);
    return Py_None;
7736 7737
}

7738 7739 7740 7741 7742
#ifdef __VMS
/* Use openssl random routine */
#include <openssl/rand.h>
PyDoc_STRVAR(vms_urandom__doc__,
"urandom(n) -> str\n\n\
7743
Return n random bytes suitable for cryptographic use.");
7744 7745 7746 7747

static PyObject*
vms_urandom(PyObject *self, PyObject *args)
{
7748 7749
    int howMany;
    PyObject* result;
7750

7751 7752 7753 7754 7755 7756 7757 7758 7759 7760 7761 7762 7763 7764 7765 7766 7767 7768 7769 7770
    /* Read arguments */
    if (! PyArg_ParseTuple(args, "i:urandom", &howMany))
        return NULL;
    if (howMany < 0)
        return PyErr_Format(PyExc_ValueError,
                            "negative argument not allowed");

    /* Allocate bytes */
    result = PyBytes_FromStringAndSize(NULL, howMany);
    if (result != NULL) {
        /* Get random data */
        if (RAND_pseudo_bytes((unsigned char*)
                              PyBytes_AS_STRING(result),
                              howMany) < 0) {
            Py_DECREF(result);
            return PyErr_Format(PyExc_ValueError,
                                "RAND_pseudo_bytes");
        }
    }
    return result;
7771 7772 7773
}
#endif

7774 7775 7776 7777 7778 7779 7780 7781
#ifdef HAVE_SETRESUID
PyDoc_STRVAR(posix_setresuid__doc__,
"setresuid(ruid, euid, suid)\n\n\
Set the current process's real, effective, and saved user ids.");

static PyObject*
posix_setresuid (PyObject *self, PyObject *args)
{
7782 7783 7784 7785 7786 7787 7788
    /* We assume uid_t is no larger than a long. */
    long ruid, euid, suid;
    if (!PyArg_ParseTuple(args, "lll", &ruid, &euid, &suid))
        return NULL;
    if (setresuid(ruid, euid, suid) < 0)
        return posix_error();
    Py_RETURN_NONE;
7789 7790 7791 7792 7793 7794 7795 7796 7797 7798 7799
}
#endif

#ifdef HAVE_SETRESGID
PyDoc_STRVAR(posix_setresgid__doc__,
"setresgid(rgid, egid, sgid)\n\n\
Set the current process's real, effective, and saved group ids.");

static PyObject*
posix_setresgid (PyObject *self, PyObject *args)
{
7800 7801 7802 7803 7804 7805 7806
    /* We assume uid_t is no larger than a long. */
    long rgid, egid, sgid;
    if (!PyArg_ParseTuple(args, "lll", &rgid, &egid, &sgid))
        return NULL;
    if (setresgid(rgid, egid, sgid) < 0)
        return posix_error();
    Py_RETURN_NONE;
7807 7808 7809 7810 7811 7812 7813 7814 7815 7816 7817
}
#endif

#ifdef HAVE_GETRESUID
PyDoc_STRVAR(posix_getresuid__doc__,
"getresuid() -> (ruid, euid, suid)\n\n\
Get tuple of the current process's real, effective, and saved user ids.");

static PyObject*
posix_getresuid (PyObject *self, PyObject *noargs)
{
7818 7819 7820 7821 7822 7823 7824 7825 7826
    uid_t ruid, euid, suid;
    long l_ruid, l_euid, l_suid;
    if (getresuid(&ruid, &euid, &suid) < 0)
        return posix_error();
    /* Force the values into long's as we don't know the size of uid_t. */
    l_ruid = ruid;
    l_euid = euid;
    l_suid = suid;
    return Py_BuildValue("(lll)", l_ruid, l_euid, l_suid);
7827 7828 7829 7830 7831 7832
}
#endif

#ifdef HAVE_GETRESGID
PyDoc_STRVAR(posix_getresgid__doc__,
"getresgid() -> (rgid, egid, sgid)\n\n\
7833
Get tuple of the current process's real, effective, and saved group ids.");
7834 7835 7836 7837

static PyObject*
posix_getresgid (PyObject *self, PyObject *noargs)
{
7838 7839 7840 7841 7842 7843 7844 7845 7846
    uid_t rgid, egid, sgid;
    long l_rgid, l_egid, l_sgid;
    if (getresgid(&rgid, &egid, &sgid) < 0)
        return posix_error();
    /* Force the values into long's as we don't know the size of uid_t. */
    l_rgid = rgid;
    l_egid = egid;
    l_sgid = sgid;
    return Py_BuildValue("(lll)", l_rgid, l_egid, l_sgid);
7847 7848 7849
}
#endif

Barry Warsaw's avatar
Barry Warsaw committed
7850
static PyMethodDef posix_methods[] = {
7851
    {"access",          posix_access, METH_VARARGS, posix_access__doc__},
7852
#ifdef HAVE_TTYNAME
7853
    {"ttyname",         posix_ttyname, METH_VARARGS, posix_ttyname__doc__},
7854
#endif
7855
    {"chdir",           posix_chdir, METH_VARARGS, posix_chdir__doc__},
7856
#ifdef HAVE_CHFLAGS
7857
    {"chflags",         posix_chflags, METH_VARARGS, posix_chflags__doc__},
7858
#endif /* HAVE_CHFLAGS */
7859
    {"chmod",           posix_chmod, METH_VARARGS, posix_chmod__doc__},
7860
#ifdef HAVE_FCHMOD
7861
    {"fchmod",          posix_fchmod, METH_VARARGS, posix_fchmod__doc__},
7862
#endif /* HAVE_FCHMOD */
7863
#ifdef HAVE_CHOWN
7864
    {"chown",           posix_chown, METH_VARARGS, posix_chown__doc__},
7865
#endif /* HAVE_CHOWN */
7866
#ifdef HAVE_LCHMOD
7867
    {"lchmod",          posix_lchmod, METH_VARARGS, posix_lchmod__doc__},
7868 7869
#endif /* HAVE_LCHMOD */
#ifdef HAVE_FCHOWN
7870
    {"fchown",          posix_fchown, METH_VARARGS, posix_fchown__doc__},
7871
#endif /* HAVE_FCHOWN */
7872
#ifdef HAVE_LCHFLAGS
7873
    {"lchflags",        posix_lchflags, METH_VARARGS, posix_lchflags__doc__},
7874
#endif /* HAVE_LCHFLAGS */
7875
#ifdef HAVE_LCHOWN
7876
    {"lchown",          posix_lchown, METH_VARARGS, posix_lchown__doc__},
7877
#endif /* HAVE_LCHOWN */
7878
#ifdef HAVE_CHROOT
7879
    {"chroot",          posix_chroot, METH_VARARGS, posix_chroot__doc__},
7880
#endif
7881
#ifdef HAVE_CTERMID
7882
    {"ctermid",         posix_ctermid, METH_NOARGS, posix_ctermid__doc__},
7883
#endif
7884
#ifdef HAVE_GETCWD
7885 7886 7887 7888
    {"getcwd",          (PyCFunction)posix_getcwd_unicode,
    METH_NOARGS, posix_getcwd__doc__},
    {"getcwdb",         (PyCFunction)posix_getcwd_bytes,
    METH_NOARGS, posix_getcwdb__doc__},
7889
#endif
7890
#ifdef HAVE_LINK
7891
    {"link",            posix_link, METH_VARARGS, posix_link__doc__},
7892
#endif /* HAVE_LINK */
7893 7894 7895
    {"listdir",         posix_listdir, METH_VARARGS, posix_listdir__doc__},
    {"lstat",           posix_lstat, METH_VARARGS, posix_lstat__doc__},
    {"mkdir",           posix_mkdir, METH_VARARGS, posix_mkdir__doc__},
7896
#ifdef HAVE_NICE
7897
    {"nice",            posix_nice, METH_VARARGS, posix_nice__doc__},
7898
#endif /* HAVE_NICE */
7899
#ifdef HAVE_READLINK
7900
    {"readlink",        posix_readlink, METH_VARARGS, posix_readlink__doc__},
7901
#endif /* HAVE_READLINK */
7902
#if !defined(HAVE_READLINK) && defined(MS_WINDOWS)
7903
    {"readlink",        win_readlink, METH_VARARGS, win_readlink__doc__},
7904
#endif /* !defined(HAVE_READLINK) && defined(MS_WINDOWS) */
7905 7906 7907
    {"rename",          posix_rename, METH_VARARGS, posix_rename__doc__},
    {"rmdir",           posix_rmdir, METH_VARARGS, posix_rmdir__doc__},
    {"stat",            posix_stat, METH_VARARGS, posix_stat__doc__},
7908
    {"stat_float_times", stat_float_times, METH_VARARGS, stat_float_times__doc__},
7909
#if defined(HAVE_SYMLINK) && !defined(MS_WINDOWS)
7910
    {"symlink",         posix_symlink, METH_VARARGS, posix_symlink__doc__},
7911
#endif /* HAVE_SYMLINK */
7912
#if defined(HAVE_SYMLINK) && defined(MS_WINDOWS)
7913
    {"symlink", (PyCFunction)win_symlink, METH_VARARGS | METH_KEYWORDS,
7914 7915
                 win_symlink__doc__},
#endif /* defined(HAVE_SYMLINK) && defined(MS_WINDOWS) */
7916
#ifdef HAVE_SYSTEM
7917
    {"system",          posix_system, METH_VARARGS, posix_system__doc__},
7918
#endif
7919
    {"umask",           posix_umask, METH_VARARGS, posix_umask__doc__},
7920
#ifdef HAVE_UNAME
7921
    {"uname",           posix_uname, METH_NOARGS, posix_uname__doc__},
7922
#endif /* HAVE_UNAME */
7923 7924 7925
    {"unlink",          posix_unlink, METH_VARARGS, posix_unlink__doc__},
    {"remove",          posix_unlink, METH_VARARGS, posix_remove__doc__},
    {"utime",           posix_utime, METH_VARARGS, posix_utime__doc__},
7926
#ifdef HAVE_TIMES
7927
    {"times",           posix_times, METH_NOARGS, posix_times__doc__},
7928
#endif /* HAVE_TIMES */
7929
    {"_exit",           posix__exit, METH_VARARGS, posix__exit__doc__},
7930
#ifdef HAVE_EXECV
7931 7932
    {"execv",           posix_execv, METH_VARARGS, posix_execv__doc__},
    {"execve",          posix_execve, METH_VARARGS, posix_execve__doc__},
7933
#endif /* HAVE_EXECV */
7934
#ifdef HAVE_SPAWNV
7935 7936
    {"spawnv",          posix_spawnv, METH_VARARGS, posix_spawnv__doc__},
    {"spawnve",         posix_spawnve, METH_VARARGS, posix_spawnve__doc__},
7937
#if defined(PYOS_OS2)
7938 7939
    {"spawnvp",         posix_spawnvp, METH_VARARGS, posix_spawnvp__doc__},
    {"spawnvpe",        posix_spawnvpe, METH_VARARGS, posix_spawnvpe__doc__},
7940
#endif /* PYOS_OS2 */
7941
#endif /* HAVE_SPAWNV */
7942
#ifdef HAVE_FORK1
7943
    {"fork1",       posix_fork1, METH_NOARGS, posix_fork1__doc__},
7944
#endif /* HAVE_FORK1 */
Guido van Rossum's avatar
Guido van Rossum committed
7945
#ifdef HAVE_FORK
7946
    {"fork",            posix_fork, METH_NOARGS, posix_fork__doc__},
Guido van Rossum's avatar
Guido van Rossum committed
7947
#endif /* HAVE_FORK */
7948
#if defined(HAVE_OPENPTY) || defined(HAVE__GETPTY) || defined(HAVE_DEV_PTMX)
7949
    {"openpty",         posix_openpty, METH_NOARGS, posix_openpty__doc__},
7950
#endif /* HAVE_OPENPTY || HAVE__GETPTY || HAVE_DEV_PTMX */
7951
#ifdef HAVE_FORKPTY
7952
    {"forkpty",         posix_forkpty, METH_NOARGS, posix_forkpty__doc__},
7953
#endif /* HAVE_FORKPTY */
Guido van Rossum's avatar
Guido van Rossum committed
7954
#ifdef HAVE_GETEGID
7955
    {"getegid",         posix_getegid, METH_NOARGS, posix_getegid__doc__},
Guido van Rossum's avatar
Guido van Rossum committed
7956 7957
#endif /* HAVE_GETEGID */
#ifdef HAVE_GETEUID
7958
    {"geteuid",         posix_geteuid, METH_NOARGS, posix_geteuid__doc__},
Guido van Rossum's avatar
Guido van Rossum committed
7959 7960
#endif /* HAVE_GETEUID */
#ifdef HAVE_GETGID
7961
    {"getgid",          posix_getgid, METH_NOARGS, posix_getgid__doc__},
Guido van Rossum's avatar
Guido van Rossum committed
7962
#endif /* HAVE_GETGID */
7963
#ifdef HAVE_GETGROUPS
7964
    {"getgroups",       posix_getgroups, METH_NOARGS, posix_getgroups__doc__},
7965
#endif
7966
    {"getpid",          posix_getpid, METH_NOARGS, posix_getpid__doc__},
7967
#ifdef HAVE_GETPGRP
7968
    {"getpgrp",         posix_getpgrp, METH_NOARGS, posix_getpgrp__doc__},
7969
#endif /* HAVE_GETPGRP */
Guido van Rossum's avatar
Guido van Rossum committed
7970
#ifdef HAVE_GETPPID
7971
    {"getppid",         posix_getppid, METH_NOARGS, posix_getppid__doc__},
Guido van Rossum's avatar
Guido van Rossum committed
7972 7973
#endif /* HAVE_GETPPID */
#ifdef HAVE_GETUID
7974
    {"getuid",          posix_getuid, METH_NOARGS, posix_getuid__doc__},
Guido van Rossum's avatar
Guido van Rossum committed
7975
#endif /* HAVE_GETUID */
7976
#ifdef HAVE_GETLOGIN
7977
    {"getlogin",        posix_getlogin, METH_NOARGS, posix_getlogin__doc__},
7978
#endif
Guido van Rossum's avatar
Guido van Rossum committed
7979
#ifdef HAVE_KILL
7980
    {"kill",            posix_kill, METH_VARARGS, posix_kill__doc__},
Guido van Rossum's avatar
Guido van Rossum committed
7981
#endif /* HAVE_KILL */
7982
#ifdef HAVE_KILLPG
7983
    {"killpg",          posix_killpg, METH_VARARGS, posix_killpg__doc__},
7984
#endif /* HAVE_KILLPG */
7985
#ifdef HAVE_PLOCK
7986
    {"plock",           posix_plock, METH_VARARGS, posix_plock__doc__},
7987
#endif /* HAVE_PLOCK */
7988
#ifdef MS_WINDOWS
7989 7990
    {"startfile",       win32_startfile, METH_VARARGS, win32_startfile__doc__},
    {"kill",    win32_kill, METH_VARARGS, win32_kill__doc__},
7991
    {"link",    win32_link, METH_VARARGS, win32_link__doc__},
7992
#endif
7993
#ifdef HAVE_SETUID
7994
    {"setuid",          posix_setuid, METH_VARARGS, posix_setuid__doc__},
7995
#endif /* HAVE_SETUID */
7996
#ifdef HAVE_SETEUID
7997
    {"seteuid",         posix_seteuid, METH_VARARGS, posix_seteuid__doc__},
7998 7999
#endif /* HAVE_SETEUID */
#ifdef HAVE_SETEGID
8000
    {"setegid",         posix_setegid, METH_VARARGS, posix_setegid__doc__},
8001 8002
#endif /* HAVE_SETEGID */
#ifdef HAVE_SETREUID
8003
    {"setreuid",        posix_setreuid, METH_VARARGS, posix_setreuid__doc__},
8004 8005
#endif /* HAVE_SETREUID */
#ifdef HAVE_SETREGID
8006
    {"setregid",        posix_setregid, METH_VARARGS, posix_setregid__doc__},
8007
#endif /* HAVE_SETREGID */
8008
#ifdef HAVE_SETGID
8009
    {"setgid",          posix_setgid, METH_VARARGS, posix_setgid__doc__},
8010
#endif /* HAVE_SETGID */
8011
#ifdef HAVE_SETGROUPS
8012
    {"setgroups",       posix_setgroups, METH_O, posix_setgroups__doc__},
8013
#endif /* HAVE_SETGROUPS */
8014
#ifdef HAVE_INITGROUPS
8015
    {"initgroups",      posix_initgroups, METH_VARARGS, posix_initgroups__doc__},
8016
#endif /* HAVE_INITGROUPS */
8017
#ifdef HAVE_GETPGID
8018
    {"getpgid",         posix_getpgid, METH_VARARGS, posix_getpgid__doc__},
8019
#endif /* HAVE_GETPGID */
8020
#ifdef HAVE_SETPGRP
8021
    {"setpgrp",         posix_setpgrp, METH_NOARGS, posix_setpgrp__doc__},
8022
#endif /* HAVE_SETPGRP */
Guido van Rossum's avatar
Guido van Rossum committed
8023
#ifdef HAVE_WAIT
8024
    {"wait",            posix_wait, METH_NOARGS, posix_wait__doc__},
Guido van Rossum's avatar
Guido van Rossum committed
8025
#endif /* HAVE_WAIT */
8026
#ifdef HAVE_WAIT3
8027
    {"wait3",           posix_wait3, METH_VARARGS, posix_wait3__doc__},
8028 8029
#endif /* HAVE_WAIT3 */
#ifdef HAVE_WAIT4
8030
    {"wait4",           posix_wait4, METH_VARARGS, posix_wait4__doc__},
8031
#endif /* HAVE_WAIT4 */
8032
#if defined(HAVE_WAITPID) || defined(HAVE_CWAIT)
8033
    {"waitpid",         posix_waitpid, METH_VARARGS, posix_waitpid__doc__},
8034
#endif /* HAVE_WAITPID */
8035
#ifdef HAVE_GETSID
8036
    {"getsid",          posix_getsid, METH_VARARGS, posix_getsid__doc__},
8037
#endif /* HAVE_GETSID */
8038
#ifdef HAVE_SETSID
8039
    {"setsid",          posix_setsid, METH_NOARGS, posix_setsid__doc__},
8040
#endif /* HAVE_SETSID */
8041
#ifdef HAVE_SETPGID
8042
    {"setpgid",         posix_setpgid, METH_VARARGS, posix_setpgid__doc__},
8043
#endif /* HAVE_SETPGID */
8044
#ifdef HAVE_TCGETPGRP
8045
    {"tcgetpgrp",       posix_tcgetpgrp, METH_VARARGS, posix_tcgetpgrp__doc__},
8046
#endif /* HAVE_TCGETPGRP */
8047
#ifdef HAVE_TCSETPGRP
8048
    {"tcsetpgrp",       posix_tcsetpgrp, METH_VARARGS, posix_tcsetpgrp__doc__},
8049
#endif /* HAVE_TCSETPGRP */
8050 8051 8052 8053 8054 8055 8056 8057 8058 8059 8060
    {"open",            posix_open, METH_VARARGS, posix_open__doc__},
    {"close",           posix_close, METH_VARARGS, posix_close__doc__},
    {"closerange",      posix_closerange, METH_VARARGS, posix_closerange__doc__},
    {"device_encoding", device_encoding, METH_VARARGS, device_encoding__doc__},
    {"dup",             posix_dup, METH_VARARGS, posix_dup__doc__},
    {"dup2",            posix_dup2, METH_VARARGS, posix_dup2__doc__},
    {"lseek",           posix_lseek, METH_VARARGS, posix_lseek__doc__},
    {"read",            posix_read, METH_VARARGS, posix_read__doc__},
    {"write",           posix_write, METH_VARARGS, posix_write__doc__},
    {"fstat",           posix_fstat, METH_VARARGS, posix_fstat__doc__},
    {"isatty",          posix_isatty, METH_VARARGS, posix_isatty__doc__},
8061
#ifdef HAVE_PIPE
8062
    {"pipe",            posix_pipe, METH_NOARGS, posix_pipe__doc__},
8063 8064
#endif
#ifdef HAVE_MKFIFO
8065
    {"mkfifo",          posix_mkfifo, METH_VARARGS, posix_mkfifo__doc__},
8066
#endif
8067
#if defined(HAVE_MKNOD) && defined(HAVE_MAKEDEV)
8068
    {"mknod",           posix_mknod, METH_VARARGS, posix_mknod__doc__},
8069
#endif
8070
#ifdef HAVE_DEVICE_MACROS
8071 8072 8073
    {"major",           posix_major, METH_VARARGS, posix_major__doc__},
    {"minor",           posix_minor, METH_VARARGS, posix_minor__doc__},
    {"makedev",         posix_makedev, METH_VARARGS, posix_makedev__doc__},
8074
#endif
8075
#ifdef HAVE_FTRUNCATE
8076
    {"ftruncate",       posix_ftruncate, METH_VARARGS, posix_ftruncate__doc__},
8077 8078
#endif
#ifdef HAVE_PUTENV
8079
    {"putenv",          posix_putenv, METH_VARARGS, posix_putenv__doc__},
Guido van Rossum's avatar
Guido van Rossum committed
8080
#endif
8081
#ifdef HAVE_UNSETENV
8082
    {"unsetenv",        posix_unsetenv, METH_VARARGS, posix_unsetenv__doc__},
8083
#endif
8084
    {"strerror",        posix_strerror, METH_VARARGS, posix_strerror__doc__},
8085
#ifdef HAVE_FCHDIR
8086
    {"fchdir",          posix_fchdir, METH_O, posix_fchdir__doc__},
8087
#endif
8088
#ifdef HAVE_FSYNC
8089
    {"fsync",       posix_fsync, METH_O, posix_fsync__doc__},
8090 8091
#endif
#ifdef HAVE_FDATASYNC
8092
    {"fdatasync",   posix_fdatasync,  METH_O, posix_fdatasync__doc__},
8093
#endif
8094
#ifdef HAVE_SYS_WAIT_H
8095
#ifdef WCOREDUMP
8096
    {"WCOREDUMP",       posix_WCOREDUMP, METH_VARARGS, posix_WCOREDUMP__doc__},
8097
#endif /* WCOREDUMP */
8098
#ifdef WIFCONTINUED
8099
    {"WIFCONTINUED",posix_WIFCONTINUED, METH_VARARGS, posix_WIFCONTINUED__doc__},
8100
#endif /* WIFCONTINUED */
8101
#ifdef WIFSTOPPED
8102
    {"WIFSTOPPED",      posix_WIFSTOPPED, METH_VARARGS, posix_WIFSTOPPED__doc__},
8103 8104
#endif /* WIFSTOPPED */
#ifdef WIFSIGNALED
8105
    {"WIFSIGNALED",     posix_WIFSIGNALED, METH_VARARGS, posix_WIFSIGNALED__doc__},
8106 8107
#endif /* WIFSIGNALED */
#ifdef WIFEXITED
8108
    {"WIFEXITED",       posix_WIFEXITED, METH_VARARGS, posix_WIFEXITED__doc__},
8109 8110
#endif /* WIFEXITED */
#ifdef WEXITSTATUS
8111
    {"WEXITSTATUS",     posix_WEXITSTATUS, METH_VARARGS, posix_WEXITSTATUS__doc__},
8112 8113
#endif /* WEXITSTATUS */
#ifdef WTERMSIG
8114
    {"WTERMSIG",        posix_WTERMSIG, METH_VARARGS, posix_WTERMSIG__doc__},
8115 8116
#endif /* WTERMSIG */
#ifdef WSTOPSIG
8117
    {"WSTOPSIG",        posix_WSTOPSIG, METH_VARARGS, posix_WSTOPSIG__doc__},
8118 8119
#endif /* WSTOPSIG */
#endif /* HAVE_SYS_WAIT_H */
8120
#if defined(HAVE_FSTATVFS) && defined(HAVE_SYS_STATVFS_H)
8121
    {"fstatvfs",        posix_fstatvfs, METH_VARARGS, posix_fstatvfs__doc__},
8122
#endif
8123
#if defined(HAVE_STATVFS) && defined(HAVE_SYS_STATVFS_H)
8124
    {"statvfs",         posix_statvfs, METH_VARARGS, posix_statvfs__doc__},
8125
#endif
8126
#ifdef HAVE_CONFSTR
8127
    {"confstr",         posix_confstr, METH_VARARGS, posix_confstr__doc__},
8128 8129
#endif
#ifdef HAVE_SYSCONF
8130
    {"sysconf",         posix_sysconf, METH_VARARGS, posix_sysconf__doc__},
8131 8132
#endif
#ifdef HAVE_FPATHCONF
8133
    {"fpathconf",       posix_fpathconf, METH_VARARGS, posix_fpathconf__doc__},
8134 8135
#endif
#ifdef HAVE_PATHCONF
8136
    {"pathconf",        posix_pathconf, METH_VARARGS, posix_pathconf__doc__},
8137
#endif
8138
    {"abort",           posix_abort, METH_NOARGS, posix_abort__doc__},
8139
#ifdef MS_WINDOWS
8140
    {"_getfullpathname",        posix__getfullpathname, METH_VARARGS, NULL},
8141
    {"_getfinalpathname",       posix__getfinalpathname, METH_VARARGS, NULL},
8142
    {"_getfileinformation",     posix__getfileinformation, METH_VARARGS, NULL},
8143
    {"_isdir",                  posix__isdir, METH_VARARGS, posix__isdir__doc__},
8144 8145
#endif
#ifdef HAVE_GETLOADAVG
8146
    {"getloadavg",      posix_getloadavg, METH_NOARGS, posix_getloadavg__doc__},
8147
#endif
8148
 #ifdef MS_WINDOWS
8149
    {"urandom", win32_urandom, METH_VARARGS, win32_urandom__doc__},
8150 8151
 #endif
 #ifdef __VMS
8152
    {"urandom", vms_urandom, METH_VARARGS, vms_urandom__doc__},
8153
 #endif
8154
#ifdef HAVE_SETRESUID
8155
    {"setresuid",       posix_setresuid, METH_VARARGS, posix_setresuid__doc__},
8156 8157
#endif
#ifdef HAVE_SETRESGID
8158
    {"setresgid",       posix_setresgid, METH_VARARGS, posix_setresgid__doc__},
8159 8160
#endif
#ifdef HAVE_GETRESUID
8161
    {"getresuid",       posix_getresuid, METH_NOARGS, posix_getresuid__doc__},
8162 8163
#endif
#ifdef HAVE_GETRESGID
8164
    {"getresgid",       posix_getresgid, METH_NOARGS, posix_getresgid__doc__},
8165 8166
#endif

8167
    {NULL,              NULL}            /* Sentinel */
Guido van Rossum's avatar
Guido van Rossum committed
8168 8169 8170
};


8171
static int
8172
ins(PyObject *module, char *symbol, long value)
8173
{
8174
    return PyModule_AddIntConstant(module, symbol, value);
8175 8176
}

8177 8178
#if defined(PYOS_OS2)
/* Insert Platform-Specific Constant Values (Strings & Numbers) of Common Use */
8179
static int insertvalues(PyObject *module)
8180 8181 8182 8183
{
    APIRET    rc;
    ULONG     values[QSV_MAX+1];
    PyObject *v;
8184
    char     *ver, tmp[50];
8185 8186

    Py_BEGIN_ALLOW_THREADS
8187
    rc = DosQuerySysInfo(1L, QSV_MAX, &values[1], sizeof(ULONG) * QSV_MAX);
8188 8189 8190 8191 8192 8193 8194
    Py_END_ALLOW_THREADS

    if (rc != NO_ERROR) {
        os2_error(rc);
        return -1;
    }

8195 8196 8197 8198 8199 8200 8201
    if (ins(module, "meminstalled", values[QSV_TOTPHYSMEM])) return -1;
    if (ins(module, "memkernel",    values[QSV_TOTRESMEM])) return -1;
    if (ins(module, "memvirtual",   values[QSV_TOTAVAILMEM])) return -1;
    if (ins(module, "maxpathlen",   values[QSV_MAX_PATH_LENGTH])) return -1;
    if (ins(module, "maxnamelen",   values[QSV_MAX_COMP_LENGTH])) return -1;
    if (ins(module, "revision",     values[QSV_VERSION_REVISION])) return -1;
    if (ins(module, "timeslice",    values[QSV_MIN_SLICE])) return -1;
8202 8203 8204 8205 8206 8207 8208 8209 8210

    switch (values[QSV_VERSION_MINOR]) {
    case 0:  ver = "2.00"; break;
    case 10: ver = "2.10"; break;
    case 11: ver = "2.11"; break;
    case 30: ver = "3.00"; break;
    case 40: ver = "4.00"; break;
    case 50: ver = "5.00"; break;
    default:
8211
        PyOS_snprintf(tmp, sizeof(tmp),
8212
                      "%d-%d", values[QSV_VERSION_MAJOR],
8213
                      values[QSV_VERSION_MINOR]);
8214 8215 8216 8217
        ver = &tmp[0];
    }

    /* Add Indicator of the Version of the Operating System */
8218
    if (PyModule_AddStringConstant(module, "version", tmp) < 0)
8219 8220 8221 8222 8223 8224 8225
        return -1;

    /* Add Indicator of Which Drive was Used to Boot the System */
    tmp[0] = 'A' + values[QSV_BOOT_DRIVE] - 1;
    tmp[1] = ':';
    tmp[2] = '\0';

8226
    return PyModule_AddStringConstant(module, "bootdrive", tmp);
8227 8228 8229
}
#endif

8230
#if defined(HAVE_SYMLINK) && defined(MS_WINDOWS)
8231
static int
8232 8233 8234 8235 8236 8237 8238 8239
enable_symlink()
{
    HANDLE tok;
    TOKEN_PRIVILEGES tok_priv;
    LUID luid;
    int meth_idx = 0;

    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &tok))
8240
        return 0;
8241 8242

    if (!LookupPrivilegeValue(NULL, SE_CREATE_SYMBOLIC_LINK_NAME, &luid))
8243
        return 0;
8244 8245 8246 8247 8248 8249 8250 8251

    tok_priv.PrivilegeCount = 1;
    tok_priv.Privileges[0].Luid = luid;
    tok_priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

    if (!AdjustTokenPrivileges(tok, FALSE, &tok_priv,
                               sizeof(TOKEN_PRIVILEGES),
                               (PTOKEN_PRIVILEGES) NULL, (PDWORD) NULL))
8252
        return 0;
8253

8254 8255
    /* ERROR_NOT_ALL_ASSIGNED returned when the privilege can't be assigned. */
    return GetLastError() == ERROR_NOT_ALL_ASSIGNED ? 0 : 1;
8256 8257 8258
}
#endif /* defined(HAVE_SYMLINK) && defined(MS_WINDOWS) */

8259
static int
8260
all_ins(PyObject *d)
8261
{
8262
#ifdef F_OK
8263
    if (ins(d, "F_OK", (long)F_OK)) return -1;
8264
#endif
8265
#ifdef R_OK
8266
    if (ins(d, "R_OK", (long)R_OK)) return -1;
8267
#endif
8268
#ifdef W_OK
8269
    if (ins(d, "W_OK", (long)W_OK)) return -1;
8270
#endif
8271
#ifdef X_OK
8272
    if (ins(d, "X_OK", (long)X_OK)) return -1;
8273
#endif
8274
#ifdef NGROUPS_MAX
8275
    if (ins(d, "NGROUPS_MAX", (long)NGROUPS_MAX)) return -1;
8276
#endif
8277
#ifdef TMP_MAX
8278
    if (ins(d, "TMP_MAX", (long)TMP_MAX)) return -1;
8279
#endif
8280
#ifdef WCONTINUED
8281
    if (ins(d, "WCONTINUED", (long)WCONTINUED)) return -1;
8282
#endif
8283
#ifdef WNOHANG
8284
    if (ins(d, "WNOHANG", (long)WNOHANG)) return -1;
8285
#endif
8286
#ifdef WUNTRACED
8287
    if (ins(d, "WUNTRACED", (long)WUNTRACED)) return -1;
8288
#endif
8289
#ifdef O_RDONLY
8290
    if (ins(d, "O_RDONLY", (long)O_RDONLY)) return -1;
8291 8292
#endif
#ifdef O_WRONLY
8293
    if (ins(d, "O_WRONLY", (long)O_WRONLY)) return -1;
8294 8295
#endif
#ifdef O_RDWR
8296
    if (ins(d, "O_RDWR", (long)O_RDWR)) return -1;
8297 8298
#endif
#ifdef O_NDELAY
8299
    if (ins(d, "O_NDELAY", (long)O_NDELAY)) return -1;
8300 8301
#endif
#ifdef O_NONBLOCK
8302
    if (ins(d, "O_NONBLOCK", (long)O_NONBLOCK)) return -1;
8303 8304
#endif
#ifdef O_APPEND
8305
    if (ins(d, "O_APPEND", (long)O_APPEND)) return -1;
8306 8307
#endif
#ifdef O_DSYNC
8308
    if (ins(d, "O_DSYNC", (long)O_DSYNC)) return -1;
8309 8310
#endif
#ifdef O_RSYNC
8311
    if (ins(d, "O_RSYNC", (long)O_RSYNC)) return -1;
8312 8313
#endif
#ifdef O_SYNC
8314
    if (ins(d, "O_SYNC", (long)O_SYNC)) return -1;
8315 8316
#endif
#ifdef O_NOCTTY
8317
    if (ins(d, "O_NOCTTY", (long)O_NOCTTY)) return -1;
8318 8319
#endif
#ifdef O_CREAT
8320
    if (ins(d, "O_CREAT", (long)O_CREAT)) return -1;
8321 8322
#endif
#ifdef O_EXCL
8323
    if (ins(d, "O_EXCL", (long)O_EXCL)) return -1;
8324 8325
#endif
#ifdef O_TRUNC
8326
    if (ins(d, "O_TRUNC", (long)O_TRUNC)) return -1;
8327 8328
#endif
#ifdef O_BINARY
8329
    if (ins(d, "O_BINARY", (long)O_BINARY)) return -1;
8330 8331
#endif
#ifdef O_TEXT
8332
    if (ins(d, "O_TEXT", (long)O_TEXT)) return -1;
8333
#endif
8334
#ifdef O_LARGEFILE
8335
    if (ins(d, "O_LARGEFILE", (long)O_LARGEFILE)) return -1;
8336
#endif
8337
#ifdef O_SHLOCK
8338
    if (ins(d, "O_SHLOCK", (long)O_SHLOCK)) return -1;
8339 8340
#endif
#ifdef O_EXLOCK
8341
    if (ins(d, "O_EXLOCK", (long)O_EXLOCK)) return -1;
8342
#endif
8343

8344 8345
/* MS Windows */
#ifdef O_NOINHERIT
8346 8347
    /* Don't inherit in child processes. */
    if (ins(d, "O_NOINHERIT", (long)O_NOINHERIT)) return -1;
8348 8349
#endif
#ifdef _O_SHORT_LIVED
8350 8351 8352
    /* Optimize for short life (keep in memory). */
    /* MS forgot to define this one with a non-underscore form too. */
    if (ins(d, "O_SHORT_LIVED", (long)_O_SHORT_LIVED)) return -1;
8353 8354
#endif
#ifdef O_TEMPORARY
8355 8356
    /* Automatically delete when last handle is closed. */
    if (ins(d, "O_TEMPORARY", (long)O_TEMPORARY)) return -1;
8357 8358
#endif
#ifdef O_RANDOM
8359 8360
    /* Optimize for random access. */
    if (ins(d, "O_RANDOM", (long)O_RANDOM)) return -1;
8361 8362
#endif
#ifdef O_SEQUENTIAL
8363 8364
    /* Optimize for sequential access. */
    if (ins(d, "O_SEQUENTIAL", (long)O_SEQUENTIAL)) return -1;
8365 8366
#endif

8367
/* GNU extensions. */
8368
#ifdef O_ASYNC
8369 8370 8371
    /* Send a SIGIO signal whenever input or output
       becomes available on file descriptor */
    if (ins(d, "O_ASYNC", (long)O_ASYNC)) return -1;
8372
#endif
8373
#ifdef O_DIRECT
8374 8375
    /* Direct disk access. */
    if (ins(d, "O_DIRECT", (long)O_DIRECT)) return -1;
8376 8377
#endif
#ifdef O_DIRECTORY
8378 8379
    /* Must be a directory.      */
    if (ins(d, "O_DIRECTORY", (long)O_DIRECTORY)) return -1;
8380 8381
#endif
#ifdef O_NOFOLLOW
8382 8383
    /* Do not follow links.      */
    if (ins(d, "O_NOFOLLOW", (long)O_NOFOLLOW)) return -1;
8384
#endif
8385
#ifdef O_NOATIME
8386 8387
    /* Do not update the access time. */
    if (ins(d, "O_NOATIME", (long)O_NOATIME)) return -1;
8388
#endif
8389

8390
    /* These come from sysexits.h */
8391
#ifdef EX_OK
8392
    if (ins(d, "EX_OK", (long)EX_OK)) return -1;
Neal Norwitz's avatar
Neal Norwitz committed
8393
#endif /* EX_OK */
8394
#ifdef EX_USAGE
8395
    if (ins(d, "EX_USAGE", (long)EX_USAGE)) return -1;
Neal Norwitz's avatar
Neal Norwitz committed
8396
#endif /* EX_USAGE */
8397
#ifdef EX_DATAERR
8398
    if (ins(d, "EX_DATAERR", (long)EX_DATAERR)) return -1;
Neal Norwitz's avatar
Neal Norwitz committed
8399
#endif /* EX_DATAERR */
8400
#ifdef EX_NOINPUT
8401
    if (ins(d, "EX_NOINPUT", (long)EX_NOINPUT)) return -1;
Neal Norwitz's avatar
Neal Norwitz committed
8402
#endif /* EX_NOINPUT */
8403
#ifdef EX_NOUSER
8404
    if (ins(d, "EX_NOUSER", (long)EX_NOUSER)) return -1;
Neal Norwitz's avatar
Neal Norwitz committed
8405
#endif /* EX_NOUSER */
8406
#ifdef EX_NOHOST
8407
    if (ins(d, "EX_NOHOST", (long)EX_NOHOST)) return -1;
Neal Norwitz's avatar
Neal Norwitz committed
8408
#endif /* EX_NOHOST */
8409
#ifdef EX_UNAVAILABLE
8410
    if (ins(d, "EX_UNAVAILABLE", (long)EX_UNAVAILABLE)) return -1;
Neal Norwitz's avatar
Neal Norwitz committed
8411
#endif /* EX_UNAVAILABLE */
8412
#ifdef EX_SOFTWARE
8413
    if (ins(d, "EX_SOFTWARE", (long)EX_SOFTWARE)) return -1;
Neal Norwitz's avatar
Neal Norwitz committed
8414
#endif /* EX_SOFTWARE */
8415
#ifdef EX_OSERR
8416
    if (ins(d, "EX_OSERR", (long)EX_OSERR)) return -1;
Neal Norwitz's avatar
Neal Norwitz committed
8417
#endif /* EX_OSERR */
8418
#ifdef EX_OSFILE
8419
    if (ins(d, "EX_OSFILE", (long)EX_OSFILE)) return -1;
Neal Norwitz's avatar
Neal Norwitz committed
8420
#endif /* EX_OSFILE */
8421
#ifdef EX_CANTCREAT
8422
    if (ins(d, "EX_CANTCREAT", (long)EX_CANTCREAT)) return -1;
Neal Norwitz's avatar
Neal Norwitz committed
8423
#endif /* EX_CANTCREAT */
8424
#ifdef EX_IOERR
8425
    if (ins(d, "EX_IOERR", (long)EX_IOERR)) return -1;
Neal Norwitz's avatar
Neal Norwitz committed
8426
#endif /* EX_IOERR */
8427
#ifdef EX_TEMPFAIL
8428
    if (ins(d, "EX_TEMPFAIL", (long)EX_TEMPFAIL)) return -1;
Neal Norwitz's avatar
Neal Norwitz committed
8429
#endif /* EX_TEMPFAIL */
8430
#ifdef EX_PROTOCOL
8431
    if (ins(d, "EX_PROTOCOL", (long)EX_PROTOCOL)) return -1;
Neal Norwitz's avatar
Neal Norwitz committed
8432
#endif /* EX_PROTOCOL */
8433
#ifdef EX_NOPERM
8434
    if (ins(d, "EX_NOPERM", (long)EX_NOPERM)) return -1;
Neal Norwitz's avatar
Neal Norwitz committed
8435
#endif /* EX_NOPERM */
8436
#ifdef EX_CONFIG
8437
    if (ins(d, "EX_CONFIG", (long)EX_CONFIG)) return -1;
Neal Norwitz's avatar
Neal Norwitz committed
8438
#endif /* EX_CONFIG */
8439
#ifdef EX_NOTFOUND
8440
    if (ins(d, "EX_NOTFOUND", (long)EX_NOTFOUND)) return -1;
Neal Norwitz's avatar
Neal Norwitz committed
8441
#endif /* EX_NOTFOUND */
8442

Amaury Forgeot d'Arc's avatar
Amaury Forgeot d'Arc committed
8443
    /* statvfs */
8444
#ifdef ST_RDONLY
Amaury Forgeot d'Arc's avatar
Amaury Forgeot d'Arc committed
8445
    if (ins(d, "ST_RDONLY", (long)ST_RDONLY)) return -1;
8446 8447
#endif /* ST_RDONLY */
#ifdef ST_NOSUID
Amaury Forgeot d'Arc's avatar
Amaury Forgeot d'Arc committed
8448
    if (ins(d, "ST_NOSUID", (long)ST_NOSUID)) return -1;
8449 8450
#endif /* ST_NOSUID */

Guido van Rossum's avatar
Guido van Rossum committed
8451
#ifdef HAVE_SPAWNV
8452
#if defined(PYOS_OS2) && defined(PYCC_GCC)
8453 8454 8455 8456 8457 8458 8459 8460 8461 8462 8463 8464 8465 8466 8467 8468 8469 8470 8471 8472
    if (ins(d, "P_WAIT", (long)P_WAIT)) return -1;
    if (ins(d, "P_NOWAIT", (long)P_NOWAIT)) return -1;
    if (ins(d, "P_OVERLAY", (long)P_OVERLAY)) return -1;
    if (ins(d, "P_DEBUG", (long)P_DEBUG)) return -1;
    if (ins(d, "P_SESSION", (long)P_SESSION)) return -1;
    if (ins(d, "P_DETACH", (long)P_DETACH)) return -1;
    if (ins(d, "P_PM", (long)P_PM)) return -1;
    if (ins(d, "P_DEFAULT", (long)P_DEFAULT)) return -1;
    if (ins(d, "P_MINIMIZE", (long)P_MINIMIZE)) return -1;
    if (ins(d, "P_MAXIMIZE", (long)P_MAXIMIZE)) return -1;
    if (ins(d, "P_FULLSCREEN", (long)P_FULLSCREEN)) return -1;
    if (ins(d, "P_WINDOWED", (long)P_WINDOWED)) return -1;
    if (ins(d, "P_FOREGROUND", (long)P_FOREGROUND)) return -1;
    if (ins(d, "P_BACKGROUND", (long)P_BACKGROUND)) return -1;
    if (ins(d, "P_NOCLOSE", (long)P_NOCLOSE)) return -1;
    if (ins(d, "P_NOSESSION", (long)P_NOSESSION)) return -1;
    if (ins(d, "P_QUOTE", (long)P_QUOTE)) return -1;
    if (ins(d, "P_TILDE", (long)P_TILDE)) return -1;
    if (ins(d, "P_UNRELATED", (long)P_UNRELATED)) return -1;
    if (ins(d, "P_DEBUGDESC", (long)P_DEBUGDESC)) return -1;
8473
#else
8474 8475 8476 8477 8478
    if (ins(d, "P_WAIT", (long)_P_WAIT)) return -1;
    if (ins(d, "P_NOWAIT", (long)_P_NOWAIT)) return -1;
    if (ins(d, "P_OVERLAY", (long)_OLD_P_OVERLAY)) return -1;
    if (ins(d, "P_NOWAITO", (long)_P_NOWAITO)) return -1;
    if (ins(d, "P_DETACH", (long)_P_DETACH)) return -1;
Guido van Rossum's avatar
Guido van Rossum committed
8479
#endif
8480
#endif
Guido van Rossum's avatar
Guido van Rossum committed
8481

8482
#if defined(PYOS_OS2)
8483
    if (insertvalues(d)) return -1;
8484
#endif
8485
    return 0;
8486 8487 8488
}


8489
#if (defined(_MSC_VER) || defined(__WATCOMC__) || defined(__BORLANDC__)) && !defined(__QNX__)
8490
#define INITFUNC PyInit_nt
8491
#define MODNAME "nt"
8492 8493

#elif defined(PYOS_OS2)
8494
#define INITFUNC PyInit_os2
Guido van Rossum's avatar
Guido van Rossum committed
8495
#define MODNAME "os2"
8496

Guido van Rossum's avatar
Guido van Rossum committed
8497
#else
8498
#define INITFUNC PyInit_posix
8499 8500
#define MODNAME "posix"
#endif
8501

8502
static struct PyModuleDef posixmodule = {
8503 8504 8505 8506 8507 8508 8509 8510 8511
    PyModuleDef_HEAD_INIT,
    MODNAME,
    posix__doc__,
    -1,
    posix_methods,
    NULL,
    NULL,
    NULL,
    NULL
8512 8513 8514
};


8515
PyMODINIT_FUNC
8516
INITFUNC(void)
Guido van Rossum's avatar
Guido van Rossum committed
8517
{
8518
    PyObject *m, *v;
8519

8520
#if defined(HAVE_SYMLINK) && defined(MS_WINDOWS)
8521
    win32_can_symlink = enable_symlink();
8522 8523
#endif

8524 8525 8526
    m = PyModule_Create(&posixmodule);
    if (m == NULL)
        return NULL;
8527

8528 8529 8530 8531 8532 8533
    /* Initialize environ dictionary */
    v = convertenviron();
    Py_XINCREF(v);
    if (v == NULL || PyModule_AddObject(m, "environ", v) != 0)
        return NULL;
    Py_DECREF(v);
8534

8535 8536
    if (all_ins(m))
        return NULL;
8537

8538 8539
    if (setup_confname_tables(m))
        return NULL;
8540

8541 8542
    Py_INCREF(PyExc_OSError);
    PyModule_AddObject(m, "error", PyExc_OSError);
8543

8544
#ifdef HAVE_PUTENV
8545 8546
    if (posix_putenv_garbage == NULL)
        posix_putenv_garbage = PyDict_New();
8547
#endif
8548

8549 8550 8551 8552 8553 8554 8555 8556
    if (!initialized) {
        stat_result_desc.name = MODNAME ".stat_result";
        stat_result_desc.fields[7].name = PyStructSequence_UnnamedField;
        stat_result_desc.fields[8].name = PyStructSequence_UnnamedField;
        stat_result_desc.fields[9].name = PyStructSequence_UnnamedField;
        PyStructSequence_InitType(&StatResultType, &stat_result_desc);
        structseq_new = StatResultType.tp_new;
        StatResultType.tp_new = statresult_new;
8557

8558 8559
        statvfs_result_desc.name = MODNAME ".statvfs_result";
        PyStructSequence_InitType(&StatVFSResultType, &statvfs_result_desc);
8560 8561
#ifdef NEED_TICKS_PER_SECOND
#  if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)
8562
        ticks_per_second = sysconf(_SC_CLK_TCK);
8563
#  elif defined(HZ)
8564
        ticks_per_second = HZ;
8565
#  else
8566
        ticks_per_second = 60; /* magic fallback value; may be bogus */
8567 8568
#  endif
#endif
8569 8570 8571 8572 8573 8574 8575
    }
    Py_INCREF((PyObject*) &StatResultType);
    PyModule_AddObject(m, "stat_result", (PyObject*) &StatResultType);
    Py_INCREF((PyObject*) &StatVFSResultType);
    PyModule_AddObject(m, "statvfs_result",
                       (PyObject*) &StatVFSResultType);
    initialized = 1;
8576 8577

#ifdef __APPLE__
8578 8579 8580 8581 8582 8583 8584 8585 8586 8587
    /*
     * Step 2 of weak-linking support on Mac OS X.
     *
     * The code below removes functions that are not available on the
     * currently active platform.
     *
     * This block allow one to use a python binary that was build on
     * OSX 10.4 on OSX 10.3, without loosing access to new APIs on
     * OSX 10.4.
     */
8588
#ifdef HAVE_FSTATVFS
8589 8590 8591 8592 8593
    if (fstatvfs == NULL) {
        if (PyObject_DelAttrString(m, "fstatvfs") == -1) {
            return NULL;
        }
    }
8594 8595 8596
#endif /* HAVE_FSTATVFS */

#ifdef HAVE_STATVFS
8597 8598 8599 8600 8601
    if (statvfs == NULL) {
        if (PyObject_DelAttrString(m, "statvfs") == -1) {
            return NULL;
        }
    }
8602 8603 8604
#endif /* HAVE_STATVFS */

# ifdef HAVE_LCHOWN
8605 8606 8607 8608 8609
    if (lchown == NULL) {
        if (PyObject_DelAttrString(m, "lchown") == -1) {
            return NULL;
        }
    }
8610 8611 8612 8613
#endif /* HAVE_LCHOWN */


#endif /* __APPLE__ */
8614
    return m;
8615

Guido van Rossum's avatar
Guido van Rossum committed
8616
}
8617 8618 8619 8620

#ifdef __cplusplus
}
#endif