/pypy/rpython/module/ll_os.py
Python | 1841 lines | 1837 code | 2 blank | 2 comment | 3 complexity | 07ff05b10b06658c51fca46d06c693a7 MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- """
- Low-level implementations for the external functions of the 'os' module.
- """
- # Implementation details about those functions
- # might be found in doc/rffi.txt
- import os, sys, errno
- import py
- from pypy.rpython.module.support import OOSupport
- from pypy.tool.sourcetools import func_renamer
- from pypy.rlib.rarithmetic import r_longlong
- from pypy.rpython.extfunc import (
- BaseLazyRegistering, register_external)
- from pypy.rpython.extfunc import registering, registering_if, extdef
- from pypy.annotation.model import (
- SomeInteger, SomeString, SomeTuple, SomeFloat, SomeUnicodeString)
- from pypy.annotation.model import s_ImpossibleValue, s_None, s_Bool
- from pypy.rpython.lltypesystem import rffi
- from pypy.rpython.lltypesystem import lltype
- from pypy.rpython.tool import rffi_platform as platform
- from pypy.rlib import rposix
- from pypy.translator.tool.cbuild import ExternalCompilationInfo
- from pypy.rpython.lltypesystem.llmemory import itemoffsetof, offsetof
- from pypy.rpython.lltypesystem.rstr import STR
- from pypy.rlib.objectmodel import specialize
- str0 = SomeString(no_nul=True)
- unicode0 = SomeUnicodeString(no_nul=True)
- def monkeypatch_rposix(posixfunc, unicodefunc, signature):
- func_name = posixfunc.__name__
- if hasattr(signature, '_default_signature_'):
- signature = signature._default_signature_
- arglist = ['arg%d' % (i,) for i in range(len(signature))]
- transformed_arglist = arglist[:]
- for i, arg in enumerate(signature):
- if arg in (unicode, unicode0):
- transformed_arglist[i] = transformed_arglist[i] + '.as_unicode()'
- args = ', '.join(arglist)
- transformed_args = ', '.join(transformed_arglist)
- try:
- main_arg = 'arg%d' % (signature.index(unicode0),)
- except ValueError:
- main_arg = 'arg%d' % (signature.index(unicode),)
- source = py.code.Source("""
- def %(func_name)s(%(args)s):
- if isinstance(%(main_arg)s, str):
- return posixfunc(%(args)s)
- else:
- return unicodefunc(%(transformed_args)s)
- """ % locals())
- miniglobals = {'posixfunc' : posixfunc,
- 'unicodefunc': unicodefunc,
- '__name__': __name__, # for module name propagation
- }
- exec source.compile() in miniglobals
- new_func = miniglobals[func_name]
- specialized_args = [i for i in range(len(signature))
- if signature[i] in (unicode, unicode0, None)]
- new_func = specialize.argtype(*specialized_args)(new_func)
- # Monkeypatch the function in pypy.rlib.rposix
- setattr(rposix, func_name, new_func)
- class StringTraits:
- str = str
- str0 = str0
- CHAR = rffi.CHAR
- CCHARP = rffi.CCHARP
- charp2str = staticmethod(rffi.charp2str)
- str2charp = staticmethod(rffi.str2charp)
- free_charp = staticmethod(rffi.free_charp)
- scoped_alloc_buffer = staticmethod(rffi.scoped_alloc_buffer)
- @staticmethod
- def posix_function_name(name):
- return underscore_on_windows + name
- @staticmethod
- def ll_os_name(name):
- return 'll_os.ll_os_' + name
- class UnicodeTraits:
- str = unicode
- str0 = unicode0
- CHAR = rffi.WCHAR_T
- CCHARP = rffi.CWCHARP
- charp2str = staticmethod(rffi.wcharp2unicode)
- str2charp = staticmethod(rffi.unicode2wcharp)
- free_charp = staticmethod(rffi.free_wcharp)
- scoped_alloc_buffer = staticmethod(rffi.scoped_alloc_unicodebuffer)
- @staticmethod
- def posix_function_name(name):
- return underscore_on_windows + 'w' + name
- @staticmethod
- def ll_os_name(name):
- return 'll_os.ll_os_w' + name
- def registering_str_unicode(posixfunc, condition=True):
- if not condition or posixfunc is None:
- return registering(None, condition=False)
- func_name = posixfunc.__name__
- def register_posixfunc(self, method):
- val = method(self, StringTraits())
- register_external(posixfunc, *val.def_args, **val.def_kwds)
- if sys.platform == 'win32':
- val = method(self, UnicodeTraits())
- @func_renamer(func_name + "_unicode")
- def unicodefunc(*args):
- return posixfunc(*args)
- register_external(unicodefunc, *val.def_args, **val.def_kwds)
- signature = val.def_args[0]
- monkeypatch_rposix(posixfunc, unicodefunc, signature)
- def decorator(method):
- decorated = lambda self: register_posixfunc(self, method)
- decorated._registering_func = posixfunc
- return decorated
- return decorator
- posix = __import__(os.name)
- if sys.platform.startswith('win'):
- _WIN32 = True
- else:
- _WIN32 = False
- if _WIN32:
- underscore_on_windows = '_'
- else:
- underscore_on_windows = ''
- includes = []
- if not _WIN32:
- # XXX many of these includes are not portable at all
- includes += ['dirent.h', 'sys/stat.h',
- 'sys/times.h', 'utime.h', 'sys/types.h', 'unistd.h',
- 'signal.h', 'sys/wait.h', 'fcntl.h']
- else:
- includes += ['sys/utime.h', 'sys/types.h']
- _CYGWIN = sys.platform == 'cygwin'
- class CConfig:
- """
- Definitions for platform integration.
- Note: this must be processed through platform.configure() to provide
- usable objects. For example::
- CLOCK_T = platform.configure(CConfig)['CLOCK_T']
- register(function, [CLOCK_T], ...)
- """
- _compilation_info_ = ExternalCompilationInfo(
- includes=includes
- )
- if not _WIN32:
- CLOCK_T = platform.SimpleType('clock_t', rffi.INT)
- TMS = platform.Struct(
- 'struct tms', [('tms_utime', rffi.INT),
- ('tms_stime', rffi.INT),
- ('tms_cutime', rffi.INT),
- ('tms_cstime', rffi.INT)])
- GID_T = platform.SimpleType('gid_t', rffi.INT)
- #TODO right now is used only in getgroups, may need to update other
- #functions like setgid
- # For now we require off_t to be the same size as LONGLONG, which is the
- # interface required by callers of functions that thake an argument of type
- # off_t
- OFF_T_SIZE = platform.SizeOf('off_t')
- SEEK_SET = platform.DefinedConstantInteger('SEEK_SET')
- SEEK_CUR = platform.DefinedConstantInteger('SEEK_CUR')
- SEEK_END = platform.DefinedConstantInteger('SEEK_END')
- UTIMBUF = platform.Struct('struct '+underscore_on_windows+'utimbuf',
- [('actime', rffi.INT),
- ('modtime', rffi.INT)])
- class RegisterOs(BaseLazyRegistering):
- def __init__(self):
- self.configure(CConfig)
- if not _WIN32:
- assert self.OFF_T_SIZE == rffi.sizeof(rffi.LONGLONG)
- if hasattr(os, 'getpgrp'):
- self.GETPGRP_HAVE_ARG = platform.checkcompiles(
- "getpgrp(0)",
- '#include <unistd.h>',
- [])
- if hasattr(os, 'setpgrp'):
- self.SETPGRP_HAVE_ARG = platform.checkcompiles(
- "setpgrp(0,0)",
- '#include <unistd.h>',
- [])
- # we need an indirection via c functions to get macro calls working on llvm XXX still?
- if hasattr(os, 'WCOREDUMP'):
- decl_snippet = """
- %(ret_type)s pypy_macro_wrapper_%(name)s (int status);
- """
- def_snippet = """
- %(ret_type)s pypy_macro_wrapper_%(name)s (int status) {
- return %(name)s(status);
- }
- """
- decls = []
- defs = []
- for name in self.w_star:
- data = {'ret_type': 'int', 'name': name}
- decls.append((decl_snippet % data).strip())
- defs.append((def_snippet % data).strip())
- self.compilation_info = self.compilation_info.merge(
- ExternalCompilationInfo(
- post_include_bits = decls,
- separate_module_sources = ["\n".join(defs)]
- ))
- # a simple, yet useful factory
- def extdef_for_os_function_returning_int(self, name, **kwds):
- c_func = self.llexternal(name, [], rffi.INT, **kwds)
- def c_func_llimpl():
- res = rffi.cast(rffi.SIGNED, c_func())
- if res == -1:
- raise OSError(rposix.get_errno(), "%s failed" % name)
- return res
- c_func_llimpl.func_name = name + '_llimpl'
- return extdef([], int, llimpl=c_func_llimpl,
- export_name='ll_os.ll_os_' + name)
- def extdef_for_os_function_accepting_int(self, name, **kwds):
- c_func = self.llexternal(name, [rffi.INT], rffi.INT, **kwds)
- def c_func_llimpl(arg):
- res = rffi.cast(rffi.SIGNED, c_func(arg))
- if res == -1:
- raise OSError(rposix.get_errno(), "%s failed" % name)
-
- c_func_llimpl.func_name = name + '_llimpl'
- return extdef([int], None, llimpl=c_func_llimpl,
- export_name='ll_os.ll_os_' + name)
- def extdef_for_os_function_accepting_2int(self, name, **kwds):
- c_func = self.llexternal(name, [rffi.INT, rffi.INT], rffi.INT, **kwds)
- def c_func_llimpl(arg, arg2):
- res = rffi.cast(rffi.SIGNED, c_func(arg, arg2))
- if res == -1:
- raise OSError(rposix.get_errno(), "%s failed" % name)
-
- c_func_llimpl.func_name = name + '_llimpl'
- return extdef([int, int], None, llimpl=c_func_llimpl,
- export_name='ll_os.ll_os_' + name)
- def extdef_for_os_function_accepting_0int(self, name, **kwds):
- c_func = self.llexternal(name, [], rffi.INT, **kwds)
- def c_func_llimpl():
- res = rffi.cast(rffi.SIGNED, c_func())
- if res == -1:
- raise OSError(rposix.get_errno(), "%s failed" % name)
-
- c_func_llimpl.func_name = name + '_llimpl'
- return extdef([], None, llimpl=c_func_llimpl,
- export_name='ll_os.ll_os_' + name)
- def extdef_for_os_function_int_to_int(self, name, **kwds):
- c_func = self.llexternal(name, [rffi.INT], rffi.INT, **kwds)
- def c_func_llimpl(arg):
- res = rffi.cast(rffi.SIGNED, c_func(arg))
- if res == -1:
- raise OSError(rposix.get_errno(), "%s failed" % name)
- return res
-
- c_func_llimpl.func_name = name + '_llimpl'
- return extdef([int], int, llimpl=c_func_llimpl,
- export_name='ll_os.ll_os_' + name)
- @registering_if(os, 'execv')
- def register_os_execv(self):
- eci = self.gcc_profiling_bug_workaround(
- 'int _noprof_execv(char *path, char *argv[])',
- 'return execv(path, argv);')
- os_execv = self.llexternal('_noprof_execv',
- [rffi.CCHARP, rffi.CCHARPP],
- rffi.INT, compilation_info = eci)
- def execv_llimpl(path, args):
- l_args = rffi.liststr2charpp(args)
- os_execv(path, l_args)
- rffi.free_charpp(l_args)
- raise OSError(rposix.get_errno(), "execv failed")
- return extdef([str0, [str0]], s_ImpossibleValue, llimpl=execv_llimpl,
- export_name="ll_os.ll_os_execv")
- @registering_if(os, 'execve')
- def register_os_execve(self):
- eci = self.gcc_profiling_bug_workaround(
- 'int _noprof_execve(char *filename, char *argv[], char *envp[])',
- 'return execve(filename, argv, envp);')
- os_execve = self.llexternal(
- '_noprof_execve', [rffi.CCHARP, rffi.CCHARPP, rffi.CCHARPP],
- rffi.INT, compilation_info = eci)
- def execve_llimpl(path, args, env):
- # XXX Check path, args, env for \0 and raise TypeErrors as
- # appropriate
- envstrs = []
- for item in env.iteritems():
- envstr = "%s=%s" % item
- envstrs.append(envstr)
- l_args = rffi.liststr2charpp(args)
- l_env = rffi.liststr2charpp(envstrs)
- os_execve(path, l_args, l_env)
- # XXX untested
- rffi.free_charpp(l_env)
- rffi.free_charpp(l_args)
- raise OSError(rposix.get_errno(), "execve failed")
- return extdef(
- [str0, [str0], {str0: str0}],
- s_ImpossibleValue,
- llimpl=execve_llimpl,
- export_name="ll_os.ll_os_execve")
- @registering_if(posix, 'spawnv')
- def register_os_spawnv(self):
- os_spawnv = self.llexternal('spawnv',
- [rffi.INT, rffi.CCHARP, rffi.CCHARPP],
- rffi.INT)
- def spawnv_llimpl(mode, path, args):
- mode = rffi.cast(rffi.INT, mode)
- l_args = rffi.liststr2charpp(args)
- childpid = os_spawnv(mode, path, l_args)
- rffi.free_charpp(l_args)
- if childpid == -1:
- raise OSError(rposix.get_errno(), "os_spawnv failed")
- return rffi.cast(lltype.Signed, childpid)
- return extdef([int, str0, [str0]], int, llimpl=spawnv_llimpl,
- export_name="ll_os.ll_os_spawnv")
- @registering_if(os, 'spawnve')
- def register_os_spawnve(self):
- os_spawnve = self.llexternal('spawnve',
- [rffi.INT, rffi.CCHARP, rffi.CCHARPP,
- rffi.CCHARPP],
- rffi.INT)
- def spawnve_llimpl(mode, path, args, env):
- envstrs = []
- for item in env.iteritems():
- envstrs.append("%s=%s" % item)
- mode = rffi.cast(rffi.INT, mode)
- l_args = rffi.liststr2charpp(args)
- l_env = rffi.liststr2charpp(envstrs)
- childpid = os_spawnve(mode, path, l_args, l_env)
- rffi.free_charpp(l_env)
- rffi.free_charpp(l_args)
- if childpid == -1:
- raise OSError(rposix.get_errno(), "os_spawnve failed")
- return rffi.cast(lltype.Signed, childpid)
- return extdef([int, str0, [str0], {str0: str0}], int,
- llimpl=spawnve_llimpl,
- export_name="ll_os.ll_os_spawnve")
- @registering(os.dup)
- def register_os_dup(self):
- os_dup = self.llexternal(underscore_on_windows+'dup', [rffi.INT], rffi.INT)
- def dup_llimpl(fd):
- rposix.validate_fd(fd)
- newfd = rffi.cast(lltype.Signed, os_dup(rffi.cast(rffi.INT, fd)))
- if newfd == -1:
- raise OSError(rposix.get_errno(), "dup failed")
- return newfd
-
- return extdef([int], int, llimpl=dup_llimpl,
- export_name="ll_os.ll_os_dup", oofakeimpl=os.dup)
- @registering(os.dup2)
- def register_os_dup2(self):
- os_dup2 = self.llexternal(underscore_on_windows+'dup2',
- [rffi.INT, rffi.INT], rffi.INT)
- def dup2_llimpl(fd, newfd):
- rposix.validate_fd(fd)
- error = rffi.cast(lltype.Signed, os_dup2(rffi.cast(rffi.INT, fd),
- rffi.cast(rffi.INT, newfd)))
- if error == -1:
- raise OSError(rposix.get_errno(), "dup2 failed")
- return extdef([int, int], s_None, llimpl=dup2_llimpl,
- export_name="ll_os.ll_os_dup2")
- @registering_if(os, "getlogin", condition=not _WIN32)
- def register_os_getlogin(self):
- os_getlogin = self.llexternal('getlogin', [], rffi.CCHARP)
- def getlogin_llimpl():
- result = os_getlogin()
- if not result:
- raise OSError(rposix.get_errno(), "getlogin failed")
- return rffi.charp2str(result)
- return extdef([], str, llimpl=getlogin_llimpl,
- export_name="ll_os.ll_os_getlogin")
- @registering_str_unicode(os.utime)
- def register_os_utime(self, traits):
- UTIMBUFP = lltype.Ptr(self.UTIMBUF)
- os_utime = self.llexternal('utime', [rffi.CCHARP, UTIMBUFP], rffi.INT)
- if not _WIN32:
- includes = ['sys/time.h']
- else:
- includes = ['time.h']
- class CConfig:
- _compilation_info_ = ExternalCompilationInfo(
- includes=includes
- )
- HAVE_UTIMES = platform.Has('utimes')
- config = platform.configure(CConfig)
- # XXX note that on Windows, calls to os.utime() are ignored on
- # directories. Remove that hack over there once it's fixed here!
- if config['HAVE_UTIMES']:
- class CConfig:
- if not _WIN32:
- _compilation_info_ = ExternalCompilationInfo(
- includes = includes
- )
- else:
- _compilation_info_ = ExternalCompilationInfo(
- includes = ['time.h']
- )
- TIMEVAL = platform.Struct('struct timeval', [('tv_sec', rffi.LONG),
- ('tv_usec', rffi.LONG)])
- config = platform.configure(CConfig)
- TIMEVAL = config['TIMEVAL']
- TIMEVAL2P = rffi.CArrayPtr(TIMEVAL)
- os_utimes = self.llexternal('utimes', [rffi.CCHARP, TIMEVAL2P],
- rffi.INT, compilation_info=CConfig._compilation_info_)
- def os_utime_platform(path, actime, modtime):
- import math
- l_times = lltype.malloc(TIMEVAL2P.TO, 2, flavor='raw')
- fracpart, intpart = math.modf(actime)
- rffi.setintfield(l_times[0], 'c_tv_sec', int(intpart))
- rffi.setintfield(l_times[0], 'c_tv_usec', int(fracpart * 1E6))
- fracpart, intpart = math.modf(modtime)
- rffi.setintfield(l_times[1], 'c_tv_sec', int(intpart))
- rffi.setintfield(l_times[1], 'c_tv_usec', int(fracpart * 1E6))
- error = os_utimes(path, l_times)
- lltype.free(l_times, flavor='raw')
- return error
- else:
- # we only have utime(), which does not allow sub-second resolution
- def os_utime_platform(path, actime, modtime):
- l_utimbuf = lltype.malloc(UTIMBUFP.TO, flavor='raw')
- l_utimbuf.c_actime = rffi.r_time_t(actime)
- l_utimbuf.c_modtime = rffi.r_time_t(modtime)
- error = os_utime(path, l_utimbuf)
- lltype.free(l_utimbuf, flavor='raw')
- return error
- # NB. this function is specialized; we get one version where
- # tp is known to be None, and one version where it is known
- # to be a tuple of 2 floats.
- if not _WIN32:
- assert traits.str is str
- @specialize.argtype(1)
- def os_utime_llimpl(path, tp):
- if tp is None:
- error = os_utime(path, lltype.nullptr(UTIMBUFP.TO))
- else:
- actime, modtime = tp
- error = os_utime_platform(path, actime, modtime)
- error = rffi.cast(lltype.Signed, error)
- if error == -1:
- raise OSError(rposix.get_errno(), "os_utime failed")
- else:
- from pypy.rpython.module.ll_win32file import make_utime_impl
- os_utime_llimpl = make_utime_impl(traits)
- s_tuple_of_2_floats = SomeTuple([SomeFloat(), SomeFloat()])
- def os_utime_normalize_args(s_path, s_times):
- # special handling of the arguments: they can be either
- # [str, (float, float)] or [str, s_None], and get normalized
- # to exactly one of these two.
- if not traits.str0.contains(s_path):
- raise Exception("os.utime() arg 1 must be a string, got %s" % (
- s_path,))
- case1 = s_None.contains(s_times)
- case2 = s_tuple_of_2_floats.contains(s_times)
- if case1 and case2:
- return [traits.str0, s_ImpossibleValue] #don't know which case yet
- elif case1:
- return [traits.str0, s_None]
- elif case2:
- return [traits.str0, s_tuple_of_2_floats]
- else:
- raise Exception("os.utime() arg 2 must be None or a tuple of "
- "2 floats, got %s" % (s_times,))
- os_utime_normalize_args._default_signature_ = [traits.str0, None]
- return extdef(os_utime_normalize_args, s_None,
- "ll_os.ll_os_utime",
- llimpl=os_utime_llimpl)
- @registering(os.times)
- def register_os_times(self):
- if sys.platform.startswith('win'):
- from pypy.rlib import rwin32
- GetCurrentProcess = self.llexternal('GetCurrentProcess', [],
- rwin32.HANDLE)
- GetProcessTimes = self.llexternal('GetProcessTimes',
- [rwin32.HANDLE,
- lltype.Ptr(rwin32.FILETIME),
- lltype.Ptr(rwin32.FILETIME),
- lltype.Ptr(rwin32.FILETIME),
- lltype.Ptr(rwin32.FILETIME)],
- rwin32.BOOL)
- def times_lltypeimpl():
- pcreate = lltype.malloc(rwin32.FILETIME, flavor='raw')
- pexit = lltype.malloc(rwin32.FILETIME, flavor='raw')
- pkernel = lltype.malloc(rwin32.FILETIME, flavor='raw')
- puser = lltype.malloc(rwin32.FILETIME, flavor='raw')
- hProc = GetCurrentProcess()
- GetProcessTimes(hProc, pcreate, pexit, pkernel, puser)
- # The fields of a FILETIME structure are the hi and lo parts
- # of a 64-bit value expressed in 100 nanosecond units
- # (of course).
- result = (rffi.cast(lltype.Signed, pkernel.c_dwHighDateTime) * 429.4967296 +
- rffi.cast(lltype.Signed, pkernel.c_dwLowDateTime) * 1E-7,
- rffi.cast(lltype.Signed, puser.c_dwHighDateTime) * 429.4967296 +
- rffi.cast(lltype.Signed, puser.c_dwLowDateTime) * 1E-7,
- 0, 0, 0)
- lltype.free(puser, flavor='raw')
- lltype.free(pkernel, flavor='raw')
- lltype.free(pexit, flavor='raw')
- lltype.free(pcreate, flavor='raw')
- return result
- self.register(os.times, [], (float, float, float, float, float),
- "ll_os.ll_times", llimpl=times_lltypeimpl)
- return
- TMSP = lltype.Ptr(self.TMS)
- os_times = self.llexternal('times', [TMSP], self.CLOCK_T)
- # Here is a random extra platform parameter which is important.
- # Strictly speaking, this should probably be retrieved at runtime, not
- # at translation time.
- CLOCK_TICKS_PER_SECOND = float(os.sysconf('SC_CLK_TCK'))
- def times_lltypeimpl():
- l_tmsbuf = lltype.malloc(TMSP.TO, flavor='raw')
- try:
- result = os_times(l_tmsbuf)
- result = rffi.cast(lltype.Signed, result)
- if result == -1:
- raise OSError(rposix.get_errno(), "times failed")
- return (
- rffi.cast(lltype.Signed, l_tmsbuf.c_tms_utime)
- / CLOCK_TICKS_PER_SECOND,
- rffi.cast(lltype.Signed, l_tmsbuf.c_tms_stime)
- / CLOCK_TICKS_PER_SECOND,
- rffi.cast(lltype.Signed, l_tmsbuf.c_tms_cutime)
- / CLOCK_TICKS_PER_SECOND,
- rffi.cast(lltype.Signed, l_tmsbuf.c_tms_cstime)
- / CLOCK_TICKS_PER_SECOND,
- result / CLOCK_TICKS_PER_SECOND)
- finally:
- lltype.free(l_tmsbuf, flavor='raw')
- self.register(os.times, [], (float, float, float, float, float),
- "ll_os.ll_times", llimpl=times_lltypeimpl)
- @registering_if(os, 'setsid')
- def register_os_setsid(self):
- os_setsid = self.llexternal('setsid', [], rffi.PID_T)
- def setsid_llimpl():
- result = rffi.cast(lltype.Signed, os_setsid())
- if result == -1:
- raise OSError(rposix.get_errno(), "os_setsid failed")
- return result
- return extdef([], int, export_name="ll_os.ll_os_setsid",
- llimpl=setsid_llimpl)
- @registering_if(os, 'chroot')
- def register_os_chroot(self):
- os_chroot = self.llexternal('chroot', [rffi.CCHARP], rffi.INT)
- def chroot_llimpl(arg):
- result = os_chroot(arg)
- if result == -1:
- raise OSError(rposix.get_errno(), "os_chroot failed")
- return extdef([str0], None, export_name="ll_os.ll_os_chroot",
- llimpl=chroot_llimpl)
- @registering_if(os, 'uname')
- def register_os_uname(self):
- CHARARRAY = lltype.FixedSizeArray(lltype.Char, 1)
- class CConfig:
- _compilation_info_ = ExternalCompilationInfo(
- includes = ['sys/utsname.h']
- )
- UTSNAME = platform.Struct('struct utsname', [
- ('sysname', CHARARRAY),
- ('nodename', CHARARRAY),
- ('release', CHARARRAY),
- ('version', CHARARRAY),
- ('machine', CHARARRAY)])
- config = platform.configure(CConfig)
- UTSNAMEP = lltype.Ptr(config['UTSNAME'])
- os_uname = self.llexternal('uname', [UTSNAMEP], rffi.INT,
- compilation_info=CConfig._compilation_info_)
- def uname_llimpl():
- l_utsbuf = lltype.malloc(UTSNAMEP.TO, flavor='raw')
- result = os_uname(l_utsbuf)
- if result == -1:
- raise OSError(rposix.get_errno(), "os_uname failed")
- retval = (
- rffi.charp2str(rffi.cast(rffi.CCHARP, l_utsbuf.c_sysname)),
- rffi.charp2str(rffi.cast(rffi.CCHARP, l_utsbuf.c_nodename)),
- rffi.charp2str(rffi.cast(rffi.CCHARP, l_utsbuf.c_release)),
- rffi.charp2str(rffi.cast(rffi.CCHARP, l_utsbuf.c_version)),
- rffi.charp2str(rffi.cast(rffi.CCHARP, l_utsbuf.c_machine)),
- )
- lltype.free(l_utsbuf, flavor='raw')
- return retval
- return extdef([], (str, str, str, str, str),
- "ll_os.ll_uname", llimpl=uname_llimpl)
- @registering_if(os, 'sysconf')
- def register_os_sysconf(self):
- c_sysconf = self.llexternal('sysconf', [rffi.INT], rffi.LONG)
- def sysconf_llimpl(i):
- rposix.set_errno(0)
- res = c_sysconf(i)
- if res == -1:
- errno = rposix.get_errno()
- if errno != 0:
- raise OSError(errno, "sysconf failed")
- return res
- return extdef([int], int, "ll_os.ll_sysconf", llimpl=sysconf_llimpl)
- @registering_if(os, 'fpathconf')
- def register_os_fpathconf(self):
- c_fpathconf = self.llexternal('fpathconf',
- [rffi.INT, rffi.INT], rffi.LONG)
- def fpathconf_llimpl(fd, i):
- rposix.set_errno(0)
- res = c_fpathconf(fd, i)
- if res == -1:
- errno = rposix.get_errno()
- if errno != 0:
- raise OSError(errno, "fpathconf failed")
- return res
- return extdef([int, int], int, "ll_os.ll_fpathconf",
- llimpl=fpathconf_llimpl)
- @registering_if(os, 'getuid')
- def register_os_getuid(self):
- return self.extdef_for_os_function_returning_int('getuid')
- @registering_if(os, 'geteuid')
- def register_os_geteuid(self):
- return self.extdef_for_os_function_returning_int('geteuid')
- @registering_if(os, 'setuid')
- def register_os_setuid(self):
- return self.extdef_for_os_function_accepting_int('setuid')
- @registering_if(os, 'seteuid')
- def register_os_seteuid(self):
- return self.extdef_for_os_function_accepting_int('seteuid')
- @registering_if(os, 'setgid')
- def register_os_setgid(self):
- return self.extdef_for_os_function_accepting_int('setgid')
- @registering_if(os, 'setegid')
- def register_os_setegid(self):
- return self.extdef_for_os_function_accepting_int('setegid')
- @registering_if(os, 'getpid')
- def register_os_getpid(self):
- return self.extdef_for_os_function_returning_int('getpid')
- @registering_if(os, 'getgid')
- def register_os_getgid(self):
- return self.extdef_for_os_function_returning_int('getgid')
- @registering_if(os, 'getegid')
- def register_os_getegid(self):
- return self.extdef_for_os_function_returning_int('getegid')
- @registering_if(os, 'getgroups')
- def register_os_getgroups(self):
- GP = rffi.CArrayPtr(self.GID_T)
- c_getgroups = self.llexternal('getgroups', [rffi.INT, GP], rffi.INT)
- def getgroups_llimpl():
- n = c_getgroups(0, lltype.nullptr(GP.TO))
- if n >= 0:
- groups = lltype.malloc(GP.TO, n, flavor='raw')
- try:
- n = c_getgroups(n, groups)
- result = [groups[i] for i in range(n)]
- finally:
- lltype.free(groups, flavor='raw')
- if n >= 0:
- return result
- raise OSError(rposix.get_errno(), "os_getgroups failed")
- return extdef([], [self.GID_T], llimpl=getgroups_llimpl,
- export_name="ll_os.ll_getgroups")
- @registering_if(os, 'getpgrp')
- def register_os_getpgrp(self):
- name = 'getpgrp'
- if self.GETPGRP_HAVE_ARG:
- c_func = self.llexternal(name, [rffi.INT], rffi.INT)
- def c_func_llimpl():
- res = rffi.cast(rffi.SIGNED, c_func(0))
- if res == -1:
- raise OSError(rposix.get_errno(), "%s failed" % name)
- return res
- c_func_llimpl.func_name = name + '_llimpl'
- return extdef([], int, llimpl=c_func_llimpl,
- export_name='ll_os.ll_os_' + name)
- else:
- return self.extdef_for_os_function_returning_int('getpgrp')
- @registering_if(os, 'setpgrp')
- def register_os_setpgrp(self):
- name = 'setpgrp'
- if self.SETPGRP_HAVE_ARG:
- c_func = self.llexternal(name, [rffi.INT, rffi.INT], rffi.INT)
- def c_func_llimpl():
- res = rffi.cast(rffi.SIGNED, c_func(0, 0))
- if res == -1:
- raise OSError(rposix.get_errno(), "%s failed" % name)
- c_func_llimpl.func_name = name + '_llimpl'
- return extdef([], None, llimpl=c_func_llimpl,
- export_name='ll_os.ll_os_' + name)
- else:
- return self.extdef_for_os_function_accepting_0int(name)
- @registering_if(os, 'getppid')
- def register_os_getppid(self):
- return self.extdef_for_os_function_returning_int('getppid')
- @registering_if(os, 'getpgid')
- def register_os_getpgid(self):
- return self.extdef_for_os_function_int_to_int('getpgid')
- @registering_if(os, 'setpgid')
- def register_os_setpgid(self):
- return self.extdef_for_os_function_accepting_2int('setpgid')
- @registering_if(os, 'setreuid')
- def register_os_setreuid(self):
- return self.extdef_for_os_function_accepting_2int('setreuid')
- @registering_if(os, 'setregid')
- def register_os_setregid(self):
- return self.extdef_for_os_function_accepting_2int('setregid')
- @registering_if(os, 'getsid')
- def register_os_getsid(self):
- return self.extdef_for_os_function_int_to_int('getsid')
- @registering_if(os, 'setsid')
- def register_os_setsid(self):
- return self.extdef_for_os_function_returning_int('setsid')
- @registering_str_unicode(os.open)
- def register_os_open(self, traits):
- os_open = self.llexternal(traits.posix_function_name('open'),
- [traits.CCHARP, rffi.INT, rffi.MODE_T],
- rffi.INT)
- def os_open_llimpl(path, flags, mode):
- result = rffi.cast(lltype.Signed, os_open(path, flags, mode))
- if result == -1:
- raise OSError(rposix.get_errno(), "os_open failed")
- return result
- def os_open_oofakeimpl(path, flags, mode):
- return os.open(OOSupport.from_rstr(path), flags, mode)
- return extdef([traits.str0, int, int], int, traits.ll_os_name('open'),
- llimpl=os_open_llimpl, oofakeimpl=os_open_oofakeimpl)
- @registering_if(os, 'getloadavg')
- def register_os_getloadavg(self):
- AP = rffi.CArrayPtr(lltype.Float)
- c_getloadavg = self.llexternal('getloadavg', [AP, rffi.INT], rffi.INT)
- def getloadavg_llimpl():
- load = lltype.malloc(AP.TO, 3, flavor='raw')
- r = c_getloadavg(load, 3)
- result_tuple = load[0], load[1], load[2]
- lltype.free(load, flavor='raw')
- if r != 3:
- raise OSError
- return result_tuple
- return extdef([], (float, float, float),
- "ll_os.ll_getloadavg", llimpl=getloadavg_llimpl)
- @registering_if(os, 'makedev')
- def register_os_makedev(self):
- c_makedev = self.llexternal('makedev', [rffi.INT, rffi.INT], rffi.INT)
- def makedev_llimpl(maj, min):
- return c_makedev(maj, min)
- return extdef([int, int], int,
- "ll_os.ll_makedev", llimpl=makedev_llimpl)
- @registering_if(os, 'major')
- def register_os_major(self):
- c_major = self.llexternal('major', [rffi.INT], rffi.INT)
- def major_llimpl(dev):
- return c_major(dev)
- return extdef([int], int,
- "ll_os.ll_major", llimpl=major_llimpl)
- @registering_if(os, 'minor')
- def register_os_minor(self):
- c_minor = self.llexternal('minor', [rffi.INT], rffi.INT)
- def minor_llimpl(dev):
- return c_minor(dev)
- return extdef([int], int,
- "ll_os.ll_minor", llimpl=minor_llimpl)
- # ------------------------------- os.read -------------------------------
- @registering(os.read)
- def register_os_read(self):
- os_read = self.llexternal(underscore_on_windows+'read',
- [rffi.INT, rffi.VOIDP, rffi.SIZE_T],
- rffi.SIZE_T)
- offset = offsetof(STR, 'chars') + itemoffsetof(STR.chars, 0)
- def os_read_llimpl(fd, count):
- if count < 0:
- raise OSError(errno.EINVAL, None)
- rposix.validate_fd(fd)
- raw_buf, gc_buf = rffi.alloc_buffer(count)
- try:
- void_buf = rffi.cast(rffi.VOIDP, raw_buf)
- got = rffi.cast(lltype.Signed, os_read(fd, void_buf, count))
- if got < 0:
- raise OSError(rposix.get_errno(), "os_read failed")
- return rffi.str_from_buffer(raw_buf, gc_buf, count, got)
- finally:
- rffi.keep_buffer_alive_until_here(raw_buf, gc_buf)
-
- def os_read_oofakeimpl(fd, count):
- return OOSupport.to_rstr(os.read(fd, count))
- return extdef([int, int], SomeString(can_be_None=True),
- "ll_os.ll_os_read",
- llimpl=os_read_llimpl, oofakeimpl=os_read_oofakeimpl)
- @registering(os.write)
- def register_os_write(self):
- os_write = self.llexternal(underscore_on_windows+'write',
- [rffi.INT, rffi.VOIDP, rffi.SIZE_T],
- rffi.SIZE_T)
- def os_write_llimpl(fd, data):
- count = len(data)
- rposix.validate_fd(fd)
- buf = rffi.get_nonmovingbuffer(data)
- try:
- written = rffi.cast(lltype.Signed, os_write(
- rffi.cast(rffi.INT, fd),
- buf, rffi.cast(rffi.SIZE_T, count)))
- if written < 0:
- raise OSError(rposix.get_errno(), "os_write failed")
- finally:
- rffi.free_nonmovingbuffer(data, buf)
- return written
- def os_write_oofakeimpl(fd, data):
- return os.write(fd, OOSupport.from_rstr(data))
- return extdef([int, str], SomeInteger(nonneg=True),
- "ll_os.ll_os_write", llimpl=os_write_llimpl,
- oofakeimpl=os_write_oofakeimpl)
- @registering(os.close)
- def register_os_close(self):
- os_close = self.llexternal(underscore_on_windows+'close', [rffi.INT],
- rffi.INT, threadsafe=False)
-
- def close_llimpl(fd):
- rposix.validate_fd(fd)
- error = rffi.cast(lltype.Signed, os_close(rffi.cast(rffi.INT, fd)))
- if error == -1:
- raise OSError(rposix.get_errno(), "close failed")
- return extdef([int], s_None, llimpl=close_llimpl,
- export_name="ll_os.ll_os_close", oofakeimpl=os.close)
- @registering(os.lseek)
- def register_os_lseek(self):
- if sys.platform.startswith('win'):
- funcname = '_lseeki64'
- else:
- funcname = 'lseek'
- if self.SEEK_SET is not None:
- SEEK_SET = self.SEEK_SET
- SEEK_CUR = self.SEEK_CUR
- SEEK_END = self.SEEK_END
- else:
- SEEK_SET, SEEK_CUR, SEEK_END = 0, 1, 2
- if (SEEK_SET, SEEK_CUR, SEEK_END) != (0, 1, 2):
- # Turn 0, 1, 2 into SEEK_{SET,CUR,END}
- def fix_seek_arg(n):
- if n == 0: return SEEK_SET
- if n == 1: return SEEK_CUR
- if n == 2: return SEEK_END
- return n
- else:
- def fix_seek_arg(n):
- return n
- os_lseek = self.llexternal(funcname,
- [rffi.INT, rffi.LONGLONG, rffi.INT],
- rffi.LONGLONG, macro=True)
- def lseek_llimpl(fd, pos, how):
- rposix.validate_fd(fd)
- how = fix_seek_arg(how)
- res = os_lseek(rffi.cast(rffi.INT, fd),
- rffi.cast(rffi.LONGLONG, pos),
- rffi.cast(rffi.INT, how))
- res = rffi.cast(lltype.SignedLongLong, res)
- if res < 0:
- raise OSError(rposix.get_errno(), "os_lseek failed")
- return res
- def os_lseek_oofakeimpl(fd, pos, how):
- res = os.lseek(fd, pos, how)
- return r_longlong(res)
- return extdef([int, r_longlong, int],
- r_longlong,
- llimpl = lseek_llimpl,
- export_name = "ll_os.ll_os_lseek",
- oofakeimpl = os_lseek_oofakeimpl)
- @registering_if(os, 'ftruncate')
- def register_os_ftruncate(self):
- os_ftruncate = self.llexternal('ftruncate',
- [rffi.INT, rffi.LONGLONG], rffi.INT, macro=True)
- def ftruncate_llimpl(fd, length):
- rposix.validate_fd(fd)
- res = rffi.cast(rffi.LONG,
- os_ftruncate(rffi.cast(rffi.INT, fd),
- rffi.cast(rffi.LONGLONG, length)))
- if res < 0:
- raise OSError(rposix.get_errno(), "os_ftruncate failed")
- return extdef([int, r_longlong], s_None,
- llimpl = ftruncate_llimpl,
- export_name = "ll_os.ll_os_ftruncate")
- @registering_if(os, 'fsync')
- def register_os_fsync(self):
- if not _WIN32:
- os_fsync = self.llexternal('fsync', [rffi.INT], rffi.INT)
- else:
- os_fsync = self.llexternal('_commit', [rffi.INT], rffi.INT)
- def fsync_llimpl(fd):
- rposix.validate_fd(fd)
- res = rffi.cast(rffi.SIGNED, os_fsync(rffi.cast(rffi.INT, fd)))
- if res < 0:
- raise OSError(rposix.get_errno(), "fsync failed")
- return extdef([int], s_None,
- llimpl=fsync_llimpl,
- export_name="ll_os.ll_os_fsync")
- @registering_if(os, 'fdatasync')
- def register_os_fdatasync(self):
- os_fdatasync = self.llexternal('fdatasync', [rffi.INT], rffi.INT)
- def fdatasync_llimpl(fd):
- rposix.validate_fd(fd)
- res = rffi.cast(rffi.SIGNED, os_fdatasync(rffi.cast(rffi.INT, fd)))
- if res < 0:
- raise OSError(rposix.get_errno(), "fdatasync failed")
- return extdef([int], s_None,
- llimpl=fdatasync_llimpl,
- export_name="ll_os.ll_os_fdatasync")
- @registering_if(os, 'fchdir')
- def register_os_fchdir(self):
- os_fchdir = self.llexternal('fchdir', [rffi.INT], rffi.INT)
- def fchdir_llimpl(fd):
- rposix.validate_fd(fd)
- res = rffi.cast(rffi.SIGNED, os_fchdir(rffi.cast(rffi.INT, fd)))
- if res < 0:
- raise OSError(rposix.get_errno(), "fchdir failed")
- return extdef([int], s_None,
- llimpl=fchdir_llimpl,
- export_name="ll_os.ll_os_fchdir")
- @registering_str_unicode(os.access)
- def register_os_access(self, traits):
- os_access = self.llexternal(traits.posix_function_name('access'),
- [traits.CCHARP, rffi.INT],
- rffi.INT)
- if sys.platform.startswith('win'):
- # All files are executable on Windows
- def access_llimpl(path, mode):
- mode = mode & ~os.X_OK
- error = rffi.cast(lltype.Signed, os_access(path, mode))
- return error == 0
- else:
- def access_llimpl(path, mode):
- error = rffi.cast(lltype.Signed, os_access(path, mode))
- return error == 0
- def os_access_oofakeimpl(path, mode):
- return os.access(OOSupport.from_rstr(path), mode)
- return extdef([traits.str0, int], s_Bool, llimpl=access_llimpl,
- export_name=traits.ll_os_name("access"),
- oofakeimpl=os_access_oofakeimpl)
- @registering_str_unicode(getattr(posix, '_getfullpathname', None),
- condition=sys.platform=='win32')
- def register_posix__getfullpathname(self, traits):
- # this nt function is not exposed via os, but needed
- # to get a correct implementation of os.abspath
- from pypy.rpython.module.ll_win32file import make_getfullpathname_impl
- getfullpathname_llimpl = make_getfullpathname_impl(traits)
- return extdef([traits.str0], # a single argument which is a str
- traits.str0, # returns a string
- traits.ll_os_name('_getfullpathname'),
- llimpl=getfullpathname_llimpl)
- @registering(os.getcwd)
- def register_os_getcwd(self):
- os_getcwd = self.llexternal(underscore_on_windows + 'getcwd',
- [rffi.CCHARP, rffi.SIZE_T],
- rffi.CCHARP)
- def os_getcwd_llimpl():
- bufsize = 256
- while True:
- buf = lltype.malloc(rffi.CCHARP.TO, bufsize, flavor='raw')
- res = os_getcwd(buf, rffi.cast(rffi.SIZE_T, bufsize))
- if res:
- break # ok
- error = rposix.get_errno()
- lltype.free(buf, flavor='raw')
- if error != errno.ERANGE:
- raise OSError(error, "getcwd failed")
- # else try again with a larger buffer, up to some sane limit
- bufsize *= 4
- if bufsize > 1024*1024: # xxx hard-coded upper limit
- raise OSError(error, "getcwd result too large")
- result = rffi.charp2str(res)
- lltype.free(buf, flavor='raw')
- return result
- def os_getcwd_oofakeimpl():
- return OOSupport.to_rstr(os.getcwd())
- return extdef([], str0,
- "ll_os.ll_os_getcwd", llimpl=os_getcwd_llimpl,
- oofakeimpl=os_getcwd_oofakeimpl)
- @registering(os.getcwdu, condition=sys.platform=='win32')
- def register_os_getcwdu(self):
- os_wgetcwd = self.llexternal(underscore_on_windows + 'wgetcwd',
- [rffi.CWCHARP, rffi.SIZE_T],
- rffi.CWCHARP)
- def os_getcwd_llimpl():
- bufsize = 256
- while True:
- buf = lltype.malloc(rffi.CWCHARP.TO, bufsize, flavor='raw')
- res = os_wgetcwd(buf, rffi.cast(rffi.SIZE_T, bufsize))
- if res:
- break # ok
- error = rposix.get_errno()
- lltype.free(buf, flavor='raw')
- if error != errno.ERANGE:
- raise OSError(error, "getcwd failed")
- # else try again with a larger buffer, up to some sane limit
- bufsize *= 4
- if bufsize > 1024*1024: # xxx hard-coded upper limit
- raise OSError(error, "getcwd result too large")
- result = rffi.wcharp2unicode(res)
- lltype.free(buf, flavor='raw')
- return result
- return extdef([], unicode,
- "ll_os.ll_os_wgetcwd", llimpl=os_getcwd_llimpl)
- @registering_str_unicode(os.listdir)
- def register_os_listdir(self, traits):
- # we need a different approach on Windows and on Posix
- if sys.platform.startswith('win'):
- from pypy.rpython.module.ll_win32file import make_listdir_impl
- os_listdir_llimpl = make_listdir_impl(traits)
- else:
- assert traits.str is str
- compilation_info = ExternalCompilationInfo(
- includes = ['sys/types.h', 'dirent.h']
- )
- class CConfig:
- _compilation_info_ = compilation_info
- DIRENT = platform.Struct('struct dirent',
- [('d_name', lltype.FixedSizeArray(rffi.CHAR, 1))])
- DIRP = rffi.COpaquePtr('DIR')
- config = platform.configure(CConfig)
- DIRENT = config['DIRENT']
- DIRENTP = lltype.Ptr(DIRENT)
- os_opendir = self.llexternal('opendir', [rffi.CCHARP], DIRP,
- compilation_info=compilation_info)
- # XXX macro=True is hack to make sure we get the correct kind of
- # dirent struct (which depends on defines)
- os_readdir = self.llexternal('readdir', [DIRP], DIRENTP,
- compilation_info=compilation_info,
- macro=True)
- os_closedir = self.llexternal('closedir', [DIRP], rffi.INT,
- compilation_info=compilation_info)
- def os_listdir_llimpl(path):
- dirp = os_opendir(path)
- if not dirp:
- raise OSError(rposix.get_errno(), "os_opendir failed")
- rposix.set_errno(0)
- result = []
- while True:
- direntp = os_readdir(dirp)
- if not direntp:
- error = rposix.get_errno()
- break
- namep = rffi.cast(rffi.CCHARP, direntp.c_d_name)
- name = rffi.charp2str(namep)
- if name != '.' and name != '..':
- result.append(name)
- os_closedir(dirp)
- if error:
- raise OSError(error, "os_readdir failed")
- return result
- return extdef([traits.str0], # a single argument which is a str
- [traits.str0], # returns a list of strings
- traits.ll_os_name('listdir'),
- llimpl=os_listdir_llimpl)
- @registering(os.pipe)
- def register_os_pipe(self):
- # we need a different approach on Windows and on Posix
- if sys.platform.startswith('win'):
- from pypy.rlib import rwin32
- CreatePipe = self.llexternal('CreatePipe', [rwin32.LPHANDLE,
- rwin32.LPHANDLE,
- rffi.VOIDP,
- rwin32.DWORD],
- rwin32.BOOL)
- _open_osfhandle = self.llexternal('_open_osfhandle', [rffi.INTPTR_T,
- rffi.INT],
- rffi.INT)
- null = lltype.nullptr(rffi.VOIDP.TO)
- def os_pipe_llimpl():
- pread = lltype.malloc(rwin32.LPHANDLE.TO, 1, flavor='raw')
- pwrite = lltype.malloc(rwin32.LPHANDLE.TO, 1, flavor='raw')
- ok = CreatePipe(pread, pwrite, null, 0)
- if ok:
- error = 0
- else:
- error = rwin32.GetLastError()
- hread = rffi.cast(rffi.INTPTR_T, pread[0])
- hwrite = rffi.cast(rffi.INTPTR_T, pwrite[0])
- lltype.free(pwrite, flavor='raw')
- lltype.free(pread, flavor='raw')
- if error:
- raise WindowsError(…
Large files files are truncated, but you can click here to view the full file