test_posix.py 88 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202
  1. "Test posix functions"
  2. from test import support
  3. from test.support import import_helper
  4. from test.support import os_helper
  5. from test.support import warnings_helper
  6. from test.support.script_helper import assert_python_ok
  7. # Skip these tests if there is no posix module.
  8. posix = import_helper.import_module('posix')
  9. import errno
  10. import sys
  11. import signal
  12. import time
  13. import os
  14. import platform
  15. import stat
  16. import tempfile
  17. import unittest
  18. import warnings
  19. import textwrap
  20. from contextlib import contextmanager
  21. try:
  22. import pwd
  23. except ImportError:
  24. pwd = None
  25. _DUMMY_SYMLINK = os.path.join(tempfile.gettempdir(),
  26. os_helper.TESTFN + '-dummy-symlink')
  27. requires_32b = unittest.skipUnless(
  28. # Emscripten/WASI have 32 bits pointers, but support 64 bits syscall args.
  29. sys.maxsize < 2**32 and not (support.is_emscripten or support.is_wasi),
  30. 'test is only meaningful on 32-bit builds'
  31. )
  32. def _supports_sched():
  33. if not hasattr(posix, 'sched_getscheduler'):
  34. return False
  35. try:
  36. posix.sched_getscheduler(0)
  37. except OSError as e:
  38. if e.errno == errno.ENOSYS:
  39. return False
  40. return True
  41. requires_sched = unittest.skipUnless(_supports_sched(), 'requires POSIX scheduler API')
  42. class PosixTester(unittest.TestCase):
  43. def setUp(self):
  44. # create empty file
  45. self.addCleanup(os_helper.unlink, os_helper.TESTFN)
  46. with open(os_helper.TESTFN, "wb"):
  47. pass
  48. self.enterContext(warnings_helper.check_warnings())
  49. warnings.filterwarnings('ignore', '.* potential security risk .*',
  50. RuntimeWarning)
  51. def testNoArgFunctions(self):
  52. # test posix functions which take no arguments and have
  53. # no side-effects which we need to cleanup (e.g., fork, wait, abort)
  54. NO_ARG_FUNCTIONS = [ "ctermid", "getcwd", "getcwdb", "uname",
  55. "times", "getloadavg",
  56. "getegid", "geteuid", "getgid", "getgroups",
  57. "getpid", "getpgrp", "getppid", "getuid", "sync",
  58. ]
  59. for name in NO_ARG_FUNCTIONS:
  60. posix_func = getattr(posix, name, None)
  61. if posix_func is not None:
  62. with self.subTest(name):
  63. posix_func()
  64. self.assertRaises(TypeError, posix_func, 1)
  65. @unittest.skipUnless(hasattr(posix, 'getresuid'),
  66. 'test needs posix.getresuid()')
  67. def test_getresuid(self):
  68. user_ids = posix.getresuid()
  69. self.assertEqual(len(user_ids), 3)
  70. for val in user_ids:
  71. self.assertGreaterEqual(val, 0)
  72. @unittest.skipUnless(hasattr(posix, 'getresgid'),
  73. 'test needs posix.getresgid()')
  74. def test_getresgid(self):
  75. group_ids = posix.getresgid()
  76. self.assertEqual(len(group_ids), 3)
  77. for val in group_ids:
  78. self.assertGreaterEqual(val, 0)
  79. @unittest.skipUnless(hasattr(posix, 'setresuid'),
  80. 'test needs posix.setresuid()')
  81. def test_setresuid(self):
  82. current_user_ids = posix.getresuid()
  83. self.assertIsNone(posix.setresuid(*current_user_ids))
  84. # -1 means don't change that value.
  85. self.assertIsNone(posix.setresuid(-1, -1, -1))
  86. @unittest.skipUnless(hasattr(posix, 'setresuid'),
  87. 'test needs posix.setresuid()')
  88. def test_setresuid_exception(self):
  89. # Don't do this test if someone is silly enough to run us as root.
  90. current_user_ids = posix.getresuid()
  91. if 0 not in current_user_ids:
  92. new_user_ids = (current_user_ids[0]+1, -1, -1)
  93. self.assertRaises(OSError, posix.setresuid, *new_user_ids)
  94. @unittest.skipUnless(hasattr(posix, 'setresgid'),
  95. 'test needs posix.setresgid()')
  96. def test_setresgid(self):
  97. current_group_ids = posix.getresgid()
  98. self.assertIsNone(posix.setresgid(*current_group_ids))
  99. # -1 means don't change that value.
  100. self.assertIsNone(posix.setresgid(-1, -1, -1))
  101. @unittest.skipUnless(hasattr(posix, 'setresgid'),
  102. 'test needs posix.setresgid()')
  103. def test_setresgid_exception(self):
  104. # Don't do this test if someone is silly enough to run us as root.
  105. current_group_ids = posix.getresgid()
  106. if 0 not in current_group_ids:
  107. new_group_ids = (current_group_ids[0]+1, -1, -1)
  108. self.assertRaises(OSError, posix.setresgid, *new_group_ids)
  109. @unittest.skipUnless(hasattr(posix, 'initgroups'),
  110. "test needs os.initgroups()")
  111. @unittest.skipUnless(hasattr(pwd, 'getpwuid'), "test needs pwd.getpwuid()")
  112. def test_initgroups(self):
  113. # It takes a string and an integer; check that it raises a TypeError
  114. # for other argument lists.
  115. self.assertRaises(TypeError, posix.initgroups)
  116. self.assertRaises(TypeError, posix.initgroups, None)
  117. self.assertRaises(TypeError, posix.initgroups, 3, "foo")
  118. self.assertRaises(TypeError, posix.initgroups, "foo", 3, object())
  119. # If a non-privileged user invokes it, it should fail with OSError
  120. # EPERM.
  121. if os.getuid() != 0:
  122. try:
  123. name = pwd.getpwuid(posix.getuid()).pw_name
  124. except KeyError:
  125. # the current UID may not have a pwd entry
  126. raise unittest.SkipTest("need a pwd entry")
  127. try:
  128. posix.initgroups(name, 13)
  129. except OSError as e:
  130. self.assertEqual(e.errno, errno.EPERM)
  131. else:
  132. self.fail("Expected OSError to be raised by initgroups")
  133. @unittest.skipUnless(hasattr(posix, 'statvfs'),
  134. 'test needs posix.statvfs()')
  135. def test_statvfs(self):
  136. self.assertTrue(posix.statvfs(os.curdir))
  137. @unittest.skipUnless(hasattr(posix, 'fstatvfs'),
  138. 'test needs posix.fstatvfs()')
  139. def test_fstatvfs(self):
  140. fp = open(os_helper.TESTFN)
  141. try:
  142. self.assertTrue(posix.fstatvfs(fp.fileno()))
  143. self.assertTrue(posix.statvfs(fp.fileno()))
  144. finally:
  145. fp.close()
  146. @unittest.skipUnless(hasattr(posix, 'ftruncate'),
  147. 'test needs posix.ftruncate()')
  148. def test_ftruncate(self):
  149. fp = open(os_helper.TESTFN, 'w+')
  150. try:
  151. # we need to have some data to truncate
  152. fp.write('test')
  153. fp.flush()
  154. posix.ftruncate(fp.fileno(), 0)
  155. finally:
  156. fp.close()
  157. @unittest.skipUnless(hasattr(posix, 'truncate'), "test needs posix.truncate()")
  158. def test_truncate(self):
  159. with open(os_helper.TESTFN, 'w') as fp:
  160. fp.write('test')
  161. fp.flush()
  162. posix.truncate(os_helper.TESTFN, 0)
  163. @unittest.skipUnless(getattr(os, 'execve', None) in os.supports_fd, "test needs execve() to support the fd parameter")
  164. @support.requires_fork()
  165. def test_fexecve(self):
  166. fp = os.open(sys.executable, os.O_RDONLY)
  167. try:
  168. pid = os.fork()
  169. if pid == 0:
  170. os.chdir(os.path.split(sys.executable)[0])
  171. posix.execve(fp, [sys.executable, '-c', 'pass'], os.environ)
  172. else:
  173. support.wait_process(pid, exitcode=0)
  174. finally:
  175. os.close(fp)
  176. @unittest.skipUnless(hasattr(posix, 'waitid'), "test needs posix.waitid()")
  177. @support.requires_fork()
  178. def test_waitid(self):
  179. pid = os.fork()
  180. if pid == 0:
  181. os.chdir(os.path.split(sys.executable)[0])
  182. posix.execve(sys.executable, [sys.executable, '-c', 'pass'], os.environ)
  183. else:
  184. res = posix.waitid(posix.P_PID, pid, posix.WEXITED)
  185. self.assertEqual(pid, res.si_pid)
  186. @support.requires_fork()
  187. def test_register_at_fork(self):
  188. with self.assertRaises(TypeError, msg="Positional args not allowed"):
  189. os.register_at_fork(lambda: None)
  190. with self.assertRaises(TypeError, msg="Args must be callable"):
  191. os.register_at_fork(before=2)
  192. with self.assertRaises(TypeError, msg="Args must be callable"):
  193. os.register_at_fork(after_in_child="three")
  194. with self.assertRaises(TypeError, msg="Args must be callable"):
  195. os.register_at_fork(after_in_parent=b"Five")
  196. with self.assertRaises(TypeError, msg="Args must not be None"):
  197. os.register_at_fork(before=None)
  198. with self.assertRaises(TypeError, msg="Args must not be None"):
  199. os.register_at_fork(after_in_child=None)
  200. with self.assertRaises(TypeError, msg="Args must not be None"):
  201. os.register_at_fork(after_in_parent=None)
  202. with self.assertRaises(TypeError, msg="Invalid arg was allowed"):
  203. # Ensure a combination of valid and invalid is an error.
  204. os.register_at_fork(before=None, after_in_parent=lambda: 3)
  205. with self.assertRaises(TypeError, msg="Invalid arg was allowed"):
  206. # Ensure a combination of valid and invalid is an error.
  207. os.register_at_fork(before=lambda: None, after_in_child='')
  208. # We test actual registrations in their own process so as not to
  209. # pollute this one. There is no way to unregister for cleanup.
  210. code = """if 1:
  211. import os
  212. r, w = os.pipe()
  213. fin_r, fin_w = os.pipe()
  214. os.register_at_fork(before=lambda: os.write(w, b'A'))
  215. os.register_at_fork(after_in_parent=lambda: os.write(w, b'C'))
  216. os.register_at_fork(after_in_child=lambda: os.write(w, b'E'))
  217. os.register_at_fork(before=lambda: os.write(w, b'B'),
  218. after_in_parent=lambda: os.write(w, b'D'),
  219. after_in_child=lambda: os.write(w, b'F'))
  220. pid = os.fork()
  221. if pid == 0:
  222. # At this point, after-forkers have already been executed
  223. os.close(w)
  224. # Wait for parent to tell us to exit
  225. os.read(fin_r, 1)
  226. os._exit(0)
  227. else:
  228. try:
  229. os.close(w)
  230. with open(r, "rb") as f:
  231. data = f.read()
  232. assert len(data) == 6, data
  233. # Check before-fork callbacks
  234. assert data[:2] == b'BA', data
  235. # Check after-fork callbacks
  236. assert sorted(data[2:]) == list(b'CDEF'), data
  237. assert data.index(b'C') < data.index(b'D'), data
  238. assert data.index(b'E') < data.index(b'F'), data
  239. finally:
  240. os.write(fin_w, b'!')
  241. """
  242. assert_python_ok('-c', code)
  243. @unittest.skipUnless(hasattr(posix, 'lockf'), "test needs posix.lockf()")
  244. def test_lockf(self):
  245. fd = os.open(os_helper.TESTFN, os.O_WRONLY | os.O_CREAT)
  246. try:
  247. os.write(fd, b'test')
  248. os.lseek(fd, 0, os.SEEK_SET)
  249. posix.lockf(fd, posix.F_LOCK, 4)
  250. # section is locked
  251. posix.lockf(fd, posix.F_ULOCK, 4)
  252. finally:
  253. os.close(fd)
  254. @unittest.skipUnless(hasattr(posix, 'pread'), "test needs posix.pread()")
  255. def test_pread(self):
  256. fd = os.open(os_helper.TESTFN, os.O_RDWR | os.O_CREAT)
  257. try:
  258. os.write(fd, b'test')
  259. os.lseek(fd, 0, os.SEEK_SET)
  260. self.assertEqual(b'es', posix.pread(fd, 2, 1))
  261. # the first pread() shouldn't disturb the file offset
  262. self.assertEqual(b'te', posix.read(fd, 2))
  263. finally:
  264. os.close(fd)
  265. @unittest.skipUnless(hasattr(posix, 'preadv'), "test needs posix.preadv()")
  266. def test_preadv(self):
  267. fd = os.open(os_helper.TESTFN, os.O_RDWR | os.O_CREAT)
  268. try:
  269. os.write(fd, b'test1tt2t3t5t6t6t8')
  270. buf = [bytearray(i) for i in [5, 3, 2]]
  271. self.assertEqual(posix.preadv(fd, buf, 3), 10)
  272. self.assertEqual([b't1tt2', b't3t', b'5t'], list(buf))
  273. finally:
  274. os.close(fd)
  275. @unittest.skipUnless(hasattr(posix, 'preadv'), "test needs posix.preadv()")
  276. @unittest.skipUnless(hasattr(posix, 'RWF_HIPRI'), "test needs posix.RWF_HIPRI")
  277. def test_preadv_flags(self):
  278. fd = os.open(os_helper.TESTFN, os.O_RDWR | os.O_CREAT)
  279. try:
  280. os.write(fd, b'test1tt2t3t5t6t6t8')
  281. buf = [bytearray(i) for i in [5, 3, 2]]
  282. self.assertEqual(posix.preadv(fd, buf, 3, os.RWF_HIPRI), 10)
  283. self.assertEqual([b't1tt2', b't3t', b'5t'], list(buf))
  284. except NotImplementedError:
  285. self.skipTest("preadv2 not available")
  286. except OSError as inst:
  287. # Is possible that the macro RWF_HIPRI was defined at compilation time
  288. # but the option is not supported by the kernel or the runtime libc shared
  289. # library.
  290. if inst.errno in {errno.EINVAL, errno.ENOTSUP}:
  291. raise unittest.SkipTest("RWF_HIPRI is not supported by the current system")
  292. else:
  293. raise
  294. finally:
  295. os.close(fd)
  296. @unittest.skipUnless(hasattr(posix, 'preadv'), "test needs posix.preadv()")
  297. @requires_32b
  298. def test_preadv_overflow_32bits(self):
  299. fd = os.open(os_helper.TESTFN, os.O_RDWR | os.O_CREAT)
  300. try:
  301. buf = [bytearray(2**16)] * 2**15
  302. with self.assertRaises(OSError) as cm:
  303. os.preadv(fd, buf, 0)
  304. self.assertEqual(cm.exception.errno, errno.EINVAL)
  305. self.assertEqual(bytes(buf[0]), b'\0'* 2**16)
  306. finally:
  307. os.close(fd)
  308. @unittest.skipUnless(hasattr(posix, 'pwrite'), "test needs posix.pwrite()")
  309. def test_pwrite(self):
  310. fd = os.open(os_helper.TESTFN, os.O_RDWR | os.O_CREAT)
  311. try:
  312. os.write(fd, b'test')
  313. os.lseek(fd, 0, os.SEEK_SET)
  314. posix.pwrite(fd, b'xx', 1)
  315. self.assertEqual(b'txxt', posix.read(fd, 4))
  316. finally:
  317. os.close(fd)
  318. @unittest.skipUnless(hasattr(posix, 'pwritev'), "test needs posix.pwritev()")
  319. def test_pwritev(self):
  320. fd = os.open(os_helper.TESTFN, os.O_RDWR | os.O_CREAT)
  321. try:
  322. os.write(fd, b"xx")
  323. os.lseek(fd, 0, os.SEEK_SET)
  324. n = os.pwritev(fd, [b'test1', b'tt2', b't3'], 2)
  325. self.assertEqual(n, 10)
  326. os.lseek(fd, 0, os.SEEK_SET)
  327. self.assertEqual(b'xxtest1tt2t3', posix.read(fd, 100))
  328. finally:
  329. os.close(fd)
  330. @unittest.skipUnless(hasattr(posix, 'pwritev'), "test needs posix.pwritev()")
  331. @unittest.skipUnless(hasattr(posix, 'os.RWF_SYNC'), "test needs os.RWF_SYNC")
  332. def test_pwritev_flags(self):
  333. fd = os.open(os_helper.TESTFN, os.O_RDWR | os.O_CREAT)
  334. try:
  335. os.write(fd,b"xx")
  336. os.lseek(fd, 0, os.SEEK_SET)
  337. n = os.pwritev(fd, [b'test1', b'tt2', b't3'], 2, os.RWF_SYNC)
  338. self.assertEqual(n, 10)
  339. os.lseek(fd, 0, os.SEEK_SET)
  340. self.assertEqual(b'xxtest1tt2', posix.read(fd, 100))
  341. finally:
  342. os.close(fd)
  343. @unittest.skipUnless(hasattr(posix, 'pwritev'), "test needs posix.pwritev()")
  344. @requires_32b
  345. def test_pwritev_overflow_32bits(self):
  346. fd = os.open(os_helper.TESTFN, os.O_RDWR | os.O_CREAT)
  347. try:
  348. with self.assertRaises(OSError) as cm:
  349. os.pwritev(fd, [b"x" * 2**16] * 2**15, 0)
  350. self.assertEqual(cm.exception.errno, errno.EINVAL)
  351. finally:
  352. os.close(fd)
  353. @unittest.skipUnless(hasattr(posix, 'posix_fallocate'),
  354. "test needs posix.posix_fallocate()")
  355. def test_posix_fallocate(self):
  356. fd = os.open(os_helper.TESTFN, os.O_WRONLY | os.O_CREAT)
  357. try:
  358. posix.posix_fallocate(fd, 0, 10)
  359. except OSError as inst:
  360. # issue10812, ZFS doesn't appear to support posix_fallocate,
  361. # so skip Solaris-based since they are likely to have ZFS.
  362. # issue33655: Also ignore EINVAL on *BSD since ZFS is also
  363. # often used there.
  364. if inst.errno == errno.EINVAL and sys.platform.startswith(
  365. ('sunos', 'freebsd', 'netbsd', 'openbsd', 'gnukfreebsd')):
  366. raise unittest.SkipTest("test may fail on ZFS filesystems")
  367. else:
  368. raise
  369. finally:
  370. os.close(fd)
  371. # issue31106 - posix_fallocate() does not set error in errno.
  372. @unittest.skipUnless(hasattr(posix, 'posix_fallocate'),
  373. "test needs posix.posix_fallocate()")
  374. def test_posix_fallocate_errno(self):
  375. try:
  376. posix.posix_fallocate(-42, 0, 10)
  377. except OSError as inst:
  378. if inst.errno != errno.EBADF:
  379. raise
  380. @unittest.skipUnless(hasattr(posix, 'posix_fadvise'),
  381. "test needs posix.posix_fadvise()")
  382. def test_posix_fadvise(self):
  383. fd = os.open(os_helper.TESTFN, os.O_RDONLY)
  384. try:
  385. posix.posix_fadvise(fd, 0, 0, posix.POSIX_FADV_WILLNEED)
  386. finally:
  387. os.close(fd)
  388. @unittest.skipUnless(hasattr(posix, 'posix_fadvise'),
  389. "test needs posix.posix_fadvise()")
  390. def test_posix_fadvise_errno(self):
  391. try:
  392. posix.posix_fadvise(-42, 0, 0, posix.POSIX_FADV_WILLNEED)
  393. except OSError as inst:
  394. if inst.errno != errno.EBADF:
  395. raise
  396. @unittest.skipUnless(os.utime in os.supports_fd, "test needs fd support in os.utime")
  397. def test_utime_with_fd(self):
  398. now = time.time()
  399. fd = os.open(os_helper.TESTFN, os.O_RDONLY)
  400. try:
  401. posix.utime(fd)
  402. posix.utime(fd, None)
  403. self.assertRaises(TypeError, posix.utime, fd, (None, None))
  404. self.assertRaises(TypeError, posix.utime, fd, (now, None))
  405. self.assertRaises(TypeError, posix.utime, fd, (None, now))
  406. posix.utime(fd, (int(now), int(now)))
  407. posix.utime(fd, (now, now))
  408. self.assertRaises(ValueError, posix.utime, fd, (now, now), ns=(now, now))
  409. self.assertRaises(ValueError, posix.utime, fd, (now, 0), ns=(None, None))
  410. self.assertRaises(ValueError, posix.utime, fd, (None, None), ns=(now, 0))
  411. posix.utime(fd, (int(now), int((now - int(now)) * 1e9)))
  412. posix.utime(fd, ns=(int(now), int((now - int(now)) * 1e9)))
  413. finally:
  414. os.close(fd)
  415. @unittest.skipUnless(os.utime in os.supports_follow_symlinks, "test needs follow_symlinks support in os.utime")
  416. def test_utime_nofollow_symlinks(self):
  417. now = time.time()
  418. posix.utime(os_helper.TESTFN, None, follow_symlinks=False)
  419. self.assertRaises(TypeError, posix.utime, os_helper.TESTFN,
  420. (None, None), follow_symlinks=False)
  421. self.assertRaises(TypeError, posix.utime, os_helper.TESTFN,
  422. (now, None), follow_symlinks=False)
  423. self.assertRaises(TypeError, posix.utime, os_helper.TESTFN,
  424. (None, now), follow_symlinks=False)
  425. posix.utime(os_helper.TESTFN, (int(now), int(now)),
  426. follow_symlinks=False)
  427. posix.utime(os_helper.TESTFN, (now, now), follow_symlinks=False)
  428. posix.utime(os_helper.TESTFN, follow_symlinks=False)
  429. @unittest.skipUnless(hasattr(posix, 'writev'), "test needs posix.writev()")
  430. def test_writev(self):
  431. fd = os.open(os_helper.TESTFN, os.O_RDWR | os.O_CREAT)
  432. try:
  433. n = os.writev(fd, (b'test1', b'tt2', b't3'))
  434. self.assertEqual(n, 10)
  435. os.lseek(fd, 0, os.SEEK_SET)
  436. self.assertEqual(b'test1tt2t3', posix.read(fd, 10))
  437. # Issue #20113: empty list of buffers should not crash
  438. try:
  439. size = posix.writev(fd, [])
  440. except OSError:
  441. # writev(fd, []) raises OSError(22, "Invalid argument")
  442. # on OpenIndiana
  443. pass
  444. else:
  445. self.assertEqual(size, 0)
  446. finally:
  447. os.close(fd)
  448. @unittest.skipUnless(hasattr(posix, 'writev'), "test needs posix.writev()")
  449. @requires_32b
  450. def test_writev_overflow_32bits(self):
  451. fd = os.open(os_helper.TESTFN, os.O_RDWR | os.O_CREAT)
  452. try:
  453. with self.assertRaises(OSError) as cm:
  454. os.writev(fd, [b"x" * 2**16] * 2**15)
  455. self.assertEqual(cm.exception.errno, errno.EINVAL)
  456. finally:
  457. os.close(fd)
  458. @unittest.skipUnless(hasattr(posix, 'readv'), "test needs posix.readv()")
  459. def test_readv(self):
  460. fd = os.open(os_helper.TESTFN, os.O_RDWR | os.O_CREAT)
  461. try:
  462. os.write(fd, b'test1tt2t3')
  463. os.lseek(fd, 0, os.SEEK_SET)
  464. buf = [bytearray(i) for i in [5, 3, 2]]
  465. self.assertEqual(posix.readv(fd, buf), 10)
  466. self.assertEqual([b'test1', b'tt2', b't3'], [bytes(i) for i in buf])
  467. # Issue #20113: empty list of buffers should not crash
  468. try:
  469. size = posix.readv(fd, [])
  470. except OSError:
  471. # readv(fd, []) raises OSError(22, "Invalid argument")
  472. # on OpenIndiana
  473. pass
  474. else:
  475. self.assertEqual(size, 0)
  476. finally:
  477. os.close(fd)
  478. @unittest.skipUnless(hasattr(posix, 'readv'), "test needs posix.readv()")
  479. @requires_32b
  480. def test_readv_overflow_32bits(self):
  481. fd = os.open(os_helper.TESTFN, os.O_RDWR | os.O_CREAT)
  482. try:
  483. buf = [bytearray(2**16)] * 2**15
  484. with self.assertRaises(OSError) as cm:
  485. os.readv(fd, buf)
  486. self.assertEqual(cm.exception.errno, errno.EINVAL)
  487. self.assertEqual(bytes(buf[0]), b'\0'* 2**16)
  488. finally:
  489. os.close(fd)
  490. @unittest.skipUnless(hasattr(posix, 'dup'),
  491. 'test needs posix.dup()')
  492. @unittest.skipIf(support.is_wasi, "WASI does not have dup()")
  493. def test_dup(self):
  494. fp = open(os_helper.TESTFN)
  495. try:
  496. fd = posix.dup(fp.fileno())
  497. self.assertIsInstance(fd, int)
  498. os.close(fd)
  499. finally:
  500. fp.close()
  501. @unittest.skipUnless(hasattr(posix, 'confstr'),
  502. 'test needs posix.confstr()')
  503. def test_confstr(self):
  504. self.assertRaises(ValueError, posix.confstr, "CS_garbage")
  505. self.assertEqual(len(posix.confstr("CS_PATH")) > 0, True)
  506. @unittest.skipUnless(hasattr(posix, 'dup2'),
  507. 'test needs posix.dup2()')
  508. @unittest.skipIf(support.is_wasi, "WASI does not have dup2()")
  509. def test_dup2(self):
  510. fp1 = open(os_helper.TESTFN)
  511. fp2 = open(os_helper.TESTFN)
  512. try:
  513. posix.dup2(fp1.fileno(), fp2.fileno())
  514. finally:
  515. fp1.close()
  516. fp2.close()
  517. @unittest.skipUnless(hasattr(os, 'O_CLOEXEC'), "needs os.O_CLOEXEC")
  518. @support.requires_linux_version(2, 6, 23)
  519. @support.requires_subprocess()
  520. def test_oscloexec(self):
  521. fd = os.open(os_helper.TESTFN, os.O_RDONLY|os.O_CLOEXEC)
  522. self.addCleanup(os.close, fd)
  523. self.assertFalse(os.get_inheritable(fd))
  524. @unittest.skipUnless(hasattr(posix, 'O_EXLOCK'),
  525. 'test needs posix.O_EXLOCK')
  526. def test_osexlock(self):
  527. fd = os.open(os_helper.TESTFN,
  528. os.O_WRONLY|os.O_EXLOCK|os.O_CREAT)
  529. self.assertRaises(OSError, os.open, os_helper.TESTFN,
  530. os.O_WRONLY|os.O_EXLOCK|os.O_NONBLOCK)
  531. os.close(fd)
  532. if hasattr(posix, "O_SHLOCK"):
  533. fd = os.open(os_helper.TESTFN,
  534. os.O_WRONLY|os.O_SHLOCK|os.O_CREAT)
  535. self.assertRaises(OSError, os.open, os_helper.TESTFN,
  536. os.O_WRONLY|os.O_EXLOCK|os.O_NONBLOCK)
  537. os.close(fd)
  538. @unittest.skipUnless(hasattr(posix, 'O_SHLOCK'),
  539. 'test needs posix.O_SHLOCK')
  540. def test_osshlock(self):
  541. fd1 = os.open(os_helper.TESTFN,
  542. os.O_WRONLY|os.O_SHLOCK|os.O_CREAT)
  543. fd2 = os.open(os_helper.TESTFN,
  544. os.O_WRONLY|os.O_SHLOCK|os.O_CREAT)
  545. os.close(fd2)
  546. os.close(fd1)
  547. if hasattr(posix, "O_EXLOCK"):
  548. fd = os.open(os_helper.TESTFN,
  549. os.O_WRONLY|os.O_SHLOCK|os.O_CREAT)
  550. self.assertRaises(OSError, os.open, os_helper.TESTFN,
  551. os.O_RDONLY|os.O_EXLOCK|os.O_NONBLOCK)
  552. os.close(fd)
  553. @unittest.skipUnless(hasattr(posix, 'fstat'),
  554. 'test needs posix.fstat()')
  555. def test_fstat(self):
  556. fp = open(os_helper.TESTFN)
  557. try:
  558. self.assertTrue(posix.fstat(fp.fileno()))
  559. self.assertTrue(posix.stat(fp.fileno()))
  560. self.assertRaisesRegex(TypeError,
  561. 'should be string, bytes, os.PathLike or integer, not',
  562. posix.stat, float(fp.fileno()))
  563. finally:
  564. fp.close()
  565. def test_stat(self):
  566. self.assertTrue(posix.stat(os_helper.TESTFN))
  567. self.assertTrue(posix.stat(os.fsencode(os_helper.TESTFN)))
  568. self.assertWarnsRegex(DeprecationWarning,
  569. 'should be string, bytes, os.PathLike or integer, not',
  570. posix.stat, bytearray(os.fsencode(os_helper.TESTFN)))
  571. self.assertRaisesRegex(TypeError,
  572. 'should be string, bytes, os.PathLike or integer, not',
  573. posix.stat, None)
  574. self.assertRaisesRegex(TypeError,
  575. 'should be string, bytes, os.PathLike or integer, not',
  576. posix.stat, list(os_helper.TESTFN))
  577. self.assertRaisesRegex(TypeError,
  578. 'should be string, bytes, os.PathLike or integer, not',
  579. posix.stat, list(os.fsencode(os_helper.TESTFN)))
  580. @unittest.skipUnless(hasattr(posix, 'mkfifo'), "don't have mkfifo()")
  581. def test_mkfifo(self):
  582. if sys.platform == "vxworks":
  583. fifo_path = os.path.join("/fifos/", os_helper.TESTFN)
  584. else:
  585. fifo_path = os_helper.TESTFN
  586. os_helper.unlink(fifo_path)
  587. self.addCleanup(os_helper.unlink, fifo_path)
  588. try:
  589. posix.mkfifo(fifo_path, stat.S_IRUSR | stat.S_IWUSR)
  590. except PermissionError as e:
  591. self.skipTest('posix.mkfifo(): %s' % e)
  592. self.assertTrue(stat.S_ISFIFO(posix.stat(fifo_path).st_mode))
  593. @unittest.skipUnless(hasattr(posix, 'mknod') and hasattr(stat, 'S_IFIFO'),
  594. "don't have mknod()/S_IFIFO")
  595. def test_mknod(self):
  596. # Test using mknod() to create a FIFO (the only use specified
  597. # by POSIX).
  598. os_helper.unlink(os_helper.TESTFN)
  599. mode = stat.S_IFIFO | stat.S_IRUSR | stat.S_IWUSR
  600. try:
  601. posix.mknod(os_helper.TESTFN, mode, 0)
  602. except OSError as e:
  603. # Some old systems don't allow unprivileged users to use
  604. # mknod(), or only support creating device nodes.
  605. self.assertIn(e.errno, (errno.EPERM, errno.EINVAL, errno.EACCES))
  606. else:
  607. self.assertTrue(stat.S_ISFIFO(posix.stat(os_helper.TESTFN).st_mode))
  608. # Keyword arguments are also supported
  609. os_helper.unlink(os_helper.TESTFN)
  610. try:
  611. posix.mknod(path=os_helper.TESTFN, mode=mode, device=0,
  612. dir_fd=None)
  613. except OSError as e:
  614. self.assertIn(e.errno, (errno.EPERM, errno.EINVAL, errno.EACCES))
  615. @unittest.skipUnless(hasattr(posix, 'makedev'), 'test needs posix.makedev()')
  616. def test_makedev(self):
  617. st = posix.stat(os_helper.TESTFN)
  618. dev = st.st_dev
  619. self.assertIsInstance(dev, int)
  620. self.assertGreaterEqual(dev, 0)
  621. major = posix.major(dev)
  622. self.assertIsInstance(major, int)
  623. self.assertGreaterEqual(major, 0)
  624. self.assertEqual(posix.major(dev), major)
  625. self.assertRaises(TypeError, posix.major, float(dev))
  626. self.assertRaises(TypeError, posix.major)
  627. self.assertRaises((ValueError, OverflowError), posix.major, -1)
  628. minor = posix.minor(dev)
  629. self.assertIsInstance(minor, int)
  630. self.assertGreaterEqual(minor, 0)
  631. self.assertEqual(posix.minor(dev), minor)
  632. self.assertRaises(TypeError, posix.minor, float(dev))
  633. self.assertRaises(TypeError, posix.minor)
  634. self.assertRaises((ValueError, OverflowError), posix.minor, -1)
  635. self.assertEqual(posix.makedev(major, minor), dev)
  636. self.assertRaises(TypeError, posix.makedev, float(major), minor)
  637. self.assertRaises(TypeError, posix.makedev, major, float(minor))
  638. self.assertRaises(TypeError, posix.makedev, major)
  639. self.assertRaises(TypeError, posix.makedev)
  640. def _test_all_chown_common(self, chown_func, first_param, stat_func):
  641. """Common code for chown, fchown and lchown tests."""
  642. def check_stat(uid, gid):
  643. if stat_func is not None:
  644. stat = stat_func(first_param)
  645. self.assertEqual(stat.st_uid, uid)
  646. self.assertEqual(stat.st_gid, gid)
  647. uid = os.getuid()
  648. gid = os.getgid()
  649. # test a successful chown call
  650. chown_func(first_param, uid, gid)
  651. check_stat(uid, gid)
  652. chown_func(first_param, -1, gid)
  653. check_stat(uid, gid)
  654. chown_func(first_param, uid, -1)
  655. check_stat(uid, gid)
  656. if sys.platform == "vxworks":
  657. # On VxWorks, root user id is 1 and 0 means no login user:
  658. # both are super users.
  659. is_root = (uid in (0, 1))
  660. else:
  661. is_root = (uid == 0)
  662. if support.is_emscripten:
  663. # Emscripten getuid() / geteuid() always return 0 (root), but
  664. # cannot chown uid/gid to random value.
  665. pass
  666. elif is_root:
  667. # Try an amusingly large uid/gid to make sure we handle
  668. # large unsigned values. (chown lets you use any
  669. # uid/gid you like, even if they aren't defined.)
  670. #
  671. # On VxWorks uid_t is defined as unsigned short. A big
  672. # value greater than 65535 will result in underflow error.
  673. #
  674. # This problem keeps coming up:
  675. # http://bugs.python.org/issue1747858
  676. # http://bugs.python.org/issue4591
  677. # http://bugs.python.org/issue15301
  678. # Hopefully the fix in 4591 fixes it for good!
  679. #
  680. # This part of the test only runs when run as root.
  681. # Only scary people run their tests as root.
  682. big_value = (2**31 if sys.platform != "vxworks" else 2**15)
  683. chown_func(first_param, big_value, big_value)
  684. check_stat(big_value, big_value)
  685. chown_func(first_param, -1, -1)
  686. check_stat(big_value, big_value)
  687. chown_func(first_param, uid, gid)
  688. check_stat(uid, gid)
  689. elif platform.system() in ('HP-UX', 'SunOS'):
  690. # HP-UX and Solaris can allow a non-root user to chown() to root
  691. # (issue #5113)
  692. raise unittest.SkipTest("Skipping because of non-standard chown() "
  693. "behavior")
  694. else:
  695. # non-root cannot chown to root, raises OSError
  696. self.assertRaises(OSError, chown_func, first_param, 0, 0)
  697. check_stat(uid, gid)
  698. self.assertRaises(OSError, chown_func, first_param, 0, -1)
  699. check_stat(uid, gid)
  700. if 0 not in os.getgroups():
  701. self.assertRaises(OSError, chown_func, first_param, -1, 0)
  702. check_stat(uid, gid)
  703. # test illegal types
  704. for t in str, float:
  705. self.assertRaises(TypeError, chown_func, first_param, t(uid), gid)
  706. check_stat(uid, gid)
  707. self.assertRaises(TypeError, chown_func, first_param, uid, t(gid))
  708. check_stat(uid, gid)
  709. @os_helper.skip_unless_working_chmod
  710. @unittest.skipIf(support.is_emscripten, "getgid() is a stub")
  711. def test_chown(self):
  712. # raise an OSError if the file does not exist
  713. os.unlink(os_helper.TESTFN)
  714. self.assertRaises(OSError, posix.chown, os_helper.TESTFN, -1, -1)
  715. # re-create the file
  716. os_helper.create_empty_file(os_helper.TESTFN)
  717. self._test_all_chown_common(posix.chown, os_helper.TESTFN, posix.stat)
  718. @os_helper.skip_unless_working_chmod
  719. @unittest.skipUnless(hasattr(posix, 'fchown'), "test needs os.fchown()")
  720. @unittest.skipIf(support.is_emscripten, "getgid() is a stub")
  721. def test_fchown(self):
  722. os.unlink(os_helper.TESTFN)
  723. # re-create the file
  724. test_file = open(os_helper.TESTFN, 'w')
  725. try:
  726. fd = test_file.fileno()
  727. self._test_all_chown_common(posix.fchown, fd,
  728. getattr(posix, 'fstat', None))
  729. finally:
  730. test_file.close()
  731. @os_helper.skip_unless_working_chmod
  732. @unittest.skipUnless(hasattr(posix, 'lchown'), "test needs os.lchown()")
  733. def test_lchown(self):
  734. os.unlink(os_helper.TESTFN)
  735. # create a symlink
  736. os.symlink(_DUMMY_SYMLINK, os_helper.TESTFN)
  737. self._test_all_chown_common(posix.lchown, os_helper.TESTFN,
  738. getattr(posix, 'lstat', None))
  739. @unittest.skipUnless(hasattr(posix, 'chdir'), 'test needs posix.chdir()')
  740. def test_chdir(self):
  741. posix.chdir(os.curdir)
  742. self.assertRaises(OSError, posix.chdir, os_helper.TESTFN)
  743. def test_listdir(self):
  744. self.assertIn(os_helper.TESTFN, posix.listdir(os.curdir))
  745. def test_listdir_default(self):
  746. # When listdir is called without argument,
  747. # it's the same as listdir(os.curdir).
  748. self.assertIn(os_helper.TESTFN, posix.listdir())
  749. def test_listdir_bytes(self):
  750. # When listdir is called with a bytes object,
  751. # the returned strings are of type bytes.
  752. self.assertIn(os.fsencode(os_helper.TESTFN), posix.listdir(b'.'))
  753. def test_listdir_bytes_like(self):
  754. for cls in bytearray, memoryview:
  755. with self.assertWarns(DeprecationWarning):
  756. names = posix.listdir(cls(b'.'))
  757. self.assertIn(os.fsencode(os_helper.TESTFN), names)
  758. for name in names:
  759. self.assertIs(type(name), bytes)
  760. @unittest.skipUnless(posix.listdir in os.supports_fd,
  761. "test needs fd support for posix.listdir()")
  762. def test_listdir_fd(self):
  763. f = posix.open(posix.getcwd(), posix.O_RDONLY)
  764. self.addCleanup(posix.close, f)
  765. self.assertEqual(
  766. sorted(posix.listdir('.')),
  767. sorted(posix.listdir(f))
  768. )
  769. # Check that the fd offset was reset (issue #13739)
  770. self.assertEqual(
  771. sorted(posix.listdir('.')),
  772. sorted(posix.listdir(f))
  773. )
  774. @unittest.skipUnless(hasattr(posix, 'access'), 'test needs posix.access()')
  775. def test_access(self):
  776. self.assertTrue(posix.access(os_helper.TESTFN, os.R_OK))
  777. @unittest.skipUnless(hasattr(posix, 'umask'), 'test needs posix.umask()')
  778. def test_umask(self):
  779. old_mask = posix.umask(0)
  780. self.assertIsInstance(old_mask, int)
  781. posix.umask(old_mask)
  782. @unittest.skipUnless(hasattr(posix, 'strerror'),
  783. 'test needs posix.strerror()')
  784. def test_strerror(self):
  785. self.assertTrue(posix.strerror(0))
  786. @unittest.skipUnless(hasattr(posix, 'pipe'), 'test needs posix.pipe()')
  787. def test_pipe(self):
  788. reader, writer = posix.pipe()
  789. os.close(reader)
  790. os.close(writer)
  791. @unittest.skipUnless(hasattr(os, 'pipe2'), "test needs os.pipe2()")
  792. @support.requires_linux_version(2, 6, 27)
  793. def test_pipe2(self):
  794. self.assertRaises(TypeError, os.pipe2, 'DEADBEEF')
  795. self.assertRaises(TypeError, os.pipe2, 0, 0)
  796. # try calling with flags = 0, like os.pipe()
  797. r, w = os.pipe2(0)
  798. os.close(r)
  799. os.close(w)
  800. # test flags
  801. r, w = os.pipe2(os.O_CLOEXEC|os.O_NONBLOCK)
  802. self.addCleanup(os.close, r)
  803. self.addCleanup(os.close, w)
  804. self.assertFalse(os.get_inheritable(r))
  805. self.assertFalse(os.get_inheritable(w))
  806. self.assertFalse(os.get_blocking(r))
  807. self.assertFalse(os.get_blocking(w))
  808. # try reading from an empty pipe: this should fail, not block
  809. self.assertRaises(OSError, os.read, r, 1)
  810. # try a write big enough to fill-up the pipe: this should either
  811. # fail or perform a partial write, not block
  812. try:
  813. os.write(w, b'x' * support.PIPE_MAX_SIZE)
  814. except OSError:
  815. pass
  816. @support.cpython_only
  817. @unittest.skipUnless(hasattr(os, 'pipe2'), "test needs os.pipe2()")
  818. @support.requires_linux_version(2, 6, 27)
  819. def test_pipe2_c_limits(self):
  820. # Issue 15989
  821. import _testcapi
  822. self.assertRaises(OverflowError, os.pipe2, _testcapi.INT_MAX + 1)
  823. self.assertRaises(OverflowError, os.pipe2, _testcapi.UINT_MAX + 1)
  824. @unittest.skipUnless(hasattr(posix, 'utime'), 'test needs posix.utime()')
  825. def test_utime(self):
  826. now = time.time()
  827. posix.utime(os_helper.TESTFN, None)
  828. self.assertRaises(TypeError, posix.utime,
  829. os_helper.TESTFN, (None, None))
  830. self.assertRaises(TypeError, posix.utime,
  831. os_helper.TESTFN, (now, None))
  832. self.assertRaises(TypeError, posix.utime,
  833. os_helper.TESTFN, (None, now))
  834. posix.utime(os_helper.TESTFN, (int(now), int(now)))
  835. posix.utime(os_helper.TESTFN, (now, now))
  836. def _test_chflags_regular_file(self, chflags_func, target_file, **kwargs):
  837. st = os.stat(target_file)
  838. self.assertTrue(hasattr(st, 'st_flags'))
  839. # ZFS returns EOPNOTSUPP when attempting to set flag UF_IMMUTABLE.
  840. flags = st.st_flags | stat.UF_IMMUTABLE
  841. try:
  842. chflags_func(target_file, flags, **kwargs)
  843. except OSError as err:
  844. if err.errno != errno.EOPNOTSUPP:
  845. raise
  846. msg = 'chflag UF_IMMUTABLE not supported by underlying fs'
  847. self.skipTest(msg)
  848. try:
  849. new_st = os.stat(target_file)
  850. self.assertEqual(st.st_flags | stat.UF_IMMUTABLE, new_st.st_flags)
  851. try:
  852. fd = open(target_file, 'w+')
  853. except OSError as e:
  854. self.assertEqual(e.errno, errno.EPERM)
  855. finally:
  856. posix.chflags(target_file, st.st_flags)
  857. @unittest.skipUnless(hasattr(posix, 'chflags'), 'test needs os.chflags()')
  858. def test_chflags(self):
  859. self._test_chflags_regular_file(posix.chflags, os_helper.TESTFN)
  860. @unittest.skipUnless(hasattr(posix, 'lchflags'), 'test needs os.lchflags()')
  861. def test_lchflags_regular_file(self):
  862. self._test_chflags_regular_file(posix.lchflags, os_helper.TESTFN)
  863. self._test_chflags_regular_file(posix.chflags, os_helper.TESTFN,
  864. follow_symlinks=False)
  865. @unittest.skipUnless(hasattr(posix, 'lchflags'), 'test needs os.lchflags()')
  866. def test_lchflags_symlink(self):
  867. testfn_st = os.stat(os_helper.TESTFN)
  868. self.assertTrue(hasattr(testfn_st, 'st_flags'))
  869. self.addCleanup(os_helper.unlink, _DUMMY_SYMLINK)
  870. os.symlink(os_helper.TESTFN, _DUMMY_SYMLINK)
  871. dummy_symlink_st = os.lstat(_DUMMY_SYMLINK)
  872. def chflags_nofollow(path, flags):
  873. return posix.chflags(path, flags, follow_symlinks=False)
  874. for fn in (posix.lchflags, chflags_nofollow):
  875. # ZFS returns EOPNOTSUPP when attempting to set flag UF_IMMUTABLE.
  876. flags = dummy_symlink_st.st_flags | stat.UF_IMMUTABLE
  877. try:
  878. fn(_DUMMY_SYMLINK, flags)
  879. except OSError as err:
  880. if err.errno != errno.EOPNOTSUPP:
  881. raise
  882. msg = 'chflag UF_IMMUTABLE not supported by underlying fs'
  883. self.skipTest(msg)
  884. try:
  885. new_testfn_st = os.stat(os_helper.TESTFN)
  886. new_dummy_symlink_st = os.lstat(_DUMMY_SYMLINK)
  887. self.assertEqual(testfn_st.st_flags, new_testfn_st.st_flags)
  888. self.assertEqual(dummy_symlink_st.st_flags | stat.UF_IMMUTABLE,
  889. new_dummy_symlink_st.st_flags)
  890. finally:
  891. fn(_DUMMY_SYMLINK, dummy_symlink_st.st_flags)
  892. def test_environ(self):
  893. if os.name == "nt":
  894. item_type = str
  895. else:
  896. item_type = bytes
  897. for k, v in posix.environ.items():
  898. self.assertEqual(type(k), item_type)
  899. self.assertEqual(type(v), item_type)
  900. def test_putenv(self):
  901. with self.assertRaises(ValueError):
  902. os.putenv('FRUIT\0VEGETABLE', 'cabbage')
  903. with self.assertRaises(ValueError):
  904. os.putenv(b'FRUIT\0VEGETABLE', b'cabbage')
  905. with self.assertRaises(ValueError):
  906. os.putenv('FRUIT', 'orange\0VEGETABLE=cabbage')
  907. with self.assertRaises(ValueError):
  908. os.putenv(b'FRUIT', b'orange\0VEGETABLE=cabbage')
  909. with self.assertRaises(ValueError):
  910. os.putenv('FRUIT=ORANGE', 'lemon')
  911. with self.assertRaises(ValueError):
  912. os.putenv(b'FRUIT=ORANGE', b'lemon')
  913. @unittest.skipUnless(hasattr(posix, 'getcwd'), 'test needs posix.getcwd()')
  914. def test_getcwd_long_pathnames(self):
  915. dirname = 'getcwd-test-directory-0123456789abcdef-01234567890abcdef'
  916. curdir = os.getcwd()
  917. base_path = os.path.abspath(os_helper.TESTFN) + '.getcwd'
  918. try:
  919. os.mkdir(base_path)
  920. os.chdir(base_path)
  921. except:
  922. # Just returning nothing instead of the SkipTest exception, because
  923. # the test results in Error in that case. Is that ok?
  924. # raise unittest.SkipTest("cannot create directory for testing")
  925. return
  926. def _create_and_do_getcwd(dirname, current_path_length = 0):
  927. try:
  928. os.mkdir(dirname)
  929. except:
  930. raise unittest.SkipTest("mkdir cannot create directory sufficiently deep for getcwd test")
  931. os.chdir(dirname)
  932. try:
  933. os.getcwd()
  934. if current_path_length < 1027:
  935. _create_and_do_getcwd(dirname, current_path_length + len(dirname) + 1)
  936. finally:
  937. os.chdir('..')
  938. os.rmdir(dirname)
  939. _create_and_do_getcwd(dirname)
  940. finally:
  941. os.chdir(curdir)
  942. os_helper.rmtree(base_path)
  943. @unittest.skipUnless(hasattr(posix, 'getgrouplist'), "test needs posix.getgrouplist()")
  944. @unittest.skipUnless(hasattr(pwd, 'getpwuid'), "test needs pwd.getpwuid()")
  945. @unittest.skipUnless(hasattr(os, 'getuid'), "test needs os.getuid()")
  946. def test_getgrouplist(self):
  947. user = pwd.getpwuid(os.getuid())[0]
  948. group = pwd.getpwuid(os.getuid())[3]
  949. self.assertIn(group, posix.getgrouplist(user, group))
  950. @unittest.skipUnless(hasattr(os, 'getegid'), "test needs os.getegid()")
  951. @unittest.skipUnless(hasattr(os, 'popen'), "test needs os.popen()")
  952. @support.requires_subprocess()
  953. def test_getgroups(self):
  954. with os.popen('id -G 2>/dev/null') as idg:
  955. groups = idg.read().strip()
  956. ret = idg.close()
  957. try:
  958. idg_groups = set(int(g) for g in groups.split())
  959. except ValueError:
  960. idg_groups = set()
  961. if ret is not None or not idg_groups:
  962. raise unittest.SkipTest("need working 'id -G'")
  963. # Issues 16698: OS X ABIs prior to 10.6 have limits on getgroups()
  964. if sys.platform == 'darwin':
  965. import sysconfig
  966. dt = sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET') or '10.3'
  967. if tuple(int(n) for n in dt.split('.')[0:2]) < (10, 6):
  968. raise unittest.SkipTest("getgroups(2) is broken prior to 10.6")
  969. # 'id -G' and 'os.getgroups()' should return the same
  970. # groups, ignoring order, duplicates, and the effective gid.
  971. # #10822/#26944 - It is implementation defined whether
  972. # posix.getgroups() includes the effective gid.
  973. symdiff = idg_groups.symmetric_difference(posix.getgroups())
  974. self.assertTrue(not symdiff or symdiff == {posix.getegid()})
  975. @unittest.skipUnless(hasattr(signal, 'SIGCHLD'), 'CLD_XXXX be placed in si_code for a SIGCHLD signal')
  976. @unittest.skipUnless(hasattr(os, 'waitid_result'), "test needs os.waitid_result")
  977. def test_cld_xxxx_constants(self):
  978. os.CLD_EXITED
  979. os.CLD_KILLED
  980. os.CLD_DUMPED
  981. os.CLD_TRAPPED
  982. os.CLD_STOPPED
  983. os.CLD_CONTINUED
  984. requires_sched_h = unittest.skipUnless(hasattr(posix, 'sched_yield'),
  985. "don't have scheduling support")
  986. requires_sched_affinity = unittest.skipUnless(hasattr(posix, 'sched_setaffinity'),
  987. "don't have sched affinity support")
  988. @requires_sched_h
  989. def test_sched_yield(self):
  990. # This has no error conditions (at least on Linux).
  991. posix.sched_yield()
  992. @requires_sched_h
  993. @unittest.skipUnless(hasattr(posix, 'sched_get_priority_max'),
  994. "requires sched_get_priority_max()")
  995. def test_sched_priority(self):
  996. # Round-robin usually has interesting priorities.
  997. pol = posix.SCHED_RR
  998. lo = posix.sched_get_priority_min(pol)
  999. hi = posix.sched_get_priority_max(pol)
  1000. self.assertIsInstance(lo, int)
  1001. self.assertIsInstance(hi, int)
  1002. self.assertGreaterEqual(hi, lo)
  1003. # OSX evidently just returns 15 without checking the argument.
  1004. if sys.platform != "darwin":
  1005. self.assertRaises(OSError, posix.sched_get_priority_min, -23)
  1006. self.assertRaises(OSError, posix.sched_get_priority_max, -23)
  1007. @requires_sched
  1008. def test_get_and_set_scheduler_and_param(self):
  1009. possible_schedulers = [sched for name, sched in posix.__dict__.items()
  1010. if name.startswith("SCHED_")]
  1011. mine = posix.sched_getscheduler(0)
  1012. self.assertIn(mine, possible_schedulers)
  1013. try:
  1014. parent = posix.sched_getscheduler(os.getppid())
  1015. except OSError as e:
  1016. if e.errno != errno.EPERM:
  1017. raise
  1018. else:
  1019. self.assertIn(parent, possible_schedulers)
  1020. self.assertRaises(OSError, posix.sched_getscheduler, -1)
  1021. self.assertRaises(OSError, posix.sched_getparam, -1)
  1022. param = posix.sched_getparam(0)
  1023. self.assertIsInstance(param.sched_priority, int)
  1024. # POSIX states that calling sched_setparam() or sched_setscheduler() on
  1025. # a process with a scheduling policy other than SCHED_FIFO or SCHED_RR
  1026. # is implementation-defined: NetBSD and FreeBSD can return EINVAL.
  1027. if not sys.platform.startswith(('freebsd', 'netbsd')):
  1028. try:
  1029. posix.sched_setscheduler(0, mine, param)
  1030. posix.sched_setparam(0, param)
  1031. except OSError as e:
  1032. if e.errno != errno.EPERM:
  1033. raise
  1034. self.assertRaises(OSError, posix.sched_setparam, -1, param)
  1035. self.assertRaises(OSError, posix.sched_setscheduler, -1, mine, param)
  1036. self.assertRaises(TypeError, posix.sched_setscheduler, 0, mine, None)
  1037. self.assertRaises(TypeError, posix.sched_setparam, 0, 43)
  1038. param = posix.sched_param(None)
  1039. self.assertRaises(TypeError, posix.sched_setparam, 0, param)
  1040. large = 214748364700
  1041. param = posix.sched_param(large)
  1042. self.assertRaises(OverflowError, posix.sched_setparam, 0, param)
  1043. param = posix.sched_param(sched_priority=-large)
  1044. self.assertRaises(OverflowError, posix.sched_setparam, 0, param)
  1045. @unittest.skipUnless(hasattr(posix, "sched_rr_get_interval"), "no function")
  1046. def test_sched_rr_get_interval(self):
  1047. try:
  1048. interval = posix.sched_rr_get_interval(0)
  1049. except OSError as e:
  1050. # This likely means that sched_rr_get_interval is only valid for
  1051. # processes with the SCHED_RR scheduler in effect.
  1052. if e.errno != errno.EINVAL:
  1053. raise
  1054. self.skipTest("only works on SCHED_RR processes")
  1055. self.assertIsInstance(interval, float)
  1056. # Reasonable constraints, I think.
  1057. self.assertGreaterEqual(interval, 0.)
  1058. self.assertLess(interval, 1.)
  1059. @requires_sched_affinity
  1060. def test_sched_getaffinity(self):
  1061. mask = posix.sched_getaffinity(0)
  1062. self.assertIsInstance(mask, set)
  1063. self.assertGreaterEqual(len(mask), 1)
  1064. if not sys.platform.startswith("freebsd"):
  1065. # bpo-47205: does not raise OSError on FreeBSD
  1066. self.assertRaises(OSError, posix.sched_getaffinity, -1)
  1067. for cpu in mask:
  1068. self.assertIsInstance(cpu, int)
  1069. self.assertGreaterEqual(cpu, 0)
  1070. self.assertLess(cpu, 1 << 32)
  1071. @requires_sched_affinity
  1072. def test_sched_setaffinity(self):
  1073. mask = posix.sched_getaffinity(0)
  1074. if len(mask) > 1:
  1075. # Empty masks are forbidden
  1076. mask.pop()
  1077. posix.sched_setaffinity(0, mask)
  1078. self.assertEqual(posix.sched_getaffinity(0), mask)
  1079. self.assertRaises(OSError, posix.sched_setaffinity, 0, [])
  1080. self.assertRaises(ValueError, posix.sched_setaffinity, 0, [-10])
  1081. self.assertRaises(ValueError, posix.sched_setaffinity, 0, map(int, "0X"))
  1082. self.assertRaises(OverflowError, posix.sched_setaffinity, 0, [1<<128])
  1083. if not sys.platform.startswith("freebsd"):
  1084. # bpo-47205: does not raise OSError on FreeBSD
  1085. self.assertRaises(OSError, posix.sched_setaffinity, -1, mask)
  1086. @unittest.skipIf(support.is_wasi, "No dynamic linking on WASI")
  1087. def test_rtld_constants(self):
  1088. # check presence of major RTLD_* constants
  1089. posix.RTLD_LAZY
  1090. posix.RTLD_NOW
  1091. posix.RTLD_GLOBAL
  1092. posix.RTLD_LOCAL
  1093. @unittest.skipUnless(hasattr(os, 'SEEK_HOLE'),
  1094. "test needs an OS that reports file holes")
  1095. def test_fs_holes(self):
  1096. # Even if the filesystem doesn't report holes,
  1097. # if the OS supports it the SEEK_* constants
  1098. # will be defined and will have a consistent
  1099. # behaviour:
  1100. # os.SEEK_DATA = current position
  1101. # os.SEEK_HOLE = end of file position
  1102. with open(os_helper.TESTFN, 'r+b') as fp:
  1103. fp.write(b"hello")
  1104. fp.flush()
  1105. size = fp.tell()
  1106. fno = fp.fileno()
  1107. try :
  1108. for i in range(size):
  1109. self.assertEqual(i, os.lseek(fno, i, os.SEEK_DATA))
  1110. self.assertLessEqual(size, os.lseek(fno, i, os.SEEK_HOLE))
  1111. self.assertRaises(OSError, os.lseek, fno, size, os.SEEK_DATA)
  1112. self.assertRaises(OSError, os.lseek, fno, size, os.SEEK_HOLE)
  1113. except OSError :
  1114. # Some OSs claim to support SEEK_HOLE/SEEK_DATA
  1115. # but it is not true.
  1116. # For instance:
  1117. # http://lists.freebsd.org/pipermail/freebsd-amd64/2012-January/014332.html
  1118. raise unittest.SkipTest("OSError raised!")
  1119. def test_path_error2(self):
  1120. """
  1121. Test functions that call path_error2(), providing two filenames in their exceptions.
  1122. """
  1123. for name in ("rename", "replace", "link"):
  1124. function = getattr(os, name, None)
  1125. if function is None:
  1126. continue
  1127. for dst in ("noodly2", os_helper.TESTFN):
  1128. try:
  1129. function('doesnotexistfilename', dst)
  1130. except OSError as e:
  1131. self.assertIn("'doesnotexistfilename' -> '{}'".format(dst), str(e))
  1132. break
  1133. else:
  1134. self.fail("No valid path_error2() test for os." + name)
  1135. def test_path_with_null_character(self):
  1136. fn = os_helper.TESTFN
  1137. fn_with_NUL = fn + '\0'
  1138. self.addCleanup(os_helper.unlink, fn)
  1139. os_helper.unlink(fn)
  1140. fd = None
  1141. try:
  1142. with self.assertRaises(ValueError):
  1143. fd = os.open(fn_with_NUL, os.O_WRONLY | os.O_CREAT) # raises
  1144. finally:
  1145. if fd is not None:
  1146. os.close(fd)
  1147. self.assertFalse(os.path.exists(fn))
  1148. self.assertRaises(ValueError, os.mkdir, fn_with_NUL)
  1149. self.assertFalse(os.path.exists(fn))
  1150. open(fn, 'wb').close()
  1151. self.assertRaises(ValueError, os.stat, fn_with_NUL)
  1152. def test_path_with_null_byte(self):
  1153. fn = os.fsencode(os_helper.TESTFN)
  1154. fn_with_NUL = fn + b'\0'
  1155. self.addCleanup(os_helper.unlink, fn)
  1156. os_helper.unlink(fn)
  1157. fd = None
  1158. try:
  1159. with self.assertRaises(ValueError):
  1160. fd = os.open(fn_with_NUL, os.O_WRONLY | os.O_CREAT) # raises
  1161. finally:
  1162. if fd is not None:
  1163. os.close(fd)
  1164. self.assertFalse(os.path.exists(fn))
  1165. self.assertRaises(ValueError, os.mkdir, fn_with_NUL)
  1166. self.assertFalse(os.path.exists(fn))
  1167. open(fn, 'wb').close()
  1168. self.assertRaises(ValueError, os.stat, fn_with_NUL)
  1169. @unittest.skipUnless(hasattr(os, "pidfd_open"), "pidfd_open unavailable")
  1170. def test_pidfd_open(self):
  1171. with self.assertRaises(OSError) as cm:
  1172. os.pidfd_open(-1)
  1173. if cm.exception.errno == errno.ENOSYS:
  1174. self.skipTest("system does not support pidfd_open")
  1175. if isinstance(cm.exception, PermissionError):
  1176. self.skipTest(f"pidfd_open syscall blocked: {cm.exception!r}")
  1177. self.assertEqual(cm.exception.errno, errno.EINVAL)
  1178. os.close(os.pidfd_open(os.getpid(), 0))
  1179. # tests for the posix *at functions follow
  1180. class TestPosixDirFd(unittest.TestCase):
  1181. count = 0
  1182. @contextmanager
  1183. def prepare(self):
  1184. TestPosixDirFd.count += 1
  1185. name = f'{os_helper.TESTFN}_{self.count}'
  1186. base_dir = f'{os_helper.TESTFN}_{self.count}base'
  1187. posix.mkdir(base_dir)
  1188. self.addCleanup(posix.rmdir, base_dir)
  1189. fullname = os.path.join(base_dir, name)
  1190. assert not os.path.exists(fullname)
  1191. with os_helper.open_dir_fd(base_dir) as dir_fd:
  1192. yield (dir_fd, name, fullname)
  1193. @contextmanager
  1194. def prepare_file(self):
  1195. with self.prepare() as (dir_fd, name, fullname):
  1196. os_helper.create_empty_file(fullname)
  1197. self.addCleanup(posix.unlink, fullname)
  1198. yield (dir_fd, name, fullname)
  1199. @unittest.skipUnless(os.access in os.supports_dir_fd, "test needs dir_fd support for os.access()")
  1200. def test_access_dir_fd(self):
  1201. with self.prepare_file() as (dir_fd, name, fullname):
  1202. self.assertTrue(posix.access(name, os.R_OK, dir_fd=dir_fd))
  1203. @unittest.skipUnless(os.chmod in os.supports_dir_fd, "test needs dir_fd support in os.chmod()")
  1204. def test_chmod_dir_fd(self):
  1205. with self.prepare_file() as (dir_fd, name, fullname):
  1206. posix.chmod(fullname, stat.S_IRUSR)
  1207. posix.chmod(name, stat.S_IRUSR | stat.S_IWUSR, dir_fd=dir_fd)
  1208. s = posix.stat(fullname)
  1209. self.assertEqual(s.st_mode & stat.S_IRWXU,
  1210. stat.S_IRUSR | stat.S_IWUSR)
  1211. @unittest.skipUnless(hasattr(os, 'chown') and (os.chown in os.supports_dir_fd),
  1212. "test needs dir_fd support in os.chown()")
  1213. @unittest.skipIf(support.is_emscripten, "getgid() is a stub")
  1214. def test_chown_dir_fd(self):
  1215. with self.prepare_file() as (dir_fd, name, fullname):
  1216. posix.chown(name, os.getuid(), os.getgid(), dir_fd=dir_fd)
  1217. @unittest.skipUnless(os.stat in os.supports_dir_fd, "test needs dir_fd support in os.stat()")
  1218. def test_stat_dir_fd(self):
  1219. with self.prepare() as (dir_fd, name, fullname):
  1220. with open(fullname, 'w') as outfile:
  1221. outfile.write("testline\n")
  1222. self.addCleanup(posix.unlink, fullname)
  1223. s1 = posix.stat(fullname)
  1224. s2 = posix.stat(name, dir_fd=dir_fd)
  1225. self.assertEqual(s1, s2)
  1226. s2 = posix.stat(fullname, dir_fd=None)
  1227. self.assertEqual(s1, s2)
  1228. self.assertRaisesRegex(TypeError, 'should be integer or None, not',
  1229. posix.stat, name, dir_fd=posix.getcwd())
  1230. self.assertRaisesRegex(TypeError, 'should be integer or None, not',
  1231. posix.stat, name, dir_fd=float(dir_fd))
  1232. self.assertRaises(OverflowError,
  1233. posix.stat, name, dir_fd=10**20)
  1234. @unittest.skipUnless(os.utime in os.supports_dir_fd, "test needs dir_fd support in os.utime()")
  1235. def test_utime_dir_fd(self):
  1236. with self.prepare_file() as (dir_fd, name, fullname):
  1237. now = time.time()
  1238. posix.utime(name, None, dir_fd=dir_fd)
  1239. posix.utime(name, dir_fd=dir_fd)
  1240. self.assertRaises(TypeError, posix.utime, name,
  1241. now, dir_fd=dir_fd)
  1242. self.assertRaises(TypeError, posix.utime, name,
  1243. (None, None), dir_fd=dir_fd)
  1244. self.assertRaises(TypeError, posix.utime, name,
  1245. (now, None), dir_fd=dir_fd)
  1246. self.assertRaises(TypeError, posix.utime, name,
  1247. (None, now), dir_fd=dir_fd)
  1248. self.assertRaises(TypeError, posix.utime, name,
  1249. (now, "x"), dir_fd=dir_fd)
  1250. posix.utime(name, (int(now), int(now)), dir_fd=dir_fd)
  1251. posix.utime(name, (now, now), dir_fd=dir_fd)
  1252. posix.utime(name,
  1253. (int(now), int((now - int(now)) * 1e9)), dir_fd=dir_fd)
  1254. posix.utime(name, dir_fd=dir_fd,
  1255. times=(int(now), int((now - int(now)) * 1e9)))
  1256. # try dir_fd and follow_symlinks together
  1257. if os.utime in os.supports_follow_symlinks:
  1258. try:
  1259. posix.utime(name, follow_symlinks=False, dir_fd=dir_fd)
  1260. except ValueError:
  1261. # whoops! using both together not supported on this platform.
  1262. pass
  1263. @unittest.skipIf(
  1264. support.is_wasi,
  1265. "WASI: symlink following on path_link is not supported"
  1266. )
  1267. @unittest.skipUnless(
  1268. hasattr(os, "link") and os.link in os.supports_dir_fd,
  1269. "test needs dir_fd support in os.link()"
  1270. )
  1271. def test_link_dir_fd(self):
  1272. with self.prepare_file() as (dir_fd, name, fullname), \
  1273. self.prepare() as (dir_fd2, linkname, fulllinkname):
  1274. try:
  1275. posix.link(name, linkname, src_dir_fd=dir_fd, dst_dir_fd=dir_fd2)
  1276. except PermissionError as e:
  1277. self.skipTest('posix.link(): %s' % e)
  1278. self.addCleanup(posix.unlink, fulllinkname)
  1279. # should have same inodes
  1280. self.assertEqual(posix.stat(fullname)[1],
  1281. posix.stat(fulllinkname)[1])
  1282. @unittest.skipUnless(os.mkdir in os.supports_dir_fd, "test needs dir_fd support in os.mkdir()")
  1283. def test_mkdir_dir_fd(self):
  1284. with self.prepare() as (dir_fd, name, fullname):
  1285. posix.mkdir(name, dir_fd=dir_fd)
  1286. self.addCleanup(posix.rmdir, fullname)
  1287. posix.stat(fullname) # should not raise exception
  1288. @unittest.skipUnless(hasattr(os, 'mknod')
  1289. and (os.mknod in os.supports_dir_fd)
  1290. and hasattr(stat, 'S_IFIFO'),
  1291. "test requires both stat.S_IFIFO and dir_fd support for os.mknod()")
  1292. def test_mknod_dir_fd(self):
  1293. # Test using mknodat() to create a FIFO (the only use specified
  1294. # by POSIX).
  1295. with self.prepare() as (dir_fd, name, fullname):
  1296. mode = stat.S_IFIFO | stat.S_IRUSR | stat.S_IWUSR
  1297. try:
  1298. posix.mknod(name, mode, 0, dir_fd=dir_fd)
  1299. except OSError as e:
  1300. # Some old systems don't allow unprivileged users to use
  1301. # mknod(), or only support creating device nodes.
  1302. self.assertIn(e.errno, (errno.EPERM, errno.EINVAL, errno.EACCES))
  1303. else:
  1304. self.addCleanup(posix.unlink, fullname)
  1305. self.assertTrue(stat.S_ISFIFO(posix.stat(fullname).st_mode))
  1306. @unittest.skipUnless(os.open in os.supports_dir_fd, "test needs dir_fd support in os.open()")
  1307. def test_open_dir_fd(self):
  1308. with self.prepare() as (dir_fd, name, fullname):
  1309. with open(fullname, 'wb') as outfile:
  1310. outfile.write(b"testline\n")
  1311. self.addCleanup(posix.unlink, fullname)
  1312. fd = posix.open(name, posix.O_RDONLY, dir_fd=dir_fd)
  1313. try:
  1314. res = posix.read(fd, 9)
  1315. self.assertEqual(b"testline\n", res)
  1316. finally:
  1317. posix.close(fd)
  1318. @unittest.skipUnless(hasattr(os, 'readlink') and (os.readlink in os.supports_dir_fd),
  1319. "test needs dir_fd support in os.readlink()")
  1320. def test_readlink_dir_fd(self):
  1321. with self.prepare() as (dir_fd, name, fullname):
  1322. os.symlink('symlink', fullname)
  1323. self.addCleanup(posix.unlink, fullname)
  1324. self.assertEqual(posix.readlink(name, dir_fd=dir_fd), 'symlink')
  1325. @unittest.skipUnless(os.rename in os.supports_dir_fd, "test needs dir_fd support in os.rename()")
  1326. def test_rename_dir_fd(self):
  1327. with self.prepare_file() as (dir_fd, name, fullname), \
  1328. self.prepare() as (dir_fd2, name2, fullname2):
  1329. posix.rename(name, name2,
  1330. src_dir_fd=dir_fd, dst_dir_fd=dir_fd2)
  1331. posix.stat(fullname2) # should not raise exception
  1332. posix.rename(fullname2, fullname)
  1333. @unittest.skipUnless(os.symlink in os.supports_dir_fd, "test needs dir_fd support in os.symlink()")
  1334. def test_symlink_dir_fd(self):
  1335. with self.prepare() as (dir_fd, name, fullname):
  1336. posix.symlink('symlink', name, dir_fd=dir_fd)
  1337. self.addCleanup(posix.unlink, fullname)
  1338. self.assertEqual(posix.readlink(fullname), 'symlink')
  1339. @unittest.skipUnless(os.unlink in os.supports_dir_fd, "test needs dir_fd support in os.unlink()")
  1340. def test_unlink_dir_fd(self):
  1341. with self.prepare() as (dir_fd, name, fullname):
  1342. os_helper.create_empty_file(fullname)
  1343. posix.stat(fullname) # should not raise exception
  1344. try:
  1345. posix.unlink(name, dir_fd=dir_fd)
  1346. self.assertRaises(OSError, posix.stat, fullname)
  1347. except:
  1348. self.addCleanup(posix.unlink, fullname)
  1349. raise
  1350. @unittest.skipUnless(hasattr(os, 'mkfifo') and os.mkfifo in os.supports_dir_fd, "test needs dir_fd support in os.mkfifo()")
  1351. def test_mkfifo_dir_fd(self):
  1352. with self.prepare() as (dir_fd, name, fullname):
  1353. try:
  1354. posix.mkfifo(name, stat.S_IRUSR | stat.S_IWUSR, dir_fd=dir_fd)
  1355. except PermissionError as e:
  1356. self.skipTest('posix.mkfifo(): %s' % e)
  1357. self.addCleanup(posix.unlink, fullname)
  1358. self.assertTrue(stat.S_ISFIFO(posix.stat(fullname).st_mode))
  1359. class PosixGroupsTester(unittest.TestCase):
  1360. def setUp(self):
  1361. if posix.getuid() != 0:
  1362. raise unittest.SkipTest("not enough privileges")
  1363. if not hasattr(posix, 'getgroups'):
  1364. raise unittest.SkipTest("need posix.getgroups")
  1365. if sys.platform == 'darwin':
  1366. raise unittest.SkipTest("getgroups(2) is broken on OSX")
  1367. self.saved_groups = posix.getgroups()
  1368. def tearDown(self):
  1369. if hasattr(posix, 'setgroups'):
  1370. posix.setgroups(self.saved_groups)
  1371. elif hasattr(posix, 'initgroups'):
  1372. name = pwd.getpwuid(posix.getuid()).pw_name
  1373. posix.initgroups(name, self.saved_groups[0])
  1374. @unittest.skipUnless(hasattr(posix, 'initgroups'),
  1375. "test needs posix.initgroups()")
  1376. def test_initgroups(self):
  1377. # find missing group
  1378. g = max(self.saved_groups or [0]) + 1
  1379. name = pwd.getpwuid(posix.getuid()).pw_name
  1380. posix.initgroups(name, g)
  1381. self.assertIn(g, posix.getgroups())
  1382. @unittest.skipUnless(hasattr(posix, 'setgroups'),
  1383. "test needs posix.setgroups()")
  1384. def test_setgroups(self):
  1385. for groups in [[0], list(range(16))]:
  1386. posix.setgroups(groups)
  1387. self.assertListEqual(groups, posix.getgroups())
  1388. class _PosixSpawnMixin:
  1389. # Program which does nothing and exits with status 0 (success)
  1390. NOOP_PROGRAM = (sys.executable, '-I', '-S', '-c', 'pass')
  1391. spawn_func = None
  1392. def python_args(self, *args):
  1393. # Disable site module to avoid side effects. For example,
  1394. # on Fedora 28, if the HOME environment variable is not set,
  1395. # site._getuserbase() calls pwd.getpwuid() which opens
  1396. # /var/lib/sss/mc/passwd but then leaves the file open which makes
  1397. # test_close_file() to fail.
  1398. return (sys.executable, '-I', '-S', *args)
  1399. def test_returns_pid(self):
  1400. pidfile = os_helper.TESTFN
  1401. self.addCleanup(os_helper.unlink, pidfile)
  1402. script = f"""if 1:
  1403. import os
  1404. with open({pidfile!r}, "w") as pidfile:
  1405. pidfile.write(str(os.getpid()))
  1406. """
  1407. args = self.python_args('-c', script)
  1408. pid = self.spawn_func(args[0], args, os.environ)
  1409. support.wait_process(pid, exitcode=0)
  1410. with open(pidfile, encoding="utf-8") as f:
  1411. self.assertEqual(f.read(), str(pid))
  1412. def test_no_such_executable(self):
  1413. no_such_executable = 'no_such_executable'
  1414. try:
  1415. pid = self.spawn_func(no_such_executable,
  1416. [no_such_executable],
  1417. os.environ)
  1418. # bpo-35794: PermissionError can be raised if there are
  1419. # directories in the $PATH that are not accessible.
  1420. except (FileNotFoundError, PermissionError) as exc:
  1421. self.assertEqual(exc.filename, no_such_executable)
  1422. else:
  1423. pid2, status = os.waitpid(pid, 0)
  1424. self.assertEqual(pid2, pid)
  1425. self.assertNotEqual(status, 0)
  1426. def test_specify_environment(self):
  1427. envfile = os_helper.TESTFN
  1428. self.addCleanup(os_helper.unlink, envfile)
  1429. script = f"""if 1:
  1430. import os
  1431. with open({envfile!r}, "w", encoding="utf-8") as envfile:
  1432. envfile.write(os.environ['foo'])
  1433. """
  1434. args = self.python_args('-c', script)
  1435. pid = self.spawn_func(args[0], args,
  1436. {**os.environ, 'foo': 'bar'})
  1437. support.wait_process(pid, exitcode=0)
  1438. with open(envfile, encoding="utf-8") as f:
  1439. self.assertEqual(f.read(), 'bar')
  1440. def test_none_file_actions(self):
  1441. pid = self.spawn_func(
  1442. self.NOOP_PROGRAM[0],
  1443. self.NOOP_PROGRAM,
  1444. os.environ,
  1445. file_actions=None
  1446. )
  1447. support.wait_process(pid, exitcode=0)
  1448. def test_empty_file_actions(self):
  1449. pid = self.spawn_func(
  1450. self.NOOP_PROGRAM[0],
  1451. self.NOOP_PROGRAM,
  1452. os.environ,
  1453. file_actions=[]
  1454. )
  1455. support.wait_process(pid, exitcode=0)
  1456. def test_resetids_explicit_default(self):
  1457. pid = self.spawn_func(
  1458. sys.executable,
  1459. [sys.executable, '-c', 'pass'],
  1460. os.environ,
  1461. resetids=False
  1462. )
  1463. support.wait_process(pid, exitcode=0)
  1464. def test_resetids(self):
  1465. pid = self.spawn_func(
  1466. sys.executable,
  1467. [sys.executable, '-c', 'pass'],
  1468. os.environ,
  1469. resetids=True
  1470. )
  1471. support.wait_process(pid, exitcode=0)
  1472. def test_resetids_wrong_type(self):
  1473. with self.assertRaises(TypeError):
  1474. self.spawn_func(sys.executable,
  1475. [sys.executable, "-c", "pass"],
  1476. os.environ, resetids=None)
  1477. def test_setpgroup(self):
  1478. pid = self.spawn_func(
  1479. sys.executable,
  1480. [sys.executable, '-c', 'pass'],
  1481. os.environ,
  1482. setpgroup=os.getpgrp()
  1483. )
  1484. support.wait_process(pid, exitcode=0)
  1485. def test_setpgroup_wrong_type(self):
  1486. with self.assertRaises(TypeError):
  1487. self.spawn_func(sys.executable,
  1488. [sys.executable, "-c", "pass"],
  1489. os.environ, setpgroup="023")
  1490. @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
  1491. 'need signal.pthread_sigmask()')
  1492. def test_setsigmask(self):
  1493. code = textwrap.dedent("""\
  1494. import signal
  1495. signal.raise_signal(signal.SIGUSR1)""")
  1496. pid = self.spawn_func(
  1497. sys.executable,
  1498. [sys.executable, '-c', code],
  1499. os.environ,
  1500. setsigmask=[signal.SIGUSR1]
  1501. )
  1502. support.wait_process(pid, exitcode=0)
  1503. def test_setsigmask_wrong_type(self):
  1504. with self.assertRaises(TypeError):
  1505. self.spawn_func(sys.executable,
  1506. [sys.executable, "-c", "pass"],
  1507. os.environ, setsigmask=34)
  1508. with self.assertRaises(TypeError):
  1509. self.spawn_func(sys.executable,
  1510. [sys.executable, "-c", "pass"],
  1511. os.environ, setsigmask=["j"])
  1512. with self.assertRaises(ValueError):
  1513. self.spawn_func(sys.executable,
  1514. [sys.executable, "-c", "pass"],
  1515. os.environ, setsigmask=[signal.NSIG,
  1516. signal.NSIG+1])
  1517. def test_setsid(self):
  1518. rfd, wfd = os.pipe()
  1519. self.addCleanup(os.close, rfd)
  1520. try:
  1521. os.set_inheritable(wfd, True)
  1522. code = textwrap.dedent(f"""
  1523. import os
  1524. fd = {wfd}
  1525. sid = os.getsid(0)
  1526. os.write(fd, str(sid).encode())
  1527. """)
  1528. try:
  1529. pid = self.spawn_func(sys.executable,
  1530. [sys.executable, "-c", code],
  1531. os.environ, setsid=True)
  1532. except NotImplementedError as exc:
  1533. self.skipTest(f"setsid is not supported: {exc!r}")
  1534. except PermissionError as exc:
  1535. self.skipTest(f"setsid failed with: {exc!r}")
  1536. finally:
  1537. os.close(wfd)
  1538. support.wait_process(pid, exitcode=0)
  1539. output = os.read(rfd, 100)
  1540. child_sid = int(output)
  1541. parent_sid = os.getsid(os.getpid())
  1542. self.assertNotEqual(parent_sid, child_sid)
  1543. @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),
  1544. 'need signal.pthread_sigmask()')
  1545. def test_setsigdef(self):
  1546. original_handler = signal.signal(signal.SIGUSR1, signal.SIG_IGN)
  1547. code = textwrap.dedent("""\
  1548. import signal
  1549. signal.raise_signal(signal.SIGUSR1)""")
  1550. try:
  1551. pid = self.spawn_func(
  1552. sys.executable,
  1553. [sys.executable, '-c', code],
  1554. os.environ,
  1555. setsigdef=[signal.SIGUSR1]
  1556. )
  1557. finally:
  1558. signal.signal(signal.SIGUSR1, original_handler)
  1559. support.wait_process(pid, exitcode=-signal.SIGUSR1)
  1560. def test_setsigdef_wrong_type(self):
  1561. with self.assertRaises(TypeError):
  1562. self.spawn_func(sys.executable,
  1563. [sys.executable, "-c", "pass"],
  1564. os.environ, setsigdef=34)
  1565. with self.assertRaises(TypeError):
  1566. self.spawn_func(sys.executable,
  1567. [sys.executable, "-c", "pass"],
  1568. os.environ, setsigdef=["j"])
  1569. with self.assertRaises(ValueError):
  1570. self.spawn_func(sys.executable,
  1571. [sys.executable, "-c", "pass"],
  1572. os.environ, setsigdef=[signal.NSIG, signal.NSIG+1])
  1573. @requires_sched
  1574. @unittest.skipIf(sys.platform.startswith(('freebsd', 'netbsd')),
  1575. "bpo-34685: test can fail on BSD")
  1576. def test_setscheduler_only_param(self):
  1577. policy = os.sched_getscheduler(0)
  1578. priority = os.sched_get_priority_min(policy)
  1579. code = textwrap.dedent(f"""\
  1580. import os, sys
  1581. if os.sched_getscheduler(0) != {policy}:
  1582. sys.exit(101)
  1583. if os.sched_getparam(0).sched_priority != {priority}:
  1584. sys.exit(102)""")
  1585. pid = self.spawn_func(
  1586. sys.executable,
  1587. [sys.executable, '-c', code],
  1588. os.environ,
  1589. scheduler=(None, os.sched_param(priority))
  1590. )
  1591. support.wait_process(pid, exitcode=0)
  1592. @requires_sched
  1593. @unittest.skipIf(sys.platform.startswith(('freebsd', 'netbsd')),
  1594. "bpo-34685: test can fail on BSD")
  1595. def test_setscheduler_with_policy(self):
  1596. policy = os.sched_getscheduler(0)
  1597. priority = os.sched_get_priority_min(policy)
  1598. code = textwrap.dedent(f"""\
  1599. import os, sys
  1600. if os.sched_getscheduler(0) != {policy}:
  1601. sys.exit(101)
  1602. if os.sched_getparam(0).sched_priority != {priority}:
  1603. sys.exit(102)""")
  1604. pid = self.spawn_func(
  1605. sys.executable,
  1606. [sys.executable, '-c', code],
  1607. os.environ,
  1608. scheduler=(policy, os.sched_param(priority))
  1609. )
  1610. support.wait_process(pid, exitcode=0)
  1611. def test_multiple_file_actions(self):
  1612. file_actions = [
  1613. (os.POSIX_SPAWN_OPEN, 3, os.path.realpath(__file__), os.O_RDONLY, 0),
  1614. (os.POSIX_SPAWN_CLOSE, 0),
  1615. (os.POSIX_SPAWN_DUP2, 1, 4),
  1616. ]
  1617. pid = self.spawn_func(self.NOOP_PROGRAM[0],
  1618. self.NOOP_PROGRAM,
  1619. os.environ,
  1620. file_actions=file_actions)
  1621. support.wait_process(pid, exitcode=0)
  1622. def test_bad_file_actions(self):
  1623. args = self.NOOP_PROGRAM
  1624. with self.assertRaises(TypeError):
  1625. self.spawn_func(args[0], args, os.environ,
  1626. file_actions=[None])
  1627. with self.assertRaises(TypeError):
  1628. self.spawn_func(args[0], args, os.environ,
  1629. file_actions=[()])
  1630. with self.assertRaises(TypeError):
  1631. self.spawn_func(args[0], args, os.environ,
  1632. file_actions=[(None,)])
  1633. with self.assertRaises(TypeError):
  1634. self.spawn_func(args[0], args, os.environ,
  1635. file_actions=[(12345,)])
  1636. with self.assertRaises(TypeError):
  1637. self.spawn_func(args[0], args, os.environ,
  1638. file_actions=[(os.POSIX_SPAWN_CLOSE,)])
  1639. with self.assertRaises(TypeError):
  1640. self.spawn_func(args[0], args, os.environ,
  1641. file_actions=[(os.POSIX_SPAWN_CLOSE, 1, 2)])
  1642. with self.assertRaises(TypeError):
  1643. self.spawn_func(args[0], args, os.environ,
  1644. file_actions=[(os.POSIX_SPAWN_CLOSE, None)])
  1645. with self.assertRaises(ValueError):
  1646. self.spawn_func(args[0], args, os.environ,
  1647. file_actions=[(os.POSIX_SPAWN_OPEN,
  1648. 3, __file__ + '\0',
  1649. os.O_RDONLY, 0)])
  1650. def test_open_file(self):
  1651. outfile = os_helper.TESTFN
  1652. self.addCleanup(os_helper.unlink, outfile)
  1653. script = """if 1:
  1654. import sys
  1655. sys.stdout.write("hello")
  1656. """
  1657. file_actions = [
  1658. (os.POSIX_SPAWN_OPEN, 1, outfile,
  1659. os.O_WRONLY | os.O_CREAT | os.O_TRUNC,
  1660. stat.S_IRUSR | stat.S_IWUSR),
  1661. ]
  1662. args = self.python_args('-c', script)
  1663. pid = self.spawn_func(args[0], args, os.environ,
  1664. file_actions=file_actions)
  1665. support.wait_process(pid, exitcode=0)
  1666. with open(outfile, encoding="utf-8") as f:
  1667. self.assertEqual(f.read(), 'hello')
  1668. def test_close_file(self):
  1669. closefile = os_helper.TESTFN
  1670. self.addCleanup(os_helper.unlink, closefile)
  1671. script = f"""if 1:
  1672. import os
  1673. try:
  1674. os.fstat(0)
  1675. except OSError as e:
  1676. with open({closefile!r}, 'w', encoding='utf-8') as closefile:
  1677. closefile.write('is closed %d' % e.errno)
  1678. """
  1679. args = self.python_args('-c', script)
  1680. pid = self.spawn_func(args[0], args, os.environ,
  1681. file_actions=[(os.POSIX_SPAWN_CLOSE, 0)])
  1682. support.wait_process(pid, exitcode=0)
  1683. with open(closefile, encoding="utf-8") as f:
  1684. self.assertEqual(f.read(), 'is closed %d' % errno.EBADF)
  1685. def test_dup2(self):
  1686. dupfile = os_helper.TESTFN
  1687. self.addCleanup(os_helper.unlink, dupfile)
  1688. script = """if 1:
  1689. import sys
  1690. sys.stdout.write("hello")
  1691. """
  1692. with open(dupfile, "wb") as childfile:
  1693. file_actions = [
  1694. (os.POSIX_SPAWN_DUP2, childfile.fileno(), 1),
  1695. ]
  1696. args = self.python_args('-c', script)
  1697. pid = self.spawn_func(args[0], args, os.environ,
  1698. file_actions=file_actions)
  1699. support.wait_process(pid, exitcode=0)
  1700. with open(dupfile, encoding="utf-8") as f:
  1701. self.assertEqual(f.read(), 'hello')
  1702. @unittest.skipUnless(hasattr(os, 'posix_spawn'), "test needs os.posix_spawn")
  1703. class TestPosixSpawn(unittest.TestCase, _PosixSpawnMixin):
  1704. spawn_func = getattr(posix, 'posix_spawn', None)
  1705. @unittest.skipUnless(hasattr(os, 'posix_spawnp'), "test needs os.posix_spawnp")
  1706. class TestPosixSpawnP(unittest.TestCase, _PosixSpawnMixin):
  1707. spawn_func = getattr(posix, 'posix_spawnp', None)
  1708. @os_helper.skip_unless_symlink
  1709. def test_posix_spawnp(self):
  1710. # Use a symlink to create a program in its own temporary directory
  1711. temp_dir = tempfile.mkdtemp()
  1712. self.addCleanup(os_helper.rmtree, temp_dir)
  1713. program = 'posix_spawnp_test_program.exe'
  1714. program_fullpath = os.path.join(temp_dir, program)
  1715. os.symlink(sys.executable, program_fullpath)
  1716. try:
  1717. path = os.pathsep.join((temp_dir, os.environ['PATH']))
  1718. except KeyError:
  1719. path = temp_dir # PATH is not set
  1720. spawn_args = (program, '-I', '-S', '-c', 'pass')
  1721. code = textwrap.dedent("""
  1722. import os
  1723. from test import support
  1724. args = %a
  1725. pid = os.posix_spawnp(args[0], args, os.environ)
  1726. support.wait_process(pid, exitcode=0)
  1727. """ % (spawn_args,))
  1728. # Use a subprocess to test os.posix_spawnp() with a modified PATH
  1729. # environment variable: posix_spawnp() uses the current environment
  1730. # to locate the program, not its environment argument.
  1731. args = ('-c', code)
  1732. assert_python_ok(*args, PATH=path)
  1733. @unittest.skipUnless(sys.platform == "darwin", "test weak linking on macOS")
  1734. class TestPosixWeaklinking(unittest.TestCase):
  1735. # These test cases verify that weak linking support on macOS works
  1736. # as expected. These cases only test new behaviour introduced by weak linking,
  1737. # regular behaviour is tested by the normal test cases.
  1738. #
  1739. # See the section on Weak Linking in Mac/README.txt for more information.
  1740. def setUp(self):
  1741. import sysconfig
  1742. import platform
  1743. config_vars = sysconfig.get_config_vars()
  1744. self.available = { nm for nm in config_vars if nm.startswith("HAVE_") and config_vars[nm] }
  1745. self.mac_ver = tuple(int(part) for part in platform.mac_ver()[0].split("."))
  1746. def _verify_available(self, name):
  1747. if name not in self.available:
  1748. raise unittest.SkipTest(f"{name} not weak-linked")
  1749. def test_pwritev(self):
  1750. self._verify_available("HAVE_PWRITEV")
  1751. if self.mac_ver >= (10, 16):
  1752. self.assertTrue(hasattr(os, "pwritev"), "os.pwritev is not available")
  1753. self.assertTrue(hasattr(os, "preadv"), "os.readv is not available")
  1754. else:
  1755. self.assertFalse(hasattr(os, "pwritev"), "os.pwritev is available")
  1756. self.assertFalse(hasattr(os, "preadv"), "os.readv is available")
  1757. def test_stat(self):
  1758. self._verify_available("HAVE_FSTATAT")
  1759. if self.mac_ver >= (10, 10):
  1760. self.assertIn("HAVE_FSTATAT", posix._have_functions)
  1761. else:
  1762. self.assertNotIn("HAVE_FSTATAT", posix._have_functions)
  1763. with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
  1764. os.stat("file", dir_fd=0)
  1765. def test_access(self):
  1766. self._verify_available("HAVE_FACCESSAT")
  1767. if self.mac_ver >= (10, 10):
  1768. self.assertIn("HAVE_FACCESSAT", posix._have_functions)
  1769. else:
  1770. self.assertNotIn("HAVE_FACCESSAT", posix._have_functions)
  1771. with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
  1772. os.access("file", os.R_OK, dir_fd=0)
  1773. with self.assertRaisesRegex(NotImplementedError, "follow_symlinks unavailable"):
  1774. os.access("file", os.R_OK, follow_symlinks=False)
  1775. with self.assertRaisesRegex(NotImplementedError, "effective_ids unavailable"):
  1776. os.access("file", os.R_OK, effective_ids=True)
  1777. def test_chmod(self):
  1778. self._verify_available("HAVE_FCHMODAT")
  1779. if self.mac_ver >= (10, 10):
  1780. self.assertIn("HAVE_FCHMODAT", posix._have_functions)
  1781. else:
  1782. self.assertNotIn("HAVE_FCHMODAT", posix._have_functions)
  1783. self.assertIn("HAVE_LCHMOD", posix._have_functions)
  1784. with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
  1785. os.chmod("file", 0o644, dir_fd=0)
  1786. def test_chown(self):
  1787. self._verify_available("HAVE_FCHOWNAT")
  1788. if self.mac_ver >= (10, 10):
  1789. self.assertIn("HAVE_FCHOWNAT", posix._have_functions)
  1790. else:
  1791. self.assertNotIn("HAVE_FCHOWNAT", posix._have_functions)
  1792. self.assertIn("HAVE_LCHOWN", posix._have_functions)
  1793. with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
  1794. os.chown("file", 0, 0, dir_fd=0)
  1795. def test_link(self):
  1796. self._verify_available("HAVE_LINKAT")
  1797. if self.mac_ver >= (10, 10):
  1798. self.assertIn("HAVE_LINKAT", posix._have_functions)
  1799. else:
  1800. self.assertNotIn("HAVE_LINKAT", posix._have_functions)
  1801. with self.assertRaisesRegex(NotImplementedError, "src_dir_fd unavailable"):
  1802. os.link("source", "target", src_dir_fd=0)
  1803. with self.assertRaisesRegex(NotImplementedError, "dst_dir_fd unavailable"):
  1804. os.link("source", "target", dst_dir_fd=0)
  1805. with self.assertRaisesRegex(NotImplementedError, "src_dir_fd unavailable"):
  1806. os.link("source", "target", src_dir_fd=0, dst_dir_fd=0)
  1807. # issue 41355: !HAVE_LINKAT code path ignores the follow_symlinks flag
  1808. with os_helper.temp_dir() as base_path:
  1809. link_path = os.path.join(base_path, "link")
  1810. target_path = os.path.join(base_path, "target")
  1811. source_path = os.path.join(base_path, "source")
  1812. with open(source_path, "w") as fp:
  1813. fp.write("data")
  1814. os.symlink("target", link_path)
  1815. # Calling os.link should fail in the link(2) call, and
  1816. # should not reject *follow_symlinks* (to match the
  1817. # behaviour you'd get when building on a platform without
  1818. # linkat)
  1819. with self.assertRaises(FileExistsError):
  1820. os.link(source_path, link_path, follow_symlinks=True)
  1821. with self.assertRaises(FileExistsError):
  1822. os.link(source_path, link_path, follow_symlinks=False)
  1823. def test_listdir_scandir(self):
  1824. self._verify_available("HAVE_FDOPENDIR")
  1825. if self.mac_ver >= (10, 10):
  1826. self.assertIn("HAVE_FDOPENDIR", posix._have_functions)
  1827. else:
  1828. self.assertNotIn("HAVE_FDOPENDIR", posix._have_functions)
  1829. with self.assertRaisesRegex(TypeError, "listdir: path should be string, bytes, os.PathLike or None, not int"):
  1830. os.listdir(0)
  1831. with self.assertRaisesRegex(TypeError, "scandir: path should be string, bytes, os.PathLike or None, not int"):
  1832. os.scandir(0)
  1833. def test_mkdir(self):
  1834. self._verify_available("HAVE_MKDIRAT")
  1835. if self.mac_ver >= (10, 10):
  1836. self.assertIn("HAVE_MKDIRAT", posix._have_functions)
  1837. else:
  1838. self.assertNotIn("HAVE_MKDIRAT", posix._have_functions)
  1839. with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
  1840. os.mkdir("dir", dir_fd=0)
  1841. def test_mkfifo(self):
  1842. self._verify_available("HAVE_MKFIFOAT")
  1843. if self.mac_ver >= (13, 0):
  1844. self.assertIn("HAVE_MKFIFOAT", posix._have_functions)
  1845. else:
  1846. self.assertNotIn("HAVE_MKFIFOAT", posix._have_functions)
  1847. with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
  1848. os.mkfifo("path", dir_fd=0)
  1849. def test_mknod(self):
  1850. self._verify_available("HAVE_MKNODAT")
  1851. if self.mac_ver >= (13, 0):
  1852. self.assertIn("HAVE_MKNODAT", posix._have_functions)
  1853. else:
  1854. self.assertNotIn("HAVE_MKNODAT", posix._have_functions)
  1855. with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
  1856. os.mknod("path", dir_fd=0)
  1857. def test_rename_replace(self):
  1858. self._verify_available("HAVE_RENAMEAT")
  1859. if self.mac_ver >= (10, 10):
  1860. self.assertIn("HAVE_RENAMEAT", posix._have_functions)
  1861. else:
  1862. self.assertNotIn("HAVE_RENAMEAT", posix._have_functions)
  1863. with self.assertRaisesRegex(NotImplementedError, "src_dir_fd and dst_dir_fd unavailable"):
  1864. os.rename("a", "b", src_dir_fd=0)
  1865. with self.assertRaisesRegex(NotImplementedError, "src_dir_fd and dst_dir_fd unavailable"):
  1866. os.rename("a", "b", dst_dir_fd=0)
  1867. with self.assertRaisesRegex(NotImplementedError, "src_dir_fd and dst_dir_fd unavailable"):
  1868. os.replace("a", "b", src_dir_fd=0)
  1869. with self.assertRaisesRegex(NotImplementedError, "src_dir_fd and dst_dir_fd unavailable"):
  1870. os.replace("a", "b", dst_dir_fd=0)
  1871. def test_unlink_rmdir(self):
  1872. self._verify_available("HAVE_UNLINKAT")
  1873. if self.mac_ver >= (10, 10):
  1874. self.assertIn("HAVE_UNLINKAT", posix._have_functions)
  1875. else:
  1876. self.assertNotIn("HAVE_UNLINKAT", posix._have_functions)
  1877. with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
  1878. os.unlink("path", dir_fd=0)
  1879. with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
  1880. os.rmdir("path", dir_fd=0)
  1881. def test_open(self):
  1882. self._verify_available("HAVE_OPENAT")
  1883. if self.mac_ver >= (10, 10):
  1884. self.assertIn("HAVE_OPENAT", posix._have_functions)
  1885. else:
  1886. self.assertNotIn("HAVE_OPENAT", posix._have_functions)
  1887. with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
  1888. os.open("path", os.O_RDONLY, dir_fd=0)
  1889. def test_readlink(self):
  1890. self._verify_available("HAVE_READLINKAT")
  1891. if self.mac_ver >= (10, 10):
  1892. self.assertIn("HAVE_READLINKAT", posix._have_functions)
  1893. else:
  1894. self.assertNotIn("HAVE_READLINKAT", posix._have_functions)
  1895. with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
  1896. os.readlink("path", dir_fd=0)
  1897. def test_symlink(self):
  1898. self._verify_available("HAVE_SYMLINKAT")
  1899. if self.mac_ver >= (10, 10):
  1900. self.assertIn("HAVE_SYMLINKAT", posix._have_functions)
  1901. else:
  1902. self.assertNotIn("HAVE_SYMLINKAT", posix._have_functions)
  1903. with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
  1904. os.symlink("a", "b", dir_fd=0)
  1905. def test_utime(self):
  1906. self._verify_available("HAVE_FUTIMENS")
  1907. self._verify_available("HAVE_UTIMENSAT")
  1908. if self.mac_ver >= (10, 13):
  1909. self.assertIn("HAVE_FUTIMENS", posix._have_functions)
  1910. self.assertIn("HAVE_UTIMENSAT", posix._have_functions)
  1911. else:
  1912. self.assertNotIn("HAVE_FUTIMENS", posix._have_functions)
  1913. self.assertNotIn("HAVE_UTIMENSAT", posix._have_functions)
  1914. with self.assertRaisesRegex(NotImplementedError, "dir_fd unavailable"):
  1915. os.utime("path", dir_fd=0)
  1916. def tearDownModule():
  1917. support.reap_children()
  1918. if __name__ == '__main__':
  1919. unittest.main()