PageRenderTime 77ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 0ms

/pypy/rpython/module/ll_os.py

https://bitbucket.org/SeanTater/pypy-bugfix-st
Python | 1841 lines | 1837 code | 2 blank | 2 comment | 3 complexity | 07ff05b10b06658c51fca46d06c693a7 MD5 | raw file
  1. """
  2. Low-level implementations for the external functions of the 'os' module.
  3. """
  4. # Implementation details about those functions
  5. # might be found in doc/rffi.txt
  6. import os, sys, errno
  7. import py
  8. from pypy.rpython.module.support import OOSupport
  9. from pypy.tool.sourcetools import func_renamer
  10. from pypy.rlib.rarithmetic import r_longlong
  11. from pypy.rpython.extfunc import (
  12. BaseLazyRegistering, register_external)
  13. from pypy.rpython.extfunc import registering, registering_if, extdef
  14. from pypy.annotation.model import (
  15. SomeInteger, SomeString, SomeTuple, SomeFloat, SomeUnicodeString)
  16. from pypy.annotation.model import s_ImpossibleValue, s_None, s_Bool
  17. from pypy.rpython.lltypesystem import rffi
  18. from pypy.rpython.lltypesystem import lltype
  19. from pypy.rpython.tool import rffi_platform as platform
  20. from pypy.rlib import rposix
  21. from pypy.translator.tool.cbuild import ExternalCompilationInfo
  22. from pypy.rpython.lltypesystem.llmemory import itemoffsetof, offsetof
  23. from pypy.rpython.lltypesystem.rstr import STR
  24. from pypy.rlib.objectmodel import specialize
  25. str0 = SomeString(no_nul=True)
  26. unicode0 = SomeUnicodeString(no_nul=True)
  27. def monkeypatch_rposix(posixfunc, unicodefunc, signature):
  28. func_name = posixfunc.__name__
  29. if hasattr(signature, '_default_signature_'):
  30. signature = signature._default_signature_
  31. arglist = ['arg%d' % (i,) for i in range(len(signature))]
  32. transformed_arglist = arglist[:]
  33. for i, arg in enumerate(signature):
  34. if arg in (unicode, unicode0):
  35. transformed_arglist[i] = transformed_arglist[i] + '.as_unicode()'
  36. args = ', '.join(arglist)
  37. transformed_args = ', '.join(transformed_arglist)
  38. try:
  39. main_arg = 'arg%d' % (signature.index(unicode0),)
  40. except ValueError:
  41. main_arg = 'arg%d' % (signature.index(unicode),)
  42. source = py.code.Source("""
  43. def %(func_name)s(%(args)s):
  44. if isinstance(%(main_arg)s, str):
  45. return posixfunc(%(args)s)
  46. else:
  47. return unicodefunc(%(transformed_args)s)
  48. """ % locals())
  49. miniglobals = {'posixfunc' : posixfunc,
  50. 'unicodefunc': unicodefunc,
  51. '__name__': __name__, # for module name propagation
  52. }
  53. exec source.compile() in miniglobals
  54. new_func = miniglobals[func_name]
  55. specialized_args = [i for i in range(len(signature))
  56. if signature[i] in (unicode, unicode0, None)]
  57. new_func = specialize.argtype(*specialized_args)(new_func)
  58. # Monkeypatch the function in pypy.rlib.rposix
  59. setattr(rposix, func_name, new_func)
  60. class StringTraits:
  61. str = str
  62. str0 = str0
  63. CHAR = rffi.CHAR
  64. CCHARP = rffi.CCHARP
  65. charp2str = staticmethod(rffi.charp2str)
  66. str2charp = staticmethod(rffi.str2charp)
  67. free_charp = staticmethod(rffi.free_charp)
  68. scoped_alloc_buffer = staticmethod(rffi.scoped_alloc_buffer)
  69. @staticmethod
  70. def posix_function_name(name):
  71. return underscore_on_windows + name
  72. @staticmethod
  73. def ll_os_name(name):
  74. return 'll_os.ll_os_' + name
  75. class UnicodeTraits:
  76. str = unicode
  77. str0 = unicode0
  78. CHAR = rffi.WCHAR_T
  79. CCHARP = rffi.CWCHARP
  80. charp2str = staticmethod(rffi.wcharp2unicode)
  81. str2charp = staticmethod(rffi.unicode2wcharp)
  82. free_charp = staticmethod(rffi.free_wcharp)
  83. scoped_alloc_buffer = staticmethod(rffi.scoped_alloc_unicodebuffer)
  84. @staticmethod
  85. def posix_function_name(name):
  86. return underscore_on_windows + 'w' + name
  87. @staticmethod
  88. def ll_os_name(name):
  89. return 'll_os.ll_os_w' + name
  90. def registering_str_unicode(posixfunc, condition=True):
  91. if not condition or posixfunc is None:
  92. return registering(None, condition=False)
  93. func_name = posixfunc.__name__
  94. def register_posixfunc(self, method):
  95. val = method(self, StringTraits())
  96. register_external(posixfunc, *val.def_args, **val.def_kwds)
  97. if sys.platform == 'win32':
  98. val = method(self, UnicodeTraits())
  99. @func_renamer(func_name + "_unicode")
  100. def unicodefunc(*args):
  101. return posixfunc(*args)
  102. register_external(unicodefunc, *val.def_args, **val.def_kwds)
  103. signature = val.def_args[0]
  104. monkeypatch_rposix(posixfunc, unicodefunc, signature)
  105. def decorator(method):
  106. decorated = lambda self: register_posixfunc(self, method)
  107. decorated._registering_func = posixfunc
  108. return decorated
  109. return decorator
  110. posix = __import__(os.name)
  111. if sys.platform.startswith('win'):
  112. _WIN32 = True
  113. else:
  114. _WIN32 = False
  115. if _WIN32:
  116. underscore_on_windows = '_'
  117. else:
  118. underscore_on_windows = ''
  119. includes = []
  120. if not _WIN32:
  121. # XXX many of these includes are not portable at all
  122. includes += ['dirent.h', 'sys/stat.h',
  123. 'sys/times.h', 'utime.h', 'sys/types.h', 'unistd.h',
  124. 'signal.h', 'sys/wait.h', 'fcntl.h']
  125. else:
  126. includes += ['sys/utime.h', 'sys/types.h']
  127. _CYGWIN = sys.platform == 'cygwin'
  128. class CConfig:
  129. """
  130. Definitions for platform integration.
  131. Note: this must be processed through platform.configure() to provide
  132. usable objects. For example::
  133. CLOCK_T = platform.configure(CConfig)['CLOCK_T']
  134. register(function, [CLOCK_T], ...)
  135. """
  136. _compilation_info_ = ExternalCompilationInfo(
  137. includes=includes
  138. )
  139. if not _WIN32:
  140. CLOCK_T = platform.SimpleType('clock_t', rffi.INT)
  141. TMS = platform.Struct(
  142. 'struct tms', [('tms_utime', rffi.INT),
  143. ('tms_stime', rffi.INT),
  144. ('tms_cutime', rffi.INT),
  145. ('tms_cstime', rffi.INT)])
  146. GID_T = platform.SimpleType('gid_t', rffi.INT)
  147. #TODO right now is used only in getgroups, may need to update other
  148. #functions like setgid
  149. # For now we require off_t to be the same size as LONGLONG, which is the
  150. # interface required by callers of functions that thake an argument of type
  151. # off_t
  152. OFF_T_SIZE = platform.SizeOf('off_t')
  153. SEEK_SET = platform.DefinedConstantInteger('SEEK_SET')
  154. SEEK_CUR = platform.DefinedConstantInteger('SEEK_CUR')
  155. SEEK_END = platform.DefinedConstantInteger('SEEK_END')
  156. UTIMBUF = platform.Struct('struct '+underscore_on_windows+'utimbuf',
  157. [('actime', rffi.INT),
  158. ('modtime', rffi.INT)])
  159. class RegisterOs(BaseLazyRegistering):
  160. def __init__(self):
  161. self.configure(CConfig)
  162. if not _WIN32:
  163. assert self.OFF_T_SIZE == rffi.sizeof(rffi.LONGLONG)
  164. if hasattr(os, 'getpgrp'):
  165. self.GETPGRP_HAVE_ARG = platform.checkcompiles(
  166. "getpgrp(0)",
  167. '#include <unistd.h>',
  168. [])
  169. if hasattr(os, 'setpgrp'):
  170. self.SETPGRP_HAVE_ARG = platform.checkcompiles(
  171. "setpgrp(0,0)",
  172. '#include <unistd.h>',
  173. [])
  174. # we need an indirection via c functions to get macro calls working on llvm XXX still?
  175. if hasattr(os, 'WCOREDUMP'):
  176. decl_snippet = """
  177. %(ret_type)s pypy_macro_wrapper_%(name)s (int status);
  178. """
  179. def_snippet = """
  180. %(ret_type)s pypy_macro_wrapper_%(name)s (int status) {
  181. return %(name)s(status);
  182. }
  183. """
  184. decls = []
  185. defs = []
  186. for name in self.w_star:
  187. data = {'ret_type': 'int', 'name': name}
  188. decls.append((decl_snippet % data).strip())
  189. defs.append((def_snippet % data).strip())
  190. self.compilation_info = self.compilation_info.merge(
  191. ExternalCompilationInfo(
  192. post_include_bits = decls,
  193. separate_module_sources = ["\n".join(defs)]
  194. ))
  195. # a simple, yet useful factory
  196. def extdef_for_os_function_returning_int(self, name, **kwds):
  197. c_func = self.llexternal(name, [], rffi.INT, **kwds)
  198. def c_func_llimpl():
  199. res = rffi.cast(rffi.SIGNED, c_func())
  200. if res == -1:
  201. raise OSError(rposix.get_errno(), "%s failed" % name)
  202. return res
  203. c_func_llimpl.func_name = name + '_llimpl'
  204. return extdef([], int, llimpl=c_func_llimpl,
  205. export_name='ll_os.ll_os_' + name)
  206. def extdef_for_os_function_accepting_int(self, name, **kwds):
  207. c_func = self.llexternal(name, [rffi.INT], rffi.INT, **kwds)
  208. def c_func_llimpl(arg):
  209. res = rffi.cast(rffi.SIGNED, c_func(arg))
  210. if res == -1:
  211. raise OSError(rposix.get_errno(), "%s failed" % name)
  212. c_func_llimpl.func_name = name + '_llimpl'
  213. return extdef([int], None, llimpl=c_func_llimpl,
  214. export_name='ll_os.ll_os_' + name)
  215. def extdef_for_os_function_accepting_2int(self, name, **kwds):
  216. c_func = self.llexternal(name, [rffi.INT, rffi.INT], rffi.INT, **kwds)
  217. def c_func_llimpl(arg, arg2):
  218. res = rffi.cast(rffi.SIGNED, c_func(arg, arg2))
  219. if res == -1:
  220. raise OSError(rposix.get_errno(), "%s failed" % name)
  221. c_func_llimpl.func_name = name + '_llimpl'
  222. return extdef([int, int], None, llimpl=c_func_llimpl,
  223. export_name='ll_os.ll_os_' + name)
  224. def extdef_for_os_function_accepting_0int(self, name, **kwds):
  225. c_func = self.llexternal(name, [], rffi.INT, **kwds)
  226. def c_func_llimpl():
  227. res = rffi.cast(rffi.SIGNED, c_func())
  228. if res == -1:
  229. raise OSError(rposix.get_errno(), "%s failed" % name)
  230. c_func_llimpl.func_name = name + '_llimpl'
  231. return extdef([], None, llimpl=c_func_llimpl,
  232. export_name='ll_os.ll_os_' + name)
  233. def extdef_for_os_function_int_to_int(self, name, **kwds):
  234. c_func = self.llexternal(name, [rffi.INT], rffi.INT, **kwds)
  235. def c_func_llimpl(arg):
  236. res = rffi.cast(rffi.SIGNED, c_func(arg))
  237. if res == -1:
  238. raise OSError(rposix.get_errno(), "%s failed" % name)
  239. return res
  240. c_func_llimpl.func_name = name + '_llimpl'
  241. return extdef([int], int, llimpl=c_func_llimpl,
  242. export_name='ll_os.ll_os_' + name)
  243. @registering_if(os, 'execv')
  244. def register_os_execv(self):
  245. eci = self.gcc_profiling_bug_workaround(
  246. 'int _noprof_execv(char *path, char *argv[])',
  247. 'return execv(path, argv);')
  248. os_execv = self.llexternal('_noprof_execv',
  249. [rffi.CCHARP, rffi.CCHARPP],
  250. rffi.INT, compilation_info = eci)
  251. def execv_llimpl(path, args):
  252. l_args = rffi.liststr2charpp(args)
  253. os_execv(path, l_args)
  254. rffi.free_charpp(l_args)
  255. raise OSError(rposix.get_errno(), "execv failed")
  256. return extdef([str0, [str0]], s_ImpossibleValue, llimpl=execv_llimpl,
  257. export_name="ll_os.ll_os_execv")
  258. @registering_if(os, 'execve')
  259. def register_os_execve(self):
  260. eci = self.gcc_profiling_bug_workaround(
  261. 'int _noprof_execve(char *filename, char *argv[], char *envp[])',
  262. 'return execve(filename, argv, envp);')
  263. os_execve = self.llexternal(
  264. '_noprof_execve', [rffi.CCHARP, rffi.CCHARPP, rffi.CCHARPP],
  265. rffi.INT, compilation_info = eci)
  266. def execve_llimpl(path, args, env):
  267. # XXX Check path, args, env for \0 and raise TypeErrors as
  268. # appropriate
  269. envstrs = []
  270. for item in env.iteritems():
  271. envstr = "%s=%s" % item
  272. envstrs.append(envstr)
  273. l_args = rffi.liststr2charpp(args)
  274. l_env = rffi.liststr2charpp(envstrs)
  275. os_execve(path, l_args, l_env)
  276. # XXX untested
  277. rffi.free_charpp(l_env)
  278. rffi.free_charpp(l_args)
  279. raise OSError(rposix.get_errno(), "execve failed")
  280. return extdef(
  281. [str0, [str0], {str0: str0}],
  282. s_ImpossibleValue,
  283. llimpl=execve_llimpl,
  284. export_name="ll_os.ll_os_execve")
  285. @registering_if(posix, 'spawnv')
  286. def register_os_spawnv(self):
  287. os_spawnv = self.llexternal('spawnv',
  288. [rffi.INT, rffi.CCHARP, rffi.CCHARPP],
  289. rffi.INT)
  290. def spawnv_llimpl(mode, path, args):
  291. mode = rffi.cast(rffi.INT, mode)
  292. l_args = rffi.liststr2charpp(args)
  293. childpid = os_spawnv(mode, path, l_args)
  294. rffi.free_charpp(l_args)
  295. if childpid == -1:
  296. raise OSError(rposix.get_errno(), "os_spawnv failed")
  297. return rffi.cast(lltype.Signed, childpid)
  298. return extdef([int, str0, [str0]], int, llimpl=spawnv_llimpl,
  299. export_name="ll_os.ll_os_spawnv")
  300. @registering_if(os, 'spawnve')
  301. def register_os_spawnve(self):
  302. os_spawnve = self.llexternal('spawnve',
  303. [rffi.INT, rffi.CCHARP, rffi.CCHARPP,
  304. rffi.CCHARPP],
  305. rffi.INT)
  306. def spawnve_llimpl(mode, path, args, env):
  307. envstrs = []
  308. for item in env.iteritems():
  309. envstrs.append("%s=%s" % item)
  310. mode = rffi.cast(rffi.INT, mode)
  311. l_args = rffi.liststr2charpp(args)
  312. l_env = rffi.liststr2charpp(envstrs)
  313. childpid = os_spawnve(mode, path, l_args, l_env)
  314. rffi.free_charpp(l_env)
  315. rffi.free_charpp(l_args)
  316. if childpid == -1:
  317. raise OSError(rposix.get_errno(), "os_spawnve failed")
  318. return rffi.cast(lltype.Signed, childpid)
  319. return extdef([int, str0, [str0], {str0: str0}], int,
  320. llimpl=spawnve_llimpl,
  321. export_name="ll_os.ll_os_spawnve")
  322. @registering(os.dup)
  323. def register_os_dup(self):
  324. os_dup = self.llexternal(underscore_on_windows+'dup', [rffi.INT], rffi.INT)
  325. def dup_llimpl(fd):
  326. rposix.validate_fd(fd)
  327. newfd = rffi.cast(lltype.Signed, os_dup(rffi.cast(rffi.INT, fd)))
  328. if newfd == -1:
  329. raise OSError(rposix.get_errno(), "dup failed")
  330. return newfd
  331. return extdef([int], int, llimpl=dup_llimpl,
  332. export_name="ll_os.ll_os_dup", oofakeimpl=os.dup)
  333. @registering(os.dup2)
  334. def register_os_dup2(self):
  335. os_dup2 = self.llexternal(underscore_on_windows+'dup2',
  336. [rffi.INT, rffi.INT], rffi.INT)
  337. def dup2_llimpl(fd, newfd):
  338. rposix.validate_fd(fd)
  339. error = rffi.cast(lltype.Signed, os_dup2(rffi.cast(rffi.INT, fd),
  340. rffi.cast(rffi.INT, newfd)))
  341. if error == -1:
  342. raise OSError(rposix.get_errno(), "dup2 failed")
  343. return extdef([int, int], s_None, llimpl=dup2_llimpl,
  344. export_name="ll_os.ll_os_dup2")
  345. @registering_if(os, "getlogin", condition=not _WIN32)
  346. def register_os_getlogin(self):
  347. os_getlogin = self.llexternal('getlogin', [], rffi.CCHARP)
  348. def getlogin_llimpl():
  349. result = os_getlogin()
  350. if not result:
  351. raise OSError(rposix.get_errno(), "getlogin failed")
  352. return rffi.charp2str(result)
  353. return extdef([], str, llimpl=getlogin_llimpl,
  354. export_name="ll_os.ll_os_getlogin")
  355. @registering_str_unicode(os.utime)
  356. def register_os_utime(self, traits):
  357. UTIMBUFP = lltype.Ptr(self.UTIMBUF)
  358. os_utime = self.llexternal('utime', [rffi.CCHARP, UTIMBUFP], rffi.INT)
  359. if not _WIN32:
  360. includes = ['sys/time.h']
  361. else:
  362. includes = ['time.h']
  363. class CConfig:
  364. _compilation_info_ = ExternalCompilationInfo(
  365. includes=includes
  366. )
  367. HAVE_UTIMES = platform.Has('utimes')
  368. config = platform.configure(CConfig)
  369. # XXX note that on Windows, calls to os.utime() are ignored on
  370. # directories. Remove that hack over there once it's fixed here!
  371. if config['HAVE_UTIMES']:
  372. class CConfig:
  373. if not _WIN32:
  374. _compilation_info_ = ExternalCompilationInfo(
  375. includes = includes
  376. )
  377. else:
  378. _compilation_info_ = ExternalCompilationInfo(
  379. includes = ['time.h']
  380. )
  381. TIMEVAL = platform.Struct('struct timeval', [('tv_sec', rffi.LONG),
  382. ('tv_usec', rffi.LONG)])
  383. config = platform.configure(CConfig)
  384. TIMEVAL = config['TIMEVAL']
  385. TIMEVAL2P = rffi.CArrayPtr(TIMEVAL)
  386. os_utimes = self.llexternal('utimes', [rffi.CCHARP, TIMEVAL2P],
  387. rffi.INT, compilation_info=CConfig._compilation_info_)
  388. def os_utime_platform(path, actime, modtime):
  389. import math
  390. l_times = lltype.malloc(TIMEVAL2P.TO, 2, flavor='raw')
  391. fracpart, intpart = math.modf(actime)
  392. rffi.setintfield(l_times[0], 'c_tv_sec', int(intpart))
  393. rffi.setintfield(l_times[0], 'c_tv_usec', int(fracpart * 1E6))
  394. fracpart, intpart = math.modf(modtime)
  395. rffi.setintfield(l_times[1], 'c_tv_sec', int(intpart))
  396. rffi.setintfield(l_times[1], 'c_tv_usec', int(fracpart * 1E6))
  397. error = os_utimes(path, l_times)
  398. lltype.free(l_times, flavor='raw')
  399. return error
  400. else:
  401. # we only have utime(), which does not allow sub-second resolution
  402. def os_utime_platform(path, actime, modtime):
  403. l_utimbuf = lltype.malloc(UTIMBUFP.TO, flavor='raw')
  404. l_utimbuf.c_actime = rffi.r_time_t(actime)
  405. l_utimbuf.c_modtime = rffi.r_time_t(modtime)
  406. error = os_utime(path, l_utimbuf)
  407. lltype.free(l_utimbuf, flavor='raw')
  408. return error
  409. # NB. this function is specialized; we get one version where
  410. # tp is known to be None, and one version where it is known
  411. # to be a tuple of 2 floats.
  412. if not _WIN32:
  413. assert traits.str is str
  414. @specialize.argtype(1)
  415. def os_utime_llimpl(path, tp):
  416. if tp is None:
  417. error = os_utime(path, lltype.nullptr(UTIMBUFP.TO))
  418. else:
  419. actime, modtime = tp
  420. error = os_utime_platform(path, actime, modtime)
  421. error = rffi.cast(lltype.Signed, error)
  422. if error == -1:
  423. raise OSError(rposix.get_errno(), "os_utime failed")
  424. else:
  425. from pypy.rpython.module.ll_win32file import make_utime_impl
  426. os_utime_llimpl = make_utime_impl(traits)
  427. s_tuple_of_2_floats = SomeTuple([SomeFloat(), SomeFloat()])
  428. def os_utime_normalize_args(s_path, s_times):
  429. # special handling of the arguments: they can be either
  430. # [str, (float, float)] or [str, s_None], and get normalized
  431. # to exactly one of these two.
  432. if not traits.str0.contains(s_path):
  433. raise Exception("os.utime() arg 1 must be a string, got %s" % (
  434. s_path,))
  435. case1 = s_None.contains(s_times)
  436. case2 = s_tuple_of_2_floats.contains(s_times)
  437. if case1 and case2:
  438. return [traits.str0, s_ImpossibleValue] #don't know which case yet
  439. elif case1:
  440. return [traits.str0, s_None]
  441. elif case2:
  442. return [traits.str0, s_tuple_of_2_floats]
  443. else:
  444. raise Exception("os.utime() arg 2 must be None or a tuple of "
  445. "2 floats, got %s" % (s_times,))
  446. os_utime_normalize_args._default_signature_ = [traits.str0, None]
  447. return extdef(os_utime_normalize_args, s_None,
  448. "ll_os.ll_os_utime",
  449. llimpl=os_utime_llimpl)
  450. @registering(os.times)
  451. def register_os_times(self):
  452. if sys.platform.startswith('win'):
  453. from pypy.rlib import rwin32
  454. GetCurrentProcess = self.llexternal('GetCurrentProcess', [],
  455. rwin32.HANDLE)
  456. GetProcessTimes = self.llexternal('GetProcessTimes',
  457. [rwin32.HANDLE,
  458. lltype.Ptr(rwin32.FILETIME),
  459. lltype.Ptr(rwin32.FILETIME),
  460. lltype.Ptr(rwin32.FILETIME),
  461. lltype.Ptr(rwin32.FILETIME)],
  462. rwin32.BOOL)
  463. def times_lltypeimpl():
  464. pcreate = lltype.malloc(rwin32.FILETIME, flavor='raw')
  465. pexit = lltype.malloc(rwin32.FILETIME, flavor='raw')
  466. pkernel = lltype.malloc(rwin32.FILETIME, flavor='raw')
  467. puser = lltype.malloc(rwin32.FILETIME, flavor='raw')
  468. hProc = GetCurrentProcess()
  469. GetProcessTimes(hProc, pcreate, pexit, pkernel, puser)
  470. # The fields of a FILETIME structure are the hi and lo parts
  471. # of a 64-bit value expressed in 100 nanosecond units
  472. # (of course).
  473. result = (rffi.cast(lltype.Signed, pkernel.c_dwHighDateTime) * 429.4967296 +
  474. rffi.cast(lltype.Signed, pkernel.c_dwLowDateTime) * 1E-7,
  475. rffi.cast(lltype.Signed, puser.c_dwHighDateTime) * 429.4967296 +
  476. rffi.cast(lltype.Signed, puser.c_dwLowDateTime) * 1E-7,
  477. 0, 0, 0)
  478. lltype.free(puser, flavor='raw')
  479. lltype.free(pkernel, flavor='raw')
  480. lltype.free(pexit, flavor='raw')
  481. lltype.free(pcreate, flavor='raw')
  482. return result
  483. self.register(os.times, [], (float, float, float, float, float),
  484. "ll_os.ll_times", llimpl=times_lltypeimpl)
  485. return
  486. TMSP = lltype.Ptr(self.TMS)
  487. os_times = self.llexternal('times', [TMSP], self.CLOCK_T)
  488. # Here is a random extra platform parameter which is important.
  489. # Strictly speaking, this should probably be retrieved at runtime, not
  490. # at translation time.
  491. CLOCK_TICKS_PER_SECOND = float(os.sysconf('SC_CLK_TCK'))
  492. def times_lltypeimpl():
  493. l_tmsbuf = lltype.malloc(TMSP.TO, flavor='raw')
  494. try:
  495. result = os_times(l_tmsbuf)
  496. result = rffi.cast(lltype.Signed, result)
  497. if result == -1:
  498. raise OSError(rposix.get_errno(), "times failed")
  499. return (
  500. rffi.cast(lltype.Signed, l_tmsbuf.c_tms_utime)
  501. / CLOCK_TICKS_PER_SECOND,
  502. rffi.cast(lltype.Signed, l_tmsbuf.c_tms_stime)
  503. / CLOCK_TICKS_PER_SECOND,
  504. rffi.cast(lltype.Signed, l_tmsbuf.c_tms_cutime)
  505. / CLOCK_TICKS_PER_SECOND,
  506. rffi.cast(lltype.Signed, l_tmsbuf.c_tms_cstime)
  507. / CLOCK_TICKS_PER_SECOND,
  508. result / CLOCK_TICKS_PER_SECOND)
  509. finally:
  510. lltype.free(l_tmsbuf, flavor='raw')
  511. self.register(os.times, [], (float, float, float, float, float),
  512. "ll_os.ll_times", llimpl=times_lltypeimpl)
  513. @registering_if(os, 'setsid')
  514. def register_os_setsid(self):
  515. os_setsid = self.llexternal('setsid', [], rffi.PID_T)
  516. def setsid_llimpl():
  517. result = rffi.cast(lltype.Signed, os_setsid())
  518. if result == -1:
  519. raise OSError(rposix.get_errno(), "os_setsid failed")
  520. return result
  521. return extdef([], int, export_name="ll_os.ll_os_setsid",
  522. llimpl=setsid_llimpl)
  523. @registering_if(os, 'chroot')
  524. def register_os_chroot(self):
  525. os_chroot = self.llexternal('chroot', [rffi.CCHARP], rffi.INT)
  526. def chroot_llimpl(arg):
  527. result = os_chroot(arg)
  528. if result == -1:
  529. raise OSError(rposix.get_errno(), "os_chroot failed")
  530. return extdef([str0], None, export_name="ll_os.ll_os_chroot",
  531. llimpl=chroot_llimpl)
  532. @registering_if(os, 'uname')
  533. def register_os_uname(self):
  534. CHARARRAY = lltype.FixedSizeArray(lltype.Char, 1)
  535. class CConfig:
  536. _compilation_info_ = ExternalCompilationInfo(
  537. includes = ['sys/utsname.h']
  538. )
  539. UTSNAME = platform.Struct('struct utsname', [
  540. ('sysname', CHARARRAY),
  541. ('nodename', CHARARRAY),
  542. ('release', CHARARRAY),
  543. ('version', CHARARRAY),
  544. ('machine', CHARARRAY)])
  545. config = platform.configure(CConfig)
  546. UTSNAMEP = lltype.Ptr(config['UTSNAME'])
  547. os_uname = self.llexternal('uname', [UTSNAMEP], rffi.INT,
  548. compilation_info=CConfig._compilation_info_)
  549. def uname_llimpl():
  550. l_utsbuf = lltype.malloc(UTSNAMEP.TO, flavor='raw')
  551. result = os_uname(l_utsbuf)
  552. if result == -1:
  553. raise OSError(rposix.get_errno(), "os_uname failed")
  554. retval = (
  555. rffi.charp2str(rffi.cast(rffi.CCHARP, l_utsbuf.c_sysname)),
  556. rffi.charp2str(rffi.cast(rffi.CCHARP, l_utsbuf.c_nodename)),
  557. rffi.charp2str(rffi.cast(rffi.CCHARP, l_utsbuf.c_release)),
  558. rffi.charp2str(rffi.cast(rffi.CCHARP, l_utsbuf.c_version)),
  559. rffi.charp2str(rffi.cast(rffi.CCHARP, l_utsbuf.c_machine)),
  560. )
  561. lltype.free(l_utsbuf, flavor='raw')
  562. return retval
  563. return extdef([], (str, str, str, str, str),
  564. "ll_os.ll_uname", llimpl=uname_llimpl)
  565. @registering_if(os, 'sysconf')
  566. def register_os_sysconf(self):
  567. c_sysconf = self.llexternal('sysconf', [rffi.INT], rffi.LONG)
  568. def sysconf_llimpl(i):
  569. rposix.set_errno(0)
  570. res = c_sysconf(i)
  571. if res == -1:
  572. errno = rposix.get_errno()
  573. if errno != 0:
  574. raise OSError(errno, "sysconf failed")
  575. return res
  576. return extdef([int], int, "ll_os.ll_sysconf", llimpl=sysconf_llimpl)
  577. @registering_if(os, 'fpathconf')
  578. def register_os_fpathconf(self):
  579. c_fpathconf = self.llexternal('fpathconf',
  580. [rffi.INT, rffi.INT], rffi.LONG)
  581. def fpathconf_llimpl(fd, i):
  582. rposix.set_errno(0)
  583. res = c_fpathconf(fd, i)
  584. if res == -1:
  585. errno = rposix.get_errno()
  586. if errno != 0:
  587. raise OSError(errno, "fpathconf failed")
  588. return res
  589. return extdef([int, int], int, "ll_os.ll_fpathconf",
  590. llimpl=fpathconf_llimpl)
  591. @registering_if(os, 'getuid')
  592. def register_os_getuid(self):
  593. return self.extdef_for_os_function_returning_int('getuid')
  594. @registering_if(os, 'geteuid')
  595. def register_os_geteuid(self):
  596. return self.extdef_for_os_function_returning_int('geteuid')
  597. @registering_if(os, 'setuid')
  598. def register_os_setuid(self):
  599. return self.extdef_for_os_function_accepting_int('setuid')
  600. @registering_if(os, 'seteuid')
  601. def register_os_seteuid(self):
  602. return self.extdef_for_os_function_accepting_int('seteuid')
  603. @registering_if(os, 'setgid')
  604. def register_os_setgid(self):
  605. return self.extdef_for_os_function_accepting_int('setgid')
  606. @registering_if(os, 'setegid')
  607. def register_os_setegid(self):
  608. return self.extdef_for_os_function_accepting_int('setegid')
  609. @registering_if(os, 'getpid')
  610. def register_os_getpid(self):
  611. return self.extdef_for_os_function_returning_int('getpid')
  612. @registering_if(os, 'getgid')
  613. def register_os_getgid(self):
  614. return self.extdef_for_os_function_returning_int('getgid')
  615. @registering_if(os, 'getegid')
  616. def register_os_getegid(self):
  617. return self.extdef_for_os_function_returning_int('getegid')
  618. @registering_if(os, 'getgroups')
  619. def register_os_getgroups(self):
  620. GP = rffi.CArrayPtr(self.GID_T)
  621. c_getgroups = self.llexternal('getgroups', [rffi.INT, GP], rffi.INT)
  622. def getgroups_llimpl():
  623. n = c_getgroups(0, lltype.nullptr(GP.TO))
  624. if n >= 0:
  625. groups = lltype.malloc(GP.TO, n, flavor='raw')
  626. try:
  627. n = c_getgroups(n, groups)
  628. result = [groups[i] for i in range(n)]
  629. finally:
  630. lltype.free(groups, flavor='raw')
  631. if n >= 0:
  632. return result
  633. raise OSError(rposix.get_errno(), "os_getgroups failed")
  634. return extdef([], [self.GID_T], llimpl=getgroups_llimpl,
  635. export_name="ll_os.ll_getgroups")
  636. @registering_if(os, 'getpgrp')
  637. def register_os_getpgrp(self):
  638. name = 'getpgrp'
  639. if self.GETPGRP_HAVE_ARG:
  640. c_func = self.llexternal(name, [rffi.INT], rffi.INT)
  641. def c_func_llimpl():
  642. res = rffi.cast(rffi.SIGNED, c_func(0))
  643. if res == -1:
  644. raise OSError(rposix.get_errno(), "%s failed" % name)
  645. return res
  646. c_func_llimpl.func_name = name + '_llimpl'
  647. return extdef([], int, llimpl=c_func_llimpl,
  648. export_name='ll_os.ll_os_' + name)
  649. else:
  650. return self.extdef_for_os_function_returning_int('getpgrp')
  651. @registering_if(os, 'setpgrp')
  652. def register_os_setpgrp(self):
  653. name = 'setpgrp'
  654. if self.SETPGRP_HAVE_ARG:
  655. c_func = self.llexternal(name, [rffi.INT, rffi.INT], rffi.INT)
  656. def c_func_llimpl():
  657. res = rffi.cast(rffi.SIGNED, c_func(0, 0))
  658. if res == -1:
  659. raise OSError(rposix.get_errno(), "%s failed" % name)
  660. c_func_llimpl.func_name = name + '_llimpl'
  661. return extdef([], None, llimpl=c_func_llimpl,
  662. export_name='ll_os.ll_os_' + name)
  663. else:
  664. return self.extdef_for_os_function_accepting_0int(name)
  665. @registering_if(os, 'getppid')
  666. def register_os_getppid(self):
  667. return self.extdef_for_os_function_returning_int('getppid')
  668. @registering_if(os, 'getpgid')
  669. def register_os_getpgid(self):
  670. return self.extdef_for_os_function_int_to_int('getpgid')
  671. @registering_if(os, 'setpgid')
  672. def register_os_setpgid(self):
  673. return self.extdef_for_os_function_accepting_2int('setpgid')
  674. @registering_if(os, 'setreuid')
  675. def register_os_setreuid(self):
  676. return self.extdef_for_os_function_accepting_2int('setreuid')
  677. @registering_if(os, 'setregid')
  678. def register_os_setregid(self):
  679. return self.extdef_for_os_function_accepting_2int('setregid')
  680. @registering_if(os, 'getsid')
  681. def register_os_getsid(self):
  682. return self.extdef_for_os_function_int_to_int('getsid')
  683. @registering_if(os, 'setsid')
  684. def register_os_setsid(self):
  685. return self.extdef_for_os_function_returning_int('setsid')
  686. @registering_str_unicode(os.open)
  687. def register_os_open(self, traits):
  688. os_open = self.llexternal(traits.posix_function_name('open'),
  689. [traits.CCHARP, rffi.INT, rffi.MODE_T],
  690. rffi.INT)
  691. def os_open_llimpl(path, flags, mode):
  692. result = rffi.cast(lltype.Signed, os_open(path, flags, mode))
  693. if result == -1:
  694. raise OSError(rposix.get_errno(), "os_open failed")
  695. return result
  696. def os_open_oofakeimpl(path, flags, mode):
  697. return os.open(OOSupport.from_rstr(path), flags, mode)
  698. return extdef([traits.str0, int, int], int, traits.ll_os_name('open'),
  699. llimpl=os_open_llimpl, oofakeimpl=os_open_oofakeimpl)
  700. @registering_if(os, 'getloadavg')
  701. def register_os_getloadavg(self):
  702. AP = rffi.CArrayPtr(lltype.Float)
  703. c_getloadavg = self.llexternal('getloadavg', [AP, rffi.INT], rffi.INT)
  704. def getloadavg_llimpl():
  705. load = lltype.malloc(AP.TO, 3, flavor='raw')
  706. r = c_getloadavg(load, 3)
  707. result_tuple = load[0], load[1], load[2]
  708. lltype.free(load, flavor='raw')
  709. if r != 3:
  710. raise OSError
  711. return result_tuple
  712. return extdef([], (float, float, float),
  713. "ll_os.ll_getloadavg", llimpl=getloadavg_llimpl)
  714. @registering_if(os, 'makedev')
  715. def register_os_makedev(self):
  716. c_makedev = self.llexternal('makedev', [rffi.INT, rffi.INT], rffi.INT)
  717. def makedev_llimpl(maj, min):
  718. return c_makedev(maj, min)
  719. return extdef([int, int], int,
  720. "ll_os.ll_makedev", llimpl=makedev_llimpl)
  721. @registering_if(os, 'major')
  722. def register_os_major(self):
  723. c_major = self.llexternal('major', [rffi.INT], rffi.INT)
  724. def major_llimpl(dev):
  725. return c_major(dev)
  726. return extdef([int], int,
  727. "ll_os.ll_major", llimpl=major_llimpl)
  728. @registering_if(os, 'minor')
  729. def register_os_minor(self):
  730. c_minor = self.llexternal('minor', [rffi.INT], rffi.INT)
  731. def minor_llimpl(dev):
  732. return c_minor(dev)
  733. return extdef([int], int,
  734. "ll_os.ll_minor", llimpl=minor_llimpl)
  735. # ------------------------------- os.read -------------------------------
  736. @registering(os.read)
  737. def register_os_read(self):
  738. os_read = self.llexternal(underscore_on_windows+'read',
  739. [rffi.INT, rffi.VOIDP, rffi.SIZE_T],
  740. rffi.SIZE_T)
  741. offset = offsetof(STR, 'chars') + itemoffsetof(STR.chars, 0)
  742. def os_read_llimpl(fd, count):
  743. if count < 0:
  744. raise OSError(errno.EINVAL, None)
  745. rposix.validate_fd(fd)
  746. raw_buf, gc_buf = rffi.alloc_buffer(count)
  747. try:
  748. void_buf = rffi.cast(rffi.VOIDP, raw_buf)
  749. got = rffi.cast(lltype.Signed, os_read(fd, void_buf, count))
  750. if got < 0:
  751. raise OSError(rposix.get_errno(), "os_read failed")
  752. return rffi.str_from_buffer(raw_buf, gc_buf, count, got)
  753. finally:
  754. rffi.keep_buffer_alive_until_here(raw_buf, gc_buf)
  755. def os_read_oofakeimpl(fd, count):
  756. return OOSupport.to_rstr(os.read(fd, count))
  757. return extdef([int, int], SomeString(can_be_None=True),
  758. "ll_os.ll_os_read",
  759. llimpl=os_read_llimpl, oofakeimpl=os_read_oofakeimpl)
  760. @registering(os.write)
  761. def register_os_write(self):
  762. os_write = self.llexternal(underscore_on_windows+'write',
  763. [rffi.INT, rffi.VOIDP, rffi.SIZE_T],
  764. rffi.SIZE_T)
  765. def os_write_llimpl(fd, data):
  766. count = len(data)
  767. rposix.validate_fd(fd)
  768. buf = rffi.get_nonmovingbuffer(data)
  769. try:
  770. written = rffi.cast(lltype.Signed, os_write(
  771. rffi.cast(rffi.INT, fd),
  772. buf, rffi.cast(rffi.SIZE_T, count)))
  773. if written < 0:
  774. raise OSError(rposix.get_errno(), "os_write failed")
  775. finally:
  776. rffi.free_nonmovingbuffer(data, buf)
  777. return written
  778. def os_write_oofakeimpl(fd, data):
  779. return os.write(fd, OOSupport.from_rstr(data))
  780. return extdef([int, str], SomeInteger(nonneg=True),
  781. "ll_os.ll_os_write", llimpl=os_write_llimpl,
  782. oofakeimpl=os_write_oofakeimpl)
  783. @registering(os.close)
  784. def register_os_close(self):
  785. os_close = self.llexternal(underscore_on_windows+'close', [rffi.INT],
  786. rffi.INT, threadsafe=False)
  787. def close_llimpl(fd):
  788. rposix.validate_fd(fd)
  789. error = rffi.cast(lltype.Signed, os_close(rffi.cast(rffi.INT, fd)))
  790. if error == -1:
  791. raise OSError(rposix.get_errno(), "close failed")
  792. return extdef([int], s_None, llimpl=close_llimpl,
  793. export_name="ll_os.ll_os_close", oofakeimpl=os.close)
  794. @registering(os.lseek)
  795. def register_os_lseek(self):
  796. if sys.platform.startswith('win'):
  797. funcname = '_lseeki64'
  798. else:
  799. funcname = 'lseek'
  800. if self.SEEK_SET is not None:
  801. SEEK_SET = self.SEEK_SET
  802. SEEK_CUR = self.SEEK_CUR
  803. SEEK_END = self.SEEK_END
  804. else:
  805. SEEK_SET, SEEK_CUR, SEEK_END = 0, 1, 2
  806. if (SEEK_SET, SEEK_CUR, SEEK_END) != (0, 1, 2):
  807. # Turn 0, 1, 2 into SEEK_{SET,CUR,END}
  808. def fix_seek_arg(n):
  809. if n == 0: return SEEK_SET
  810. if n == 1: return SEEK_CUR
  811. if n == 2: return SEEK_END
  812. return n
  813. else:
  814. def fix_seek_arg(n):
  815. return n
  816. os_lseek = self.llexternal(funcname,
  817. [rffi.INT, rffi.LONGLONG, rffi.INT],
  818. rffi.LONGLONG, macro=True)
  819. def lseek_llimpl(fd, pos, how):
  820. rposix.validate_fd(fd)
  821. how = fix_seek_arg(how)
  822. res = os_lseek(rffi.cast(rffi.INT, fd),
  823. rffi.cast(rffi.LONGLONG, pos),
  824. rffi.cast(rffi.INT, how))
  825. res = rffi.cast(lltype.SignedLongLong, res)
  826. if res < 0:
  827. raise OSError(rposix.get_errno(), "os_lseek failed")
  828. return res
  829. def os_lseek_oofakeimpl(fd, pos, how):
  830. res = os.lseek(fd, pos, how)
  831. return r_longlong(res)
  832. return extdef([int, r_longlong, int],
  833. r_longlong,
  834. llimpl = lseek_llimpl,
  835. export_name = "ll_os.ll_os_lseek",
  836. oofakeimpl = os_lseek_oofakeimpl)
  837. @registering_if(os, 'ftruncate')
  838. def register_os_ftruncate(self):
  839. os_ftruncate = self.llexternal('ftruncate',
  840. [rffi.INT, rffi.LONGLONG], rffi.INT, macro=True)
  841. def ftruncate_llimpl(fd, length):
  842. rposix.validate_fd(fd)
  843. res = rffi.cast(rffi.LONG,
  844. os_ftruncate(rffi.cast(rffi.INT, fd),
  845. rffi.cast(rffi.LONGLONG, length)))
  846. if res < 0:
  847. raise OSError(rposix.get_errno(), "os_ftruncate failed")
  848. return extdef([int, r_longlong], s_None,
  849. llimpl = ftruncate_llimpl,
  850. export_name = "ll_os.ll_os_ftruncate")
  851. @registering_if(os, 'fsync')
  852. def register_os_fsync(self):
  853. if not _WIN32:
  854. os_fsync = self.llexternal('fsync', [rffi.INT], rffi.INT)
  855. else:
  856. os_fsync = self.llexternal('_commit', [rffi.INT], rffi.INT)
  857. def fsync_llimpl(fd):
  858. rposix.validate_fd(fd)
  859. res = rffi.cast(rffi.SIGNED, os_fsync(rffi.cast(rffi.INT, fd)))
  860. if res < 0:
  861. raise OSError(rposix.get_errno(), "fsync failed")
  862. return extdef([int], s_None,
  863. llimpl=fsync_llimpl,
  864. export_name="ll_os.ll_os_fsync")
  865. @registering_if(os, 'fdatasync')
  866. def register_os_fdatasync(self):
  867. os_fdatasync = self.llexternal('fdatasync', [rffi.INT], rffi.INT)
  868. def fdatasync_llimpl(fd):
  869. rposix.validate_fd(fd)
  870. res = rffi.cast(rffi.SIGNED, os_fdatasync(rffi.cast(rffi.INT, fd)))
  871. if res < 0:
  872. raise OSError(rposix.get_errno(), "fdatasync failed")
  873. return extdef([int], s_None,
  874. llimpl=fdatasync_llimpl,
  875. export_name="ll_os.ll_os_fdatasync")
  876. @registering_if(os, 'fchdir')
  877. def register_os_fchdir(self):
  878. os_fchdir = self.llexternal('fchdir', [rffi.INT], rffi.INT)
  879. def fchdir_llimpl(fd):
  880. rposix.validate_fd(fd)
  881. res = rffi.cast(rffi.SIGNED, os_fchdir(rffi.cast(rffi.INT, fd)))
  882. if res < 0:
  883. raise OSError(rposix.get_errno(), "fchdir failed")
  884. return extdef([int], s_None,
  885. llimpl=fchdir_llimpl,
  886. export_name="ll_os.ll_os_fchdir")
  887. @registering_str_unicode(os.access)
  888. def register_os_access(self, traits):
  889. os_access = self.llexternal(traits.posix_function_name('access'),
  890. [traits.CCHARP, rffi.INT],
  891. rffi.INT)
  892. if sys.platform.startswith('win'):
  893. # All files are executable on Windows
  894. def access_llimpl(path, mode):
  895. mode = mode & ~os.X_OK
  896. error = rffi.cast(lltype.Signed, os_access(path, mode))
  897. return error == 0
  898. else:
  899. def access_llimpl(path, mode):
  900. error = rffi.cast(lltype.Signed, os_access(path, mode))
  901. return error == 0
  902. def os_access_oofakeimpl(path, mode):
  903. return os.access(OOSupport.from_rstr(path), mode)
  904. return extdef([traits.str0, int], s_Bool, llimpl=access_llimpl,
  905. export_name=traits.ll_os_name("access"),
  906. oofakeimpl=os_access_oofakeimpl)
  907. @registering_str_unicode(getattr(posix, '_getfullpathname', None),
  908. condition=sys.platform=='win32')
  909. def register_posix__getfullpathname(self, traits):
  910. # this nt function is not exposed via os, but needed
  911. # to get a correct implementation of os.abspath
  912. from pypy.rpython.module.ll_win32file import make_getfullpathname_impl
  913. getfullpathname_llimpl = make_getfullpathname_impl(traits)
  914. return extdef([traits.str0], # a single argument which is a str
  915. traits.str0, # returns a string
  916. traits.ll_os_name('_getfullpathname'),
  917. llimpl=getfullpathname_llimpl)
  918. @registering(os.getcwd)
  919. def register_os_getcwd(self):
  920. os_getcwd = self.llexternal(underscore_on_windows + 'getcwd',
  921. [rffi.CCHARP, rffi.SIZE_T],
  922. rffi.CCHARP)
  923. def os_getcwd_llimpl():
  924. bufsize = 256
  925. while True:
  926. buf = lltype.malloc(rffi.CCHARP.TO, bufsize, flavor='raw')
  927. res = os_getcwd(buf, rffi.cast(rffi.SIZE_T, bufsize))
  928. if res:
  929. break # ok
  930. error = rposix.get_errno()
  931. lltype.free(buf, flavor='raw')
  932. if error != errno.ERANGE:
  933. raise OSError(error, "getcwd failed")
  934. # else try again with a larger buffer, up to some sane limit
  935. bufsize *= 4
  936. if bufsize > 1024*1024: # xxx hard-coded upper limit
  937. raise OSError(error, "getcwd result too large")
  938. result = rffi.charp2str(res)
  939. lltype.free(buf, flavor='raw')
  940. return result
  941. def os_getcwd_oofakeimpl():
  942. return OOSupport.to_rstr(os.getcwd())
  943. return extdef([], str0,
  944. "ll_os.ll_os_getcwd", llimpl=os_getcwd_llimpl,
  945. oofakeimpl=os_getcwd_oofakeimpl)
  946. @registering(os.getcwdu, condition=sys.platform=='win32')
  947. def register_os_getcwdu(self):
  948. os_wgetcwd = self.llexternal(underscore_on_windows + 'wgetcwd',
  949. [rffi.CWCHARP, rffi.SIZE_T],
  950. rffi.CWCHARP)
  951. def os_getcwd_llimpl():
  952. bufsize = 256
  953. while True:
  954. buf = lltype.malloc(rffi.CWCHARP.TO, bufsize, flavor='raw')
  955. res = os_wgetcwd(buf, rffi.cast(rffi.SIZE_T, bufsize))
  956. if res:
  957. break # ok
  958. error = rposix.get_errno()
  959. lltype.free(buf, flavor='raw')
  960. if error != errno.ERANGE:
  961. raise OSError(error, "getcwd failed")
  962. # else try again with a larger buffer, up to some sane limit
  963. bufsize *= 4
  964. if bufsize > 1024*1024: # xxx hard-coded upper limit
  965. raise OSError(error, "getcwd result too large")
  966. result = rffi.wcharp2unicode(res)
  967. lltype.free(buf, flavor='raw')
  968. return result
  969. return extdef([], unicode,
  970. "ll_os.ll_os_wgetcwd", llimpl=os_getcwd_llimpl)
  971. @registering_str_unicode(os.listdir)
  972. def register_os_listdir(self, traits):
  973. # we need a different approach on Windows and on Posix
  974. if sys.platform.startswith('win'):
  975. from pypy.rpython.module.ll_win32file import make_listdir_impl
  976. os_listdir_llimpl = make_listdir_impl(traits)
  977. else:
  978. assert traits.str is str
  979. compilation_info = ExternalCompilationInfo(
  980. includes = ['sys/types.h', 'dirent.h']
  981. )
  982. class CConfig:
  983. _compilation_info_ = compilation_info
  984. DIRENT = platform.Struct('struct dirent',
  985. [('d_name', lltype.FixedSizeArray(rffi.CHAR, 1))])
  986. DIRP = rffi.COpaquePtr('DIR')
  987. config = platform.configure(CConfig)
  988. DIRENT = config['DIRENT']
  989. DIRENTP = lltype.Ptr(DIRENT)
  990. os_opendir = self.llexternal('opendir', [rffi.CCHARP], DIRP,
  991. compilation_info=compilation_info)
  992. # XXX macro=True is hack to make sure we get the correct kind of
  993. # dirent struct (which depends on defines)
  994. os_readdir = self.llexternal('readdir', [DIRP], DIRENTP,
  995. compilation_info=compilation_info,
  996. macro=True)
  997. os_closedir = self.llexternal('closedir', [DIRP], rffi.INT,
  998. compilation_info=compilation_info)
  999. def os_listdir_llimpl(path):
  1000. dirp = os_opendir(path)
  1001. if not dirp:
  1002. raise OSError(rposix.get_errno(), "os_opendir failed")
  1003. rposix.set_errno(0)
  1004. result = []
  1005. while True:
  1006. direntp = os_readdir(dirp)
  1007. if not direntp:
  1008. error = rposix.get_errno()
  1009. break
  1010. namep = rffi.cast(rffi.CCHARP, direntp.c_d_name)
  1011. name = rffi.charp2str(namep)
  1012. if name != '.' and name != '..':
  1013. result.append(name)
  1014. os_closedir(dirp)
  1015. if error:
  1016. raise OSError(error, "os_readdir failed")
  1017. return result
  1018. return extdef([traits.str0], # a single argument which is a str
  1019. [traits.str0], # returns a list of strings
  1020. traits.ll_os_name('listdir'),
  1021. llimpl=os_listdir_llimpl)
  1022. @registering(os.pipe)
  1023. def register_os_pipe(self):
  1024. # we need a different approach on Windows and on Posix
  1025. if sys.platform.startswith('win'):
  1026. from pypy.rlib import rwin32
  1027. CreatePipe = self.llexternal('CreatePipe', [rwin32.LPHANDLE,
  1028. rwin32.LPHANDLE,
  1029. rffi.VOIDP,
  1030. rwin32.DWORD],
  1031. rwin32.BOOL)
  1032. _open_osfhandle = self.llexternal('_open_osfhandle', [rffi.INTPTR_T,
  1033. rffi.INT],
  1034. rffi.INT)
  1035. null = lltype.nullptr(rffi.VOIDP.TO)
  1036. def os_pipe_llimpl():
  1037. pread = lltype.malloc(rwin32.LPHANDLE.TO, 1, flavor='raw')
  1038. pwrite = lltype.malloc(rwin32.LPHANDLE.TO, 1, flavor='raw')
  1039. ok = CreatePipe(pread, pwrite, null, 0)
  1040. if ok:
  1041. error = 0
  1042. else:
  1043. error = rwin32.GetLastError()
  1044. hread = rffi.cast(rffi.INTPTR_T, pread[0])
  1045. hwrite = rffi.cast(rffi.INTPTR_T, pwrite[0])
  1046. lltype.free(pwrite, flavor='raw')
  1047. lltype.free(pread, flavor='raw')
  1048. if error:
  1049. raise WindowsError(error, "os_pipe failed")
  1050. fdread = _open_osfhandle(hread, 0)
  1051. fdwrite = _open_osfhandle(hwrite, 1)
  1052. return (fdread, fdwrite)
  1053. else:
  1054. INT_ARRAY_P = rffi.CArrayPtr(rffi.INT)
  1055. os_pipe = self.llexternal('pipe', [INT_ARRAY_P], rffi.INT)
  1056. def os_pipe_llimpl():
  1057. filedes = lltype.malloc(INT_ARRAY_P.TO, 2, flavor='raw')
  1058. error = rffi.cast(lltype.Signed, os_pipe(filedes))
  1059. read_fd = filedes[0]
  1060. write_fd = filedes[1]
  1061. lltype.free(filedes, flavor='raw')
  1062. if error != 0:
  1063. raise OSError(rposix.get_errno(), "os_pipe failed")
  1064. return (rffi.cast(lltype.Signed, read_fd),
  1065. rffi.cast(lltype.Signed, write_fd))
  1066. return extdef([], (int, int),
  1067. "ll_os.ll_os_pipe",
  1068. llimpl=os_pipe_llimpl)
  1069. @registering_if(os, 'chown')
  1070. def register_os_chown(self):
  1071. os_chown = self.llexternal('chown', [rffi.CCHARP, rffi.INT, rffi.INT],
  1072. rffi.INT)
  1073. def os_chown_llimpl(path, uid, gid):
  1074. res = os_chown(path, uid, gid)
  1075. if res == -1:
  1076. raise OSError(rposix.get_errno(), "os_chown failed")
  1077. return extdef([str0, int, int], None, "ll_os.ll_os_chown",
  1078. llimpl=os_chown_llimpl)
  1079. @registering_if(os, 'lchown')
  1080. def register_os_lchown(self):
  1081. os_lchown = self.llexternal('lchown',[rffi.CCHARP, rffi.INT, rffi.INT],
  1082. rffi.INT)
  1083. def os_lchown_llimpl(path, uid, gid):
  1084. res = os_lchown(path, uid, gid)
  1085. if res == -1:
  1086. raise OSError(rposix.get_errno(), "os_lchown failed")
  1087. return extdef([str0, int, int], None, "ll_os.ll_os_lchown",
  1088. llimpl=os_lchown_llimpl)
  1089. @registering_if(os, 'fchown')
  1090. def register_os_fchown(self):
  1091. os_fchown = self.llexternal('fchown',[rffi.INT, rffi.INT, rffi.INT],
  1092. rffi.INT)
  1093. def os_fchown_llimpl(fd, uid, gid):
  1094. res = os_fchown(fd, uid, gid)
  1095. if res == -1:
  1096. raise OSError(rposix.get_errno(), "os_fchown failed")
  1097. return extdef([int, int, int], None, "ll_os.ll_os_fchown",
  1098. llimpl=os_fchown_llimpl)
  1099. @registering_if(os, 'readlink')
  1100. def register_os_readlink(self):
  1101. os_readlink = self.llexternal('readlink',
  1102. [rffi.CCHARP, rffi.CCHARP, rffi.SIZE_T],
  1103. rffi.INT)
  1104. # XXX SSIZE_T in POSIX.1-2001
  1105. def os_readlink_llimpl(path):
  1106. bufsize = 1023
  1107. while True:
  1108. l_path = rffi.str2charp(path)
  1109. buf = lltype.malloc(rffi.CCHARP.TO, bufsize,
  1110. flavor='raw')
  1111. res = rffi.cast(lltype.Signed, os_readlink(l_path, buf, bufsize))
  1112. lltype.free(l_path, flavor='raw')
  1113. if res < 0:
  1114. error = rposix.get_errno() # failed
  1115. lltype.free(buf, flavor='raw')
  1116. raise OSError(error, "readlink failed")
  1117. elif res < bufsize:
  1118. break # ok
  1119. else:
  1120. # buf too small, try again with a larger buffer
  1121. lltype.free(buf, flavor='raw')
  1122. bufsize *= 4
  1123. # convert the result to a string
  1124. result = rffi.charp2strn(buf, res)
  1125. lltype.free(buf, flavor='raw')
  1126. return result
  1127. return extdef([str0], str0,
  1128. "ll_os.ll_os_readlink",
  1129. llimpl=os_readlink_llimpl)
  1130. @registering(os.waitpid)
  1131. def register_os_waitpid(self):
  1132. if sys.platform.startswith('win'):
  1133. # emulate waitpid() with the _cwait() of Microsoft's compiler
  1134. os__cwait = self.llexternal('_cwait',
  1135. [rffi.INTP, rffi.PID_T, rffi.INT],
  1136. rffi.PID_T)
  1137. def os_waitpid(pid, status_p, options):
  1138. result = os__cwait(status_p, pid, options)
  1139. # shift the status left a byte so this is more
  1140. # like the POSIX waitpid
  1141. tmp = rffi.cast(rffi.SIGNED, status_p[0])
  1142. tmp <<= 8
  1143. status_p[0] = rffi.cast(rffi.INT, tmp)
  1144. return result
  1145. else:
  1146. # Posix
  1147. if _CYGWIN:
  1148. os_waitpid = self.llexternal('cygwin_waitpid',
  1149. [rffi.PID_T, rffi.INTP, rffi.INT],
  1150. rffi.PID_T)
  1151. else:
  1152. os_waitpid = self.llexternal('waitpid',
  1153. [rffi.PID_T, rffi.INTP, rffi.INT],
  1154. rffi.PID_T)
  1155. def os_waitpid_llimpl(pid, options):
  1156. status_p = lltype.malloc(rffi.INTP.TO, 1, flavor='raw')
  1157. status_p[0] = rffi.cast(rffi.INT, 0)
  1158. result = os_waitpid(rffi.cast(rffi.PID_T, pid),
  1159. status_p,
  1160. rffi.cast(rffi.INT, options))
  1161. result = rffi.cast(lltype.Signed, result)
  1162. status = status_p[0]
  1163. lltype.free(status_p, flavor='raw')
  1164. if result == -1:
  1165. raise OSError(rposix.get_errno(), "os_waitpid failed")
  1166. return (rffi.cast(lltype.Signed, result),
  1167. rffi.cast(lltype.Signed, status))
  1168. return extdef([int, int], (int, int),
  1169. "ll_os.ll_os_waitpid",
  1170. llimpl=os_waitpid_llimpl)
  1171. @registering(os.isatty)
  1172. def register_os_isatty(self):
  1173. os_isatty = self.llexternal(underscore_on_windows+'isatty', [rffi.INT], rffi.INT)
  1174. def isatty_llimpl(fd):
  1175. if not rposix.is_valid_fd(fd):
  1176. return False
  1177. res = rffi.cast(lltype.Signed, os_isatty(rffi.cast(rffi.INT, fd)))
  1178. return res != 0
  1179. return extdef([int], bool, llimpl=isatty_llimpl,
  1180. export_name="ll_os.ll_os_isatty")
  1181. @registering(os.strerror)
  1182. def register_os_strerror(self):
  1183. os_strerror = self.llexternal('strerror', [rffi.INT], rffi.CCHARP)
  1184. def strerror_llimpl(errnum):
  1185. res = os_strerror(rffi.cast(rffi.INT, errnum))
  1186. if not res:
  1187. raise ValueError("os_strerror failed")
  1188. return rffi.charp2str(res)
  1189. return extdef([int], str, llimpl=strerror_llimpl,
  1190. export_name="ll_os.ll_os_strerror")
  1191. @registering(os.system)
  1192. def register_os_system(self):
  1193. os_system = self.llexternal('system', [rffi.CCHARP], rffi.INT)
  1194. def system_llimpl(command):
  1195. res = os_system(command)
  1196. return rffi.cast(lltype.Signed, res)
  1197. return extdef([str0], int, llimpl=system_llimpl,
  1198. export_name="ll_os.ll_os_system")
  1199. @registering_str_unicode(os.unlink)
  1200. def register_os_unlink(self, traits):
  1201. os_unlink = self.llexternal(traits.posix_function_name('unlink'),
  1202. [traits.CCHARP], rffi.INT)
  1203. def unlink_llimpl(pathname):
  1204. res = rffi.cast(lltype.Signed, os_unlink(pathname))
  1205. if res < 0:
  1206. raise OSError(rposix.get_errno(), "os_unlink failed")
  1207. if sys.platform == 'win32':
  1208. from pypy.rpython.module.ll_win32file import make_win32_traits
  1209. win32traits = make_win32_traits(traits)
  1210. @func_renamer('unlink_llimpl_%s' % traits.str.__name__)
  1211. def unlink_llimpl(path):
  1212. if not win32traits.DeleteFile(path):
  1213. raise rwin32.lastWindowsError()
  1214. return extdef([traits.str0], s_None, llimpl=unlink_llimpl,
  1215. export_name=traits.ll_os_name('unlink'))
  1216. @registering_str_unicode(os.chdir)
  1217. def register_os_chdir(self, traits):
  1218. os_chdir = self.llexternal(traits.posix_function_name('chdir'),
  1219. [traits.CCHARP], rffi.INT)
  1220. def os_chdir_llimpl(path):
  1221. res = rffi.cast(lltype.Signed, os_chdir(path))
  1222. if res < 0:
  1223. raise OSError(rposix.get_errno(), "os_chdir failed")
  1224. # On Windows, use an implementation that will produce Win32 errors
  1225. if sys.platform == 'win32':
  1226. from pypy.rpython.module.ll_win32file import make_chdir_impl
  1227. os_chdir_llimpl = make_chdir_impl(traits)
  1228. return extdef([traits.str0], s_None, llimpl=os_chdir_llimpl,
  1229. export_name=traits.ll_os_name('chdir'))
  1230. @registering_str_unicode(os.mkdir)
  1231. def register_os_mkdir(self, traits):
  1232. os_mkdir = self.llexternal(traits.posix_function_name('mkdir'),
  1233. [traits.CCHARP, rffi.MODE_T], rffi.INT)
  1234. if sys.platform == 'win32':
  1235. from pypy.rpython.module.ll_win32file import make_win32_traits
  1236. win32traits = make_win32_traits(traits)
  1237. @func_renamer('mkdir_llimpl_%s' % traits.str.__name__)
  1238. def os_mkdir_llimpl(path, mode):
  1239. if not win32traits.CreateDirectory(path, None):
  1240. raise rwin32.lastWindowsError()
  1241. else:
  1242. def os_mkdir_llimpl(pathname, mode):
  1243. res = os_mkdir(pathname, mode)
  1244. res = rffi.cast(lltype.Signed, res)
  1245. if res < 0:
  1246. raise OSError(rposix.get_errno(), "os_mkdir failed")
  1247. return extdef([traits.str0, int], s_None, llimpl=os_mkdir_llimpl,
  1248. export_name=traits.ll_os_name('mkdir'))
  1249. @registering_str_unicode(os.rmdir)
  1250. def register_os_rmdir(self, traits):
  1251. os_rmdir = self.llexternal(traits.posix_function_name('rmdir'),
  1252. [traits.CCHARP], rffi.INT)
  1253. def rmdir_llimpl(pathname):
  1254. res = rffi.cast(lltype.Signed, os_rmdir(pathname))
  1255. if res < 0:
  1256. raise OSError(rposix.get_errno(), "os_rmdir failed")
  1257. return extdef([traits.str0], s_None, llimpl=rmdir_llimpl,
  1258. export_name=traits.ll_os_name('rmdir'))
  1259. @registering_str_unicode(os.chmod)
  1260. def register_os_chmod(self, traits):
  1261. os_chmod = self.llexternal(traits.posix_function_name('chmod'),
  1262. [traits.CCHARP, rffi.MODE_T], rffi.INT)
  1263. def chmod_llimpl(path, mode):
  1264. res = rffi.cast(lltype.Signed, os_chmod(path, rffi.cast(rffi.MODE_T, mode)))
  1265. if res < 0:
  1266. raise OSError(rposix.get_errno(), "os_chmod failed")
  1267. if sys.platform == 'win32':
  1268. from pypy.rpython.module.ll_win32file import make_chmod_impl
  1269. chmod_llimpl = make_chmod_impl(traits)
  1270. return extdef([traits.str0, int], s_None, llimpl=chmod_llimpl,
  1271. export_name=traits.ll_os_name('chmod'))
  1272. @registering_if(os, 'fchmod')
  1273. def register_os_fchmod(self):
  1274. os_fchmod = self.llexternal('fchmod', [rffi.INT, rffi.MODE_T],
  1275. rffi.INT)
  1276. def fchmod_llimpl(fd, mode):
  1277. mode = rffi.cast(rffi.MODE_T, mode)
  1278. res = rffi.cast(lltype.Signed, os_fchmod(fd, mode))
  1279. if res < 0:
  1280. raise OSError(rposix.get_errno(), "os_fchmod failed")
  1281. return extdef([int, int], s_None, "ll_os.ll_os_fchmod",
  1282. llimpl=fchmod_llimpl)
  1283. @registering_str_unicode(os.rename)
  1284. def register_os_rename(self, traits):
  1285. os_rename = self.llexternal(traits.posix_function_name('rename'),
  1286. [traits.CCHARP, traits.CCHARP], rffi.INT)
  1287. def rename_llimpl(oldpath, newpath):
  1288. res = rffi.cast(lltype.Signed, os_rename(oldpath, newpath))
  1289. if res < 0:
  1290. raise OSError(rposix.get_errno(), "os_rename failed")
  1291. if sys.platform == 'win32':
  1292. from pypy.rpython.module.ll_win32file import make_win32_traits
  1293. win32traits = make_win32_traits(traits)
  1294. @func_renamer('rename_llimpl_%s' % traits.str.__name__)
  1295. def rename_llimpl(oldpath, newpath):
  1296. if not win32traits.MoveFile(oldpath, newpath):
  1297. raise rwin32.lastWindowsError()
  1298. return extdef([traits.str0, traits.str0], s_None, llimpl=rename_llimpl,
  1299. export_name=traits.ll_os_name('rename'))
  1300. @registering_str_unicode(getattr(os, 'mkfifo', None))
  1301. def register_os_mkfifo(self, traits):
  1302. os_mkfifo = self.llexternal(traits.posix_function_name('mkfifo'),
  1303. [traits.CCHARP, rffi.MODE_T], rffi.INT)
  1304. def mkfifo_llimpl(path, mode):
  1305. res = rffi.cast(lltype.Signed, os_mkfifo(path, mode))
  1306. if res < 0:
  1307. raise OSError(rposix.get_errno(), "os_mkfifo failed")
  1308. return extdef([traits.str0, int], s_None, llimpl=mkfifo_llimpl,
  1309. export_name=traits.ll_os_name('mkfifo'))
  1310. @registering_str_unicode(getattr(os, 'mknod', None))
  1311. def register_os_mknod(self, traits):
  1312. os_mknod = self.llexternal(traits.posix_function_name('mknod'),
  1313. [traits.CCHARP, rffi.MODE_T, rffi.INT],
  1314. rffi.INT) # xxx: actually ^^^ dev_t
  1315. def mknod_llimpl(path, mode, dev):
  1316. res = rffi.cast(lltype.Signed, os_mknod(path, mode, dev))
  1317. if res < 0:
  1318. raise OSError(rposix.get_errno(), "os_mknod failed")
  1319. return extdef([traits.str0, int, int], s_None, llimpl=mknod_llimpl,
  1320. export_name=traits.ll_os_name('mknod'))
  1321. @registering(os.umask)
  1322. def register_os_umask(self):
  1323. os_umask = self.llexternal(underscore_on_windows+'umask', [rffi.MODE_T], rffi.MODE_T)
  1324. def umask_llimpl(newmask):
  1325. res = os_umask(rffi.cast(rffi.MODE_T, newmask))
  1326. return rffi.cast(lltype.Signed, res)
  1327. return extdef([int], int, llimpl=umask_llimpl,
  1328. export_name="ll_os.ll_os_umask")
  1329. @registering_if(os, 'kill', sys.platform != 'win32')
  1330. def register_os_kill(self):
  1331. os_kill = self.llexternal('kill', [rffi.PID_T, rffi.INT],
  1332. rffi.INT)
  1333. def kill_llimpl(pid, sig):
  1334. res = rffi.cast(lltype.Signed, os_kill(rffi.cast(rffi.PID_T, pid),
  1335. rffi.cast(rffi.INT, sig)))
  1336. if res < 0:
  1337. raise OSError(rposix.get_errno(), "os_kill failed")
  1338. return extdef([int, int], s_None, llimpl=kill_llimpl,
  1339. export_name="ll_os.ll_os_kill")
  1340. @registering_if(os, 'killpg')
  1341. def register_os_killpg(self):
  1342. os_killpg = self.llexternal('killpg', [rffi.INT, rffi.INT],
  1343. rffi.INT)
  1344. def killpg_llimpl(pid, sig):
  1345. res = rffi.cast(lltype.Signed, os_killpg(rffi.cast(rffi.INT, pid),
  1346. rffi.cast(rffi.INT, sig)))
  1347. if res < 0:
  1348. raise OSError(rposix.get_errno(), "os_killpg failed")
  1349. return extdef([int, int], s_None, llimpl=killpg_llimpl,
  1350. export_name="ll_os.ll_os_killpg")
  1351. @registering_if(os, 'link')
  1352. def register_os_link(self):
  1353. os_link = self.llexternal('link', [rffi.CCHARP, rffi.CCHARP],
  1354. rffi.INT)
  1355. def link_llimpl(oldpath, newpath):
  1356. res = rffi.cast(lltype.Signed, os_link(oldpath, newpath))
  1357. if res < 0:
  1358. raise OSError(rposix.get_errno(), "os_link failed")
  1359. return extdef([str0, str0], s_None, llimpl=link_llimpl,
  1360. export_name="ll_os.ll_os_link")
  1361. @registering_if(os, 'symlink')
  1362. def register_os_symlink(self):
  1363. os_symlink = self.llexternal('symlink', [rffi.CCHARP, rffi.CCHARP],
  1364. rffi.INT)
  1365. def symlink_llimpl(oldpath, newpath):
  1366. res = rffi.cast(lltype.Signed, os_symlink(oldpath, newpath))
  1367. if res < 0:
  1368. raise OSError(rposix.get_errno(), "os_symlink failed")
  1369. return extdef([str0, str0], s_None, llimpl=symlink_llimpl,
  1370. export_name="ll_os.ll_os_symlink")
  1371. @registering_if(os, 'fork')
  1372. def register_os_fork(self):
  1373. from pypy.module.thread import ll_thread
  1374. eci = self.gcc_profiling_bug_workaround('pid_t _noprof_fork(void)',
  1375. 'return fork();')
  1376. os_fork = self.llexternal('_noprof_fork', [], rffi.PID_T,
  1377. compilation_info = eci,
  1378. _nowrapper = True)
  1379. def fork_llimpl():
  1380. opaqueaddr = ll_thread.gc_thread_before_fork()
  1381. childpid = rffi.cast(lltype.Signed, os_fork())
  1382. ll_thread.gc_thread_after_fork(childpid, opaqueaddr)
  1383. if childpid == -1:
  1384. raise OSError(rposix.get_errno(), "os_fork failed")
  1385. return rffi.cast(lltype.Signed, childpid)
  1386. return extdef([], int, llimpl=fork_llimpl,
  1387. export_name="ll_os.ll_os_fork")
  1388. @registering_if(os, 'openpty')
  1389. def register_os_openpty(self):
  1390. os_openpty = self.llexternal(
  1391. 'openpty',
  1392. [rffi.INTP, rffi.INTP, rffi.VOIDP, rffi.VOIDP, rffi.VOIDP],
  1393. rffi.INT,
  1394. compilation_info=ExternalCompilationInfo(libraries=['util']))
  1395. def openpty_llimpl():
  1396. master_p = lltype.malloc(rffi.INTP.TO, 1, flavor='raw')
  1397. slave_p = lltype.malloc(rffi.INTP.TO, 1, flavor='raw')
  1398. result = os_openpty(master_p, slave_p, None, None, None)
  1399. master_fd = master_p[0]
  1400. slave_fd = slave_p[0]
  1401. lltype.free(master_p, flavor='raw')
  1402. lltype.free(slave_p, flavor='raw')
  1403. if result == -1:
  1404. raise OSError(rposix.get_errno(), "os_openpty failed")
  1405. return (rffi.cast(lltype.Signed, master_fd),
  1406. rffi.cast(lltype.Signed, slave_fd))
  1407. return extdef([], (int, int), "ll_os.ll_os_openpty",
  1408. llimpl=openpty_llimpl)
  1409. @registering_if(os, 'forkpty')
  1410. def register_os_forkpty(self):
  1411. os_forkpty = self.llexternal(
  1412. 'forkpty',
  1413. [rffi.INTP, rffi.VOIDP, rffi.VOIDP, rffi.VOIDP],
  1414. rffi.PID_T,
  1415. compilation_info=ExternalCompilationInfo(libraries=['util']))
  1416. def forkpty_llimpl():
  1417. master_p = lltype.malloc(rffi.INTP.TO, 1, flavor='raw')
  1418. childpid = os_forkpty(master_p, None, None, None)
  1419. master_fd = master_p[0]
  1420. lltype.free(master_p, flavor='raw')
  1421. if childpid == -1:
  1422. raise OSError(rposix.get_errno(), "os_forkpty failed")
  1423. return (rffi.cast(lltype.Signed, childpid),
  1424. rffi.cast(lltype.Signed, master_fd))
  1425. return extdef([], (int, int), "ll_os.ll_os_forkpty",
  1426. llimpl=forkpty_llimpl)
  1427. @registering(os._exit)
  1428. def register_os__exit(self):
  1429. os__exit = self.llexternal('_exit', [rffi.INT], lltype.Void)
  1430. def _exit_llimpl(status):
  1431. os__exit(rffi.cast(rffi.INT, status))
  1432. return extdef([int], s_None, llimpl=_exit_llimpl,
  1433. export_name="ll_os.ll_os__exit")
  1434. @registering_if(os, 'nice')
  1435. def register_os_nice(self):
  1436. os_nice = self.llexternal('nice', [rffi.INT], rffi.INT)
  1437. def nice_llimpl(inc):
  1438. # Assume that the system provides a standard-compliant version
  1439. # of nice() that returns the new priority. Nowadays, FreeBSD
  1440. # might be the last major non-compliant system (xxx check me).
  1441. rposix.set_errno(0)
  1442. res = rffi.cast(lltype.Signed, os_nice(inc))
  1443. if res == -1:
  1444. err = rposix.get_errno()
  1445. if err != 0:
  1446. raise OSError(err, "os_nice failed")
  1447. return res
  1448. return extdef([int], int, llimpl=nice_llimpl,
  1449. export_name="ll_os.ll_os_nice")
  1450. # --------------------------- os.stat & variants ---------------------------
  1451. @registering(os.fstat)
  1452. def register_os_fstat(self):
  1453. from pypy.rpython.module import ll_os_stat
  1454. return ll_os_stat.register_stat_variant('fstat', StringTraits())
  1455. @registering_str_unicode(os.stat)
  1456. def register_os_stat(self, traits):
  1457. from pypy.rpython.module import ll_os_stat
  1458. return ll_os_stat.register_stat_variant('stat', traits)
  1459. @registering_str_unicode(os.lstat)
  1460. def register_os_lstat(self, traits):
  1461. from pypy.rpython.module import ll_os_stat
  1462. return ll_os_stat.register_stat_variant('lstat', traits)
  1463. # ------------------------------- os.W* ---------------------------------
  1464. w_star = ['WCOREDUMP', 'WIFCONTINUED', 'WIFSTOPPED',
  1465. 'WIFSIGNALED', 'WIFEXITED', 'WEXITSTATUS',
  1466. 'WSTOPSIG', 'WTERMSIG']
  1467. # last 3 are returning int
  1468. w_star_returning_int = dict.fromkeys(w_star[-3:])
  1469. def declare_new_w_star(self, name):
  1470. """ stupid workaround for the python late-binding
  1471. 'feature'
  1472. """
  1473. def fake(status):
  1474. return int(getattr(os, name)(status))
  1475. fake.func_name = 'fake_' + name
  1476. os_c_func = self.llexternal("pypy_macro_wrapper_" + name,
  1477. [lltype.Signed], lltype.Signed,
  1478. _callable=fake)
  1479. if name in self.w_star_returning_int:
  1480. def llimpl(status):
  1481. return os_c_func(status)
  1482. resulttype = int
  1483. else:
  1484. def llimpl(status):
  1485. return bool(os_c_func(status))
  1486. resulttype = bool
  1487. llimpl.func_name = name + '_llimpl'
  1488. return extdef([int], resulttype, "ll_os." + name,
  1489. llimpl=llimpl)
  1490. for name in w_star:
  1491. locals()['register_w_' + name] = registering_if(os, name)(
  1492. lambda self, xname=name : self.declare_new_w_star(xname))
  1493. @registering_if(os, 'ttyname')
  1494. def register_os_ttyname(self):
  1495. os_ttyname = self.llexternal('ttyname', [lltype.Signed], rffi.CCHARP)
  1496. def ttyname_llimpl(fd):
  1497. l_name = os_ttyname(fd)
  1498. if not l_name:
  1499. raise OSError(rposix.get_errno(), "ttyname raised")
  1500. return rffi.charp2str(l_name)
  1501. return extdef([int], str, "ll_os.ttyname",
  1502. llimpl=ttyname_llimpl)
  1503. # ____________________________________________________________
  1504. # XXX horrible workaround for a bug of profiling in gcc on
  1505. # OS X with functions containing a direct call to some system calls
  1506. # like fork(), execv(), execve()
  1507. def gcc_profiling_bug_workaround(self, decl, body):
  1508. body = ('/*--no-profiling-for-this-file!--*/\n'
  1509. '%s {\n'
  1510. '\t%s\n'
  1511. '}\n' % (decl, body,))
  1512. return ExternalCompilationInfo(
  1513. post_include_bits = [decl + ';'],
  1514. separate_module_sources = [body])
  1515. # ____________________________________________________________
  1516. # Support for os.environ
  1517. # XXX only for systems where os.environ is an instance of _Environ,
  1518. # which should cover Unix and Windows at least
  1519. assert type(os.environ) is not dict
  1520. from pypy.rpython.controllerentry import ControllerEntryForPrebuilt
  1521. class EnvironExtRegistry(ControllerEntryForPrebuilt):
  1522. _about_ = os.environ
  1523. def getcontroller(self):
  1524. from pypy.rpython.module.ll_os_environ import OsEnvironController
  1525. return OsEnvironController()
  1526. # ____________________________________________________________
  1527. # Support for the WindowsError exception
  1528. if sys.platform == 'win32':
  1529. from pypy.rlib import rwin32
  1530. class RegisterFormatError(BaseLazyRegistering):
  1531. def __init__(self):
  1532. pass
  1533. @registering(rwin32.FormatError)
  1534. def register_rwin32_FormatError(self):
  1535. return extdef([lltype.Signed], str,
  1536. "rwin32_FormatError",
  1537. llimpl=rwin32.llimpl_FormatError,
  1538. ooimpl=rwin32.fake_FormatError)