PageRenderTime 62ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/pypy/rpython/module/ll_os.py

https://bitbucket.org/uiappstore/pypy
Python | 1799 lines | 1795 code | 2 blank | 2 comment | 3 complexity | 75a44129efb163711c43a7d4d2e87a1a MD5 | raw file

Large files files are truncated, but you can click here to view the full 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 ll_strcpy, OOSupport
  9. from pypy.tool.sourcetools import func_with_new_name, func_renamer
  10. from pypy.rlib.rarithmetic import r_longlong
  11. from pypy.rpython.extfunc import (
  12. BaseLazyRegistering, lazy_register, 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.tool.udir import udir
  22. from pypy.translator.tool.cbuild import ExternalCompilationInfo
  23. from pypy.rpython.lltypesystem.rstr import mallocstr
  24. from pypy.rpython.annlowlevel import llstr
  25. from pypy.rpython.lltypesystem.llmemory import sizeof,\
  26. itemoffsetof, cast_ptr_to_adr, cast_adr_to_ptr, offsetof
  27. from pypy.rpython.lltypesystem.rstr import STR
  28. from pypy.rpython.annlowlevel import llstr
  29. from pypy.rlib import rgc
  30. from pypy.rlib.objectmodel import specialize
  31. str0 = SomeString(no_nul=True)
  32. unicode0 = SomeUnicodeString(no_nul=True)
  33. def monkeypatch_rposix(posixfunc, unicodefunc, signature):
  34. func_name = posixfunc.__name__
  35. if hasattr(signature, '_default_signature_'):
  36. signature = signature._default_signature_
  37. arglist = ['arg%d' % (i,) for i in range(len(signature))]
  38. transformed_arglist = arglist[:]
  39. for i, arg in enumerate(signature):
  40. if arg in (unicode, unicode0):
  41. transformed_arglist[i] = transformed_arglist[i] + '.as_unicode()'
  42. args = ', '.join(arglist)
  43. transformed_args = ', '.join(transformed_arglist)
  44. try:
  45. main_arg = 'arg%d' % (signature.index(unicode0),)
  46. except ValueError:
  47. main_arg = 'arg%d' % (signature.index(unicode),)
  48. source = py.code.Source("""
  49. def %(func_name)s(%(args)s):
  50. if isinstance(%(main_arg)s, str):
  51. return posixfunc(%(args)s)
  52. else:
  53. return unicodefunc(%(transformed_args)s)
  54. """ % locals())
  55. miniglobals = {'posixfunc' : posixfunc,
  56. 'unicodefunc': unicodefunc,
  57. '__name__': __name__, # for module name propagation
  58. }
  59. exec source.compile() in miniglobals
  60. new_func = miniglobals[func_name]
  61. specialized_args = [i for i in range(len(signature))
  62. if signature[i] in (unicode, unicode0, None)]
  63. new_func = specialize.argtype(*specialized_args)(new_func)
  64. # Monkeypatch the function in pypy.rlib.rposix
  65. setattr(rposix, func_name, new_func)
  66. class StringTraits:
  67. str = str
  68. str0 = str0
  69. CHAR = rffi.CHAR
  70. CCHARP = rffi.CCHARP
  71. charp2str = staticmethod(rffi.charp2str)
  72. str2charp = staticmethod(rffi.str2charp)
  73. free_charp = staticmethod(rffi.free_charp)
  74. scoped_alloc_buffer = staticmethod(rffi.scoped_alloc_buffer)
  75. @staticmethod
  76. def posix_function_name(name):
  77. return underscore_on_windows + name
  78. @staticmethod
  79. def ll_os_name(name):
  80. return 'll_os.ll_os_' + name
  81. class UnicodeTraits:
  82. str = unicode
  83. str0 = unicode0
  84. CHAR = rffi.WCHAR_T
  85. CCHARP = rffi.CWCHARP
  86. charp2str = staticmethod(rffi.wcharp2unicode)
  87. str2charp = staticmethod(rffi.unicode2wcharp)
  88. free_charp = staticmethod(rffi.free_wcharp)
  89. scoped_alloc_buffer = staticmethod(rffi.scoped_alloc_unicodebuffer)
  90. @staticmethod
  91. def posix_function_name(name):
  92. return underscore_on_windows + 'w' + name
  93. @staticmethod
  94. def ll_os_name(name):
  95. return 'll_os.ll_os_w' + name
  96. def registering_str_unicode(posixfunc, condition=True):
  97. if not condition or posixfunc is None:
  98. return registering(None, condition=False)
  99. func_name = posixfunc.__name__
  100. def register_posixfunc(self, method):
  101. val = method(self, StringTraits())
  102. register_external(posixfunc, *val.def_args, **val.def_kwds)
  103. if sys.platform == 'win32':
  104. val = method(self, UnicodeTraits())
  105. @func_renamer(func_name + "_unicode")
  106. def unicodefunc(*args):
  107. return posixfunc(*args)
  108. register_external(unicodefunc, *val.def_args, **val.def_kwds)
  109. signature = val.def_args[0]
  110. monkeypatch_rposix(posixfunc, unicodefunc, signature)
  111. def decorator(method):
  112. decorated = lambda self: register_posixfunc(self, method)
  113. decorated._registering_func = posixfunc
  114. return decorated
  115. return decorator
  116. posix = __import__(os.name)
  117. if sys.platform.startswith('win'):
  118. _WIN32 = True
  119. else:
  120. _WIN32 = False
  121. if _WIN32:
  122. underscore_on_windows = '_'
  123. else:
  124. underscore_on_windows = ''
  125. includes = []
  126. if not _WIN32:
  127. # XXX many of these includes are not portable at all
  128. includes += ['dirent.h', 'sys/stat.h',
  129. 'sys/times.h', 'utime.h', 'sys/types.h', 'unistd.h',
  130. 'signal.h', 'sys/wait.h', 'fcntl.h']
  131. else:
  132. includes += ['sys/utime.h']
  133. class CConfig:
  134. """
  135. Definitions for platform integration.
  136. Note: this must be processed through platform.configure() to provide
  137. usable objects. For example::
  138. CLOCK_T = platform.configure(CConfig)['CLOCK_T']
  139. register(function, [CLOCK_T], ...)
  140. """
  141. _compilation_info_ = ExternalCompilationInfo(
  142. includes=includes
  143. )
  144. if not _WIN32:
  145. CLOCK_T = platform.SimpleType('clock_t', rffi.INT)
  146. TMS = platform.Struct(
  147. 'struct tms', [('tms_utime', rffi.INT),
  148. ('tms_stime', rffi.INT),
  149. ('tms_cutime', rffi.INT),
  150. ('tms_cstime', rffi.INT)])
  151. GID_T = platform.SimpleType('gid_t',rffi.INT)
  152. #TODO right now is used only in getgroups, may need to update other
  153. #functions like setgid
  154. SEEK_SET = platform.DefinedConstantInteger('SEEK_SET')
  155. SEEK_CUR = platform.DefinedConstantInteger('SEEK_CUR')
  156. SEEK_END = platform.DefinedConstantInteger('SEEK_END')
  157. UTIMBUF = platform.Struct('struct '+underscore_on_windows+'utimbuf',
  158. [('actime', rffi.INT),
  159. ('modtime', rffi.INT)])
  160. class RegisterOs(BaseLazyRegistering):
  161. def __init__(self):
  162. self.configure(CConfig)
  163. if hasattr(os, 'getpgrp'):
  164. self.GETPGRP_HAVE_ARG = platform.checkcompiles(
  165. "getpgrp(0)",
  166. '#include <unistd.h>',
  167. [])
  168. if hasattr(os, 'setpgrp'):
  169. self.SETPGRP_HAVE_ARG = platform.checkcompiles(
  170. "setpgrp(0,0)",
  171. '#include <unistd.h>',
  172. [])
  173. # we need an indirection via c functions to get macro calls working on llvm XXX still?
  174. if hasattr(os, 'WCOREDUMP'):
  175. decl_snippet = """
  176. %(ret_type)s pypy_macro_wrapper_%(name)s (int status);
  177. """
  178. def_snippet = """
  179. %(ret_type)s pypy_macro_wrapper_%(name)s (int status) {
  180. return %(name)s(status);
  181. }
  182. """
  183. decls = []
  184. defs = []
  185. for name in self.w_star:
  186. data = {'ret_type': 'int', 'name': name}
  187. decls.append((decl_snippet % data).strip())
  188. defs.append((def_snippet % data).strip())
  189. self.compilation_info = self.compilation_info.merge(
  190. ExternalCompilationInfo(
  191. post_include_bits = decls,
  192. separate_module_sources = ["\n".join(defs)]
  193. ))
  194. # a simple, yet useful factory
  195. def extdef_for_os_function_returning_int(self, name, **kwds):
  196. c_func = self.llexternal(name, [], rffi.INT, **kwds)
  197. def c_func_llimpl():
  198. res = rffi.cast(rffi.SIGNED, c_func())
  199. if res == -1:
  200. raise OSError(rposix.get_errno(), "%s failed" % name)
  201. return res
  202. c_func_llimpl.func_name = name + '_llimpl'
  203. return extdef([], int, llimpl=c_func_llimpl,
  204. export_name='ll_os.ll_os_' + name)
  205. def extdef_for_os_function_accepting_int(self, name, **kwds):
  206. c_func = self.llexternal(name, [rffi.INT], rffi.INT, **kwds)
  207. def c_func_llimpl(arg):
  208. res = rffi.cast(rffi.SIGNED, c_func(arg))
  209. if res == -1:
  210. raise OSError(rposix.get_errno(), "%s failed" % name)
  211. c_func_llimpl.func_name = name + '_llimpl'
  212. return extdef([int], None, llimpl=c_func_llimpl,
  213. export_name='ll_os.ll_os_' + name)
  214. def extdef_for_os_function_accepting_2int(self, name, **kwds):
  215. c_func = self.llexternal(name, [rffi.INT, rffi.INT], rffi.INT, **kwds)
  216. def c_func_llimpl(arg, arg2):
  217. res = rffi.cast(rffi.SIGNED, c_func(arg, arg2))
  218. if res == -1:
  219. raise OSError(rposix.get_errno(), "%s failed" % name)
  220. c_func_llimpl.func_name = name + '_llimpl'
  221. return extdef([int, int], None, llimpl=c_func_llimpl,
  222. export_name='ll_os.ll_os_' + name)
  223. def extdef_for_os_function_accepting_0int(self, name, **kwds):
  224. c_func = self.llexternal(name, [], rffi.INT, **kwds)
  225. def c_func_llimpl():
  226. res = rffi.cast(rffi.SIGNED, c_func())
  227. if res == -1:
  228. raise OSError(rposix.get_errno(), "%s failed" % name)
  229. c_func_llimpl.func_name = name + '_llimpl'
  230. return extdef([], None, llimpl=c_func_llimpl,
  231. export_name='ll_os.ll_os_' + name)
  232. def extdef_for_os_function_int_to_int(self, name, **kwds):
  233. c_func = self.llexternal(name, [rffi.INT], rffi.INT, **kwds)
  234. def c_func_llimpl(arg):
  235. res = rffi.cast(rffi.SIGNED, c_func(arg))
  236. if res == -1:
  237. raise OSError(rposix.get_errno(), "%s failed" % name)
  238. return res
  239. c_func_llimpl.func_name = name + '_llimpl'
  240. return extdef([int], int, llimpl=c_func_llimpl,
  241. export_name='ll_os.ll_os_' + name)
  242. @registering_if(os, 'execv')
  243. def register_os_execv(self):
  244. eci = self.gcc_profiling_bug_workaround(
  245. 'int _noprof_execv(char *path, char *argv[])',
  246. 'return execv(path, argv);')
  247. os_execv = self.llexternal('_noprof_execv',
  248. [rffi.CCHARP, rffi.CCHARPP],
  249. rffi.INT, compilation_info = eci)
  250. def execv_llimpl(path, args):
  251. l_args = rffi.liststr2charpp(args)
  252. os_execv(path, l_args)
  253. rffi.free_charpp(l_args)
  254. raise OSError(rposix.get_errno(), "execv failed")
  255. return extdef([str0, [str0]], s_ImpossibleValue, llimpl=execv_llimpl,
  256. export_name="ll_os.ll_os_execv")
  257. @registering_if(os, 'execve')
  258. def register_os_execve(self):
  259. eci = self.gcc_profiling_bug_workaround(
  260. 'int _noprof_execve(char *filename, char *argv[], char *envp[])',
  261. 'return execve(filename, argv, envp);')
  262. os_execve = self.llexternal(
  263. '_noprof_execve', [rffi.CCHARP, rffi.CCHARPP, rffi.CCHARPP],
  264. rffi.INT, compilation_info = eci)
  265. def execve_llimpl(path, args, env):
  266. # XXX Check path, args, env for \0 and raise TypeErrors as
  267. # appropriate
  268. envstrs = []
  269. for item in env.iteritems():
  270. envstr = "%s=%s" % item
  271. envstrs.append(envstr)
  272. l_args = rffi.liststr2charpp(args)
  273. l_env = rffi.liststr2charpp(envstrs)
  274. os_execve(path, l_args, l_env)
  275. # XXX untested
  276. rffi.free_charpp(l_env)
  277. rffi.free_charpp(l_args)
  278. raise OSError(rposix.get_errno(), "execve failed")
  279. return extdef(
  280. [str0, [str0], {str0: str0}],
  281. s_ImpossibleValue,
  282. llimpl=execve_llimpl,
  283. export_name="ll_os.ll_os_execve")
  284. @registering_if(posix, 'spawnv')
  285. def register_os_spawnv(self):
  286. os_spawnv = self.llexternal('spawnv',
  287. [rffi.INT, rffi.CCHARP, rffi.CCHARPP],
  288. rffi.INT)
  289. def spawnv_llimpl(mode, path, args):
  290. mode = rffi.cast(rffi.INT, mode)
  291. l_args = rffi.liststr2charpp(args)
  292. childpid = os_spawnv(mode, path, l_args)
  293. rffi.free_charpp(l_args)
  294. if childpid == -1:
  295. raise OSError(rposix.get_errno(), "os_spawnv failed")
  296. return rffi.cast(lltype.Signed, childpid)
  297. return extdef([int, str0, [str0]], int, llimpl=spawnv_llimpl,
  298. export_name="ll_os.ll_os_spawnv")
  299. @registering_if(os, 'spawnve')
  300. def register_os_spawnve(self):
  301. os_spawnve = self.llexternal('spawnve',
  302. [rffi.INT, rffi.CCHARP, rffi.CCHARPP,
  303. rffi.CCHARPP],
  304. rffi.INT)
  305. def spawnve_llimpl(mode, path, args, env):
  306. envstrs = []
  307. for item in env.iteritems():
  308. envstrs.append("%s=%s" % item)
  309. mode = rffi.cast(rffi.INT, mode)
  310. l_args = rffi.liststr2charpp(args)
  311. l_env = rffi.liststr2charpp(envstrs)
  312. childpid = os_spawnve(mode, path, l_args, l_env)
  313. rffi.free_charpp(l_env)
  314. rffi.free_charpp(l_args)
  315. if childpid == -1:
  316. raise OSError(rposix.get_errno(), "os_spawnve failed")
  317. return rffi.cast(lltype.Signed, childpid)
  318. return extdef([int, str0, [str0], {str0: str0}], int,
  319. llimpl=spawnve_llimpl,
  320. export_name="ll_os.ll_os_spawnve")
  321. @registering(os.dup)
  322. def register_os_dup(self):
  323. os_dup = self.llexternal(underscore_on_windows+'dup', [rffi.INT], rffi.INT)
  324. def dup_llimpl(fd):
  325. newfd = rffi.cast(lltype.Signed, os_dup(rffi.cast(rffi.INT, fd)))
  326. if newfd == -1:
  327. raise OSError(rposix.get_errno(), "dup failed")
  328. return newfd
  329. return extdef([int], int, llimpl=dup_llimpl,
  330. export_name="ll_os.ll_os_dup", oofakeimpl=os.dup)
  331. @registering(os.dup2)
  332. def register_os_dup2(self):
  333. os_dup2 = self.llexternal(underscore_on_windows+'dup2',
  334. [rffi.INT, rffi.INT], rffi.INT)
  335. def dup2_llimpl(fd, newfd):
  336. error = rffi.cast(lltype.Signed, os_dup2(rffi.cast(rffi.INT, fd),
  337. rffi.cast(rffi.INT, newfd)))
  338. if error == -1:
  339. raise OSError(rposix.get_errno(), "dup2 failed")
  340. return extdef([int, int], s_None, llimpl=dup2_llimpl,
  341. export_name="ll_os.ll_os_dup2")
  342. @registering_if(os, "getlogin", condition=not _WIN32)
  343. def register_os_getlogin(self):
  344. os_getlogin = self.llexternal('getlogin', [], rffi.CCHARP)
  345. def getlogin_llimpl():
  346. result = os_getlogin()
  347. if not result:
  348. raise OSError(rposix.get_errno(), "getlogin failed")
  349. return rffi.charp2str(result)
  350. return extdef([], str, llimpl=getlogin_llimpl,
  351. export_name="ll_os.ll_os_getlogin")
  352. @registering_str_unicode(os.utime)
  353. def register_os_utime(self, traits):
  354. UTIMBUFP = lltype.Ptr(self.UTIMBUF)
  355. os_utime = self.llexternal('utime', [rffi.CCHARP, UTIMBUFP], rffi.INT)
  356. if not _WIN32:
  357. includes = ['sys/time.h']
  358. else:
  359. includes = ['time.h']
  360. class CConfig:
  361. _compilation_info_ = ExternalCompilationInfo(
  362. includes=includes
  363. )
  364. HAVE_UTIMES = platform.Has('utimes')
  365. config = platform.configure(CConfig)
  366. # XXX note that on Windows, calls to os.utime() are ignored on
  367. # directories. Remove that hack over there once it's fixed here!
  368. if config['HAVE_UTIMES']:
  369. class CConfig:
  370. if not _WIN32:
  371. _compilation_info_ = ExternalCompilationInfo(
  372. includes = includes
  373. )
  374. else:
  375. _compilation_info_ = ExternalCompilationInfo(
  376. includes = ['time.h']
  377. )
  378. TIMEVAL = platform.Struct('struct timeval', [('tv_sec', rffi.LONG),
  379. ('tv_usec', rffi.LONG)])
  380. config = platform.configure(CConfig)
  381. TIMEVAL = config['TIMEVAL']
  382. TIMEVAL2P = rffi.CArrayPtr(TIMEVAL)
  383. os_utimes = self.llexternal('utimes', [rffi.CCHARP, TIMEVAL2P],
  384. rffi.INT, compilation_info=CConfig._compilation_info_)
  385. def os_utime_platform(path, actime, modtime):
  386. import math
  387. l_times = lltype.malloc(TIMEVAL2P.TO, 2, flavor='raw')
  388. fracpart, intpart = math.modf(actime)
  389. rffi.setintfield(l_times[0], 'c_tv_sec', int(intpart))
  390. rffi.setintfield(l_times[0], 'c_tv_usec', int(fracpart * 1E6))
  391. fracpart, intpart = math.modf(modtime)
  392. rffi.setintfield(l_times[1], 'c_tv_sec', int(intpart))
  393. rffi.setintfield(l_times[1], 'c_tv_usec', int(fracpart * 1E6))
  394. error = os_utimes(path, l_times)
  395. lltype.free(l_times, flavor='raw')
  396. return error
  397. else:
  398. # we only have utime(), which does not allow sub-second resolution
  399. def os_utime_platform(path, actime, modtime):
  400. l_utimbuf = lltype.malloc(UTIMBUFP.TO, flavor='raw')
  401. l_utimbuf.c_actime = rffi.r_time_t(actime)
  402. l_utimbuf.c_modtime = rffi.r_time_t(modtime)
  403. error = os_utime(path, l_utimbuf)
  404. lltype.free(l_utimbuf, flavor='raw')
  405. return error
  406. # NB. this function is specialized; we get one version where
  407. # tp is known to be None, and one version where it is known
  408. # to be a tuple of 2 floats.
  409. if not _WIN32:
  410. assert traits.str is str
  411. @specialize.argtype(1)
  412. def os_utime_llimpl(path, tp):
  413. if tp is None:
  414. error = os_utime(path, lltype.nullptr(UTIMBUFP.TO))
  415. else:
  416. actime, modtime = tp
  417. error = os_utime_platform(path, actime, modtime)
  418. error = rffi.cast(lltype.Signed, error)
  419. if error == -1:
  420. raise OSError(rposix.get_errno(), "os_utime failed")
  421. else:
  422. from pypy.rpython.module.ll_win32file import make_utime_impl
  423. os_utime_llimpl = make_utime_impl(traits)
  424. if traits.str is str:
  425. s_string = SomeString()
  426. else:
  427. s_string = SomeUnicodeString()
  428. s_tuple_of_2_floats = SomeTuple([SomeFloat(), SomeFloat()])
  429. def os_utime_normalize_args(s_path, s_times):
  430. # special handling of the arguments: they can be either
  431. # [str, (float, float)] or [str, s_None], and get normalized
  432. # to exactly one of these two.
  433. if not s_string.contains(s_path):
  434. raise Exception("os.utime() arg 1 must be a string, got %s" % (
  435. s_path,))
  436. case1 = s_None.contains(s_times)
  437. case2 = s_tuple_of_2_floats.contains(s_times)
  438. if case1 and case2:
  439. return [s_string, s_ImpossibleValue] #don't know which case yet
  440. elif case1:
  441. return [s_string, s_None]
  442. elif case2:
  443. return [s_string, s_tuple_of_2_floats]
  444. else:
  445. raise Exception("os.utime() arg 2 must be None or a tuple of "
  446. "2 floats, got %s" % (s_times,))
  447. os_utime_normalize_args._default_signature_ = [traits.str0, None]
  448. return extdef(os_utime_normalize_args, s_None,
  449. "ll_os.ll_os_utime",
  450. llimpl=os_utime_llimpl)
  451. @registering(os.times)
  452. def register_os_times(self):
  453. if sys.platform.startswith('win'):
  454. from pypy.rlib import rwin32
  455. GetCurrentProcess = self.llexternal('GetCurrentProcess', [],
  456. rwin32.HANDLE)
  457. GetProcessTimes = self.llexternal('GetProcessTimes',
  458. [rwin32.HANDLE,
  459. lltype.Ptr(rwin32.FILETIME),
  460. lltype.Ptr(rwin32.FILETIME),
  461. lltype.Ptr(rwin32.FILETIME),
  462. lltype.Ptr(rwin32.FILETIME)],
  463. rwin32.BOOL)
  464. def times_lltypeimpl():
  465. pcreate = lltype.malloc(rwin32.FILETIME, flavor='raw')
  466. pexit = lltype.malloc(rwin32.FILETIME, flavor='raw')
  467. pkernel = lltype.malloc(rwin32.FILETIME, flavor='raw')
  468. puser = lltype.malloc(rwin32.FILETIME, flavor='raw')
  469. hProc = GetCurrentProcess()
  470. GetProcessTimes(hProc, pcreate, pexit, pkernel, puser)
  471. # The fields of a FILETIME structure are the hi and lo parts
  472. # of a 64-bit value expressed in 100 nanosecond units
  473. # (of course).
  474. result = (rffi.cast(lltype.Signed, pkernel.c_dwHighDateTime) * 429.4967296 +
  475. rffi.cast(lltype.Signed, pkernel.c_dwLowDateTime) * 1E-7,
  476. rffi.cast(lltype.Signed, puser.c_dwHighDateTime) * 429.4967296 +
  477. rffi.cast(lltype.Signed, puser.c_dwLowDateTime) * 1E-7,
  478. 0, 0, 0)
  479. lltype.free(puser, flavor='raw')
  480. lltype.free(pkernel, flavor='raw')
  481. lltype.free(pexit, flavor='raw')
  482. lltype.free(pcreate, flavor='raw')
  483. return result
  484. self.register(os.times, [], (float, float, float, float, float),
  485. "ll_os.ll_times", llimpl=times_lltypeimpl)
  486. return
  487. TMSP = lltype.Ptr(self.TMS)
  488. os_times = self.llexternal('times', [TMSP], self.CLOCK_T)
  489. # Here is a random extra platform parameter which is important.
  490. # Strictly speaking, this should probably be retrieved at runtime, not
  491. # at translation time.
  492. CLOCK_TICKS_PER_SECOND = float(os.sysconf('SC_CLK_TCK'))
  493. def times_lltypeimpl():
  494. l_tmsbuf = lltype.malloc(TMSP.TO, flavor='raw')
  495. try:
  496. result = os_times(l_tmsbuf)
  497. result = rffi.cast(lltype.Signed, result)
  498. if result == -1:
  499. raise OSError(rposix.get_errno(), "times failed")
  500. return (
  501. rffi.cast(lltype.Signed, l_tmsbuf.c_tms_utime)
  502. / CLOCK_TICKS_PER_SECOND,
  503. rffi.cast(lltype.Signed, l_tmsbuf.c_tms_stime)
  504. / CLOCK_TICKS_PER_SECOND,
  505. rffi.cast(lltype.Signed, l_tmsbuf.c_tms_cutime)
  506. / CLOCK_TICKS_PER_SECOND,
  507. rffi.cast(lltype.Signed, l_tmsbuf.c_tms_cstime)
  508. / CLOCK_TICKS_PER_SECOND,
  509. result / CLOCK_TICKS_PER_SECOND)
  510. finally:
  511. lltype.free(l_tmsbuf, flavor='raw')
  512. self.register(os.times, [], (float, float, float, float, float),
  513. "ll_os.ll_times", llimpl=times_lltypeimpl)
  514. @registering_if(os, 'setsid')
  515. def register_os_setsid(self):
  516. os_setsid = self.llexternal('setsid', [], rffi.PID_T)
  517. def setsid_llimpl():
  518. result = rffi.cast(lltype.Signed, os_setsid())
  519. if result == -1:
  520. raise OSError(rposix.get_errno(), "os_setsid failed")
  521. return result
  522. return extdef([], int, export_name="ll_os.ll_os_setsid",
  523. llimpl=setsid_llimpl)
  524. @registering_if(os, 'chroot')
  525. def register_os_chroot(self):
  526. os_chroot = self.llexternal('chroot', [rffi.CCHARP], rffi.INT)
  527. def chroot_llimpl(arg):
  528. result = os_chroot(arg)
  529. if result == -1:
  530. raise OSError(rposix.get_errno(), "os_chroot failed")
  531. return extdef([str0], None, export_name="ll_os.ll_os_chroot",
  532. llimpl=chroot_llimpl)
  533. @registering_if(os, 'uname')
  534. def register_os_uname(self):
  535. CHARARRAY = lltype.FixedSizeArray(lltype.Char, 1)
  536. class CConfig:
  537. _compilation_info_ = ExternalCompilationInfo(
  538. includes = ['sys/utsname.h']
  539. )
  540. UTSNAME = platform.Struct('struct utsname', [
  541. ('sysname', CHARARRAY),
  542. ('nodename', CHARARRAY),
  543. ('release', CHARARRAY),
  544. ('version', CHARARRAY),
  545. ('machine', CHARARRAY)])
  546. config = platform.configure(CConfig)
  547. UTSNAMEP = lltype.Ptr(config['UTSNAME'])
  548. os_uname = self.llexternal('uname', [UTSNAMEP], rffi.INT,
  549. compilation_info=CConfig._compilation_info_)
  550. def uname_llimpl():
  551. l_utsbuf = lltype.malloc(UTSNAMEP.TO, flavor='raw')
  552. result = os_uname(l_utsbuf)
  553. if result == -1:
  554. raise OSError(rposix.get_errno(), "os_uname failed")
  555. retval = (
  556. rffi.charp2str(rffi.cast(rffi.CCHARP, l_utsbuf.c_sysname)),
  557. rffi.charp2str(rffi.cast(rffi.CCHARP, l_utsbuf.c_nodename)),
  558. rffi.charp2str(rffi.cast(rffi.CCHARP, l_utsbuf.c_release)),
  559. rffi.charp2str(rffi.cast(rffi.CCHARP, l_utsbuf.c_version)),
  560. rffi.charp2str(rffi.cast(rffi.CCHARP, l_utsbuf.c_machine)),
  561. )
  562. lltype.free(l_utsbuf, flavor='raw')
  563. return retval
  564. return extdef([], (str, str, str, str, str),
  565. "ll_os.ll_uname", llimpl=uname_llimpl)
  566. @registering_if(os, 'sysconf')
  567. def register_os_sysconf(self):
  568. c_sysconf = self.llexternal('sysconf', [rffi.INT], rffi.LONG)
  569. def sysconf_llimpl(i):
  570. rposix.set_errno(0)
  571. res = c_sysconf(i)
  572. if res == -1:
  573. errno = rposix.get_errno()
  574. if errno != 0:
  575. raise OSError(errno, "sysconf failed")
  576. return res
  577. return extdef([int], int, "ll_os.ll_sysconf", llimpl=sysconf_llimpl)
  578. @registering_if(os, 'fpathconf')
  579. def register_os_fpathconf(self):
  580. c_fpathconf = self.llexternal('fpathconf',
  581. [rffi.INT, rffi.INT], rffi.LONG)
  582. def fpathconf_llimpl(fd, i):
  583. rposix.set_errno(0)
  584. res = c_fpathconf(fd, i)
  585. if res == -1:
  586. errno = rposix.get_errno()
  587. if errno != 0:
  588. raise OSError(errno, "fpathconf failed")
  589. return res
  590. return extdef([int, int], int, "ll_os.ll_fpathconf",
  591. llimpl=fpathconf_llimpl)
  592. @registering_if(os, 'getuid')
  593. def register_os_getuid(self):
  594. return self.extdef_for_os_function_returning_int('getuid')
  595. @registering_if(os, 'geteuid')
  596. def register_os_geteuid(self):
  597. return self.extdef_for_os_function_returning_int('geteuid')
  598. @registering_if(os, 'setuid')
  599. def register_os_setuid(self):
  600. return self.extdef_for_os_function_accepting_int('setuid')
  601. @registering_if(os, 'seteuid')
  602. def register_os_seteuid(self):
  603. return self.extdef_for_os_function_accepting_int('seteuid')
  604. @registering_if(os, 'setgid')
  605. def register_os_setgid(self):
  606. return self.extdef_for_os_function_accepting_int('setgid')
  607. @registering_if(os, 'setegid')
  608. def register_os_setegid(self):
  609. return self.extdef_for_os_function_accepting_int('setegid')
  610. @registering_if(os, 'getpid')
  611. def register_os_getpid(self):
  612. return self.extdef_for_os_function_returning_int('getpid')
  613. @registering_if(os, 'getgid')
  614. def register_os_getgid(self):
  615. return self.extdef_for_os_function_returning_int('getgid')
  616. @registering_if(os, 'getegid')
  617. def register_os_getegid(self):
  618. return self.extdef_for_os_function_returning_int('getegid')
  619. @registering_if(os, 'getgroups')
  620. def register_os_getgroups(self):
  621. GP = rffi.CArrayPtr(self.GID_T)
  622. c_getgroups = self.llexternal('getgroups', [rffi.INT, GP], rffi.INT)
  623. def getgroups_llimpl():
  624. n = c_getgroups(0, lltype.nullptr(GP.TO))
  625. if n >= 0:
  626. groups = lltype.malloc(GP.TO, n, flavor='raw')
  627. try:
  628. n = c_getgroups(n, groups)
  629. result = [groups[i] for i in range(n)]
  630. finally:
  631. lltype.free(groups, flavor='raw')
  632. if n >= 0:
  633. return result
  634. raise OSError(rposix.get_errno(), "os_getgroups failed")
  635. return extdef([], [self.GID_T], llimpl=getgroups_llimpl,
  636. export_name="ll_os.ll_getgroups")
  637. @registering_if(os, 'getpgrp')
  638. def register_os_getpgrp(self):
  639. name = 'getpgrp'
  640. if self.GETPGRP_HAVE_ARG:
  641. c_func = self.llexternal(name, [rffi.INT], rffi.INT)
  642. def c_func_llimpl():
  643. res = rffi.cast(rffi.SIGNED, c_func(0))
  644. if res == -1:
  645. raise OSError(rposix.get_errno(), "%s failed" % name)
  646. return res
  647. c_func_llimpl.func_name = name + '_llimpl'
  648. return extdef([], int, llimpl=c_func_llimpl,
  649. export_name='ll_os.ll_os_' + name)
  650. else:
  651. return self.extdef_for_os_function_returning_int('getpgrp')
  652. @registering_if(os, 'setpgrp')
  653. def register_os_setpgrp(self):
  654. name = 'setpgrp'
  655. if self.SETPGRP_HAVE_ARG:
  656. c_func = self.llexternal(name, [rffi.INT, rffi.INT], rffi.INT)
  657. def c_func_llimpl():
  658. res = rffi.cast(rffi.SIGNED, c_func(0, 0))
  659. if res == -1:
  660. raise OSError(rposix.get_errno(), "%s failed" % name)
  661. c_func_llimpl.func_name = name + '_llimpl'
  662. return extdef([], None, llimpl=c_func_llimpl,
  663. export_name='ll_os.ll_os_' + name)
  664. else:
  665. return self.extdef_for_os_function_accepting_0int(name)
  666. @registering_if(os, 'getppid')
  667. def register_os_getppid(self):
  668. return self.extdef_for_os_function_returning_int('getppid')
  669. @registering_if(os, 'getpgid')
  670. def register_os_getpgid(self):
  671. return self.extdef_for_os_function_int_to_int('getpgid')
  672. @registering_if(os, 'setpgid')
  673. def register_os_setpgid(self):
  674. return self.extdef_for_os_function_accepting_2int('setpgid')
  675. @registering_if(os, 'setreuid')
  676. def register_os_setreuid(self):
  677. return self.extdef_for_os_function_accepting_2int('setreuid')
  678. @registering_if(os, 'setregid')
  679. def register_os_setregid(self):
  680. return self.extdef_for_os_function_accepting_2int('setregid')
  681. @registering_if(os, 'getsid')
  682. def register_os_getsid(self):
  683. return self.extdef_for_os_function_int_to_int('getsid')
  684. @registering_if(os, 'setsid')
  685. def register_os_setsid(self):
  686. return self.extdef_for_os_function_returning_int('setsid')
  687. @registering_str_unicode(os.open)
  688. def register_os_open(self, traits):
  689. os_open = self.llexternal(traits.posix_function_name('open'),
  690. [traits.CCHARP, rffi.INT, rffi.MODE_T],
  691. rffi.INT)
  692. def os_open_llimpl(path, flags, mode):
  693. result = rffi.cast(lltype.Signed, os_open(path, flags, mode))
  694. if result == -1:
  695. raise OSError(rposix.get_errno(), "os_open failed")
  696. return result
  697. def os_open_oofakeimpl(path, flags, mode):
  698. return os.open(OOSupport.from_rstr(path), flags, mode)
  699. return extdef([traits.str0, int, int], int, traits.ll_os_name('open'),
  700. llimpl=os_open_llimpl, oofakeimpl=os_open_oofakeimpl)
  701. @registering_if(os, 'getloadavg')
  702. def register_os_getloadavg(self):
  703. AP = rffi.CArrayPtr(lltype.Float)
  704. c_getloadavg = self.llexternal('getloadavg', [AP, rffi.INT], rffi.INT)
  705. def getloadavg_llimpl():
  706. load = lltype.malloc(AP.TO, 3, flavor='raw')
  707. r = c_getloadavg(load, 3)
  708. result_tuple = load[0], load[1], load[2]
  709. lltype.free(load, flavor='raw')
  710. if r != 3:
  711. raise OSError
  712. return result_tuple
  713. return extdef([], (float, float, float),
  714. "ll_os.ll_getloadavg", llimpl=getloadavg_llimpl)
  715. @registering_if(os, 'makedev')
  716. def register_os_makedev(self):
  717. c_makedev = self.llexternal('makedev', [rffi.INT, rffi.INT], rffi.INT)
  718. def makedev_llimpl(maj, min):
  719. return c_makedev(maj, min)
  720. return extdef([int, int], int,
  721. "ll_os.ll_makedev", llimpl=makedev_llimpl)
  722. @registering_if(os, 'major')
  723. def register_os_major(self):
  724. c_major = self.llexternal('major', [rffi.INT], rffi.INT)
  725. def major_llimpl(dev):
  726. return c_major(dev)
  727. return extdef([int], int,
  728. "ll_os.ll_major", llimpl=major_llimpl)
  729. @registering_if(os, 'minor')
  730. def register_os_minor(self):
  731. c_minor = self.llexternal('minor', [rffi.INT], rffi.INT)
  732. def minor_llimpl(dev):
  733. return c_minor(dev)
  734. return extdef([int], int,
  735. "ll_os.ll_minor", llimpl=minor_llimpl)
  736. # ------------------------------- os.read -------------------------------
  737. @registering(os.read)
  738. def register_os_read(self):
  739. os_read = self.llexternal(underscore_on_windows+'read',
  740. [rffi.INT, rffi.VOIDP, rffi.SIZE_T],
  741. rffi.SIZE_T)
  742. offset = offsetof(STR, 'chars') + itemoffsetof(STR.chars, 0)
  743. def os_read_llimpl(fd, count):
  744. if count < 0:
  745. raise OSError(errno.EINVAL, None)
  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. buf = rffi.get_nonmovingbuffer(data)
  768. try:
  769. written = rffi.cast(lltype.Signed, os_write(
  770. rffi.cast(rffi.INT, fd),
  771. buf, rffi.cast(rffi.SIZE_T, count)))
  772. if written < 0:
  773. raise OSError(rposix.get_errno(), "os_write failed")
  774. finally:
  775. rffi.free_nonmovingbuffer(data, buf)
  776. return written
  777. def os_write_oofakeimpl(fd, data):
  778. return os.write(fd, OOSupport.from_rstr(data))
  779. return extdef([int, str], SomeInteger(nonneg=True),
  780. "ll_os.ll_os_write", llimpl=os_write_llimpl,
  781. oofakeimpl=os_write_oofakeimpl)
  782. @registering(os.close)
  783. def register_os_close(self):
  784. os_close = self.llexternal(underscore_on_windows+'close', [rffi.INT],
  785. rffi.INT, threadsafe=False)
  786. def close_llimpl(fd):
  787. error = rffi.cast(lltype.Signed, os_close(rffi.cast(rffi.INT, fd)))
  788. if error == -1:
  789. raise OSError(rposix.get_errno(), "close failed")
  790. return extdef([int], s_None, llimpl=close_llimpl,
  791. export_name="ll_os.ll_os_close", oofakeimpl=os.close)
  792. @registering(os.lseek)
  793. def register_os_lseek(self):
  794. if sys.platform.startswith('win'):
  795. funcname = '_lseeki64'
  796. else:
  797. funcname = 'lseek'
  798. if self.SEEK_SET is not None:
  799. SEEK_SET = self.SEEK_SET
  800. SEEK_CUR = self.SEEK_CUR
  801. SEEK_END = self.SEEK_END
  802. else:
  803. SEEK_SET, SEEK_CUR, SEEK_END = 0, 1, 2
  804. if (SEEK_SET, SEEK_CUR, SEEK_END) != (0, 1, 2):
  805. # Turn 0, 1, 2 into SEEK_{SET,CUR,END}
  806. def fix_seek_arg(n):
  807. if n == 0: return SEEK_SET
  808. if n == 1: return SEEK_CUR
  809. if n == 2: return SEEK_END
  810. return n
  811. else:
  812. def fix_seek_arg(n):
  813. return n
  814. os_lseek = self.llexternal(funcname,
  815. [rffi.INT, rffi.LONGLONG, rffi.INT],
  816. rffi.LONGLONG)
  817. def lseek_llimpl(fd, pos, how):
  818. how = fix_seek_arg(how)
  819. res = os_lseek(rffi.cast(rffi.INT, fd),
  820. rffi.cast(rffi.LONGLONG, pos),
  821. rffi.cast(rffi.INT, how))
  822. res = rffi.cast(lltype.SignedLongLong, res)
  823. if res < 0:
  824. raise OSError(rposix.get_errno(), "os_lseek failed")
  825. return res
  826. def os_lseek_oofakeimpl(fd, pos, how):
  827. res = os.lseek(fd, pos, how)
  828. return r_longlong(res)
  829. return extdef([int, r_longlong, int],
  830. r_longlong,
  831. llimpl = lseek_llimpl,
  832. export_name = "ll_os.ll_os_lseek",
  833. oofakeimpl = os_lseek_oofakeimpl)
  834. @registering_if(os, 'ftruncate')
  835. def register_os_ftruncate(self):
  836. os_ftruncate = self.llexternal('ftruncate',
  837. [rffi.INT, rffi.LONGLONG], rffi.INT)
  838. def ftruncate_llimpl(fd, length):
  839. res = rffi.cast(rffi.LONG,
  840. os_ftruncate(rffi.cast(rffi.INT, fd),
  841. rffi.cast(rffi.LONGLONG, length)))
  842. if res < 0:
  843. raise OSError(rposix.get_errno(), "os_ftruncate failed")
  844. return extdef([int, r_longlong], s_None,
  845. llimpl = ftruncate_llimpl,
  846. export_name = "ll_os.ll_os_ftruncate")
  847. @registering_if(os, 'fsync')
  848. def register_os_fsync(self):
  849. if not _WIN32:
  850. os_fsync = self.llexternal('fsync', [rffi.INT], rffi.INT)
  851. else:
  852. os_fsync = self.llexternal('_commit', [rffi.INT], rffi.INT)
  853. def fsync_llimpl(fd):
  854. res = rffi.cast(rffi.SIGNED, os_fsync(rffi.cast(rffi.INT, fd)))
  855. if res < 0:
  856. raise OSError(rposix.get_errno(), "fsync failed")
  857. return extdef([int], s_None,
  858. llimpl=fsync_llimpl,
  859. export_name="ll_os.ll_os_fsync")
  860. @registering_if(os, 'fdatasync')
  861. def register_os_fdatasync(self):
  862. os_fdatasync = self.llexternal('fdatasync', [rffi.INT], rffi.INT)
  863. def fdatasync_llimpl(fd):
  864. res = rffi.cast(rffi.SIGNED, os_fdatasync(rffi.cast(rffi.INT, fd)))
  865. if res < 0:
  866. raise OSError(rposix.get_errno(), "fdatasync failed")
  867. return extdef([int], s_None,
  868. llimpl=fdatasync_llimpl,
  869. export_name="ll_os.ll_os_fdatasync")
  870. @registering_if(os, 'fchdir')
  871. def register_os_fchdir(self):
  872. os_fchdir = self.llexternal('fchdir', [rffi.INT], rffi.INT)
  873. def fchdir_llimpl(fd):
  874. res = rffi.cast(rffi.SIGNED, os_fchdir(rffi.cast(rffi.INT, fd)))
  875. if res < 0:
  876. raise OSError(rposix.get_errno(), "fchdir failed")
  877. return extdef([int], s_None,
  878. llimpl=fchdir_llimpl,
  879. export_name="ll_os.ll_os_fchdir")
  880. @registering_str_unicode(os.access)
  881. def register_os_access(self, traits):
  882. os_access = self.llexternal(traits.posix_function_name('access'),
  883. [traits.CCHARP, rffi.INT],
  884. rffi.INT)
  885. if sys.platform.startswith('win'):
  886. # All files are executable on Windows
  887. def access_llimpl(path, mode):
  888. mode = mode & ~os.X_OK
  889. error = rffi.cast(lltype.Signed, os_access(path, mode))
  890. return error == 0
  891. else:
  892. def access_llimpl(path, mode):
  893. error = rffi.cast(lltype.Signed, os_access(path, mode))
  894. return error == 0
  895. def os_access_oofakeimpl(path, mode):
  896. return os.access(OOSupport.from_rstr(path), mode)
  897. return extdef([traits.str0, int], s_Bool, llimpl=access_llimpl,
  898. export_name=traits.ll_os_name("access"),
  899. oofakeimpl=os_access_oofakeimpl)
  900. @registering_str_unicode(getattr(posix, '_getfullpathname', None),
  901. condition=sys.platform=='win32')
  902. def register_posix__getfullpathname(self, traits):
  903. # this nt function is not exposed via os, but needed
  904. # to get a correct implementation of os.abspath
  905. from pypy.rpython.module.ll_win32file import make_getfullpathname_impl
  906. getfullpathname_llimpl = make_getfullpathname_impl(traits)
  907. return extdef([traits.str0], # a single argument which is a str
  908. traits.str0, # returns a string
  909. traits.ll_os_name('_getfullpathname'),
  910. llimpl=getfullpathname_llimpl)
  911. @registering(os.getcwd)
  912. def register_os_getcwd(self):
  913. os_getcwd = self.llexternal(underscore_on_windows + 'getcwd',
  914. [rffi.CCHARP, rffi.SIZE_T],
  915. rffi.CCHARP)
  916. def os_getcwd_llimpl():
  917. bufsize = 256
  918. while True:
  919. buf = lltype.malloc(rffi.CCHARP.TO, bufsize, flavor='raw')
  920. res = os_getcwd(buf, rffi.cast(rffi.SIZE_T, bufsize))
  921. if res:
  922. break # ok
  923. error = rposix.get_errno()
  924. lltype.free(buf, flavor='raw')
  925. if error != errno.ERANGE:
  926. raise OSError(error, "getcwd failed")
  927. # else try again with a larger buffer, up to some sane limit
  928. bufsize *= 4
  929. if bufsize > 1024*1024: # xxx hard-coded upper limit
  930. raise OSError(error, "getcwd result too large")
  931. result = rffi.charp2str(res)
  932. lltype.free(buf, flavor='raw')
  933. return result
  934. def os_getcwd_oofakeimpl():
  935. return OOSupport.to_rstr(os.getcwd())
  936. return extdef([], str,
  937. "ll_os.ll_os_getcwd", llimpl=os_getcwd_llimpl,
  938. oofakeimpl=os_getcwd_oofakeimpl)
  939. @registering(os.getcwdu, condition=sys.platform=='win32')
  940. def register_os_getcwdu(self):
  941. os_wgetcwd = self.llexternal(underscore_on_windows + 'wgetcwd',
  942. [rffi.CWCHARP, rffi.SIZE_T],
  943. rffi.CWCHARP)
  944. def os_getcwd_llimpl():
  945. bufsize = 256
  946. while True:
  947. buf = lltype.malloc(rffi.CWCHARP.TO, bufsize, flavor='raw')
  948. res = os_wgetcwd(buf, rffi.cast(rffi.SIZE_T, bufsize))
  949. if res:
  950. break # ok
  951. error = rposix.get_errno()
  952. lltype.free(buf, flavor='raw')
  953. if error != errno.ERANGE:
  954. raise OSError(error, "getcwd failed")
  955. # else try again with a larger buffer, up to some sane limit
  956. bufsize *= 4
  957. if bufsize > 1024*1024: # xxx hard-coded upper limit
  958. raise OSError(error, "getcwd result too large")
  959. result = rffi.wcharp2unicode(res)
  960. lltype.free(buf, flavor='raw')
  961. return result
  962. return extdef([], unicode,
  963. "ll_os.ll_os_wgetcwd", llimpl=os_getcwd_llimpl)
  964. @registering_str_unicode(os.listdir)
  965. def register_os_listdir(self, traits):
  966. # we need a different approach on Windows and on Posix
  967. if sys.platform.startswith('win'):
  968. from pypy.rpython.module.ll_win32file import make_listdir_impl
  969. os_listdir_llimpl = make_listdir_impl(traits)
  970. else:
  971. assert traits.str is str
  972. compilation_info = ExternalCompilationInfo(
  973. includes = ['sys/types.h', 'dirent.h']
  974. )
  975. class CConfig:
  976. _compilation_info_ = compilation_info
  977. DIRENT = platform.Struct('struct dirent',
  978. [('d_name', lltype.FixedSizeArray(rffi.CHAR, 1))])
  979. DIRP = rffi.COpaquePtr('DIR')
  980. config = platform.configure(CConfig)
  981. DIRENT = config['DIRENT']
  982. DIRENTP = lltype.Ptr(DIRENT)
  983. os_opendir = self.llexternal('opendir', [rffi.CCHARP], DIRP,
  984. compilation_info=compilation_info)
  985. os_readdir = self.llexternal('readdir', [DIRP], DIRENTP,
  986. compilation_info=compilation_info)
  987. os_closedir = self.llexternal('closedir', [DIRP], rffi.INT,
  988. compilation_info=compilation_info)
  989. def os_listdir_llimpl(path):
  990. dirp = os_opendir(path)
  991. if not dirp:
  992. raise OSError(rposix.get_errno(), "os_opendir failed")
  993. rposix.set_errno(0)
  994. result = []
  995. while True:
  996. direntp = os_readdir(dirp)
  997. if not direntp:
  998. error = rposix.get_errno()
  999. break
  1000. namep = rffi.cast(rffi.CCHARP, direntp.c_d_name)
  1001. name = rffi.charp2str(namep)
  1002. if name != '.' and name != '..':
  1003. result.append(name)
  1004. os_closedir(dirp)
  1005. if error:
  1006. raise OSError(error, "os_readdir failed")
  1007. return result
  1008. return extdef([traits.str0], # a single argument which is a str
  1009. [traits.str0], # returns a list of strings
  1010. traits.ll_os_name('listdir'),
  1011. llimpl=os_listdir_llimpl)
  1012. @registering(os.pipe)
  1013. def register_os_pipe(self):
  1014. # we need a different approach on Windows and on Posix
  1015. if sys.platform.startswith('win'):
  1016. from pypy.rlib import rwin32
  1017. CreatePipe = self.llexternal('CreatePipe', [rwin32.LPHANDLE,
  1018. rwin32.LPHANDLE,
  1019. rffi.VOIDP,
  1020. rwin32.DWORD],
  1021. rwin32.BOOL)
  1022. _open_osfhandle = self.llexternal('_open_osfhandle', [rffi.INTPTR_T,
  1023. rffi.INT],
  1024. rffi.INT)
  1025. null = lltype.nullptr(rffi.VOIDP.TO)
  1026. def os_pipe_llimpl():
  1027. pread = lltype.malloc(rwin32.LPHANDLE.TO, 1, flavor='raw')
  1028. pwrite = lltype.malloc(rwin32.LPHANDLE.TO, 1, flavor='raw')
  1029. ok = CreatePipe(pread, pwrite, null, 0)
  1030. if ok:
  1031. error = 0
  1032. else:
  1033. error = rwin32.GetLastError()
  1034. hread = rffi.cast(rffi.INTPTR_T, pread[0])
  1035. hwrite = rffi.cast(rffi.INTPTR_T, pwrite[0])
  1036. lltype.free(pwrite, flavor='raw')
  1037. lltype.free(pread, flavor='raw')
  1038. if error:
  1039. raise WindowsError(error, "os_pipe failed")
  1040. fdread = _open_osfhandle(hread, 0)
  1041. fdwrite = _open_osfhandle(hwrite, 1)
  1042. return (fdread, fdwrite)
  1043. else:
  1044. INT_ARRAY_P = rffi.CArrayPtr(rffi.INT)
  1045. os_pipe = self.llexternal('pipe', [INT_ARRAY_P], rffi.INT)
  1046. def os_pipe_llimpl():
  1047. filedes = lltype.malloc(INT_ARRAY_P.TO, 2, flavor='raw')
  1048. error = rffi.cast(lltype.Signed, os_pipe(filedes))
  1049. read_fd =

Large files files are truncated, but you can click here to view the full file