From ae3d4616ed9c19a29d656193254657f93d612fa2 Mon Sep 17 00:00:00 2001 From: Waldemar Brodkorb Date: Wed, 27 Nov 2013 21:30:43 +0100 Subject: try to fixup mesalib compile, it needs libxml2 python module --- mk/host-bottom.mk | 5 + mk/host.mk | 8 +- mk/vars.mk | 3 +- package/MesaLib/Makefile | 8 +- package/fltk/Makefile | 2 +- package/libdrm/Makefile | 2 + package/libxml2/Makefile | 5 +- package/libxml2/patches/patch-configure_in | 12 +- package/libxml2/patches/patch-python_Makefile_am | 17 + package/libxml2/patches/patch-python_setup_py | 11 + package/libxslt/Makefile | 3 +- package/python2/Makefile | 12 +- package/python2/files/build_scripts.py | 99 - .../python2/files/patch-Lib_distutils_sysconfig_py | 10 + package/python2/files/patch-Misc_python-config_in | 21 + package/python2/files/posixmodule.c | 9365 -------------------- package/python2/files/python-config.in | 57 - package/python2/files/setup.py | 2076 ----- package/python2/files/sysconfig.py | 572 -- .../patches/patch-Lib_distutils_sysconfig_py | 10 - .../python2/patches/patch-Misc_python-config_in | 21 - package/python3/Makefile | 16 +- 22 files changed, 105 insertions(+), 12230 deletions(-) create mode 100644 package/libxml2/patches/patch-python_Makefile_am create mode 100644 package/libxml2/patches/patch-python_setup_py delete mode 100644 package/python2/files/build_scripts.py create mode 100644 package/python2/files/patch-Lib_distutils_sysconfig_py create mode 100644 package/python2/files/patch-Misc_python-config_in delete mode 100644 package/python2/files/posixmodule.c delete mode 100644 package/python2/files/python-config.in delete mode 100644 package/python2/files/setup.py delete mode 100644 package/python2/files/sysconfig.py delete mode 100644 package/python2/patches/patch-Lib_distutils_sysconfig_py delete mode 100644 package/python2/patches/patch-Misc_python-config_in diff --git a/mk/host-bottom.mk b/mk/host-bottom.mk index 59b7cf6d8..b672df7f0 100644 --- a/mk/host-bottom.mk +++ b/mk/host-bottom.mk @@ -7,6 +7,11 @@ host-configure: ${_HOST_CONFIGURE_COOKIE}: ${_HOST_PATCH_COOKIE} @mkdir -p ${WRKBUILD} @$(CMD_TRACE) "host configuring... " +ifneq (,$(filter autoreconf,${AUTOTOOL_STYLE})) + cd ${WRKSRC}; env ${AUTOTOOL_ENV} autoreconf -if $(MAKE_TRACE) + @rm -rf ${WRKSRC}/autom4te.cache + @touch ${WRKDIR}/.autoreconf_done +endif @cd ${WRKBUILD}; \ for i in $$(find . -name config.sub);do \ if [ -f $$i ]; then \ diff --git a/mk/host.mk b/mk/host.mk index 2c07f9665..1f5f4c48a 100644 --- a/mk/host.mk +++ b/mk/host.mk @@ -3,8 +3,8 @@ HOST_CONFIGURE_ENV+= AUTOM4TE=${STAGING_HOST_DIR}/usr/bin/autom4te \ CONFIG_SHELL='$(strip ${SHELL})' \ - PATH='${TARGET_PATH}' \ - PKG_CONFIG_LIBDIR='${STAGING_HOST_DIR}/usr/lib/pkgconfig' + PKG_CONFIG_LIBDIR='${STAGING_HOST_DIR}/usr/lib/pkgconfig' \ + PATH='${HOST_PATH}' \ CFLAGS='$(strip ${CFLAGS_FOR_BUILD})' \ CXXFLAGS='$(strip ${CXXFLAGS_FOR_BUILD})' \ CPPFLAGS='$(strip ${CPPFLAGS_FOR_BUILD})' \ @@ -21,8 +21,8 @@ HOST_FAKE_FLAGS?= HOST_ALL_TARGET?= all HOST_INSTALL_TARGET?= install -HOST_MAKE_ENV+= PATH='${TARGET_PATH}' \ - PKG_CONFIG_LIBDIR='${STAGING_HOST_DIR}/usr/lib/pkgconfig' +HOST_MAKE_ENV+= PATH='${HOST_PATH}' \ + PKG_CONFIG_LIBDIR='${STAGING_HOST_DIR}/usr/lib/pkgconfig' \ CFLAGS='$(strip ${CFLAGS_FOR_BUILD})' \ CXXFLAGS='$(strip ${CXXFLAGS_FOR_BUILD})' \ CPPFLAGS='$(strip ${CPPFLAGS_FOR_BUILD})' \ diff --git a/mk/vars.mk b/mk/vars.mk index 9cc789004..50e02a204 100644 --- a/mk/vars.mk +++ b/mk/vars.mk @@ -43,7 +43,8 @@ BIN_DIR_PFX:= $(BASE_DIR)/bin PACKAGE_DIR:= $(BIN_DIR)/packages TARGET_DIR:= $(BASE_DIR)/root_${ADK_TARGET_SYSTEM}_${CPU_ARCH}_${ADK_TARGET_LIBC} TARGET_DIR_PFX:= $(BASE_DIR)/root_* -TARGET_PATH= ${SCRIPT_DIR}:${TOOLS_DIR}:${STAGING_HOST_DIR}/bin:${STAGING_HOST_DIR}/usr/bin:${STAGING_TARGET_DIR}/scripts:${_PATH} +TARGET_PATH= ${SCRIPT_DIR}:${TOOLS_DIR}:${STAGING_TARGET_DIR}/scripts:${STAGING_HOST_DIR}/bin:${STAGING_HOST_DIR}/usr/bin:${_PATH} +HOST_PATH= ${SCRIPT_DIR}:${TOOLS_DIR}:${STAGING_HOST_DIR}/bin:${STAGING_HOST_DIR}/usr/bin:${_PATH} AUTOTOOL_PATH= ${TOOLS_DIR}:${STAGING_HOST_DIR}/bin:${STAGING_HOST_DIR}/usr/bin:${STAGING_TARGET_DIR}/scripts:${_PATH} REAL_GNU_TARGET_NAME= $(CPU_ARCH)-$(ADK_VENDOR)-linux-$(ADK_TARGET_SUFFIX) GNU_TARGET_NAME= $(CPU_ARCH)-$(ADK_VENDOR)-linux diff --git a/package/MesaLib/Makefile b/package/MesaLib/Makefile index 446f465ab..10482b799 100644 --- a/package/MesaLib/Makefile +++ b/package/MesaLib/Makefile @@ -10,7 +10,8 @@ PKG_MD5SUM:= df801a975045150790e10e2ccf32193f PKG_DESCR:= MESA 3D graphics library PKG_SECTION:= libs PKG_DEPENDS:= libxdamage libxfixes libdrm libxxf86vm libexpat -PKG_BUILDDEP:= libXdamage libXfixes libXxf86vm libdrm +PKG_DEPENDS+= libxml2 libxml2-python +PKG_BUILDDEP:= python2 libxml2 libXdamage libXfixes libXxf86vm libdrm PKG_BUILDDEP+= dri2proto glproto expat libXext PKG_URL:= http://www.mesa3d.org/ PKG_SITES:= ftp://ftp.freedesktop.org/pub/mesa/${PKG_VERSION}/ @@ -26,6 +27,8 @@ include $(TOPDIR)/mk/package.mk $(eval $(call PKG_template,MESALIB,mesalib,$(PKG_VERSION)-${PKG_RELEASE},${PKG_DEPENDS},${PKG_DESCR},${PKG_SECTION},${PKG_OPTS})) +include $(TOPDIR)/mk/python.mk + ifeq (${ADK_TARGET_SYSTEM_IBM_X40},y) DRI_DRIVERS:=i915 endif @@ -36,7 +39,8 @@ CONFIGURE_ARGS+= --disable-static \ --disable-gles1 \ --disable-gles2 \ --with-dri-drivers=${DRI_DRIVERS},swrast -CONFIGURE_ENV+= PYTHON2=/usr/bin/python MISSING="echo" +CONFIGURE_ENV+= MISSING="echo" \ + PYTHON2=$(PYTHON) XAKE_FLAGS+= HOST_CC=${CC_FOR_BUILD} ifeq ($(ADK_NATIVE),y) diff --git a/package/fltk/Makefile b/package/fltk/Makefile index 99c130e1d..00795d0b6 100644 --- a/package/fltk/Makefile +++ b/package/fltk/Makefile @@ -9,6 +9,7 @@ PKG_RELEASE:= 2 PKG_MD5SUM:= 9f7e707d4fb7a5a76f0f9b73ff70623d PKG_DESCR:= fast light toolkit PKG_SECTION:= libs +PKG_DEPENDS:= mesalib libx11 libxi freeglut libfreetype PKG_BUILDDEP:= libX11 libXi MesaLib freeglut freetype PKG_URL:= http://www.fltk.org/ PKG_SITES:= http://openadk.org/distfiles/ @@ -18,7 +19,6 @@ PKG_LIBNAME:= libfltk PKG_OPTS:= dev PKG_ARCH_DEPENDS:= x86 x86_64 mips arm -PKG_HOST_DEPENDS:= !darwin DISTFILES:= ${PKG_NAME}-$(PKG_VERSION)-source.tar.gz diff --git a/package/libdrm/Makefile b/package/libdrm/Makefile index b54f62793..9ef7660d7 100644 --- a/package/libdrm/Makefile +++ b/package/libdrm/Makefile @@ -20,6 +20,8 @@ include $(TOPDIR)/mk/package.mk $(eval $(call PKG_template,LIBDRM,libdrm,$(PKG_VERSION)-${PKG_RELEASE},${PKG_DEPENDS},${PKG_DESCR},${PKG_SECTION},${PKG_OPTS})) +CONFIGURE_ARGS+= --disable-manpages + libdrm-install: $(INSTALL_DIR) $(IDIR_LIBDRM)/usr/lib $(CP) $(WRKINST)/usr/lib/libdrm*.so* \ diff --git a/package/libxml2/Makefile b/package/libxml2/Makefile index 301c6662d..624ffdb26 100644 --- a/package/libxml2/Makefile +++ b/package/libxml2/Makefile @@ -10,7 +10,7 @@ PKG_MD5SUM:= 9c0cfef285d5c4a5c80d00904ddab380 PKG_DESCR:= XML C parser and toolkit PKG_SECTION:= libs PKG_DEPENDS:= zlib -PKG_BUILDDEP:= autotool libxml2-host zlib +PKG_BUILDDEP:= autotool gettext-tiny libxml2-host zlib PKG_URL:= http://www.xmlsoft.org/ PKG_SITES:= http://xmlsoft.org/sources/ PKG_OPTS:= dev @@ -19,6 +19,7 @@ PKG_SUBPKGS:= LIBXML2 LIBXML2_PYTHON PKGSD_LIBXML2_PYTHON:= XML python bindings PKGSC_LIBXML2_PYTHON:= libs PKGSB_LIBXML2_PYTHON:= python2 +PKGSS_LIBXML2_PYTHON:= python2 ifeq ($(ADK_STATIC),y) PKG_OPTS+= libmix @@ -34,7 +35,7 @@ $(eval $(call PKG_template,LIBXML2_PYTHON,libxml2-python,${PKG_VERSION}-${PKG_RE include $(TOPDIR)/mk/python.mk HOST_STYLE:= auto -HOST_CONFIGURE_ARGS+= --without-python \ +HOST_CONFIGURE_ARGS+= --with-python \ --without-iconv \ --without-lzma \ --without-zlib diff --git a/package/libxml2/patches/patch-configure_in b/package/libxml2/patches/patch-configure_in index a8340e906..6432ced20 100644 --- a/package/libxml2/patches/patch-configure_in +++ b/package/libxml2/patches/patch-configure_in @@ -1,5 +1,5 @@ --- libxml2-2.9.1.orig/configure.in 2013-04-19 09:25:20.000000000 +0200 -+++ libxml2-2.9.1/configure.in 2013-10-31 08:37:36.000000000 +0100 ++++ libxml2-2.9.1/configure.in 2013-11-23 23:02:06.000000000 +0100 @@ -748,80 +748,16 @@ PYTHON_SITE_PACKAGES= PYTHON_TESTS= pythondir= @@ -77,11 +77,11 @@ - fi - fi - fi -+ PYTHON_INCLUDES=`$PYTHON$PYTHON_VERSION-config --includes` -+ PYTHON_LIBS=`$PYTHON$PYTHON_VERSION-config --ldflags` -+ PYTHON_SITE_PACKAGES=/usr/lib/python$PYTHON_VERSION/site-packages - pythondir='$(PYTHON_SITE_PACKAGES)' -- PYTHON_LIBS=`python$PYTHON_VERSION-config --ldflags` +- pythondir='$(PYTHON_SITE_PACKAGES)' ++ PYTHON_INCLUDES=`python$PYTHON_VERSION-config --includes` + PYTHON_LIBS=`python$PYTHON_VERSION-config --ldflags` ++ PYTHON_SITE_PACKAGES=${prefix}/lib/python$PYTHON_VERSION/site-packages ++ pythondir='$(PYTHON_SITE_PACKAGES)' else PYTHON= fi diff --git a/package/libxml2/patches/patch-python_Makefile_am b/package/libxml2/patches/patch-python_Makefile_am new file mode 100644 index 000000000..82061eee3 --- /dev/null +++ b/package/libxml2/patches/patch-python_Makefile_am @@ -0,0 +1,17 @@ +--- libxml2-2.9.1.orig/python/Makefile.am 2013-04-19 08:56:45.000000000 +0200 ++++ libxml2-2.9.1/python/Makefile.am 2013-11-24 09:18:44.000000000 +0100 +@@ -19,12 +19,12 @@ if WITH_PYTHON + AM_CPPFLAGS = \ + -I$(top_builddir)/include \ + -I$(top_srcdir)/include \ +- -I$(PYTHON_INCLUDES) ++ $(PYTHON_INCLUDES) + + python_LTLIBRARIES = libxml2mod.la + + libxml2mod_la_SOURCES = libxml.c libxml_wrap.h libxml2-py.h libxml2-py.c types.c +-libxml2mod_la_LDFLAGS = $(CYGWIN_EXTRA_LDFLAGS) $(WIN32_EXTRA_LDFLAGS) -module -avoid-version \ ++libxml2mod_la_LDFLAGS = $(LDFLAGS) $(CYGWIN_EXTRA_LDFLAGS) $(WIN32_EXTRA_LDFLAGS) -module -avoid-version \ + $(top_builddir)/libxml2.la $(CYGWIN_EXTRA_PYTHON_LIBADD) $(WIN32_EXTRA_PYTHON_LIBADD) $(PYTHON_LIBS) + + BUILT_SOURCES = libxml2-export.c libxml2-py.h libxml2-py.c diff --git a/package/libxml2/patches/patch-python_setup_py b/package/libxml2/patches/patch-python_setup_py new file mode 100644 index 000000000..13ec3493d --- /dev/null +++ b/package/libxml2/patches/patch-python_setup_py @@ -0,0 +1,11 @@ +--- libxml2-2.9.1.orig/python/setup.py 2013-04-19 09:36:20.000000000 +0200 ++++ libxml2-2.9.1/python/setup.py 2013-11-21 18:47:16.000000000 +0100 +@@ -8,7 +8,7 @@ from distutils.core import setup, Extens + # Below ROOT, we expect to find include, include/libxml2, lib and bin. + # On *nix, it is not needed (but should not harm), + # on Windows, it is set by configure.js. +-ROOT = r'/usr' ++ROOT = r'/Volumes/adk/openadk/host_i686_gnu_eglibc/usr' + + # Thread-enabled libxml2 + with_threads = 1 diff --git a/package/libxslt/Makefile b/package/libxslt/Makefile index e3b322634..8901c8a75 100644 --- a/package/libxslt/Makefile +++ b/package/libxslt/Makefile @@ -10,7 +10,7 @@ PKG_MD5SUM:= 9667bf6f9310b957254fdcf6596600b7 PKG_DESCR:= XSLT Library PKG_SECTION:= libs PKG_DEPENDS:= libxml2 -PKG_BUILDDEP:= python2-host libxml2-host libxslt-host libxml2 +PKG_BUILDDEP:= autotool python2-host libxml2-host libxslt-host libxml2 PKG_URL:= http://xmlsoft.org/XSLT PKG_SITES:= http://xmlsoft.org/sources/ PKG_NEED_CXX:= 1 @@ -37,6 +37,7 @@ HOST_CONFIGURE_ARGS+= --without-python \ --with-libxml-prefix="${STAGING_HOST_DIR}/usr" \ --with-libxml-include-prefix="${STAGING_HOST_DIR}/usr/include/libxml2" \ --with-libxml-libs-prefix="${STAGING_HOST_DIR}/usr/lib" +AUTOTOOL_STYLE:= autoreconf CONFIGURE_ARGS+= --with-libxml-prefix="${STAGING_TARGET_DIR}/usr" \ --with-libxml-include-prefix="${STAGING_TARGET_DIR}/usr/include/libxml2" \ --with-libxml-libs-prefix="${STAGING_TARGET_DIR}/usr/lib" \ diff --git a/package/python2/Makefile b/package/python2/Makefile index ee4768c3d..1fa0cce94 100644 --- a/package/python2/Makefile +++ b/package/python2/Makefile @@ -5,11 +5,11 @@ include ${TOPDIR}/rules.mk PKG_NAME:= python2 PKG_VERSION:= 2.7.5 -PKG_RELEASE:= 5 +PKG_RELEASE:= 6 PKG_MD5SUM:= b4f01a1d0ba0b46b05c73b2ac909b1df PKG_DESCR:= Python scripting language (Version 2) PKG_SECTION:= lang -PKG_BUILDDEP:= libffi python2-host autotool +PKG_BUILDDEP:= autotool libffi python2-host PKG_DEPENDS:= libpthread libffi libgcc PKG_URL:= http://www.python.org/ PKG_SITES:= http://www.python.org/ftp/python/${PKG_VERSION}/ @@ -104,6 +104,14 @@ hostpost-install: $(INSTALL_BIN) ${WRKBUILD}/Parser/pgen \ $(STAGING_HOST_DIR)/usr/bin/pgen +pre-configure: + (cd $(WRKBUILD) && patch -p1 < \ + $(TOPDIR)/package/python2/files/patch-Lib_distutils_sysconfig_py ) + (cd $(WRKBUILD) && patch -p1 < \ + $(TOPDIR)/package/python2/files/patch-Misc_python-config_in ) + $(SED) "s#@EXENAME@#$(STAGING_HOST_DIR)/usr/bin/python#" \ + $(WRKBUILD)/Misc/python-config.in + python2-install: ${INSTALL_MODS_y} ${INSTALL_MODS_m} ${INSTALL_DIR} ${IDIR_PYTHON2}/usr/bin ${IDIR_PYTHON2}/usr/lib ${INSTALL_DIR} ${IDIR_PYTHON2}/usr/lib/python2.7 diff --git a/package/python2/files/build_scripts.py b/package/python2/files/build_scripts.py deleted file mode 100644 index fe81a5341..000000000 --- a/package/python2/files/build_scripts.py +++ /dev/null @@ -1,99 +0,0 @@ -"""distutils.command.build_scripts - -Implements the Distutils 'build_scripts' command.""" - -__revision__ = "$Id: build_scripts.py 77704 2010-01-23 09:23:15Z tarek.ziade $" - -import os, re -from stat import ST_MODE -from distutils.core import Command -from distutils.dep_util import newer -from distutils.util import convert_path -from distutils import log - -# check if Python is called on the first line with this expression -first_line_re = re.compile('^#!.*python[0-9.]*([ \t].*)?$') - -class build_scripts (Command): - - description = "\"build\" scripts (copy and fixup #! line)" - - user_options = [ - ('build-dir=', 'd', "directory to \"build\" (copy) to"), - ('force', 'f', "forcibly build everything (ignore file timestamps"), - ('executable=', 'e', "specify final destination interpreter path"), - ] - - boolean_options = ['force'] - - - def initialize_options (self): - self.build_dir = None - self.scripts = None - self.force = None - self.executable = None - self.outfiles = None - - def finalize_options (self): - self.set_undefined_options('build', - ('build_scripts', 'build_dir'), - ('force', 'force'), - ('executable', 'executable')) - self.scripts = self.distribution.scripts - - def get_source_files(self): - return self.scripts - - def run (self): - if not self.scripts: - return - self.copy_scripts() - - - def copy_scripts (self): - """Copy each script listed in 'self.scripts'; if it's marked as a - Python script in the Unix way (first line matches 'first_line_re', - ie. starts with "\#!" and contains "python"), then adjust the first - line to refer to the current Python interpreter as we copy. - """ - _sysconfig = __import__('sysconfig') - self.mkpath(self.build_dir) - outfiles = [] - for script in self.scripts: - adjust = 0 - script = convert_path(script) - outfile = os.path.join(self.build_dir, os.path.basename(script)) - outfiles.append(outfile) - - if not self.force and not newer(script, outfile): - log.debug("not copying %s (up-to-date)", script) - continue - - # Always open the file, but ignore failures in dry-run mode -- - # that way, we'll get accurate feedback if we can read the - # script. - try: - f = open(script, "r") - except IOError: - if not self.dry_run: - raise - f = None - if f: - f.close() - self.copy_file(script, outfile) - - if os.name == 'posix': - for file in outfiles: - if self.dry_run: - log.info("changing mode of %s", file) - else: - oldmode = os.stat(file)[ST_MODE] & 07777 - newmode = (oldmode | 0555) & 07777 - if newmode != oldmode: - log.info("changing mode of %s from %o to %o", - file, oldmode, newmode) - os.chmod(file, newmode) - - # copy_scripts () - -# class build_scripts diff --git a/package/python2/files/patch-Lib_distutils_sysconfig_py b/package/python2/files/patch-Lib_distutils_sysconfig_py new file mode 100644 index 000000000..30aae0816 --- /dev/null +++ b/package/python2/files/patch-Lib_distutils_sysconfig_py @@ -0,0 +1,10 @@ +--- Python-2.7.5.orig/Lib/distutils/sysconfig.py 2013-05-12 05:32:42.000000000 +0200 ++++ Python-2.7.5/Lib/distutils/sysconfig.py 2013-11-03 18:03:53.000000000 +0100 +@@ -76,6 +76,7 @@ def get_python_inc(plat_specific=0, pref + """ + if prefix is None: + prefix = plat_specific and EXEC_PREFIX or PREFIX ++ prefix = re.sub('host_', 'target_', prefix) + + if os.name == "posix": + if python_build: diff --git a/package/python2/files/patch-Misc_python-config_in b/package/python2/files/patch-Misc_python-config_in new file mode 100644 index 000000000..9734d4fbd --- /dev/null +++ b/package/python2/files/patch-Misc_python-config_in @@ -0,0 +1,21 @@ +--- Python-2.7.5.orig/Misc/python-config.in 2013-05-12 05:32:49.000000000 +0200 ++++ Python-2.7.5/Misc/python-config.in 2013-10-30 21:29:47.000000000 +0100 +@@ -3,6 +3,7 @@ + import sys + import os + import getopt ++import re + from distutils import sysconfig + + valid_opts = ['prefix', 'exec-prefix', 'includes', 'libs', 'cflags', +@@ -37,8 +38,8 @@ for opt in opt_flags: + print sysconfig.EXEC_PREFIX + + elif opt in ('--includes', '--cflags'): +- flags = ['-I' + sysconfig.get_python_inc(), +- '-I' + sysconfig.get_python_inc(plat_specific=True)] ++ flags = ['-I' + re.sub('host_', 'target_', sysconfig.get_python_inc()), ++ '-I' + re.sub('host_', 'target_', sysconfig.get_python_inc(plat_specific=True))] + if opt == '--cflags': + flags.extend(getvar('CFLAGS').split()) + print ' '.join(flags) diff --git a/package/python2/files/posixmodule.c b/package/python2/files/posixmodule.c deleted file mode 100644 index 312861b65..000000000 --- a/package/python2/files/posixmodule.c +++ /dev/null @@ -1,9365 +0,0 @@ - -/* 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 -#endif /* defined(__VMS) */ - -#ifdef __cplusplus -extern "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 -#if defined(PYCC_GCC) -#include -#include -#include -#include -#endif -#include "osdefs.h" -#endif - -#ifdef HAVE_SYS_TYPES_H -#include -#endif /* HAVE_SYS_TYPES_H */ - -#ifdef HAVE_SYS_STAT_H -#include -#endif /* HAVE_SYS_STAT_H */ - -#ifdef HAVE_SYS_WAIT_H -#include /* For WNOHANG */ -#endif - -#ifdef HAVE_SIGNAL_H -#include -#endif - -#ifdef HAVE_FCNTL_H -#include -#endif /* HAVE_FCNTL_H */ - -#ifdef HAVE_GRP_H -#include -#endif - -#ifdef HAVE_SYSEXITS_H -#include -#endif /* HAVE_SYSEXITS_H */ - -#ifdef HAVE_SYS_LOADAVG_H -#include -#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 -#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 -#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 *); -#else -extern int mkdir(const char *, mode_t); -#endif -#endif -#if defined(__IBMC__) || defined(__IBMCPP__) -extern int chdir(char *); -extern int rmdir(char *); -#else -extern int chdir(const char *); -extern int rmdir(const char *); -#endif -#ifdef __BORLANDC__ -extern int chmod(const char *, int); -#else -extern int chmod(const char *, mode_t); -#endif -/*#ifdef HAVE_FCHMOD -extern int fchmod(int, mode_t); -#endif*/ -/*#ifdef HAVE_LCHMOD -extern int lchmod(const char *, mode_t); -#endif*/ -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 *); -extern int pclose(FILE *); -#ifdef HAVE_SYMLINK -extern int symlink(const char *, const char *); -#endif /* HAVE_SYMLINK */ -#ifdef HAVE_LSTAT -extern int lstat(const char *, struct stat *); -#endif /* HAVE_LSTAT */ -#endif /* !HAVE_UNISTD_H */ - -#endif /* !_MSC_VER */ - -#ifdef HAVE_UTIME_H -#include -#endif /* HAVE_UTIME_H */ - -#ifdef HAVE_SYS_UTIME_H -#include -#define HAVE_UTIME_H /* pretend we do for the rest of this file */ -#endif /* HAVE_SYS_UTIME_H */ - -#ifdef HAVE_SYS_TIMES_H -#include -#endif /* HAVE_SYS_TIMES_H */ - -#ifdef HAVE_SYS_PARAM_H -#include -#endif /* HAVE_SYS_PARAM_H */ - -#ifdef HAVE_SYS_UTSNAME_H -#include -#endif /* HAVE_SYS_UTSNAME_H */ - -#ifdef HAVE_DIRENT_H -#include -#define NAMLEN(dirent) strlen((dirent)->d_name) -#else -#if defined(__WATCOMC__) && !defined(__QNX__) -#include -#define NAMLEN(dirent) strlen((dirent)->d_name) -#else -#define dirent direct -#define NAMLEN(dirent) (dirent)->d_namlen -#endif -#ifdef HAVE_SYS_NDIR_H -#include -#endif -#ifdef HAVE_SYS_DIR_H -#include -#endif -#ifdef HAVE_NDIR_H -#include -#endif -#endif - -#ifdef _MSC_VER -#ifdef HAVE_DIRECT_H -#include -#endif -#ifdef HAVE_IO_H -#include -#endif -#ifdef HAVE_PROCESS_H -#include -#endif -#include "osdefs.h" -#include -#include -#include /* for ShellExecute() */ -#define popen _popen -#define pclose _pclose -#endif /* _MSC_VER */ - -#if defined(PYCC_VACPP) && defined(PYOS_OS2) -#include -#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 */ - -/* Issue #1983: pid_t can be longer than a C long on some systems */ -#if !defined(SIZEOF_PID_T) || SIZEOF_PID_T == SIZEOF_INT -#define PARSE_PID "i" -#define PyLong_FromPid PyInt_FromLong -#define PyLong_AsPid PyInt_AsLong -#elif SIZEOF_PID_T == SIZEOF_LONG -#define PARSE_PID "l" -#define PyLong_FromPid PyInt_FromLong -#define PyLong_AsPid PyInt_AsLong -#elif defined(SIZEOF_LONG_LONG) && SIZEOF_PID_T == SIZEOF_LONG_LONG -#define PARSE_PID "L" -#define PyLong_FromPid PyLong_FromLongLong -#define PyLong_AsPid PyInt_AsLongLong -#else -#error "sizeof(pid_t) is neither sizeof(int), sizeof(long) or sizeof(long long)" -#endif /* SIZEOF_PID_T */ - -/* 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 -#else -#if defined(MAJOR_IN_SYSMACROS) -#include -#endif -#if defined(HAVE_MKNOD) && defined(HAVE_SYS_MKDEV_H) -#include -#endif -#endif - -#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 - * by using the exported __pinfo data member and knowledge of the - * 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()) - */ -/* The actual size of the structure is determined at runtime. - * Only the first items must be present. - */ -typedef struct { - intptr_t osfhnd; - char osfile; -} my_ioinfo; - -extern __declspec(dllimport) char * __pioinfo[]; -#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) -{ - const int i1 = fd >> IOINFO_L2E; - const int i2 = fd & ((1 << IOINFO_L2E) - 1); - - static int sizeof_ioinfo = 0; - - /* 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; - } - } - } - fail: - errno = EBADF; - return 0; -} - -/* the special case of checking dup2. The target fd must be in a sensible range */ -static int -_PyVerify_fd_dup2(int fd1, int fd2) -{ - if (!_PyVerify_fd(fd1)) - return 0; - if (fd2 == _NO_CONSOLE_FILENO) - return 0; - if ((unsigned)fd2 < _NHANDLE_) - return 1; - else - return 0; -} -#else -/* dummy version. _PyVerify_fd() is already defined in fileobject.h */ -#define _PyVerify_fd_dup2(A, B) (1) -#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 -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; -#if defined(PYOS_OS2) - APIRET rc; - char buffer[1024]; /* OS/2 Provides a Documented Max of 1024 Chars */ -#endif - 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) - 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 MS_WINDOWS -static PyObject * -posix_error_with_unicode_filename(Py_UNICODE* name) -{ - return PyErr_SetFromErrnoWithUnicodeFilename(PyExc_OSError, name); -} -#endif /* MS_WINDOWS */ - - -static PyObject * -posix_error_with_allocated_filename(char* name) -{ - PyObject *rc = PyErr_SetFromErrnoWithFilename(PyExc_OSError, name); - PyMem_Free(name); - return rc; -} - -#ifdef MS_WINDOWS -static 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); -} - -static 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 int -convert_to_unicode(PyObject **param) -{ - 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; -} - -#endif /* MS_WINDOWS */ - -#if defined(PYOS_OS2) -/********************************************************************** - * Helper Function to Trim and Format OS/2 Messages - **********************************************************************/ -static void -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 ]; - - while (lastc > msgbuf && isspace(Py_CHARMASK(*lastc))) - *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. - * - **********************************************************************/ -static char * -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 - PyOS_snprintf(msgbuf, msgbuflen, - "unknown OS error #%d", errorcode); - - 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. */ - -static PyObject * -os2_error(int code) -{ - char text[1024]; - PyObject *v; - - os2_strerror(text, sizeof(text), code, ""); - - v = Py_BuildValue("(is)", code, text); - if (v != NULL) { - PyErr_SetObject(PyExc_OSError, v); - Py_DECREF(v); - } - return NULL; /* Signal to Python that an Exception is Pending */ -} - -#endif /* OS2 */ - -/* POSIX generic methods */ - -static PyObject * -posix_fildes(PyObject *fdobj, int (*func)(int)) -{ - 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; -} - -static PyObject * -posix_1str(PyObject *args, char *format, int (*func)(const char*)) -{ - char *path1 = NULL; - int res; - if (!PyArg_ParseTuple(args, format, - Py_FileSystemDefaultEncoding, &path1)) - return NULL; - Py_BEGIN_ALLOW_THREADS - res = (*func)(path1); - Py_END_ALLOW_THREADS - if (res < 0) - return posix_error_with_allocated_filename(path1); - PyMem_Free(path1); - Py_INCREF(Py_None); - return Py_None; -} - -static PyObject * -posix_2str(PyObject *args, - char *format, - int (*func)(const char *, const char *)) -{ - char *path1 = NULL, *path2 = NULL; - int res; - if (!PyArg_ParseTuple(args, format, - Py_FileSystemDefaultEncoding, &path1, - Py_FileSystemDefaultEncoding, &path2)) - return NULL; - Py_BEGIN_ALLOW_THREADS - res = (*func)(path1, path2); - Py_END_ALLOW_THREADS - PyMem_Free(path1); - PyMem_Free(path2); - if (res != 0) - /* XXX how to report both path1 and path2??? */ - return posix_error(); - Py_INCREF(Py_None); - return Py_None; -} - -#ifdef MS_WINDOWS -static PyObject* -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; - -} - -/* 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 =: */ -static BOOL __stdcall -win32_chdir(LPCSTR path) -{ - 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); -} - -/* The Unicode version differs from the ANSI version - since the current directory might exceed MAX_PATH characters */ -static BOOL __stdcall -win32_wchdir(LPCWSTR path) -{ - 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; -} -#endif - -#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. -*/ -#define HAVE_STAT_NSEC 1 - -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; - int st_atime; - int st_atime_nsec; - int st_mtime; - int st_mtime_nsec; - int st_ctime; - int st_ctime_nsec; -}; - -static __int64 secs_between_epochs = 11644473600; /* Seconds between 1.1.1601 and 1.1.1970 */ - -static void -FILE_TIME_to_time_t_nsec(FILETIME *in_ptr, int *time_out, int* nsec_out) -{ - /* 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. */ - /* XXX Win32 supports time stamps past 2038; we currently don't */ - *time_out = Py_SAFE_DOWNCAST((in / 10000000) - secs_between_epochs, __int64, int); -} - -static void -time_t_to_FILE_TIME(int time_in, int nsec_in, FILETIME *out_ptr) -{ - /* XXX endianness */ - __int64 out; - out = time_in + secs_between_epochs; - out = out * 10000000 + nsec_in / 100; - memcpy(out_ptr, &out, sizeof(out)); -} - -/* Below, we *know* that ugo+r is 0444 */ -#if _S_IREAD != 0400 -#error Unsupported C library -#endif -static int -attributes_to_mode(DWORD attr) -{ - 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; -} - -static int -attribute_data_to_stat(WIN32_FILE_ATTRIBUTE_DATA *info, struct win32_stat *result) -{ - 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); - - return 0; -} - -static BOOL -attributes_from_dir(LPCSTR pszFile, LPWIN32_FILE_ATTRIBUTE_DATA pfad) -{ - HANDLE hFindFile; - WIN32_FIND_DATAA FileData; - hFindFile = FindFirstFileA(pszFile, &FileData); - if (hFindFile == INVALID_HANDLE_VALUE) - return FALSE; - FindClose(hFindFile); - pfad->dwFileAttributes = FileData.dwFileAttributes; - pfad->ftCreationTime = FileData.ftCreationTime; - pfad->ftLastAccessTime = FileData.ftLastAccessTime; - pfad->ftLastWriteTime = FileData.ftLastWriteTime; - pfad->nFileSizeHigh = FileData.nFileSizeHigh; - pfad->nFileSizeLow = FileData.nFileSizeLow; - return TRUE; -} - -static BOOL -attributes_from_dir_w(LPCWSTR pszFile, LPWIN32_FILE_ATTRIBUTE_DATA pfad) -{ - HANDLE hFindFile; - WIN32_FIND_DATAW FileData; - hFindFile = FindFirstFileW(pszFile, &FileData); - if (hFindFile == INVALID_HANDLE_VALUE) - return FALSE; - FindClose(hFindFile); - pfad->dwFileAttributes = FileData.dwFileAttributes; - pfad->ftCreationTime = FileData.ftCreationTime; - pfad->ftLastAccessTime = FileData.ftLastAccessTime; - pfad->ftLastWriteTime = FileData.ftLastWriteTime; - pfad->nFileSizeHigh = FileData.nFileSizeHigh; - pfad->nFileSizeLow = FileData.nFileSizeLow; - return TRUE; -} - -static int -win32_stat(const char* path, struct win32_stat *result) -{ - WIN32_FILE_ATTRIBUTE_DATA info; - int code; - char *dot; - if (!GetFileAttributesExA(path, GetFileExInfoStandard, &info)) { - if (GetLastError() != ERROR_SHARING_VIOLATION) { - /* Protocol violation: we explicitly clear errno, instead of - setting it to a POSIX error. Callers should use GetLastError. */ - errno = 0; - return -1; - } else { - /* Could not get attributes on open file. Fall back to - reading the directory. */ - if (!attributes_from_dir(path, &info)) { - /* Very strange. This should not fail now */ - errno = 0; - return -1; - } - } - } - code = attribute_data_to_stat(&info, result); - if (code != 0) - return code; - /* Set S_IFEXEC if it is an .exe, .bat, ... */ - dot = strrchr(path, '.'); - if (dot) { - if (stricmp(dot, ".bat") == 0 || - stricmp(dot, ".cmd") == 0 || - stricmp(dot, ".exe") == 0 || - stricmp(dot, ".com") == 0) - result->st_mode |= 0111; - } - return code; -} - -static int -win32_wstat(const wchar_t* path, struct win32_stat *result) -{ - int code; - const wchar_t *dot; - WIN32_FILE_ATTRIBUTE_DATA info; - if (!GetFileAttributesExW(path, GetFileExInfoStandard, &info)) { - if (GetLastError() != ERROR_SHARING_VIOLATION) { - /* Protocol violation: we explicitly clear errno, instead of - setting it to a POSIX error. Callers should use GetLastError. */ - errno = 0; - return -1; - } else { - /* Could not get attributes on open file. Fall back to - reading the directory. */ - if (!attributes_from_dir_w(path, &info)) { - /* Very strange. This should not fail now */ - errno = 0; - return -1; - } - } - } - code = attribute_data_to_stat(&info, result); - if (code < 0) - return code; - /* Set IFEXEC 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; - } - return code; -} - -static int -win32_fstat(int file_number, struct win32_stat *result) -{ - 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) { - return -1; - } - /* 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; - } - - /* similar to stat() */ - 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); - /* specific to fstat() */ - result->st_nlink = info.nNumberOfLinks; - result->st_ino = (((__int64)info.nFileIndexHigh)<<32) + info.nFileIndexLow; - return 0; -} - -#endif /* MS_WINDOWS */ - -PyDoc_STRVAR(stat_result__doc__, -"stat_result: Result from stat or lstat.\n\n\ -This object may be accessed either as a tuple of\n\ - (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime)\n\ -or via the attributes st_mode, st_ino, st_dev, st_nlink, st_uid, and so on.\n\ -\n\ -Posix/windows: If your platform supports st_blksize, st_blocks, st_rdev,\n\ -or st_flags, they are available as attributes only.\n\ -\n\ -See os.stat for more information."); - -static PyStructSequence_Field stat_result_fields[] = { - {"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"}, -#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE - {"st_blksize", "blocksize for filesystem I/O"}, -#endif -#ifdef HAVE_STRUCT_STAT_ST_BLOCKS - {"st_blocks", "number of blocks allocated"}, -#endif -#ifdef HAVE_STRUCT_STAT_ST_RDEV - {"st_rdev", "device type (if inode device)"}, -#endif -#ifdef HAVE_STRUCT_STAT_ST_FLAGS - {"st_flags", "user defined flags for file"}, -#endif -#ifdef HAVE_STRUCT_STAT_ST_GEN - {"st_gen", "generation number"}, -#endif -#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME - {"st_birthtime", "time of creation"}, -#endif - {0} -}; - -#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE -#define ST_BLKSIZE_IDX 13 -#else -#define ST_BLKSIZE_IDX 12 -#endif - -#ifdef HAVE_STRUCT_STAT_ST_BLOCKS -#define ST_BLOCKS_IDX (ST_BLKSIZE_IDX+1) -#else -#define ST_BLOCKS_IDX ST_BLKSIZE_IDX -#endif - -#ifdef HAVE_STRUCT_STAT_ST_RDEV -#define ST_RDEV_IDX (ST_BLOCKS_IDX+1) -#else -#define ST_RDEV_IDX ST_BLOCKS_IDX -#endif - -#ifdef HAVE_STRUCT_STAT_ST_FLAGS -#define ST_FLAGS_IDX (ST_RDEV_IDX+1) -#else -#define ST_FLAGS_IDX ST_RDEV_IDX -#endif - -#ifdef HAVE_STRUCT_STAT_ST_GEN -#define ST_GEN_IDX (ST_FLAGS_IDX+1) -#else -#define ST_GEN_IDX ST_FLAGS_IDX -#endif - -#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME -#define ST_BIRTHTIME_IDX (ST_GEN_IDX+1) -#else -#define ST_BIRTHTIME_IDX ST_GEN_IDX -#endif - -static PyStructSequence_Desc stat_result_desc = { - "stat_result", /* name */ - stat_result__doc__, /* doc */ - stat_result_fields, - 10 -}; - -PyDoc_STRVAR(statvfs_result__doc__, -"statvfs_result: Result from statvfs or fstatvfs.\n\n\ -This object may be accessed either as a tuple of\n\ - (bsize, frsize, blocks, bfree, bavail, files, ffree, favail, flag, namemax),\n\ -or via the attributes f_bsize, f_frsize, f_blocks, f_bfree, and so on.\n\ -\n\ -See os.statvfs for more information."); - -static PyStructSequence_Field statvfs_result_fields[] = { - {"f_bsize", }, - {"f_frsize", }, - {"f_blocks", }, - {"f_bfree", }, - {"f_bavail", }, - {"f_files", }, - {"f_ffree", }, - {"f_favail", }, - {"f_flag", }, - {"f_namemax",}, - {0} -}; - -static PyStructSequence_Desc statvfs_result_desc = { - "statvfs_result", /* name */ - statvfs_result__doc__, /* doc */ - statvfs_result_fields, - 10 -}; - -static int initialized; -static PyTypeObject StatResultType; -static PyTypeObject StatVFSResultType; -static newfunc structseq_new; - -static PyObject * -statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - PyStructSequence *result; - int i; - - 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; -} - - - -/* If true, st_?time is float. */ -static int _stat_float_times = 1; - -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) -{ - 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; -} - -static void -fill_time(PyObject *v, int index, time_t sec, unsigned long nsec) -{ - PyObject *fval,*ival; -#if SIZEOF_TIME_T > SIZEOF_LONG - ival = PyLong_FromLongLong((PY_LONG_LONG)sec); -#else - ival = PyInt_FromLong((long)sec); -#endif - 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); -} - -/* pack a system stat C structure into the Python stat tuple - (used by posix_stat() and posix_fstat()) */ -static PyObject* -_pystat_fromstructstat(STRUCT_STAT *st) -{ - unsigned long ansec, mnsec, cnsec; - PyObject *v = PyStructSequence_New(&StatResultType); - if (v == NULL) - return NULL; - - PyStructSequence_SET_ITEM(v, 0, PyInt_FromLong((long)st->st_mode)); -#ifdef HAVE_LARGEFILE_SUPPORT - PyStructSequence_SET_ITEM(v, 1, - PyLong_FromLongLong((PY_LONG_LONG)st->st_ino)); -#else - PyStructSequence_SET_ITEM(v, 1, PyInt_FromLong((long)st->st_ino)); -#endif -#if defined(HAVE_LONG_LONG) && !defined(MS_WINDOWS) - PyStructSequence_SET_ITEM(v, 2, - PyLong_FromLongLong((PY_LONG_LONG)st->st_dev)); -#else - PyStructSequence_SET_ITEM(v, 2, PyInt_FromLong((long)st->st_dev)); -#endif - PyStructSequence_SET_ITEM(v, 3, PyInt_FromLong((long)st->st_nlink)); - PyStructSequence_SET_ITEM(v, 4, PyInt_FromLong((long)st->st_uid)); - PyStructSequence_SET_ITEM(v, 5, PyInt_FromLong((long)st->st_gid)); -#ifdef HAVE_LARGEFILE_SUPPORT - PyStructSequence_SET_ITEM(v, 6, - PyLong_FromLongLong((PY_LONG_LONG)st->st_size)); -#else - PyStructSequence_SET_ITEM(v, 6, PyInt_FromLong(st->st_size)); -#endif - -#if defined(HAVE_STAT_TV_NSEC) - ansec = st->st_atim.tv_nsec; - mnsec = st->st_mtim.tv_nsec; - cnsec = st->st_ctim.tv_nsec; -#elif defined(HAVE_STAT_TV_NSEC2) - ansec = st->st_atimespec.tv_nsec; - mnsec = st->st_mtimespec.tv_nsec; - cnsec = st->st_ctimespec.tv_nsec; -#elif defined(HAVE_STAT_NSEC) - ansec = st->st_atime_nsec; - mnsec = st->st_mtime_nsec; - cnsec = st->st_ctime_nsec; -#else - ansec = mnsec = cnsec = 0; -#endif - fill_time(v, 7, st->st_atime, ansec); - fill_time(v, 8, st->st_mtime, mnsec); - fill_time(v, 9, st->st_ctime, cnsec); - -#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE - PyStructSequence_SET_ITEM(v, ST_BLKSIZE_IDX, - PyInt_FromLong((long)st->st_blksize)); -#endif -#ifdef HAVE_STRUCT_STAT_ST_BLOCKS - PyStructSequence_SET_ITEM(v, ST_BLOCKS_IDX, - PyInt_FromLong((long)st->st_blocks)); -#endif -#ifdef HAVE_STRUCT_STAT_ST_RDEV - PyStructSequence_SET_ITEM(v, ST_RDEV_IDX, - PyInt_FromLong((long)st->st_rdev)); -#endif -#ifdef HAVE_STRUCT_STAT_ST_GEN - PyStructSequence_SET_ITEM(v, ST_GEN_IDX, - PyInt_FromLong((long)st->st_gen)); -#endif -#ifdef HAVE_STRUCT_STAT_ST_BIRTHTIME - { - PyObject *val; - unsigned long bsec,bnsec; - bsec = (long)st->st_birthtime; -#ifdef HAVE_STAT_TV_NSEC2 - bnsec = st->st_birthtimespec.tv_nsec; -#else - bnsec = 0; -#endif - if (_stat_float_times) { - val = PyFloat_FromDouble(bsec + 1e-9*bnsec); - } else { - val = PyInt_FromLong((long)bsec); - } - PyStructSequence_SET_ITEM(v, ST_BIRTHTIME_IDX, - val); - } -#endif -#ifdef HAVE_STRUCT_STAT_ST_FLAGS - PyStructSequence_SET_ITEM(v, ST_FLAGS_IDX, - PyInt_FromLong((long)st->st_flags)); -#endif - - if (PyErr_Occurred()) { - Py_DECREF(v); - return NULL; - } - - return v; -} - -#ifdef MS_WINDOWS - -/* IsUNCRoot -- test whether the supplied path is of the form \\SERVER\SHARE\, - where / can be used in place of \ and the trailing slash is optional. - Both SERVER and SHARE must have at least one character. -*/ - -#define ISSLASHA(c) ((c) == '\\' || (c) == '/') -#define ISSLASHW(c) ((c) == L'\\' || (c) == L'/') -#ifndef ARRAYSIZE -#define ARRAYSIZE(a) (sizeof(a) / sizeof(a[0])) -#endif - -static BOOL -IsUNCRootA(char *path, int pathlen) -{ - #define ISSLASH ISSLASHA - - int i, share; - - if (pathlen < 5 || !ISSLASH(path[0]) || !ISSLASH(path[1])) - /* minimum UNCRoot is \\x\y */ - return FALSE; - for (i = 2; i < pathlen ; i++) - if (ISSLASH(path[i])) break; - if (i == 2 || i == pathlen) - /* do not allow \\\SHARE or \\SERVER */ - return FALSE; - share = i+1; - for (i = share; i < pathlen; i++) - if (ISSLASH(path[i])) break; - return (i != share && (i == pathlen || i == pathlen-1)); - - #undef ISSLASH -} - -static BOOL -IsUNCRootW(Py_UNICODE *path, int pathlen) -{ - #define ISSLASH ISSLASHW - - int i, share; - - if (pathlen < 5 || !ISSLASH(path[0]) || !ISSLASH(path[1])) - /* minimum UNCRoot is \\x\y */ - return FALSE; - for (i = 2; i < pathlen ; i++) - if (ISSLASH(path[i])) break; - if (i == 2 || i == pathlen) - /* do not allow \\\SHARE or \\SERVER */ - return FALSE; - share = i+1; - for (i = share; i < pathlen; i++) - if (ISSLASH(path[i])) break; - return (i != share && (i == pathlen || i == pathlen-1)); - - #undef ISSLASH -} -#endif /* MS_WINDOWS */ - -static PyObject * -posix_do_stat(PyObject *self, PyObject *args, - char *format, -#ifdef __VMS - int (*statfunc)(const char *, STRUCT_STAT *, ...), -#else - int (*statfunc)(const char *, STRUCT_STAT *), -#endif - char *wformat, - int (*wstatfunc)(const Py_UNICODE *, STRUCT_STAT *)) -{ - STRUCT_STAT st; - char *path = NULL; /* pass this to stat; do not free() it */ - char *pathfree = NULL; /* this memory must be free'd */ - int res; - PyObject *result; - -#ifdef MS_WINDOWS - 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, - Py_FileSystemDefaultEncoding, &path)) - return NULL; - pathfree = path; - - Py_BEGIN_ALLOW_THREADS - res = (*statfunc)(path, &st); - Py_END_ALLOW_THREADS - - if (res != 0) { -#ifdef MS_WINDOWS - result = win32_error("stat", pathfree); -#else - result = posix_error_with_filename(pathfree); -#endif - } - else - result = _pystat_fromstructstat(&st); - - PyMem_Free(pathfree); - return result; -} - -/* POSIX methods */ - -PyDoc_STRVAR(posix_access__doc__, -"access(path, mode) -> True if granted, False otherwise\n\n\ -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."); - -static PyObject * -posix_access(PyObject *self, PyObject *args) -{ - char *path; - int mode; - -#ifdef MS_WINDOWS - 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, "eti:access", - Py_FileSystemDefaultEncoding, &path, &mode)) - return NULL; - Py_BEGIN_ALLOW_THREADS - attr = GetFileAttributesA(path); - Py_END_ALLOW_THREADS - PyMem_Free(path); -finish: - if (attr == 0xFFFFFFFF) - /* File does not exist, or cannot read attributes */ - return PyBool_FromLong(0); - /