8756 lines · 218.4 KB · C
RawDownload
 /* POSIX module implementation */ /* 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   assumes that for Windows NT, the macro 'MS_WINDOWS' is defined independent   of the compiler used.  Different compilers define their own feature   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. */ /* See also ../Dos/dosmodule.c */ #ifdef __APPLE__   /*    * Step 1 of support for weak-linking a number of symbols existing on     * 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__ */ #define PY_SSIZE_T_CLEAN #include "Python.h"#include "structseq.h" #if defined(__VMS)#    include <unixio.h>#endif /* defined(__VMS) */ #ifdef __cplusplusextern "C" {#endif PyDoc_STRVAR(posix__doc__,"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\corresponding Unix manual entries for more information on calls."); #ifndef Py_USING_UNICODE/* This is used in signatures of functions. */#define Py_UNICODE void#endif #if defined(PYOS_OS2)#define  INCL_DOS#define  INCL_DOSERRORS#define  INCL_DOSPROCESS#define  INCL_NOPMAPI#include <os2.h>#if defined(PYCC_GCC)#include <ctype.h>#include <io.h>#include <stdio.h>#include <process.h>#endif#include "osdefs.h"#endif #ifdef HAVE_SYS_TYPES_H#include <sys/types.h>#endif /* HAVE_SYS_TYPES_H */ #ifdef HAVE_SYS_STAT_H#include <sys/stat.h>#endif /* HAVE_SYS_STAT_H */ #ifdef HAVE_SYS_WAIT_H#include <sys/wait.h>		/* For WNOHANG */#endif #ifdef HAVE_SIGNAL_H#include <signal.h>#endif #ifdef HAVE_FCNTL_H#include <fcntl.h>#endif /* HAVE_FCNTL_H */ #ifdef HAVE_GRP_H#include <grp.h>#endif #ifdef HAVE_SYSEXITS_H#include <sysexits.h>#endif /* HAVE_SYSEXITS_H */ #ifdef HAVE_SYS_LOADAVG_H#include <sys/loadavg.h>#endif /* Various compilers have only certain posix functions *//* XXX Gosh I wish these were all moved into pyconfig.h */#if defined(PYCC_VACPP) && defined(PYOS_OS2)#include <process.h>#else#if defined(__WATCOMC__) && !defined(__QNX__)		/* Watcom compiler */#define HAVE_GETCWD     1#define HAVE_OPENDIR    1#define HAVE_SYSTEM	1#if defined(__OS2__)#define HAVE_EXECV      1#define HAVE_WAIT       1#endif#include <process.h>#else#ifdef __BORLANDC__		/* Borland compiler */#define HAVE_EXECV      1#define HAVE_GETCWD     1#define HAVE_OPENDIR    1#define HAVE_PIPE       1#define HAVE_POPEN      1#define HAVE_SYSTEM	1#define HAVE_WAIT       1#else#ifdef _MSC_VER		/* Microsoft compiler */#define HAVE_GETCWD     1#define HAVE_SPAWNV	1#define HAVE_EXECV      1#define HAVE_PIPE       1#define HAVE_POPEN      1#define HAVE_SYSTEM	1#define HAVE_CWAIT	1#define HAVE_FSYNC	1#define fsync _commit#else#if defined(PYOS_OS2) && defined(PYCC_GCC) || defined(__VMS)/* Everything needed is defined in PC/os2emx/pyconfig.h or vms/pyconfig.h */#else			/* all other compilers *//* Unix functions that the configure script doesn't check for */#define HAVE_EXECV      1#define HAVE_FORK       1#if defined(__USLC__) && defined(__SCO_VERSION__)	/* SCO UDK Compiler */#define HAVE_FORK1      1#endif#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#ifndef __rtems__#define HAVE_POPEN      1#endif#define HAVE_SYSTEM	1#define HAVE_WAIT       1#define HAVE_TTYNAME	1#endif  /* PYOS_OS2 && PYCC_GCC && __VMS */#endif  /* _MSC_VER */#endif  /* __BORLANDC__ */#endif  /* ! __WATCOMC__ || __QNX__ */#endif /* ! __IBMC__ */ #ifndef _MSC_VER #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 #ifndef HAVE_UNISTD_H#if defined(PYCC_VACPP)extern int mkdir(char *);#else#if ( defined(__WATCOMC__) || defined(_MSC_VER) ) && !defined(__QNX__)extern int mkdir(const char *);#elseextern int mkdir(const char *, mode_t);#endif#endif#if defined(__IBMC__) || defined(__IBMCPP__)extern int chdir(char *);extern int rmdir(char *);#elseextern int chdir(const char *);extern int rmdir(const char *);#endif#ifdef __BORLANDC__extern int chmod(const char *, int);#elseextern int chmod(const char *, mode_t);#endifextern 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 *);extern int pclose(FILE *);#ifdef HAVE_SYMLINKextern int symlink(const char *, const char *);#endif /* HAVE_SYMLINK */#ifdef HAVE_LSTATextern int lstat(const char *, struct stat *);#endif /* HAVE_LSTAT */#endif /* !HAVE_UNISTD_H */ #endif /* !_MSC_VER */ #ifdef HAVE_UTIME_H#include <utime.h>#endif /* HAVE_UTIME_H */ #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 */ #ifdef HAVE_SYS_TIMES_H#include <sys/times.h>#endif /* HAVE_SYS_TIMES_H */ #ifdef HAVE_SYS_PARAM_H#include <sys/param.h>#endif /* HAVE_SYS_PARAM_H */ #ifdef HAVE_SYS_UTSNAME_H#include <sys/utsname.h>#endif /* HAVE_SYS_UTSNAME_H */ #ifdef HAVE_DIRENT_H#include <dirent.h>#define NAMLEN(dirent) strlen((dirent)->d_name)#else#if defined(__WATCOMC__) && !defined(__QNX__)#include <direct.h>#define NAMLEN(dirent) strlen((dirent)->d_name)#else#define dirent direct#define NAMLEN(dirent) (dirent)->d_namlen#endif#ifdef HAVE_SYS_NDIR_H#include <sys/ndir.h>#endif#ifdef HAVE_SYS_DIR_H#include <sys/dir.h>#endif#ifdef HAVE_NDIR_H#include <ndir.h>#endif#endif #ifdef _MSC_VER#ifdef HAVE_DIRECT_H#include <direct.h>#endif#ifdef HAVE_IO_H#include <io.h>#endif#ifdef HAVE_PROCESS_H#include <process.h>#endif#include "osdefs.h"#define _WIN32_WINNT 0x0400	  /* Needed for CryptoAPI on some systems */#include <windows.h>#include <shellapi.h>	/* for ShellExecute() */#define popen	_popen#define pclose	_pclose#endif /* _MSC_VER */ #if defined(PYCC_VACPP) && defined(PYOS_OS2)#include <io.h>#endif /* OS2 */ #ifndef MAXPATHLEN#if defined(PATH_MAX) && PATH_MAX > 1024#define MAXPATHLEN PATH_MAX#else#define MAXPATHLEN 1024#endif#endif /* MAXPATHLEN */ #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 #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)#endif /* UNION_WAIT */ /* 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 #if defined(HAVE_TMPNAM_R) && defined(WITH_THREAD)#define USE_TMPNAM_R#endif /* choose the appropriate stat and fstat functions and return structs */#undef STAT#if defined(MS_WIN64) || defined(MS_WINDOWS)#	define STAT win32_stat#	define FSTAT win32_fstat#	define STRUCT_STAT struct win32_stat#else#	define STAT stat#	define FSTAT fstat#	define STRUCT_STAT struct stat#endif #if defined(MAJOR_IN_MKDEV)#include <sys/mkdev.h>#else#if defined(MAJOR_IN_SYSMACROS)#include <sys/sysmacros.h>#endif#if defined(HAVE_MKNOD) && defined(HAVE_SYS_MKDEV_H)#include <sys/mkdev.h>#endif#endif /* Return a dictionary corresponding to the POSIX environment table */#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__) )extern char **environ;#endif /* !_MSC_VER */ static PyObject *convertenviron(void){	PyObject *d;	char **e;	d = PyDict_New();	if (d == NULL)		return NULL;#ifdef WITH_NEXT_FRAMEWORK	if (environ == NULL)		environ = *_NSGetEnviron();#endif	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;		k = PyString_FromStringAndSize(*e, (int)(p-*e));		if (k == NULL) {			PyErr_Clear();			continue;		}		v = PyString_FromString(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);	}#if defined(PYOS_OS2)    {        APIRET rc;        char   buffer[1024]; /* OS/2 Provides a Documented Max of 1024 Chars */         rc = DosQueryExtLIBPATH(buffer, BEGIN_LIBPATH);	if (rc == NO_ERROR) { /* (not a type, envname is NOT 'BEGIN_LIBPATH') */            PyObject *v = PyString_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 = PyString_FromString(buffer);		    PyDict_SetItemString(d, "ENDLIBPATH", v);            Py_DECREF(v);        }    }#endif	return d;}  /* Set a POSIX-specific error from errno, and return NULL */ static PyObject *posix_error(void){	return PyErr_SetFromErrno(PyExc_OSError);}static PyObject *posix_error_with_filename(char* name){	return PyErr_SetFromErrnoWithFilename(PyExc_OSError, name);} #ifdef Py_WIN_WIDE_FILENAMESstatic PyObject *posix_error_with_unicode_filename(Py_UNICODE* name){	return PyErr_SetFromErrnoWithUnicodeFilename(PyExc_OSError, name);}#endif /* Py_WIN_WIDE_FILENAMES */  static PyObject *posix_error_with_allocated_filename(char* name){	PyObject *rc = PyErr_SetFromErrnoWithFilename(PyExc_OSError, name);	PyMem_Free(name);	return rc;} #ifdef MS_WINDOWSstatic PyObject *win32_error(char* function, char* filename){	/* 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);} #ifdef Py_WIN_WIDE_FILENAMESstatic PyObject *win32_error_unicode(char* function, Py_UNICODE* filename){	/* XXX - see win32_error for comments on 'function' */	errno = GetLastError();	if (filename)		return PyErr_SetFromWindowsErrWithUnicodeFilename(errno, filename);	else		return PyErr_SetFromWindowsErr(errno);} static PyObject *_PyUnicode_FromFileSystemEncodedObject(register PyObject *obj){} /* Function suitable for O& conversion */static intconvert_to_unicode(PyObject *arg, void* _param){	PyObject **param = (PyObject**)_param;	if (PyUnicode_CheckExact(arg)) {		Py_INCREF(arg);		*param = arg;	} 	else if (PyUnicode_Check(arg)) {		/* 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(arg),					       PyUnicode_GET_SIZE(arg));		return *param != NULL;	}	else		*param = PyUnicode_FromEncodedObject(arg,				                     Py_FileSystemDefaultEncoding,					             "strict");	return (*param) != NULL;} #endif /* Py_WIN_WIDE_FILENAMES */ 

Lines 1–500 of 8756.